summaryrefslogtreecommitdiff
path: root/marshal.c
blob: 69e730ee5dddcfbcd9f58daaf8a8ae53f08c4bf7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
/**********************************************************************

  marshal.c -

  $Author$
  $Date$
  created at: Thu Apr 27 16:30:01 JST 1995

  Copyright (C) 1993-2003 Yukihiro Matsumoto

**********************************************************************/

#include "ruby.h"
#include "rubyio.h"
#include "st.h"
#include "util.h"

#include <math.h>
#ifdef HAVE_FLOAT_H
#include <float.h>
#endif
#ifdef HAVE_IEEEFP_H
#include <ieeefp.h>
#endif

#define BITSPERSHORT (2*CHAR_BIT)
#define SHORTMASK ((1<<BITSPERSHORT)-1)
#define SHORTDN(x) RSHIFT(x,BITSPERSHORT)

#if SIZEOF_SHORT == SIZEOF_BDIGITS
#define SHORTLEN(x) (x)
#else
static int
shortlen(len, ds)
    long len;
    BDIGIT *ds;
{
    BDIGIT num;
    int offset = 0;

    num = ds[len-1];
    while (num) {
	num = SHORTDN(num);
	offset++;
    }
    return (len - 1)*sizeof(BDIGIT)/2 + offset;
}
#define SHORTLEN(x) shortlen((x),d)
#endif

#define MARSHAL_MAJOR   4
#define MARSHAL_MINOR   8

#define TYPE_NIL	'0'
#define TYPE_TRUE	'T'
#define TYPE_FALSE	'F'
#define TYPE_FIXNUM	'i'

#define TYPE_EXTENDED	'e'
#define TYPE_UCLASS	'C'
#define TYPE_OBJECT	'o'
#define TYPE_DATA       'd'
#define TYPE_USERDEF	'u'
#define TYPE_USRMARSHAL	'U'
#define TYPE_FLOAT	'f'
#define TYPE_BIGNUM	'l'
#define TYPE_STRING	'"'
#define TYPE_REGEXP	'/'
#define TYPE_ARRAY	'['
#define TYPE_HASH	'{'
#define TYPE_HASH_DEF	'}'
#define TYPE_STRUCT	'S'
#define TYPE_MODULE_OLD	'M'
#define TYPE_CLASS	'c'
#define TYPE_MODULE	'm'

#define TYPE_SYMBOL	':'
#define TYPE_SYMLINK	';'

#define TYPE_IVAR	'I'
#define TYPE_LINK	'@'

static ID s_dump, s_load, s_mdump, s_mload;
static ID s_dump_data, s_load_data, s_alloc, s_call;
static ID s_getc, s_read, s_write, s_binmode;

struct dump_arg {
    VALUE obj;
    VALUE str, dest;
    st_table *symbols;
    st_table *data;
    int taint;
    VALUE wrapper;
};

struct dump_call_arg {
    VALUE obj;
    struct dump_arg *arg;
    int limit;
};

static void
check_dump_arg(arg, sym)
    struct dump_arg *arg;
    ID sym;
{
    if (!DATA_PTR(arg->wrapper)) {
        rb_raise(rb_eRuntimeError, "Marshal.dump reentered at %s",
		 rb_id2name(sym));
    }
}

static void
mark_dump_arg(ptr)
    void *ptr;
{
    struct dump_arg *p = ptr;
    if (!ptr)
        return;
    rb_mark_set(p->data);
}

static VALUE
class2path(klass)
    VALUE klass;
{
    VALUE path = rb_class_path(klass);
    char *n = RSTRING(path)->ptr;

    if (n[0] == '#') {
	rb_raise(rb_eTypeError, "can't dump anonymous %s %s",
		 (TYPE(klass) == T_CLASS ? "class" : "module"),
		 n);
    }
    if (rb_path2class(n) != rb_class_real(klass)) {
	rb_raise(rb_eTypeError, "%s can't be referred", n);
    }
    return path;
}

static void w_long _((long, struct dump_arg*));

static void
w_nbyte(s, n, arg)
    const char *s;
    int n;
    struct dump_arg *arg;
{
    VALUE buf = arg->str;
    rb_str_buf_cat(buf, s, n);
    if (arg->dest && RSTRING(buf)->len >= BUFSIZ) {
	if (arg->taint) OBJ_TAINT(buf);
	rb_io_write(arg->dest, buf);
	rb_str_resize(buf, 0);
    }
}

static void
w_byte(c, arg)
    char c;
    struct dump_arg *arg;
{
    w_nbyte(&c, 1, arg);
}

static void
w_bytes(s, n, arg)
    const char *s;
    int n;
    struct dump_arg *arg;
{
    w_long(n, arg);
    w_nbyte(s, n, arg);
}

static void
w_short(x, arg)
    int x;
    struct dump_arg *arg;
{
    w_byte((x >> 0) & 0xff, arg);
    w_byte((x >> 8) & 0xff, arg);
}

static void
w_long(x, arg)
    long x;
    struct dump_arg *arg;
{
    char buf[sizeof(long)+1];
    int i, len = 0;

#if SIZEOF_LONG > 4
    if (!(RSHIFT(x, 31) == 0 || RSHIFT(x, 31) == -1)) {
	/* big long does not fit in 4 bytes */
	rb_raise(rb_eTypeError, "long too big to dump");
    }
#endif

    if (x == 0) {
	w_byte(0, arg);
	return;
    }
    if (0 < x && x < 123) {
	w_byte(x + 5, arg);
	return;
    }
    if (-124 < x && x < 0) {
	w_byte((x - 5)&0xff, arg);
	return;
    }
    for (i=1;i<sizeof(long)+1;i++) {
	buf[i] = x & 0xff;
	x = RSHIFT(x,8);
	if (x == 0) {
	    buf[0] = i;
	    break;
	}
	if (x == -1) {
	    buf[0] = -i;
	    break;
	}
    }
    len = i;
    for (i=0;i<=len;i++) {
	w_byte(buf[i], arg);
    }
}

#ifdef DBL_MANT_DIG
#define DECIMAL_MANT (53-16)	/* from IEEE754 double precision */

#if DBL_MANT_DIG > 32
#define MANT_BITS 32
#elif DBL_MANT_DIG > 24
#define MANT_BITS 24
#elif DBL_MANT_DIG > 16
#define MANT_BITS 16
#else
#define MANT_BITS 8
#endif

static int
save_mantissa(d, buf)
    double d;
    char *buf;
{
    int e, i = 0;
    unsigned long m;
    double n;

    d = modf(ldexp(frexp(fabs(d), &e), DECIMAL_MANT), &d);
    if (d > 0) {
	buf[i++] = 0;
	do {
	    d = modf(ldexp(d, MANT_BITS), &n);
	    m = (unsigned long)n;
#if MANT_BITS > 24
	    buf[i++] = m >> 24;
#endif
#if MANT_BITS > 16
	    buf[i++] = m >> 16;
#endif
#if MANT_BITS > 8
	    buf[i++] = m >> 8;
#endif
	    buf[i++] = m;
	} while (d > 0);
	while (!buf[i - 1]) --i;
    }
    return i;
}

static double
load_mantissa(d, buf, len)
    double d;
    const char *buf;
    int len;
{
    if (--len > 0 && !*buf++) {	/* binary mantissa mark */
	int e, s = d < 0, dig = 0;
	unsigned long m;

	modf(ldexp(frexp(fabs(d), &e), DECIMAL_MANT), &d);
	do {
	    m = 0;
	    switch (len) {
	      default: m = *buf++ & 0xff;
#if MANT_BITS > 24
	      case 3: m = (m << 8) | (*buf++ & 0xff);
#endif
#if MANT_BITS > 16
	      case 2: m = (m << 8) | (*buf++ & 0xff);
#endif
#if MANT_BITS > 8
	      case 1: m = (m << 8) | (*buf++ & 0xff);
#endif
	    }
	    dig -= len < MANT_BITS / 8 ? 8 * (unsigned)len : MANT_BITS;
	    d += ldexp((double)m, dig);
	} while ((len -= MANT_BITS / 8) > 0);
	d = ldexp(d, e - DECIMAL_MANT);
	if (s) d = -d;
    }
    return d;
}
#else
#define load_mantissa(d, buf, len) (d)
#define save_mantissa(d, buf) 0
#endif

#ifdef DBL_DIG
#define FLOAT_DIG (DBL_DIG+2)
#else
#define FLOAT_DIG 17
#endif

static void
w_float(d, arg)
    double d;
    struct dump_arg *arg;
{
    char buf[100];

    if (isinf(d)) {
	if (d < 0) strcpy(buf, "-inf");
	else       strcpy(buf, "inf");
    }
    else if (isnan(d)) {
	strcpy(buf, "nan");
    }
    else if (d == 0.0) {
	if (1.0/d < 0) strcpy(buf, "-0");
	else           strcpy(buf, "0");
    }
    else {
	int len;

	/* xxx: should not use system's sprintf(3) */
	sprintf(buf, "%.*g", FLOAT_DIG, d);
	len = strlen(buf);
	w_bytes(buf, len + save_mantissa(d, buf + len), arg);
	return;
    }
    w_bytes(buf, strlen(buf), arg);
}

static void
w_symbol(id, arg)
    ID id;
    struct dump_arg *arg;
{
    const char *sym = rb_id2name(id);
    st_data_t num;

    if (st_lookup(arg->symbols, id, &num)) {
	w_byte(TYPE_SYMLINK, arg);
	w_long((long)num, arg);
    }
    else {
	w_byte(TYPE_SYMBOL, arg);
	w_bytes(sym, strlen(sym), arg);
	st_add_direct(arg->symbols, id, arg->symbols->num_entries);
    }
}

static void
w_unique(s, arg)
    const char *s;
    struct dump_arg *arg;
{
    if (s[0] == '#') {
	rb_raise(rb_eTypeError, "can't dump anonymous class %s", s);
    }
    w_symbol(rb_intern(s), arg);
}

static void w_object _((VALUE,struct dump_arg*,int));

static int
hash_each(key, value, arg)
    VALUE key, value;
    struct dump_call_arg *arg;
{
    w_object(key, arg->arg, arg->limit);
    w_object(value, arg->arg, arg->limit);
    return ST_CONTINUE;
}

static void
w_extended(klass, arg, check)
    VALUE klass;
    struct dump_arg *arg;
    int check;
{
    const char *path;

    if (check && FL_TEST(klass, FL_SINGLETON)) {
	if (RCLASS(klass)->m_tbl->num_entries ||
	    (RCLASS(klass)->iv_tbl && RCLASS(klass)->iv_tbl->num_entries > 1)) {
	    rb_raise(rb_eTypeError, "singleton can't be dumped");
	}
	klass = RCLASS(klass)->super;
    }
    while (BUILTIN_TYPE(klass) == T_ICLASS) {
	path = rb_class2name(RBASIC(klass)->klass);
	w_byte(TYPE_EXTENDED, arg);
	w_unique(path, arg);
	klass = RCLASS(klass)->super;
    }
}

static void
w_class(type, obj, arg, check)
    int type;
    VALUE obj;
    struct dump_arg *arg;
    int check;
{
    char *path;

    VALUE klass = CLASS_OF(obj);
    w_extended(klass, arg, check);
    w_byte(type, arg);
    path = RSTRING(class2path(rb_class_real(klass)))->ptr;
    w_unique(path, arg);
}

static void
w_uclass(obj, base_klass, arg)
    VALUE obj, base_klass;
    struct dump_arg *arg;
{
    VALUE klass = CLASS_OF(obj);

    w_extended(klass, arg, Qtrue);
    klass = rb_class_real(klass);
    if (klass != base_klass) {
	w_byte(TYPE_UCLASS, arg);
	w_unique(RSTRING(class2path(klass))->ptr, arg);
    }
}

static int
w_obj_each(id, value, arg)
    ID id;
    VALUE value;
    struct dump_call_arg *arg;
{
    w_symbol(id, arg->arg);
    w_object(value, arg->arg, arg->limit);
    return ST_CONTINUE;
}

static void
w_ivar(tbl, arg)
    st_table *tbl;
    struct dump_call_arg *arg;
{
    if (tbl) {
	w_long(tbl->num_entries, arg->arg);
	st_foreach_safe(tbl, w_obj_each, (st_data_t)arg);
    }
    else {
	w_long(0, arg->arg);
    }
}

static void
w_object(obj, arg, limit)
    VALUE obj;
    struct dump_arg *arg;
    int limit;
{
    struct dump_call_arg c_arg;
    st_table *ivtbl = 0;
    st_data_t num;

    if (limit == 0) {
	rb_raise(rb_eArgError, "exceed depth limit");
    }

    limit--;
    c_arg.limit = limit;
    c_arg.arg = arg;

    if (st_lookup(arg->data, obj, &num)) {
	w_byte(TYPE_LINK, arg);
	w_long((long)num, arg);
	return;
    }

    if ((ivtbl = rb_generic_ivar_table(obj)) != 0) {
	w_byte(TYPE_IVAR, arg);
    }
    if (obj == Qnil) {
	w_byte(TYPE_NIL, arg);
    }
    else if (obj == Qtrue) {
	w_byte(TYPE_TRUE, arg);
    }
    else if (obj == Qfalse) {
	w_byte(TYPE_FALSE, arg);
    }
    else if (FIXNUM_P(obj)) {
#if SIZEOF_LONG <= 4
	w_byte(TYPE_FIXNUM, arg);
	w_long(FIX2INT(obj), arg);
#else
	if (RSHIFT((long)obj, 31) == 0 || RSHIFT((long)obj, 31) == -1) {
	    w_byte(TYPE_FIXNUM, arg);
	    w_long(FIX2LONG(obj), arg);
	}
	else {
	    w_object(rb_int2big(FIX2LONG(obj)), arg, limit);
	}
#endif
    }
    else if (SYMBOL_P(obj)) {
	w_symbol(SYM2ID(obj), arg);
    }
    else {
	if (OBJ_TAINTED(obj)) arg->taint = Qtrue;

	st_add_direct(arg->data, obj, arg->data->num_entries);
	if (rb_respond_to(obj, s_mdump)) {
	    volatile VALUE v;

	    v = rb_funcall(obj, s_mdump, 0, 0);
	    check_dump_arg(arg, s_mdump);
	    w_class(TYPE_USRMARSHAL, obj, arg, Qfalse);
	    w_object(v, arg, limit);
	    if (ivtbl) w_ivar(0, &c_arg);
	    return;
	}
	if (rb_respond_to(obj, s_dump)) {
	    VALUE v;

	    v = rb_funcall(obj, s_dump, 1, INT2NUM(limit));
	    check_dump_arg(arg, s_dump);
	    if (TYPE(v) != T_STRING) {
		rb_raise(rb_eTypeError, "_dump() must return string");
	    }
	    if (!ivtbl && (ivtbl = rb_generic_ivar_table(v))) {
		w_byte(TYPE_IVAR, arg);
	    }
	    w_class(TYPE_USERDEF, obj, arg, Qfalse);
	    w_bytes(RSTRING(v)->ptr, RSTRING(v)->len, arg);
	    if (ivtbl) {
		w_ivar(ivtbl, &c_arg);
	    }
	    return;
	}

	switch (BUILTIN_TYPE(obj)) {
	  case T_CLASS:
	    if (FL_TEST(obj, FL_SINGLETON)) {
		rb_raise(rb_eTypeError, "singleton class can't be dumped");
	    }
	    w_byte(TYPE_CLASS, arg);
	    {
		VALUE path = class2path(obj);
		w_bytes(RSTRING(path)->ptr, RSTRING(path)->len, arg);
	    }
	    break;

	  case T_MODULE:
	    w_byte(TYPE_MODULE, arg);
	    {
		VALUE path = class2path(obj);
		w_bytes(RSTRING(path)->ptr, RSTRING(path)->len, arg);
	    }
	    break;

	  case T_FLOAT:
	    w_byte(TYPE_FLOAT, arg);
	    w_float(RFLOAT(obj)->value, arg);
	    break;

	  case T_BIGNUM:
	    w_byte(TYPE_BIGNUM, arg);
	    {
		char sign = RBIGNUM(obj)->sign ? '+' : '-';
		long len = RBIGNUM(obj)->len;
		BDIGIT *d = RBIGNUM(obj)->digits;

		w_byte(sign, arg);
		w_long(SHORTLEN(len), arg); /* w_short? */
		while (len--) {
#if SIZEOF_BDIGITS > SIZEOF_SHORT
		    BDIGIT num = *d;
		    int i;

		    for (i=0; i<SIZEOF_BDIGITS; i+=SIZEOF_SHORT) {
			w_short(num & SHORTMASK, arg);
			num = SHORTDN(num);
			if (len == 0 && num == 0) break;
		    }
#else
		    w_short(*d, arg);
#endif
		    d++;
		}
	    }
	    break;

	  case T_STRING:
	    w_uclass(obj, rb_cString, arg);
	    w_byte(TYPE_STRING, arg);
	    w_bytes(RSTRING(obj)->ptr, RSTRING(obj)->len, arg);
	    break;

	  case T_REGEXP:
	    w_uclass(obj, rb_cRegexp, arg);
	    w_byte(TYPE_REGEXP, arg);
	    w_bytes(RREGEXP(obj)->str, RREGEXP(obj)->len, arg);
	    w_byte(rb_reg_options(obj), arg);
	    break;

	  case T_ARRAY:
	    w_uclass(obj, rb_cArray, arg);
	    w_byte(TYPE_ARRAY, arg);
	    {
		long len = RARRAY(obj)->len;
		VALUE *ptr = RARRAY(obj)->ptr;

		w_long(len, arg);
		while (len--) {
		    w_object(*ptr, arg, limit);
		    ptr++;
		}
	    }
	    break;

	  case T_HASH:
	    w_uclass(obj, rb_cHash, arg);
	    if (NIL_P(RHASH(obj)->ifnone)) {
		w_byte(TYPE_HASH, arg);
	    }
	    else if (FL_TEST(obj, FL_USER2)) {
		/* FL_USER2 means HASH_PROC_DEFAULT (see hash.c) */
		rb_raise(rb_eTypeError, "can't dump hash with default proc");
	    }
	    else {
		w_byte(TYPE_HASH_DEF, arg);
	    }
	    w_long(RHASH(obj)->tbl->num_entries, arg);
	    rb_hash_foreach(obj, hash_each, (st_data_t)&c_arg);
	    if (!NIL_P(RHASH(obj)->ifnone)) {
		w_object(RHASH(obj)->ifnone, arg, limit);
	    }
	    break;

	  case T_STRUCT:
	    w_class(TYPE_STRUCT, obj, arg, Qtrue);
	    {
		long len = RSTRUCT(obj)->len;
		VALUE mem;
		long i;

		w_long(len, arg);
		mem = rb_struct_members(obj);
		for (i=0; i<len; i++) {
		    w_symbol(SYM2ID(RARRAY(mem)->ptr[i]), arg);
		    w_object(RSTRUCT(obj)->ptr[i], arg, limit);
		}
	    }
	    break;

	  case T_OBJECT:
	    w_class(TYPE_OBJECT, obj, arg, Qtrue);
	    w_ivar(ROBJECT(obj)->iv_tbl, &c_arg);
	    break;

	  case T_DATA:
	    {
		VALUE v;

		if (!rb_respond_to(obj, s_dump_data)) {
		    rb_raise(rb_eTypeError,
			     "no marshal_dump is defined for class %s",
			     rb_obj_classname(obj));
		}
		v = rb_funcall(obj, s_dump_data, 0);
		check_dump_arg(arg, s_dump_data);
		w_class(TYPE_DATA, obj, arg, Qtrue);
		w_object(v, arg, limit);
	    }
	    break;

	  default:
	    rb_raise(rb_eTypeError, "can't dump %s",
		     rb_obj_classname(obj));
	    break;
	}
    }
    if (ivtbl) {
	w_ivar(ivtbl, &c_arg);
    }
}

static VALUE
dump(arg)
    struct dump_call_arg *arg;
{
    w_object(arg->obj, arg->arg, arg->limit);
    if (arg->arg->dest) {
	rb_io_write(arg->arg->dest, arg->arg->str);
	rb_str_resize(arg->arg->str, 0);
    }
    return 0;
}

static VALUE
dump_ensure(arg)
    struct dump_arg *arg;
{
    if (!DATA_PTR(arg->wrapper)) return 0;
    st_free_table(arg->symbols);
    st_free_table(arg->data);
    DATA_PTR(arg->wrapper) = 0;
    arg->wrapper = 0;
    if (arg->taint) {
	OBJ_TAINT(arg->str);
    }

    return 0;
}

/*
 * call-seq:
 *      dump( obj [, anIO] , limit=--1 ) => anIO
 *
 * Serializes obj and all descendent objects. If anIO is
 * specified, the serialized data will be written to it, otherwise the
 * data will be returned as a String. If limit is specified, the
 * traversal of subobjects will be limited to that depth. If limit is
 * negative, no checking of depth will be performed.
 *
 *     class Klass
 *       def initialize(str)
 *         @str = str
 *       end
 *       def sayHello
 *         @str
 *       end
 *     end
 *
 * (produces no output)
 *
 *     o = Klass.new("hello\n")
 *     data = Marshal.dump(o)
 *     obj = Marshal.load(data)
 *     obj.sayHello   #=> "hello\n"
 */
static VALUE
marshal_dump(argc, argv)
    int argc;
    VALUE* argv;
{
    VALUE obj, port, a1, a2;
    int limit = -1;
    struct dump_arg arg;
    struct dump_call_arg c_arg;

    port = Qnil;
    rb_scan_args(argc, argv, "12", &obj, &a1, &a2);
    if (argc == 3) {
	if (!NIL_P(a2)) limit = NUM2INT(a2);
	if (NIL_P(a1)) goto type_error;
	port = a1;
    }
    else if (argc == 2) {
	if (FIXNUM_P(a1)) limit = FIX2INT(a1);
	else if (NIL_P(a1)) goto type_error;
	else port = a1;
    }
    arg.dest = 0;
    arg.symbols = st_init_numtable();
    arg.data    = st_init_numtable();
    arg.taint   = Qfalse;
    arg.str = rb_str_buf_new(0);
    RBASIC(arg.str)->klass = 0;
    arg.wrapper = Data_Wrap_Struct(rb_cData, mark_dump_arg, 0, &arg);
    if (!NIL_P(port)) {
	if (!rb_respond_to(port, s_write)) {
	  type_error:
	    rb_raise(rb_eTypeError, "instance of IO needed");
	}
	arg.dest = port;
	if (rb_respond_to(port, s_binmode)) {
	    rb_funcall2(port, s_binmode, 0, 0);
	    check_dump_arg(&arg, s_binmode);
	}
    }
    else {
	port = arg.str;
    }

    c_arg.obj   = obj;
    c_arg.arg   = &arg;
    c_arg.limit = limit;

    w_byte(MARSHAL_MAJOR, &arg);
    w_byte(MARSHAL_MINOR, &arg);

    rb_ensure(dump, (VALUE)&c_arg, dump_ensure, (VALUE)&arg);
    RBASIC(arg.str)->klass = rb_cString;

    return port;
}

struct load_arg {
    VALUE src;
    long offset;
    st_table *symbols;
    st_table *data;
    VALUE proc;
    int taint;
    VALUE wrapper;
};

static void
check_load_arg(arg, sym)
    struct load_arg *arg;
    ID sym;
{
    if (!DATA_PTR(arg->wrapper)) {
        rb_raise(rb_eRuntimeError, "Marshal.load reentered at %s",
		 rb_id2name(sym));
    }
}

static void
mark_load_arg(ptr)
    void *ptr;
{
    struct load_arg *p = ptr;
    if (!ptr)
        return;
    rb_mark_tbl(p->data);
}

static VALUE r_object _((struct load_arg *arg));

static int
r_byte(arg)
    struct load_arg *arg;
{
    int c;

    if (TYPE(arg->src) == T_STRING) {
	if (RSTRING(arg->src)->len > arg->offset) {
	    c = (unsigned char)RSTRING(arg->src)->ptr[arg->offset++];
	}
	else {
	    rb_raise(rb_eArgError, "marshal data too short");
	}
    }
    else {
	VALUE src = arg->src;
	VALUE v = rb_funcall2(src, s_getc, 0, 0);
	check_load_arg(arg, s_getc);
	if (NIL_P(v)) rb_eof_error();
	c = (unsigned char)FIX2INT(v);
    }
    return c;
}

static void
long_toobig(size)
    int size;
{
    rb_raise(rb_eTypeError, "long too big for this architecture (size %d, given %d)",
	     sizeof(long), size);
}

#undef SIGN_EXTEND_CHAR
#if __STDC__
# define SIGN_EXTEND_CHAR(c) ((signed char)(c))
#else  /* not __STDC__ */
/* As in Harbison and Steele.  */
# define SIGN_EXTEND_CHAR(c) ((((unsigned char)(c)) ^ 128) - 128)
#endif

static long
r_long(arg)
    struct load_arg *arg;
{
    register long x;
    int c = SIGN_EXTEND_CHAR(r_byte(arg));
    long i;

    if (c == 0) return 0;
    if (c > 0) {
	if (4 < c && c < 128) {
	    return c - 5;
	}
	if (c > sizeof(long)) long_toobig(c);
	x = 0;
	for (i=0;i<c;i++) {
	    x |= (long)r_byte(arg) << (8*i);
	}
    }
    else {
	if (-129 < c && c < -4) {
	    return c + 5;
	}
	c = -c;
	if (c > sizeof(long)) long_toobig(c);
	x = -1;
	for (i=0;i<c;i++) {
	    x &= ~((long)0xff << (8*i));
	    x |= (long)r_byte(arg) << (8*i);
	}
    }
    return x;
}

#define r_bytes(arg) r_bytes0(r_long(arg), (arg))

static VALUE
r_bytes0(len, arg)
    long len;
    struct load_arg *arg;
{
    VALUE str;

    if (len == 0) return rb_str_new(0, 0);
    if (TYPE(arg->src) == T_STRING) {
	if (RSTRING(arg->src)->len - arg->offset >= len) {
	    str = rb_str_new(RSTRING(arg->src)->ptr+arg->offset, len);
	    arg->offset += len;
	}
	else {
	  too_short:
	    rb_raise(rb_eArgError, "marshal data too short");
	}
    }
    else {
	VALUE src = arg->src;
	VALUE n = LONG2NUM(len);
	str = rb_funcall2(src, s_read, 1, &n);
	check_load_arg(arg, s_read);
	if (NIL_P(str)) goto too_short;
	StringValue(str);
	if (RSTRING(str)->len != len) goto too_short;
	if (OBJ_TAINTED(str)) arg->taint = Qtrue;
    }
    return str;
}

static ID
r_symlink(arg)
    struct load_arg *arg;
{
    ID id;
    long num = r_long(arg);

    if (st_lookup(arg->symbols, num, &id)) {
	return id;
    }
    rb_raise(rb_eArgError, "bad symbol");
}

static ID
r_symreal(arg)
    struct load_arg *arg;
{
    ID id;

    id = rb_intern(RSTRING(r_bytes(arg))->ptr);
    st_insert(arg->symbols, arg->symbols->num_entries, id);

    return id;
}

static ID
r_symbol(arg)
    struct load_arg *arg;
{
    if (r_byte(arg) == TYPE_SYMLINK) {
	return r_symlink(arg);
    }
    return r_symreal(arg);
}

static const char*
r_unique(arg)
    struct load_arg *arg;
{
    return rb_id2name(r_symbol(arg));
}

static VALUE
r_string(arg)
    struct load_arg *arg;
{
    return r_bytes(arg);
}

static VALUE
r_entry(v, arg)
    VALUE v;
    struct load_arg *arg;
{
    st_insert(arg->data, arg->data->num_entries, (st_data_t)v);
    if (arg->taint) OBJ_TAINT(v);
    return v;
}

static void
r_ivar(obj, arg)
    VALUE obj;
    struct load_arg *arg;
{
    long len;

    len = r_long(arg);
    if (len > 0) {
	while (len--) {
	    ID id = r_symbol(arg);
	    VALUE val = r_object(arg);
	    rb_ivar_set(obj, id, val);
	}
    }
}

static VALUE
path2class(path)
    const char *path;
{
    VALUE v = rb_path2class(path);

    if (TYPE(v) != T_CLASS) {
	rb_raise(rb_eArgError, "%s does not refer class", path);
    }
    return v;
}

static VALUE
path2module(path)
    const char *path;
{
    VALUE v = rb_path2class(path);

    if (TYPE(v) != T_MODULE) {
	rb_raise(rb_eArgError, "%s does not refer module", path);
    }
    return v;
}

static VALUE
r_object0(arg, proc, ivp, extmod)
    struct load_arg *arg;
    VALUE proc;
    int *ivp;
    VALUE extmod;
{
    VALUE v = Qnil;
    int type = r_byte(arg);
    long id;
    st_data_t link;

    switch (type) {
      case TYPE_LINK:
	id = r_long(arg);
 	if (!st_lookup(arg->data, (st_data_t)id, &link)) {
	    rb_raise(rb_eArgError, "dump format error (unlinked)");
	}
	v = (st_data_t)link;
	return v;

      case TYPE_IVAR:
        {
	    int ivar = Qtrue;

	    v = r_object0(arg, 0, &ivar, extmod);
	    if (ivar) r_ivar(v, arg);
	}
	break;

      case TYPE_EXTENDED:
	{
	    VALUE m = path2module(r_unique(arg));

            if (NIL_P(extmod)) extmod = rb_ary_new2(0);
            rb_ary_push(extmod, m);

	    v = r_object0(arg, 0, 0, extmod);
            while (RARRAY(extmod)->len > 0) {
                m = rb_ary_pop(extmod);
                rb_extend_object(v, m);
            }
	}
	break;

      case TYPE_UCLASS:
	{
	    VALUE c = path2class(r_unique(arg));

	    if (FL_TEST(c, FL_SINGLETON)) {
		rb_raise(rb_eTypeError, "singleton can't be loaded");
	    }
	    v = r_object0(arg, 0, 0, extmod);
	    if (rb_special_const_p(v) || TYPE(v) == T_OBJECT || TYPE(v) == T_CLASS) {
	      format_error:
		rb_raise(rb_eArgError, "dump format error (user class)");
	    }
	    if (TYPE(v) == T_MODULE || !RTEST(rb_class_inherited_p(c, RBASIC(v)->klass))) {
		VALUE tmp = rb_obj_alloc(c);

		if (TYPE(v) != TYPE(tmp)) goto format_error;
	    }
	    RBASIC(v)->klass = c;
	}
	break;

      case TYPE_NIL:
	v = Qnil;
	break;

      case TYPE_TRUE:
	v = Qtrue;
	break;

      case TYPE_FALSE:
	v = Qfalse;
	break;

      case TYPE_FIXNUM:
	{
	    long i = r_long(arg);
	    v = LONG2FIX(i);
	}
	break;

      case TYPE_FLOAT:
	{
	    double d, t = 0.0;
	    VALUE str = r_bytes(arg);
	    const char *ptr = RSTRING(str)->ptr;

	    if (strcmp(ptr, "nan") == 0) {
		d = t / t;
	    }
	    else if (strcmp(ptr, "inf") == 0) {
		d = 1.0 / t;
	    }
	    else if (strcmp(ptr, "-inf") == 0) {
		d = -1.0 / t;
	    }
	    else {
		char *e;
		d = strtod(ptr, &e);
		d = load_mantissa(d, e, RSTRING(str)->len - (e - ptr));
	    }
	    v = rb_float_new(d);
	    r_entry(v, arg);
	}
	break;

      case TYPE_BIGNUM:
	{
	    long len;
	    BDIGIT *digits;
	    volatile VALUE data;

	    NEWOBJ(big, struct RBignum);
	    OBJSETUP(big, rb_cBignum, T_BIGNUM);
	    big->sign = (r_byte(arg) == '+');
	    len = r_long(arg);
	    data = r_bytes0(len * 2, arg);
#if SIZEOF_BDIGITS == SIZEOF_SHORT
	    big->len = len;
#else
	    big->len = (len + 1) * 2 / sizeof(BDIGIT);
#endif
	    big->digits = digits = ALLOC_N(BDIGIT, big->len);
	    MEMCPY(digits, RSTRING(data)->ptr, char, len * 2);
#if SIZEOF_BDIGITS > SIZEOF_SHORT
	    MEMZERO((char *)digits + len * 2, char,
		    big->len * sizeof(BDIGIT) - len * 2);
#endif
	    len = big->len;
	    while (len > 0) {
		unsigned char *p = (unsigned char *)digits;
		BDIGIT num = 0;
#if SIZEOF_BDIGITS > SIZEOF_SHORT
		int shift = 0;
		int i;

		for (i=0; i<SIZEOF_BDIGITS; i++) {
		    num |= (int)p[i] << shift;
		    shift += 8;
		}
#else
		num = p[0] | (p[1] << 8);
#endif
		*digits++ = num;
		len--;
	    }
	    v = rb_big_norm((VALUE)big);
	    r_entry(v, arg);
	}
	break;

      case TYPE_STRING:
	v = r_entry(r_string(arg), arg);
	break;

      case TYPE_REGEXP:
	{
	    volatile VALUE str = r_bytes(arg);
	    int options = r_byte(arg);
	    v = r_entry(rb_reg_new(RSTRING(str)->ptr, RSTRING(str)->len, options), arg);
	}
	break;

      case TYPE_ARRAY:
	{
	    volatile long len = r_long(arg); /* gcc 2.7.2.3 -O2 bug?? */

	    v = rb_ary_new2(len);
	    r_entry(v, arg);
	    while (len--) {
		rb_ary_push(v, r_object(arg));
	    }
	}
	break;

      case TYPE_HASH:
      case TYPE_HASH_DEF:
	{
	    long len = r_long(arg);

	    v = rb_hash_new();
	    r_entry(v, arg);
	    while (len--) {
		VALUE key = r_object(arg);
		VALUE value = r_object(arg);
		rb_hash_aset(v, key, value);
	    }
	    if (type == TYPE_HASH_DEF) {
		RHASH(v)->ifnone = r_object(arg);
	    }
	}
	break;

      case TYPE_STRUCT:
	{
	    VALUE klass, mem, values;
	    volatile long i;	/* gcc 2.7.2.3 -O2 bug?? */
	    long len;
	    ID slot;

	    klass = path2class(r_unique(arg));
	    mem = rb_struct_s_members(klass);
	    len = r_long(arg);

	    values = rb_ary_new2(len);
	    for (i=0; i<len; i++) {
		rb_ary_push(values, Qnil);
	    }
	    v = rb_struct_alloc(klass, values);
	    r_entry(v, arg);
	    for (i=0; i<len; i++) {
		slot = r_symbol(arg);

		if (RARRAY(mem)->ptr[i] != ID2SYM(slot)) {
		    rb_raise(rb_eTypeError, "struct %s not compatible (:%s for :%s)",
			     rb_class2name(klass),
			     rb_id2name(slot),
			     rb_id2name(SYM2ID(RARRAY(mem)->ptr[i])));
		}
		rb_struct_aset(v, LONG2FIX(i), r_object(arg));
	    }
	}
	break;

      case TYPE_USERDEF:
        {
	    VALUE klass = path2class(r_unique(arg));
	    VALUE data;

	    if (!rb_respond_to(klass, s_load)) {
		rb_raise(rb_eTypeError, "class %s needs to have method `_load'",
			 rb_class2name(klass));
	    }
	    data = r_string(arg);
	    if (ivp) {
		r_ivar(data, arg);
		*ivp = Qfalse;
	    }
	    v = rb_funcall(klass, s_load, 1, data);
	    check_load_arg(arg, s_load);
	    r_entry(v, arg);
	}
        break;

      case TYPE_USRMARSHAL:
        {
	    VALUE klass = path2class(r_unique(arg));
	    VALUE data;

	    v = rb_obj_alloc(klass);
            if (! NIL_P(extmod)) {
                while (RARRAY(extmod)->len > 0) {
                    VALUE m = rb_ary_pop(extmod);
                    rb_extend_object(v, m);
                }
            }
	    if (!rb_respond_to(v, s_mload)) {
		rb_raise(rb_eTypeError, "instance of %s needs to have method `marshal_load'",
			 rb_class2name(klass));
	    }
	    r_entry(v, arg);
	    data = r_object(arg);
	    rb_funcall(v, s_mload, 1, data);
	    check_load_arg(arg, s_mload);
	}
        break;

      case TYPE_OBJECT:
	{
	    VALUE klass = path2class(r_unique(arg));

	    v = rb_obj_alloc(klass);
	    if (TYPE(v) != T_OBJECT) {
		rb_raise(rb_eArgError, "dump format error");
	    }
	    r_entry(v, arg);
	    r_ivar(v, arg);
	}
	break;

      case TYPE_DATA:
       {
           VALUE klass = path2class(r_unique(arg));
           if (rb_respond_to(klass, s_alloc)) {
	       static int warn = Qtrue;
	       if (warn) {
		   rb_warn("define `allocate' instead of `_alloc'");
		   warn = Qfalse;
	       }
	       v = rb_funcall(klass, s_alloc, 0);
	       check_load_arg(arg, s_alloc);
           }
	   else {
	       v = rb_obj_alloc(klass);
	   }
           if (TYPE(v) != T_DATA) {
               rb_raise(rb_eArgError, "dump format error");
           }
           r_entry(v, arg);
           if (!rb_respond_to(v, s_load_data)) {
               rb_raise(rb_eTypeError,
                        "class %s needs to have instance method `_load_data'",
                        rb_class2name(klass));
           }
           rb_funcall(v, s_load_data, 1, r_object0(arg, 0, 0, extmod));
	   check_load_arg(arg, s_load_data);
       }
       break;

      case TYPE_MODULE_OLD:
        {
	    volatile VALUE str = r_bytes(arg);

	    v = rb_path2class(RSTRING(str)->ptr);
	    r_entry(v, arg);
	}
	break;

      case TYPE_CLASS:
        {
	    volatile VALUE str = r_bytes(arg);

	    v = path2class(RSTRING(str)->ptr);
	    r_entry(v, arg);
	}
	break;

      case TYPE_MODULE:
        {
	    volatile VALUE str = r_bytes(arg);

	    v = path2module(RSTRING(str)->ptr);
	    r_entry(v, arg);
	}
	break;

      case TYPE_SYMBOL:
	v = ID2SYM(r_symreal(arg));
	break;

      case TYPE_SYMLINK:
	return ID2SYM(r_symlink(arg));

      default:
	rb_raise(rb_eArgError, "dump format error(0x%x)", type);
	break;
    }
    if (proc) {
	rb_funcall(proc, s_call, 1, v);
	check_load_arg(arg, s_call);
    }
    return v;
}

static VALUE
r_object(arg)
    struct load_arg *arg;
{
    return r_object0(arg, arg->proc, 0, Qnil);
}

static VALUE
load(arg)
    struct load_arg *arg;
{
    return r_object(arg);
}

static VALUE
load_ensure(arg)
    struct load_arg *arg;
{
    if (!DATA_PTR(arg->wrapper)) return 0;
    st_free_table(arg->symbols);
    st_free_table(arg->data);
    DATA_PTR(arg->wrapper) = 0;
    arg->wrapper = 0;
    return 0;
}

/*
 * call-seq:
 *     load( source [, proc] ) => obj
 *     restore( source [, proc] ) => obj
 * 
 * Returns the result of converting the serialized data in source into a
 * Ruby object (possibly with associated subordinate objects). source
 * may be either an instance of IO or an object that responds to
 * to_str. If proc is specified, it will be passed each object as it
 * is deserialized.
 */
static VALUE
marshal_load(argc, argv)
    int argc;
    VALUE *argv;
{
    VALUE port, proc;
    int major, minor;
    VALUE v;
    struct load_arg arg;

    rb_scan_args(argc, argv, "11", &port, &proc);
    v = rb_check_string_type(port);
    if (!NIL_P(v)) {
	arg.taint = OBJ_TAINTED(port); /* original taintedness */
	port = v;
    }
    else if (rb_respond_to(port, s_getc) && rb_respond_to(port, s_read)) {
	if (rb_respond_to(port, s_binmode)) {
	    rb_funcall2(port, s_binmode, 0, 0);
	}
	arg.taint = Qtrue;
    }
    else {
	rb_raise(rb_eTypeError, "instance of IO needed");
    }
    arg.src = port;
    arg.offset = 0;
    arg.symbols = st_init_numtable();
    arg.data    = st_init_numtable();
    arg.proc = 0;
    arg.wrapper = Data_Wrap_Struct(rb_cData, mark_load_arg, 0, &arg);

    major = r_byte(&arg);
    minor = r_byte(&arg);
    if (major != MARSHAL_MAJOR || minor > MARSHAL_MINOR) {
	rb_raise(rb_eTypeError, "incompatible marshal file format (can't be read)\n\
\tformat version %d.%d required; %d.%d given",
		 MARSHAL_MAJOR, MARSHAL_MINOR, major, minor);
    }
    if (RTEST(ruby_verbose) && minor != MARSHAL_MINOR) {
	rb_warn("incompatible marshal file format (can be read)\n\
\tformat version %d.%d required; %d.%d given",
		MARSHAL_MAJOR, MARSHAL_MINOR, major, minor);
    }

    if (!NIL_P(proc)) arg.proc = proc;
    v = rb_ensure(load, (VALUE)&arg, load_ensure, (VALUE)&arg);

    return v;
}

/*
 * The marshaling library converts collections of Ruby objects into a
 * byte stream, allowing them to be stored outside the currently
 * active script. This data may subsequently be read and the original
 * objects reconstituted.
 * Marshaled data has major and minor version numbers stored along
 * with the object information. In normal use, marshaling can only
 * load data written with the same major version number and an equal
 * or lower minor version number. If Ruby's ``verbose'' flag is set
 * (normally using -d, -v, -w, or --verbose) the major and minor
 * numbers must match exactly. Marshal versioning is independent of
 * Ruby's version numbers. You can extract the version by reading the
 * first two bytes of marshaled data.
 *
 *     str = Marshal.dump("thing")
 *     RUBY_VERSION   #=> "1.8.0"
 *     str[0]         #=> 4
 *     str[1]         #=> 8
 *
 * Some objects cannot be dumped: if the objects to be dumped include
 * bindings, procedure or method objects, instances of class IO, or
 * singleton objects, a TypeError will be raised.
 * If your class has special serialization needs (for example, if you
 * want to serialize in some specific format), or if it contains
 * objects that would otherwise not be serializable, you can implement
 * your own serialization strategy by defining two methods, _dump and
 * _load:
 * The instance method _dump should return a String object containing
 * all the information necessary to reconstitute objects of this class
 * and all referenced objects up to a maximum depth given as an integer
 * parameter (a value of -1 implies that you should disable depth checking).
 * The class method _load should take a String and return an object of this class.
 */
void
Init_marshal()
{
    VALUE rb_mMarshal = rb_define_module("Marshal");

    s_dump = rb_intern("_dump");
    s_load = rb_intern("_load");
    s_mdump = rb_intern("marshal_dump");
    s_mload = rb_intern("marshal_load");
    s_dump_data = rb_intern("_dump_data");
    s_load_data = rb_intern("_load_data");
    s_alloc = rb_intern("_alloc");
    s_call = rb_intern("call");
    s_getc = rb_intern("getc");
    s_read = rb_intern("read");
    s_write = rb_intern("write");
    s_binmode = rb_intern("binmode");

    rb_define_module_function(rb_mMarshal, "dump", marshal_dump, -1);
    rb_define_module_function(rb_mMarshal, "load", marshal_load, -1);
    rb_define_module_function(rb_mMarshal, "restore", marshal_load, -1);

    rb_define_const(rb_mMarshal, "MAJOR_VERSION", INT2FIX(MARSHAL_MAJOR));
    rb_define_const(rb_mMarshal, "MINOR_VERSION", INT2FIX(MARSHAL_MINOR));
}

VALUE
rb_marshal_dump(obj, port)
    VALUE obj, port;
{
    int argc = 1;
    VALUE argv[2];

    argv[0] = obj;
    argv[1] = port;
    if (!NIL_P(port)) argc = 2;
    return marshal_dump(argc, argv);
}

VALUE
rb_marshal_load(port)
    VALUE port;
{
    return marshal_load(1, &port);
}
one' style='width: 99.6%;'/> -rw-r--r--ext/-test-/load/resolve_symbol_target/extconf.rb1
-rw-r--r--ext/-test-/load/resolve_symbol_target/resolve_symbol_target.c15
-rw-r--r--ext/-test-/load/resolve_symbol_target/resolve_symbol_target.def4
-rw-r--r--ext/-test-/load/resolve_symbol_target/resolve_symbol_target.h4
-rw-r--r--ext/-test-/load/stringify_symbols/extconf.rb1
-rw-r--r--ext/-test-/load/stringify_symbols/stringify_symbols.c29
-rw-r--r--ext/-test-/load/stringify_target/extconf.rb1
-rw-r--r--ext/-test-/load/stringify_target/stringify_target.c15
-rw-r--r--ext/-test-/load/stringify_target/stringify_target.def4
-rw-r--r--ext/-test-/load/stringify_target/stringify_target.h4
-rw-r--r--ext/-test-/marshal/compat/depend1
-rw-r--r--ext/-test-/marshal/internal_ivar/depend1
-rw-r--r--ext/-test-/marshal/usr/depend1
-rw-r--r--ext/-test-/memory_view/depend1
-rw-r--r--ext/-test-/memory_view/memory_view.c4
-rw-r--r--ext/-test-/method/depend2
-rw-r--r--ext/-test-/notimplement/depend1
-rw-r--r--ext/-test-/num2int/depend1
-rw-r--r--ext/-test-/path_to_class/depend1
-rw-r--r--ext/-test-/popen_deadlock/depend1
-rw-r--r--ext/-test-/postponed_job/depend1
-rw-r--r--ext/-test-/postponed_job/postponed_job.c131
-rw-r--r--ext/-test-/printf/depend1
-rw-r--r--ext/-test-/proc/depend3
-rw-r--r--ext/-test-/public_header_warnings/extconf.rb23
-rw-r--r--ext/-test-/random/depend3
-rw-r--r--ext/-test-/rational/depend1
-rw-r--r--ext/-test-/rb_call_super_kw/depend1
-rw-r--r--ext/-test-/recursion/depend1
-rw-r--r--ext/-test-/regexp/depend2
-rw-r--r--ext/-test-/scan_args/depend1
-rw-r--r--ext/-test-/st/foreach/depend1
-rw-r--r--ext/-test-/st/numhash/depend1
-rw-r--r--ext/-test-/st/update/depend1
-rw-r--r--ext/-test-/string/depend177
-rw-r--r--ext/-test-/string/fstring.c10
-rw-r--r--ext/-test-/struct/depend5
-rw-r--r--ext/-test-/struct/member.c2
-rw-r--r--ext/-test-/symbol/depend2
-rw-r--r--ext/-test-/thread/id/extconf.rb3
-rw-r--r--ext/-test-/thread/id/id.c15
-rw-r--r--ext/-test-/thread/instrumentation/depend1
-rw-r--r--ext/-test-/thread/instrumentation/instrumentation.c221
-rw-r--r--ext/-test-/thread/lock_native_thread/extconf.rb2
-rw-r--r--ext/-test-/thread/lock_native_thread/lock_native_thread.c50
-rw-r--r--ext/-test-/thread_fd/depend1
-rw-r--r--ext/-test-/time/depend3
-rw-r--r--ext/-test-/tracepoint/depend2
-rw-r--r--ext/-test-/tracepoint/gc_hook.c4
-rw-r--r--ext/-test-/typeddata/depend1
-rw-r--r--ext/-test-/vm/depend1
-rw-r--r--ext/-test-/wait/depend1
-rw-r--r--ext/bigdecimal/bigdecimal.c7725
-rw-r--r--ext/bigdecimal/bigdecimal.gemspec54
-rw-r--r--ext/bigdecimal/bigdecimal.h313
-rw-r--r--ext/bigdecimal/bits.h141
-rw-r--r--ext/bigdecimal/depend327
-rw-r--r--ext/bigdecimal/extconf.rb62
-rw-r--r--ext/bigdecimal/feature.h68
-rw-r--r--ext/bigdecimal/lib/bigdecimal.rb5
-rw-r--r--ext/bigdecimal/lib/bigdecimal/jacobian.rb90
-rw-r--r--ext/bigdecimal/lib/bigdecimal/ludcmp.rb89
-rw-r--r--ext/bigdecimal/lib/bigdecimal/math.rb232
-rw-r--r--ext/bigdecimal/lib/bigdecimal/newton.rb80
-rw-r--r--ext/bigdecimal/lib/bigdecimal/util.rb185
-rw-r--r--ext/bigdecimal/missing.c27
-rw-r--r--ext/bigdecimal/missing.h196
-rw-r--r--ext/bigdecimal/missing/dtoa.c3462
-rw-r--r--ext/bigdecimal/sample/linear.rb74
-rw-r--r--ext/bigdecimal/sample/nlsolve.rb40
-rw-r--r--ext/bigdecimal/sample/pi.rb21
-rw-r--r--ext/bigdecimal/static_assert.h54
-rw-r--r--ext/cgi/escape/depend1
-rw-r--r--ext/cgi/escape/escape.c33
-rw-r--r--ext/continuation/depend1
-rw-r--r--ext/coverage/coverage.c3
-rw-r--r--ext/coverage/depend1
-rw-r--r--ext/date/date.gemspec2
-rw-r--r--ext/date/date_core.c25
-rw-r--r--ext/date/depend4
-rw-r--r--ext/digest/.document3
-rw-r--r--ext/digest/bubblebabble/bubblebabble.c7
-rw-r--r--ext/digest/bubblebabble/depend1
-rw-r--r--ext/digest/depend1
-rw-r--r--ext/digest/digest.c42
-rw-r--r--ext/digest/digest.h19
-rw-r--r--ext/digest/md5/depend2
-rw-r--r--ext/digest/md5/md5init.c3
-rw-r--r--ext/digest/rmd160/depend2
-rw-r--r--ext/digest/rmd160/rmd160init.c3
-rw-r--r--ext/digest/sha1/depend2
-rw-r--r--ext/digest/sha1/sha1init.c3
-rw-r--r--ext/digest/sha2/depend2
-rw-r--r--ext/digest/sha2/sha2init.c47
-rw-r--r--ext/erb/escape/extconf.rb3
-rw-r--r--ext/etc/.document2
-rw-r--r--ext/etc/depend1
-rw-r--r--ext/etc/etc.c108
-rw-r--r--ext/etc/mkconstants.rb32
-rwxr-xr-xext/extmk.rb58
-rw-r--r--ext/fcntl/depend1
-rw-r--r--ext/fcntl/fcntl.c98
-rw-r--r--ext/fcntl/fcntl.gemspec3
-rw-r--r--ext/fiddle/depend8
-rw-r--r--ext/fiddle/fiddle.gemspec1
-rw-r--r--ext/fiddle/lib/fiddle/version.rb2
-rw-r--r--ext/io/console/console.c170
-rw-r--r--ext/io/console/depend1
-rw-r--r--ext/io/console/extconf.rb6
-rw-r--r--ext/io/console/io-console.gemspec11
-rw-r--r--ext/io/nonblock/depend1
-rw-r--r--ext/io/nonblock/io-nonblock.gemspec2
-rw-r--r--ext/io/wait/depend1
-rw-r--r--ext/io/wait/io-wait.gemspec2
-rw-r--r--ext/json/VERSION1
-rw-r--r--ext/json/generator/depend1
-rw-r--r--ext/json/generator/extconf.rb9
-rw-r--r--ext/json/generator/generator.c150
-rw-r--r--ext/json/generator/generator.h20
-rw-r--r--ext/json/json.gemspec7
-rw-r--r--ext/json/lib/json.rb9
-rw-r--r--ext/json/lib/json/add/bigdecimal.rb38
-rw-r--r--ext/json/lib/json/add/complex.rb33
-rw-r--r--ext/json/lib/json/add/date.rb32
-rw-r--r--ext/json/lib/json/add/date_time.rb33
-rw-r--r--ext/json/lib/json/add/exception.rb30
-rw-r--r--ext/json/lib/json/add/ostruct.rb39
-rw-r--r--ext/json/lib/json/add/range.rb40
-rw-r--r--ext/json/lib/json/add/rational.rb32
-rw-r--r--ext/json/lib/json/add/regexp.rb32
-rw-r--r--ext/json/lib/json/add/set.rb31
-rw-r--r--ext/json/lib/json/add/struct.rb34
-rw-r--r--ext/json/lib/json/add/symbol.rb31
-rw-r--r--ext/json/lib/json/add/time.rb31
-rw-r--r--ext/json/lib/json/common.rb35
-rw-r--r--ext/json/lib/json/ext.rb18
-rw-r--r--ext/json/lib/json/generic_object.rb8
-rw-r--r--ext/json/lib/json/version.rb2
-rw-r--r--ext/json/parser/depend1
-rw-r--r--ext/json/parser/parser.c28
-rw-r--r--ext/json/parser/parser.h7
-rw-r--r--ext/json/parser/parser.rl28
-rw-r--r--ext/monitor/depend1
-rw-r--r--ext/nkf/depend181
-rw-r--r--ext/nkf/extconf.rb3
-rw-r--r--ext/nkf/lib/kconv.rb283
-rw-r--r--ext/nkf/nkf-utf8/config.h51
-rw-r--r--ext/nkf/nkf-utf8/nkf.c7205
-rw-r--r--ext/nkf/nkf-utf8/nkf.h189
-rw-r--r--ext/nkf/nkf-utf8/utf8tbl.c14638
-rw-r--r--ext/nkf/nkf-utf8/utf8tbl.h72
-rw-r--r--ext/nkf/nkf.c506
-rw-r--r--ext/nkf/nkf.gemspec35
-rw-r--r--ext/objspace/depend9
-rw-r--r--ext/objspace/objspace.c148
-rw-r--r--ext/objspace/objspace_dump.c42
-rw-r--r--ext/openssl/History.md2
-rw-r--r--ext/openssl/depend33
-rw-r--r--ext/openssl/extconf.rb15
-rw-r--r--ext/openssl/lib/openssl.rb2
-rw-r--r--ext/openssl/lib/openssl/bn.rb2
-rw-r--r--ext/openssl/lib/openssl/buffering.rb27
-rw-r--r--ext/openssl/lib/openssl/cipher.rb2
-rw-r--r--ext/openssl/lib/openssl/digest.rb2
-rw-r--r--ext/openssl/lib/openssl/marshal.rb2
-rw-r--r--ext/openssl/lib/openssl/ssl.rb68
-rw-r--r--ext/openssl/lib/openssl/x509.rb2
-rw-r--r--ext/openssl/openssl.gemspec4
-rw-r--r--ext/openssl/openssl_missing.c2
-rw-r--r--ext/openssl/openssl_missing.h2
-rw-r--r--ext/openssl/ossl.c2
-rw-r--r--ext/openssl/ossl.h2
-rw-r--r--ext/openssl/ossl_asn1.c9
-rw-r--r--ext/openssl/ossl_asn1.h2
-rw-r--r--ext/openssl/ossl_bio.c2
-rw-r--r--ext/openssl/ossl_bio.h2
-rw-r--r--ext/openssl/ossl_bn.c2
-rw-r--r--ext/openssl/ossl_bn.h2
-rw-r--r--ext/openssl/ossl_cipher.c24
-rw-r--r--ext/openssl/ossl_cipher.h2
-rw-r--r--ext/openssl/ossl_config.c2
-rw-r--r--ext/openssl/ossl_config.h2
-rw-r--r--ext/openssl/ossl_digest.c35
-rw-r--r--ext/openssl/ossl_digest.h2
-rw-r--r--ext/openssl/ossl_engine.c2
-rw-r--r--ext/openssl/ossl_engine.h2
-rw-r--r--ext/openssl/ossl_hmac.c2
-rw-r--r--ext/openssl/ossl_hmac.h2
-rw-r--r--ext/openssl/ossl_kdf.c10
-rw-r--r--ext/openssl/ossl_ns_spki.c6
-rw-r--r--ext/openssl/ossl_ns_spki.h2
-rw-r--r--ext/openssl/ossl_ocsp.c2
-rw-r--r--ext/openssl/ossl_ocsp.h2
-rw-r--r--ext/openssl/ossl_pkcs12.c10
-rw-r--r--ext/openssl/ossl_pkcs12.h2
-rw-r--r--ext/openssl/ossl_pkcs7.c30
-rw-r--r--ext/openssl/ossl_pkcs7.h2
-rw-r--r--ext/openssl/ossl_pkey.c2
-rw-r--r--ext/openssl/ossl_pkey.h2
-rw-r--r--ext/openssl/ossl_pkey_dh.c2
-rw-r--r--ext/openssl/ossl_pkey_dsa.c2
-rw-r--r--ext/openssl/ossl_pkey_rsa.c2
-rw-r--r--ext/openssl/ossl_provider.c2
-rw-r--r--ext/openssl/ossl_rand.c2
-rw-r--r--ext/openssl/ossl_rand.h2
-rw-r--r--ext/openssl/ossl_ssl.c25
-rw-r--r--ext/openssl/ossl_ssl.h2
-rw-r--r--ext/openssl/ossl_ts.c62
-rw-r--r--ext/openssl/ossl_ts.h2
-rw-r--r--ext/openssl/ossl_x509.c2
-rw-r--r--ext/openssl/ossl_x509.h2
-rw-r--r--ext/openssl/ossl_x509attr.c2
-rw-r--r--ext/openssl/ossl_x509cert.c37
-rw-r--r--ext/openssl/ossl_x509crl.c2
-rw-r--r--ext/openssl/ossl_x509ext.c2
-rw-r--r--ext/openssl/ossl_x509name.c2
-rw-r--r--ext/openssl/ossl_x509req.c2
-rw-r--r--ext/openssl/ossl_x509revoked.c2
-rw-r--r--ext/openssl/ossl_x509store.c2
-rw-r--r--ext/pathname/depend1
-rw-r--r--ext/pathname/extconf.rb1
-rw-r--r--ext/pathname/lib/pathname.rb3
-rw-r--r--ext/pathname/pathname.c5
-rw-r--r--ext/psych/depend5
-rw-r--r--ext/psych/lib/psych.rb14
-rw-r--r--ext/psych/lib/psych/versions.rb2
-rw-r--r--ext/psych/lib/psych/visitors/to_ruby.rb2
-rw-r--r--ext/psych/lib/psych/visitors/yaml_tree.rb24
-rw-r--r--ext/psych/psych.gemspec2
-rw-r--r--ext/pty/depend1
-rw-r--r--ext/pty/extconf.rb7
-rw-r--r--ext/pty/pty.c115
-rw-r--r--ext/rbconfig/sizeof/depend2
-rw-r--r--ext/ripper/depend15
-rw-r--r--ext/ripper/eventids2.c2
-rw-r--r--ext/ripper/ripper_init.c.tmpl164
-rw-r--r--ext/ripper/ripper_init.h2
-rw-r--r--ext/ripper/tools/dsl.rb158
-rw-r--r--ext/ripper/tools/generate.rb12
-rw-r--r--ext/ripper/tools/preproc.rb51
-rw-r--r--ext/socket/depend45
-rw-r--r--ext/socket/extconf.rb2
-rw-r--r--ext/socket/init.c62
-rw-r--r--ext/socket/lib/socket.rb533
-rw-r--r--ext/socket/mkconstants.rb46
-rw-r--r--ext/socket/raddrinfo.c97
-rw-r--r--ext/socket/rubysocket.h4
-rw-r--r--ext/socket/socket.c2
-rw-r--r--ext/stringio/.document1
-rw-r--r--ext/stringio/depend1
-rw-r--r--ext/stringio/extconf.rb6
-rw-r--r--ext/stringio/stringio.c188
-rw-r--r--ext/stringio/stringio.gemspec6
-rw-r--r--ext/strscan/depend1
-rw-r--r--ext/strscan/strscan.c1332
-rw-r--r--ext/strscan/strscan.gemspec5
-rw-r--r--ext/syslog/depend161
-rw-r--r--ext/syslog/extconf.rb13
-rw-r--r--ext/syslog/lib/syslog/logger.rb209
-rw-r--r--ext/syslog/syslog.c592
-rw-r--r--ext/syslog/syslog.gemspec28
-rw-r--r--ext/syslog/syslog.txt124
-rw-r--r--ext/win32/lib/win32/registry.rb37
-rw-r--r--ext/win32ole/.document1
-rw-r--r--ext/win32ole/lib/win32ole.rb3
-rw-r--r--ext/win32ole/lib/win32ole/property.rb18
-rw-r--r--ext/win32ole/sample/olegen.rb348
-rw-r--r--ext/win32ole/win32ole.c96
-rw-r--r--ext/win32ole/win32ole.gemspec9
-rw-r--r--ext/win32ole/win32ole_error.c17
-rw-r--r--ext/win32ole/win32ole_event.c51
-rw-r--r--ext/win32ole/win32ole_method.c127
-rw-r--r--ext/win32ole/win32ole_param.c113
-rw-r--r--ext/win32ole/win32ole_record.c51
-rw-r--r--ext/win32ole/win32ole_type.c142
-rw-r--r--ext/win32ole/win32ole_typelib.c75
-rw-r--r--ext/win32ole/win32ole_variable.c37
-rw-r--r--ext/win32ole/win32ole_variant.c67
-rw-r--r--ext/win32ole/win32ole_variant_m.c12
-rw-r--r--ext/zlib/depend1
-rw-r--r--ext/zlib/zlib.c113
-rw-r--r--ext/zlib/zlib.gemspec2
-rw-r--r--file.c515
-rw-r--r--gc.c2357
-rw-r--r--gc.rb8
-rw-r--r--gems/bundled_gems37
-rw-r--r--gems/lib/envutil.rb1
-rw-r--r--gems/lib/rake/extensiontask.rb2
-rw-r--r--hash.c507
-rw-r--r--hrtime.h14
-rw-r--r--id_table.c4
-rw-r--r--imemo.c590
-rw-r--r--include/ruby/assert.h100
-rw-r--r--include/ruby/atomic.h69
-rw-r--r--include/ruby/debug.h152
-rw-r--r--include/ruby/fiber/scheduler.h2
-rw-r--r--include/ruby/internal/abi.h2
-rw-r--r--include/ruby/internal/arithmetic/long.h14
-rw-r--r--include/ruby/internal/arithmetic/long_long.h2
-rw-r--r--include/ruby/internal/arithmetic/st_data_t.h4
-rw-r--r--include/ruby/internal/attr/noexcept.h2
-rw-r--r--include/ruby/internal/core/rbasic.h18
-rw-r--r--include/ruby/internal/core/rdata.h17
-rw-r--r--include/ruby/internal/encoding/encoding.h3
-rw-r--r--include/ruby/internal/fl_type.h34
-rw-r--r--include/ruby/internal/gc.h26
-rw-r--r--include/ruby/internal/globals.h2
-rw-r--r--include/ruby/internal/intern/array.h2
-rw-r--r--include/ruby/internal/intern/bignum.h2
-rw-r--r--include/ruby/internal/intern/class.h8
-rw-r--r--include/ruby/internal/intern/error.h18
-rw-r--r--include/ruby/internal/intern/load.h37
-rw-r--r--include/ruby/internal/intern/object.h3
-rw-r--r--include/ruby/internal/intern/process.h2
-rw-r--r--include/ruby/internal/intern/select.h2
-rw-r--r--include/ruby/internal/intern/signal.h2
-rw-r--r--include/ruby/internal/intern/string.h4
-rw-r--r--include/ruby/internal/intern/struct.h8
-rw-r--r--include/ruby/internal/intern/vm.h3
-rw-r--r--include/ruby/internal/interpreter.h2
-rw-r--r--include/ruby/internal/memory.h12
-rw-r--r--include/ruby/internal/module.h16
-rw-r--r--include/ruby/internal/newobj.h49
-rw-r--r--include/ruby/internal/special_consts.h4
-rw-r--r--include/ruby/internal/static_assert.h2
-rw-r--r--include/ruby/internal/stdckdint.h68
-rw-r--r--include/ruby/internal/value_type.h2
-rw-r--r--include/ruby/io/buffer.h28
-rw-r--r--include/ruby/random.h2
-rw-r--r--include/ruby/ruby.h110
-rw-r--r--include/ruby/st.h4
-rw-r--r--include/ruby/thread.h64
-rw-r--r--include/ruby/version.h2
-rw-r--r--include/ruby/vm.h7
-rw-r--r--include/ruby/win32.h1
-rw-r--r--inits.c4
-rw-r--r--insns.def146
-rw-r--r--internal.h4
-rw-r--r--internal/basic_operators.h1
-rw-r--r--internal/class.h63
-rw-r--r--internal/cont.h3
-rw-r--r--internal/encoding.h4
-rw-r--r--internal/error.h5
-rw-r--r--internal/eval.h1
-rw-r--r--internal/gc.h58
-rw-r--r--internal/imemo.h34
-rw-r--r--internal/inits.h3
-rw-r--r--internal/io.h3
-rw-r--r--internal/missing.h1
-rw-r--r--internal/numeric.h3
-rw-r--r--internal/object.h4
-rw-r--r--internal/parse.h37
-rw-r--r--internal/random.h1
-rw-r--r--internal/ruby_parser.h49
-rw-r--r--internal/sanitizers.h159
-rw-r--r--internal/signal.h1
-rw-r--r--internal/st.h11
-rw-r--r--internal/string.h30
-rw-r--r--internal/symbol.h3
-rw-r--r--internal/thread.h4
-rw-r--r--internal/transcode.h3
-rw-r--r--internal/variable.h8
-rw-r--r--internal/vm.h8
-rw-r--r--io.c659
-rw-r--r--io_buffer.c673
-rw-r--r--iseq.c600
-rw-r--r--iseq.h18
-rw-r--r--kernel.rb20
-rw-r--r--lib/abbrev.gemspec29
-rw-r--r--lib/abbrev.rb133
-rw-r--r--lib/base64.gemspec27
-rw-r--r--lib/base64.rb363
-rw-r--r--lib/bundled_gems.rb102
-rw-r--r--lib/bundler.rb109
-rw-r--r--lib/bundler/build_metadata.rb2
-rw-r--r--lib/bundler/bundler.gemspec2
-rw-r--r--lib/bundler/capistrano.rb2
-rw-r--r--lib/bundler/checksum.rb109
-rw-r--r--lib/bundler/ci_detector.rb75
-rw-r--r--lib/bundler/cli.rb510
-rw-r--r--lib/bundler/cli/add.rb6
-rw-r--r--lib/bundler/cli/binstubs.rb8
-rw-r--r--lib/bundler/cli/cache.rb2
-rw-r--r--lib/bundler/cli/check.rb2
-rw-r--r--lib/bundler/cli/common.rb10
-rw-r--r--lib/bundler/cli/config.rb15
-rw-r--r--lib/bundler/cli/console.rb5
-rw-r--r--lib/bundler/cli/exec.rb2
-rw-r--r--lib/bundler/cli/gem.rb65
-rw-r--r--lib/bundler/cli/info.rb15
-rw-r--r--lib/bundler/cli/install.rb11
-rw-r--r--lib/bundler/cli/lock.rb17
-rw-r--r--lib/bundler/cli/open.rb2
-rw-r--r--lib/bundler/cli/outdated.rb12
-rw-r--r--lib/bundler/cli/plugin.rb24
-rw-r--r--lib/bundler/cli/pristine.rb68
-rw-r--r--lib/bundler/cli/update.rb10
-rw-r--r--lib/bundler/compact_index_client.rb138
-rw-r--r--lib/bundler/compact_index_client/cache.rb115
-rw-r--r--lib/bundler/compact_index_client/cache_file.rb148
-rw-r--r--lib/bundler/compact_index_client/parser.rb111
-rw-r--r--lib/bundler/compact_index_client/updater.rb156
-rw-r--r--lib/bundler/constants.rb9
-rw-r--r--lib/bundler/definition.rb266
-rw-r--r--lib/bundler/dependency.rb34
-rw-r--r--lib/bundler/digest.rb2
-rw-r--r--lib/bundler/dsl.rb69
-rw-r--r--lib/bundler/endpoint_specification.rb1
-rw-r--r--lib/bundler/environment_preserver.rb28
-rw-r--r--lib/bundler/errors.rb22
-rw-r--r--lib/bundler/fetcher.rb47
-rw-r--r--lib/bundler/fetcher/base.rb4
-rw-r--r--lib/bundler/fetcher/compact_index.rb45
-rw-r--r--lib/bundler/fetcher/downloader.rb26
-rw-r--r--lib/bundler/fetcher/gem_remote_fetcher.rb16
-rw-r--r--lib/bundler/fetcher/index.rb2
-rw-r--r--lib/bundler/friendly_errors.rb4
-rw-r--r--lib/bundler/gem_helper.rb4
-rw-r--r--lib/bundler/gem_version_promoter.rb80
-rw-r--r--lib/bundler/graph.rb18
-rw-r--r--lib/bundler/injector.rb7
-rw-r--r--lib/bundler/inline.rb6
-rw-r--r--lib/bundler/installer.rb48
-rw-r--r--lib/bundler/installer/gem_installer.rb9
-rw-r--r--lib/bundler/installer/parallel_installer.rb24
-rw-r--r--lib/bundler/installer/standalone.rb2
-rw-r--r--lib/bundler/lazy_specification.rb9
-rw-r--r--lib/bundler/lockfile_generator.rb1
-rw-r--r--lib/bundler/lockfile_parser.rb15
-rw-r--r--lib/bundler/man/bundle-add.129
-rw-r--r--lib/bundler/man/bundle-binstubs.120
-rw-r--r--lib/bundler/man/bundle-cache.127
-rw-r--r--lib/bundler/man/bundle-check.117
-rw-r--r--lib/bundler/man/bundle-check.1.ronn3
-rw-r--r--lib/bundler/man/bundle-clean.113
-rw-r--r--lib/bundler/man/bundle-config.1234
-rw-r--r--lib/bundler/man/bundle-config.1.ronn9
-rw-r--r--lib/bundler/man/bundle-console.126
-rw-r--r--lib/bundler/man/bundle-doctor.122
-rw-r--r--lib/bundler/man/bundle-exec.185
-rw-r--r--lib/bundler/man/bundle-gem.162
-rw-r--r--lib/bundler/man/bundle-help.110
-rw-r--r--lib/bundler/man/bundle-info.112
-rw-r--r--lib/bundler/man/bundle-init.115
-rw-r--r--lib/bundler/man/bundle-inject.125
-rw-r--r--lib/bundler/man/bundle-install.1156
-rw-r--r--lib/bundler/man/bundle-install.1.ronn5
-rw-r--r--lib/bundler/man/bundle-list.123
-rw-r--r--lib/bundler/man/bundle-lock.134
-rw-r--r--lib/bundler/man/bundle-open.134
-rw-r--r--lib/bundler/man/bundle-outdated.158
-rw-r--r--lib/bundler/man/bundle-outdated.1.ronn1
-rw-r--r--lib/bundler/man/bundle-platform.132
-rw-r--r--lib/bundler/man/bundle-plugin.141
-rw-r--r--lib/bundler/man/bundle-plugin.1.ronn10
-rw-r--r--lib/bundler/man/bundle-pristine.121
-rw-r--r--lib/bundler/man/bundle-remove.118
-rw-r--r--lib/bundler/man/bundle-show.113
-rw-r--r--lib/bundler/man/bundle-update.1155
-rw-r--r--lib/bundler/man/bundle-version.119
-rw-r--r--lib/bundler/man/bundle-viz.120
-rw-r--r--lib/bundler/man/bundle.149
-rw-r--r--lib/bundler/man/gemfile.5327
-rw-r--r--lib/bundler/man/gemfile.5.ronn4
-rw-r--r--lib/bundler/match_metadata.rb4
-rw-r--r--lib/bundler/mirror.rb6
-rw-r--r--lib/bundler/plugin.rb6
-rw-r--r--lib/bundler/plugin/api/source.rb6
-rw-r--r--lib/bundler/plugin/events.rb24
-rw-r--r--lib/bundler/plugin/installer.rb54
-rw-r--r--lib/bundler/plugin/installer/path.rb18
-rw-r--r--lib/bundler/plugin/source_list.rb8
-rw-r--r--lib/bundler/remote_specification.rb4
-rw-r--r--lib/bundler/resolver.rb110
-rw-r--r--lib/bundler/resolver/base.rb2
-rw-r--r--lib/bundler/resolver/candidate.rb2
-rw-r--r--lib/bundler/resolver/incompatibility.rb2
-rw-r--r--lib/bundler/ruby_dsl.rb32
-rw-r--r--lib/bundler/rubygems_ext.rb122
-rw-r--r--lib/bundler/rubygems_gem_installer.rb12
-rw-r--r--lib/bundler/rubygems_integration.rb124
-rw-r--r--lib/bundler/runtime.rb25
-rw-r--r--lib/bundler/self_manager.rb2
-rw-r--r--lib/bundler/settings.rb76
-rw-r--r--lib/bundler/setup.rb8
-rw-r--r--lib/bundler/shared_helpers.rb48
-rw-r--r--lib/bundler/source/git.rb6
-rw-r--r--lib/bundler/source/git/git_proxy.rb40
-rw-r--r--lib/bundler/source/metadata.rb2
-rw-r--r--lib/bundler/source/path.rb12
-rw-r--r--lib/bundler/source/rubygems.rb85
-rw-r--r--lib/bundler/source/rubygems/remote.rb2
-rw-r--r--lib/bundler/source_list.rb28
-rw-r--r--lib/bundler/spec_set.rb119
-rw-r--r--lib/bundler/templates/Executable.bundler2
-rw-r--r--lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt106
-rw-r--r--lib/bundler/templates/newgem/Rakefile.tt8
-rw-r--r--lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt2
-rw-r--r--lib/bundler/templates/newgem/newgem.gemspec.tt7
-rw-r--r--lib/bundler/templates/newgem/rubocop.yml.tt5
-rw-r--r--lib/bundler/ui/shell.rb2
-rw-r--r--lib/bundler/uri_credentials_filter.rb4
-rw-r--r--lib/bundler/vendor/connection_pool/.document (renamed from lib/rubygems/optparse/.document)0
-rw-r--r--lib/bundler/vendor/connection_pool/lib/connection_pool.rb59
-rw-r--r--lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb2
-rw-r--r--lib/bundler/vendor/fileutils/.document (renamed from lib/rubygems/tsort/.document)0
-rw-r--r--lib/bundler/vendor/fileutils/lib/fileutils.rb28
-rw-r--r--lib/bundler/vendor/net-http-persistent/.document1
-rw-r--r--lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb112
-rw-r--r--lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/connection.rb6
-rw-r--r--lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/pool.rb4
-rw-r--r--lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb2
-rw-r--r--lib/bundler/vendor/pub_grub/.document1
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb1
-rw-r--r--lib/bundler/vendor/thor/.document1
-rw-r--r--lib/bundler/vendor/thor/lib/thor/shell/color.rb3
-rw-r--r--lib/bundler/vendor/thor/lib/thor/shell/html.rb3
-rw-r--r--lib/bundler/vendor/thor/lib/thor/shell/lcs_diff.rb49
-rw-r--r--lib/bundler/vendor/tsort/.document1
-rw-r--r--lib/bundler/vendor/tsort/lib/tsort.rb3
-rw-r--r--lib/bundler/vendor/uri/.document1
-rw-r--r--lib/bundler/vendor/uri/lib/uri/common.rb388
-rw-r--r--lib/bundler/vendor/uri/lib/uri/generic.rb1
-rw-r--r--lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb126
-rw-r--r--lib/bundler/vendor/uri/lib/uri/version.rb2
-rw-r--r--lib/bundler/vendored_net_http.rb12
-rw-r--r--lib/bundler/vendored_persistent.rb4
-rw-r--r--lib/bundler/vendored_timeout.rb12
-rw-r--r--lib/bundler/vendored_uri.rb19
-rw-r--r--lib/bundler/version.rb2
-rw-r--r--lib/bundler/vlad.rb2
-rw-r--r--lib/bundler/yaml_serializer.rb19
-rw-r--r--lib/cgi.rb2
-rw-r--r--lib/csv.rb2882
-rw-r--r--lib/csv/core_ext/array.rb9
-rw-r--r--lib/csv/core_ext/string.rb9
-rw-r--r--lib/csv/csv.gemspec64
-rw-r--r--lib/csv/fields_converter.rb89
-rw-r--r--lib/csv/input_record_separator.rb18
-rw-r--r--lib/csv/parser.rb1288
-rw-r--r--lib/csv/row.rb757
-rw-r--r--lib/csv/table.rb1055
-rw-r--r--lib/csv/version.rb6
-rw-r--r--lib/csv/writer.rb210
-rw-r--r--lib/delegate.rb4
-rw-r--r--lib/did_you_mean/did_you_mean.gemspec2
-rw-r--r--lib/did_you_mean/jaro_winkler.rb7
-rw-r--r--lib/did_you_mean/spell_checkers/key_error_checker.rb10
-rw-r--r--lib/did_you_mean/spell_checkers/pattern_key_name_checker.rb10
-rw-r--r--lib/drb.rb3
-rw-r--r--lib/drb/acl.rb239
-rw-r--r--lib/drb/drb.gemspec43
-rw-r--r--lib/drb/drb.rb1943
-rw-r--r--lib/drb/eq.rb15
-rw-r--r--lib/drb/extserv.rb44
-rw-r--r--lib/drb/extservm.rb94
-rw-r--r--lib/drb/gw.rb161
-rw-r--r--lib/drb/invokemethod.rb35
-rw-r--r--lib/drb/observer.rb26
-rw-r--r--lib/drb/ssl.rb354
-rw-r--r--lib/drb/timeridconv.rb97
-rw-r--r--lib/drb/unix.rb118
-rw-r--r--lib/drb/version.rb3
-rw-r--r--lib/drb/weakidconv.rb59
-rw-r--r--lib/erb/version.rb2
-rw-r--r--lib/error_highlight/base.rb314
-rw-r--r--lib/error_highlight/version.rb2
-rw-r--r--lib/fileutils.rb26
-rw-r--r--lib/find.gemspec2
-rw-r--r--lib/getoptlong.gemspec30
-rw-r--r--lib/getoptlong.rb867
-rw-r--r--lib/ipaddr.rb70
-rw-r--r--lib/irb.rb1429
-rw-r--r--lib/irb/cmd/backtrace.rb21
-rw-r--r--lib/irb/cmd/break.rb21
-rw-r--r--lib/irb/cmd/catch.rb21
-rw-r--r--lib/irb/cmd/chws.rb36
-rw-r--r--lib/irb/cmd/continue.rb17
-rw-r--r--lib/irb/cmd/debug.rb80
-rw-r--r--lib/irb/cmd/delete.rb17
-rw-r--r--lib/irb/cmd/edit.rb60
-rw-r--r--lib/irb/cmd/finish.rb17
-rw-r--r--lib/irb/cmd/help.rb23
-rw-r--r--lib/irb/cmd/info.rb21
-rw-r--r--lib/irb/cmd/irb_info.rb34
-rw-r--r--lib/irb/cmd/load.rb76
-rw-r--r--lib/irb/cmd/ls.rb139
-rw-r--r--lib/irb/cmd/measure.rb48
-rw-r--r--lib/irb/cmd/next.rb17
-rw-r--r--lib/irb/cmd/nop.rb55
-rw-r--r--lib/irb/cmd/pushws.rb45
-rw-r--r--lib/irb/cmd/show_cmds.rb53
-rw-r--r--lib/irb/cmd/show_doc.rb48
-rw-r--r--lib/irb/cmd/show_source.rb61
-rw-r--r--lib/irb/cmd/step.rb17
-rw-r--r--lib/irb/cmd/subirb.rb109
-rw-r--r--lib/irb/cmd/whereami.rb25
-rw-r--r--lib/irb/color.rb4
-rw-r--r--lib/irb/command.rb23
-rw-r--r--lib/irb/command/backtrace.rb17
-rw-r--r--lib/irb/command/base.rb62
-rw-r--r--lib/irb/command/break.rb17
-rw-r--r--lib/irb/command/catch.rb17
-rw-r--r--lib/irb/command/chws.rb40
-rw-r--r--lib/irb/command/context.rb16
-rw-r--r--lib/irb/command/continue.rb17
-rw-r--r--lib/irb/command/debug.rb71
-rw-r--r--lib/irb/command/delete.rb17
-rw-r--r--lib/irb/command/disable_irb.rb19
-rw-r--r--lib/irb/command/edit.rb63
-rw-r--r--lib/irb/command/exit.rb18
-rw-r--r--lib/irb/command/finish.rb17
-rw-r--r--lib/irb/command/force_exit.rb18
-rw-r--r--lib/irb/command/help.rb83
-rw-r--r--lib/irb/command/history.rb45
-rw-r--r--lib/irb/command/info.rb17
-rw-r--r--lib/irb/command/internal_helpers.rb27
-rw-r--r--lib/irb/command/irb_info.rb33
-rw-r--r--lib/irb/command/load.rb91
-rw-r--r--lib/irb/command/ls.rb155
-rw-r--r--lib/irb/command/measure.rb49
-rw-r--r--lib/irb/command/next.rb17
-rw-r--r--lib/irb/command/pushws.rb65
-rw-r--r--lib/irb/command/show_doc.rb51
-rw-r--r--lib/irb/command/show_source.rb74
-rw-r--r--lib/irb/command/step.rb17
-rw-r--r--lib/irb/command/subirb.rb123
-rw-r--r--lib/irb/command/whereami.rb23
-rw-r--r--lib/irb/completion.rb56
-rw-r--r--lib/irb/context.rb195
-rw-r--r--lib/irb/debug.rb18
-rw-r--r--lib/irb/default_commands.rb265
-rw-r--r--lib/irb/ext/change-ws.rb14
-rw-r--r--lib/irb/ext/eval_history.rb6
-rw-r--r--lib/irb/ext/loader.rb8
-rw-r--r--lib/irb/ext/multi-irb.rb10
-rw-r--r--lib/irb/ext/tracer.rb63
-rw-r--r--lib/irb/ext/use-loader.rb14
-rw-r--r--lib/irb/ext/workspaces.rb44
-rw-r--r--lib/irb/extend-command.rb354
-rw-r--r--lib/irb/frame.rb2
-rw-r--r--lib/irb/help.rb6
-rw-r--r--lib/irb/helper_method.rb29
-rw-r--r--lib/irb/helper_method/base.rb16
-rw-r--r--lib/irb/helper_method/conf.rb11
-rw-r--r--lib/irb/history.rb19
-rw-r--r--lib/irb/init.rb159
-rw-r--r--lib/irb/input-method.rb74
-rw-r--r--lib/irb/inspector.rb6
-rw-r--r--lib/irb/irb.gemspec4
-rw-r--r--lib/irb/lc/error.rb12
-rw-r--r--lib/irb/lc/help-message1
-rw-r--r--lib/irb/lc/ja/error.rb12
-rw-r--r--lib/irb/lc/ja/help-message10
-rw-r--r--lib/irb/locale.rb4
-rw-r--r--lib/irb/nesting_parser.rb16
-rw-r--r--lib/irb/notifier.rb2
-rw-r--r--lib/irb/output-method.rb10
-rw-r--r--lib/irb/pager.rb27
-rw-r--r--lib/irb/ruby-lex.rb50
-rw-r--r--lib/irb/source_finder.rb149
-rw-r--r--lib/irb/statement.rb48
-rw-r--r--lib/irb/type_completion/completor.rb235
-rw-r--r--lib/irb/type_completion/methods.rb13
-rw-r--r--lib/irb/type_completion/scope.rb412
-rw-r--r--lib/irb/type_completion/type_analyzer.rb1169
-rw-r--r--lib/irb/type_completion/types.rb426
-rw-r--r--lib/irb/version.rb6
-rw-r--r--lib/irb/workspace.rb28
-rw-r--r--lib/irb/ws-for-case-2.rb2
-rw-r--r--lib/irb/xmp.rb6
-rw-r--r--lib/logger/period.rb16
-rw-r--r--lib/mkmf.rb231
-rw-r--r--lib/mutex_m.gemspec28
-rw-r--r--lib/mutex_m.rb116
-rw-r--r--lib/net/http.rb53
-rw-r--r--lib/net/http/header.rb2
-rw-r--r--lib/net/http/requests.rb5
-rw-r--r--lib/net/net-protocol.gemspec1
-rw-r--r--lib/observer.gemspec32
-rw-r--r--lib/observer.rb229
-rw-r--r--lib/open-uri.rb8
-rw-r--r--lib/open3.rb472
-rw-r--r--lib/open3/version.rb2
-rw-r--r--lib/optparse.rb200
-rw-r--r--lib/optparse/ac.rb16
-rw-r--r--lib/optparse/kwargs.rb11
-rw-r--r--lib/optparse/optparse.gemspec3
-rw-r--r--lib/optparse/version.rb9
-rw-r--r--lib/ostruct.rb2
-rw-r--r--lib/pp.rb29
-rw-r--r--lib/prism.rb28
-rw-r--r--lib/prism/debug.rb195
-rw-r--r--lib/prism/desugar_compiler.rb306
-rw-r--r--lib/prism/ffi.rb294
-rw-r--r--lib/prism/lex_compat.rb91
-rw-r--r--lib/prism/node_ext.rb361
-rw-r--r--lib/prism/node_inspector.rb68
-rw-r--r--lib/prism/pack.rb4
-rw-r--r--lib/prism/parse_result.rb423
-rw-r--r--lib/prism/parse_result/comments.rb58
-rw-r--r--lib/prism/parse_result/newlines.rb114
-rw-r--r--lib/prism/pattern.rb38
-rw-r--r--lib/prism/polyfill/byteindex.rb13
-rw-r--r--lib/prism/polyfill/unpack1.rb14
-rw-r--r--lib/prism/prism.gemspec95
-rw-r--r--lib/prism/ripper_compat.rb192
-rw-r--r--lib/prism/translation.rb13
-rw-r--r--lib/prism/translation/parser.rb307
-rw-r--r--lib/prism/translation/parser/compiler.rb2146
-rw-r--r--lib/prism/translation/parser/lexer.rb416
-rw-r--r--lib/prism/translation/parser/rubocop.rb73
-rw-r--r--lib/prism/translation/parser33.rb12
-rw-r--r--lib/prism/translation/parser34.rb12
-rw-r--r--lib/prism/translation/ripper.rb3452
-rw-r--r--lib/prism/translation/ripper/sexp.rb125
-rw-r--r--lib/prism/translation/ripper/shim.rb5
-rw-r--r--lib/prism/translation/ruby_parser.rb1594
-rw-r--r--lib/pstore.rb2
-rw-r--r--lib/random/formatter.rb18
-rw-r--r--lib/rdoc.rb12
-rw-r--r--lib/rdoc/context.rb2
-rw-r--r--lib/rdoc/cross_reference.rb3
-rw-r--r--lib/rdoc/encoding.rb11
-rw-r--r--lib/rdoc/generator/pot.rb1
-rw-r--r--lib/rdoc/generator/template/darkfish/css/rdoc.css11
-rw-r--r--lib/rdoc/markdown.rb8
-rw-r--r--lib/rdoc/markdown/literals.rb1
-rw-r--r--lib/rdoc/markup/attribute_manager.rb3
-rw-r--r--lib/rdoc/markup/formatter.rb2
-rw-r--r--lib/rdoc/markup/parser.rb6
-rw-r--r--lib/rdoc/markup/table.rb13
-rw-r--r--lib/rdoc/markup/to_bs.rb25
-rw-r--r--lib/rdoc/markup/to_html.rb5
-rw-r--r--lib/rdoc/markup/to_html_crossref.rb26
-rw-r--r--lib/rdoc/markup/to_html_snippet.rb3
-rw-r--r--lib/rdoc/markup/to_markdown.rb8
-rw-r--r--lib/rdoc/markup/to_rdoc.rb14
-rw-r--r--lib/rdoc/options.rb1
-rw-r--r--lib/rdoc/parser.rb6
-rw-r--r--lib/rdoc/parser/c.rb55
-rw-r--r--lib/rdoc/parser/changelog.rb15
-rw-r--r--lib/rdoc/parser/ripper_state_lex.rb10
-rw-r--r--lib/rdoc/parser/ruby.rb16
-rw-r--r--lib/rdoc/ri/driver.rb18
-rw-r--r--lib/rdoc/store.rb48
-rw-r--r--lib/rdoc/text.rb10
-rw-r--r--lib/rdoc/token_stream.rb2
-rw-r--r--lib/rdoc/top_level.rb3
-rw-r--r--lib/rdoc/version.rb2
-rw-r--r--lib/readline.gemspec2
-rw-r--r--lib/readline.rb2
-rw-r--r--lib/reline.rb293
-rw-r--r--lib/reline/ansi.rb363
-rw-r--r--lib/reline/config.rb131
-rw-r--r--lib/reline/face.rb6
-rw-r--r--lib/reline/general_io.rb116
-rw-r--r--lib/reline/history.rb2
-rw-r--r--lib/reline/io.rb41
-rw-r--r--lib/reline/io/ansi.rb360
-rw-r--r--lib/reline/io/dumb.rb106
-rw-r--r--lib/reline/io/windows.rb503
-rw-r--r--lib/reline/key_actor.rb1
-rw-r--r--lib/reline/key_actor/base.rb28
-rw-r--r--lib/reline/key_actor/composite.rb17
-rw-r--r--lib/reline/key_actor/emacs.rb30
-rw-r--r--lib/reline/key_actor/vi_command.rb50
-rw-r--r--lib/reline/key_actor/vi_insert.rb14
-rw-r--r--lib/reline/key_stroke.rb169
-rw-r--r--lib/reline/kill_ring.rb4
-rw-r--r--lib/reline/line_editor.rb2836
-rw-r--r--lib/reline/reline.gemspec5
-rw-r--r--lib/reline/terminfo.rb21
-rw-r--r--lib/reline/unicode.rb78
-rw-r--r--lib/reline/version.rb2
-rw-r--r--lib/reline/windows.rb501
-rw-r--r--lib/resolv-replace.gemspec22
-rw-r--r--lib/resolv-replace.rb76
-rw-r--r--lib/resolv.rb574
-rw-r--r--lib/rinda/rinda.gemspec35
-rw-r--r--lib/rinda/rinda.rb329
-rw-r--r--lib/rinda/ring.rb484
-rw-r--r--lib/rinda/tuplespace.rb641
-rw-r--r--lib/ruby_vm/rjit/.document1
-rw-r--r--lib/ruby_vm/rjit/assembler.rb11
-rw-r--r--lib/ruby_vm/rjit/c_pointer.rb36
-rw-r--r--lib/ruby_vm/rjit/c_type.rb8
-rw-r--r--lib/ruby_vm/rjit/code_block.rb10
-rw-r--r--lib/ruby_vm/rjit/compiler.rb15
-rw-r--r--lib/ruby_vm/rjit/context.rb6
-rw-r--r--lib/ruby_vm/rjit/insn_compiler.rb203
-rw-r--r--lib/ruby_vm/rjit/stats.rb3
-rw-r--r--lib/rubygems.rb37
-rw-r--r--lib/rubygems/basic_specification.rb21
-rw-r--r--lib/rubygems/ci_detector.rb75
-rw-r--r--lib/rubygems/command.rb16
-rw-r--r--lib/rubygems/command_manager.rb6
-rw-r--r--lib/rubygems/commands/build_command.rb13
-rw-r--r--lib/rubygems/commands/cert_command.rb2
-rw-r--r--lib/rubygems/commands/check_command.rb2
-rw-r--r--lib/rubygems/commands/cleanup_command.rb8
-rw-r--r--lib/rubygems/commands/contents_command.rb4
-rw-r--r--lib/rubygems/commands/dependency_command.rb2
-rw-r--r--lib/rubygems/commands/fetch_command.rb4
-rw-r--r--lib/rubygems/commands/generate_index_command.rb113
-rw-r--r--lib/rubygems/commands/help_command.rb6
-rw-r--r--lib/rubygems/commands/info_command.rb4
-rw-r--r--lib/rubygems/commands/install_command.rb10
-rw-r--r--lib/rubygems/commands/list_command.rb4
-rw-r--r--lib/rubygems/commands/lock_command.rb2
-rw-r--r--lib/rubygems/commands/open_command.rb2
-rw-r--r--lib/rubygems/commands/owner_command.rb2
-rw-r--r--lib/rubygems/commands/pristine_command.rb41
-rw-r--r--lib/rubygems/commands/push_command.rb2
-rw-r--r--lib/rubygems/commands/query_command.rb4
-rw-r--r--lib/rubygems/commands/rdoc_command.rb13
-rw-r--r--lib/rubygems/commands/rebuild_command.rb262
-rw-r--r--lib/rubygems/commands/search_command.rb4
-rw-r--r--lib/rubygems/commands/setup_command.rb57
-rw-r--r--lib/rubygems/commands/sources_command.rb4
-rw-r--r--lib/rubygems/commands/specification_command.rb4
-rw-r--r--lib/rubygems/commands/uninstall_command.rb6
-rw-r--r--lib/rubygems/commands/unpack_command.rb10
-rw-r--r--lib/rubygems/commands/update_command.rb27
-rw-r--r--lib/rubygems/commands/which_command.rb2
-rw-r--r--lib/rubygems/config_file.rb40
-rw-r--r--lib/rubygems/core_ext/kernel_require.rb13
-rw-r--r--lib/rubygems/defaults.rb24
-rw-r--r--lib/rubygems/dependency.rb18
-rw-r--r--lib/rubygems/dependency_installer.rb56
-rw-r--r--lib/rubygems/dependency_list.rb2
-rw-r--r--lib/rubygems/deprecate.rb156
-rw-r--r--lib/rubygems/exceptions.rb6
-rw-r--r--lib/rubygems/ext/builder.rb15
-rw-r--r--lib/rubygems/ext/cargo_builder.rb22
-rw-r--r--lib/rubygems/ext/ext_conf_builder.rb3
-rw-r--r--lib/rubygems/gemcutter_utilities.rb75
-rw-r--r--lib/rubygems/gemcutter_utilities/webauthn_listener.rb2
-rw-r--r--lib/rubygems/gemcutter_utilities/webauthn_listener/response.rb6
-rw-r--r--lib/rubygems/gemcutter_utilities/webauthn_poller.rb10
-rw-r--r--lib/rubygems/gemspec_helpers.rb19
-rw-r--r--lib/rubygems/indexer.rb429
-rw-r--r--lib/rubygems/install_update_options.rb2
-rw-r--r--lib/rubygems/installer.rb50
-rw-r--r--lib/rubygems/local_remote_options.rb12
-rw-r--r--lib/rubygems/optparse.rb3
-rw-r--r--lib/rubygems/optparse/lib/optparse.rb2308
-rw-r--r--lib/rubygems/optparse/lib/optparse/uri.rb7
-rw-r--r--lib/rubygems/package.rb61
-rw-r--r--lib/rubygems/package/old.rb4
-rw-r--r--lib/rubygems/package/tar_header.rb96
-rw-r--r--lib/rubygems/package/tar_writer.rb30
-rw-r--r--lib/rubygems/package_task.rb4
-rw-r--r--lib/rubygems/path_support.rb21
-rw-r--r--lib/rubygems/platform.rb23
-rw-r--r--lib/rubygems/psych_tree.rb4
-rw-r--r--lib/rubygems/remote_fetcher.rb20
-rw-r--r--lib/rubygems/request.rb28
-rw-r--r--lib/rubygems/request/connection_pools.rb2
-rw-r--r--lib/rubygems/request_set.rb2
-rw-r--r--lib/rubygems/request_set/gem_dependency_api.rb220
-rw-r--r--lib/rubygems/requirement.rb5
-rw-r--r--lib/rubygems/resolver.rb10
-rw-r--r--lib/rubygems/resolver/api_set.rb2
-rw-r--r--lib/rubygems/resolver/best_set.rb2
-rw-r--r--lib/rubygems/resolver/molinillo.rb3
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo.rb11
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/delegates/resolution_state.rb57
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/delegates/specification_provider.rb88
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb255
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action.rb36
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb66
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_vertex.rb62
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/delete_edge.rb63
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb61
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/log.rb126
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/set_payload.rb46
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/tag.rb36
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb164
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb149
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb6
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider.rb112
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/modules/ui.rb67
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb839
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/resolver.rb46
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/state.rb58
-rw-r--r--lib/rubygems/resolver/spec_specification.rb7
-rw-r--r--lib/rubygems/s3_uri_signer.rb10
-rw-r--r--lib/rubygems/safe_marshal/elements.rb8
-rw-r--r--lib/rubygems/safe_marshal/reader.rb4
-rw-r--r--lib/rubygems/safe_marshal/visitors/to_ruby.rb30
-rw-r--r--lib/rubygems/safe_yaml.rb11
-rw-r--r--lib/rubygems/security.rb2
-rw-r--r--lib/rubygems/security/policies.rb72
-rw-r--r--lib/rubygems/security/trust_dir.rb6
-rw-r--r--lib/rubygems/source.rb6
-rw-r--r--lib/rubygems/source/git.rb6
-rw-r--r--lib/rubygems/source_list.rb2
-rw-r--r--lib/rubygems/spec_fetcher.rb6
-rw-r--r--lib/rubygems/specification.rb240
-rw-r--r--lib/rubygems/specification_policy.rb53
-rw-r--r--lib/rubygems/specification_record.rb212
-rw-r--r--lib/rubygems/stub_specification.rb21
-rw-r--r--lib/rubygems/tsort.rb3
-rw-r--r--lib/rubygems/tsort/lib/tsort.rb452
-rw-r--r--lib/rubygems/uninstaller.rb45
-rw-r--r--lib/rubygems/update_suggestion.rb15
-rw-r--r--lib/rubygems/uri.rb12
-rw-r--r--lib/rubygems/user_interaction.rb8
-rw-r--r--lib/rubygems/util.rb6
-rw-r--r--lib/rubygems/util/licenses.rb68
-rw-r--r--lib/rubygems/vendor/molinillo/.document1
-rw-r--r--lib/rubygems/vendor/molinillo/lib/molinillo.rb11
-rw-r--r--lib/rubygems/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb57
-rw-r--r--lib/rubygems/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb88
-rw-r--r--lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph.rb255
-rw-r--r--lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/action.rb36
-rw-r--r--lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb66
-rw-r--r--lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb62
-rw-r--r--lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb63
-rw-r--r--lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb61
-rw-r--r--lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/log.rb126
-rw-r--r--lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb46
-rw-r--r--lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb36
-rw-r--r--lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb164
-rw-r--r--lib/rubygems/vendor/molinillo/lib/molinillo/errors.rb149
-rw-r--r--lib/rubygems/vendor/molinillo/lib/molinillo/gem_metadata.rb6
-rw-r--r--lib/rubygems/vendor/molinillo/lib/molinillo/modules/specification_provider.rb112
-rw-r--r--lib/rubygems/vendor/molinillo/lib/molinillo/modules/ui.rb67
-rw-r--r--lib/rubygems/vendor/molinillo/lib/molinillo/resolution.rb839
-rw-r--r--lib/rubygems/vendor/molinillo/lib/molinillo/resolver.rb46
-rw-r--r--lib/rubygems/vendor/molinillo/lib/molinillo/state.rb58
-rw-r--r--lib/rubygems/vendor/net-http/.document1
-rw-r--r--lib/rubygems/vendor/net-http/lib/net/http.rb2496
-rw-r--r--lib/rubygems/vendor/net-http/lib/net/http/backward.rb40
-rw-r--r--lib/rubygems/vendor/net-http/lib/net/http/exceptions.rb34
-rw-r--r--lib/rubygems/vendor/net-http/lib/net/http/generic_request.rb414
-rw-r--r--lib/rubygems/vendor/net-http/lib/net/http/header.rb981
-rw-r--r--lib/rubygems/vendor/net-http/lib/net/http/proxy_delta.rb17
-rw-r--r--lib/rubygems/vendor/net-http/lib/net/http/request.rb88
-rw-r--r--lib/rubygems/vendor/net-http/lib/net/http/requests.rb425
-rw-r--r--lib/rubygems/vendor/net-http/lib/net/http/response.rb738
-rw-r--r--lib/rubygems/vendor/net-http/lib/net/http/responses.rb1174
-rw-r--r--lib/rubygems/vendor/net-http/lib/net/http/status.rb84
-rw-r--r--lib/rubygems/vendor/net-http/lib/net/https.rb23
-rw-r--r--lib/rubygems/vendor/net-protocol/.document1
-rw-r--r--lib/rubygems/vendor/net-protocol/lib/net/protocol.rb544
-rw-r--r--lib/rubygems/vendor/optparse/.document1
-rw-r--r--lib/rubygems/vendor/optparse/lib/optionparser.rb (renamed from lib/rubygems/optparse/lib/optionparser.rb)0
-rw-r--r--lib/rubygems/vendor/optparse/lib/optparse.rb2330
-rw-r--r--lib/rubygems/vendor/optparse/lib/optparse/ac.rb (renamed from lib/rubygems/optparse/lib/optparse/ac.rb)0
-rw-r--r--lib/rubygems/vendor/optparse/lib/optparse/date.rb (renamed from lib/rubygems/optparse/lib/optparse/date.rb)0
-rw-r--r--lib/rubygems/vendor/optparse/lib/optparse/kwargs.rb (renamed from lib/rubygems/optparse/lib/optparse/kwargs.rb)0
-rw-r--r--lib/rubygems/vendor/optparse/lib/optparse/shellwords.rb (renamed from lib/rubygems/optparse/lib/optparse/shellwords.rb)0
-rw-r--r--lib/rubygems/vendor/optparse/lib/optparse/time.rb (renamed from lib/rubygems/optparse/lib/optparse/time.rb)0
-rw-r--r--lib/rubygems/vendor/optparse/lib/optparse/uri.rb7
-rw-r--r--lib/rubygems/vendor/optparse/lib/optparse/version.rb (renamed from lib/rubygems/optparse/lib/optparse/version.rb)0
-rw-r--r--lib/rubygems/vendor/resolv/.document1
-rw-r--r--lib/rubygems/vendor/resolv/lib/resolv.rb3442
-rw-r--r--lib/rubygems/vendor/timeout/.document1
-rw-r--r--lib/rubygems/vendor/timeout/lib/timeout.rb199
-rw-r--r--lib/rubygems/vendor/tsort/.document1
-rw-r--r--lib/rubygems/vendor/tsort/lib/tsort.rb455
-rw-r--r--lib/rubygems/vendor/uri/.document1
-rw-r--r--lib/rubygems/vendor/uri/lib/uri.rb104
-rw-r--r--lib/rubygems/vendor/uri/lib/uri/common.rb853
-rw-r--r--lib/rubygems/vendor/uri/lib/uri/file.rb100
-rw-r--r--lib/rubygems/vendor/uri/lib/uri/ftp.rb267
-rw-r--r--lib/rubygems/vendor/uri/lib/uri/generic.rb1588
-rw-r--r--lib/rubygems/vendor/uri/lib/uri/http.rb125
-rw-r--r--lib/rubygems/vendor/uri/lib/uri/https.rb23
-rw-r--r--lib/rubygems/vendor/uri/lib/uri/ldap.rb261
-rw-r--r--lib/rubygems/vendor/uri/lib/uri/ldaps.rb22
-rw-r--r--lib/rubygems/vendor/uri/lib/uri/mailto.rb293
-rw-r--r--lib/rubygems/vendor/uri/lib/uri/rfc2396_parser.rb539
-rw-r--r--lib/rubygems/vendor/uri/lib/uri/rfc3986_parser.rb183
-rw-r--r--lib/rubygems/vendor/uri/lib/uri/version.rb6
-rw-r--r--lib/rubygems/vendor/uri/lib/uri/ws.rb83
-rw-r--r--lib/rubygems/vendor/uri/lib/uri/wss.rb23
-rw-r--r--lib/rubygems/vendored_molinillo.rb3
-rw-r--r--lib/rubygems/vendored_net_http.rb5
-rw-r--r--lib/rubygems/vendored_optparse.rb3
-rw-r--r--lib/rubygems/vendored_timeout.rb5
-rw-r--r--lib/rubygems/vendored_tsort.rb3
-rw-r--r--lib/rubygems/yaml_serializer.rb19
-rw-r--r--lib/securerandom.gemspec9
-rw-r--r--lib/securerandom.rb13
-rw-r--r--lib/set.rb36
-rw-r--r--lib/set/set.gemspec2
-rw-r--r--lib/syntax_suggest/api.rb47
-rw-r--r--lib/syntax_suggest/around_block_scan.rb4
-rw-r--r--lib/syntax_suggest/block_expand.rb2
-rw-r--r--lib/syntax_suggest/capture_code_context.rb2
-rw-r--r--lib/syntax_suggest/clean_document.rb14
-rw-r--r--lib/syntax_suggest/code_block.rb2
-rw-r--r--lib/syntax_suggest/code_frontier.rb2
-rw-r--r--lib/syntax_suggest/code_line.rb17
-rw-r--r--lib/syntax_suggest/code_search.rb4
-rw-r--r--lib/syntax_suggest/display_invalid_blocks.rb2
-rw-r--r--lib/syntax_suggest/explain_syntax.rb22
-rw-r--r--lib/syntax_suggest/lex_all.rb39
-rw-r--r--lib/syntax_suggest/parse_blocks_from_indent_line.rb2
-rw-r--r--lib/syntax_suggest/ripper_errors.rb5
-rw-r--r--lib/syntax_suggest/scan_history.rb2
-rw-r--r--lib/syntax_suggest/syntax_suggest.gemspec2
-rw-r--r--lib/syntax_suggest/version.rb2
-rw-r--r--lib/tempfile.gemspec8
-rw-r--r--lib/tempfile.rb206
-rw-r--r--lib/time.gemspec8
-rw-r--r--lib/time.rb4
-rw-r--r--lib/timeout.gemspec1
-rw-r--r--lib/timeout.rb5
-rw-r--r--lib/tmpdir.gemspec8
-rw-r--r--lib/tmpdir.rb15
-rw-r--r--lib/uri.rb18
-rw-r--r--lib/uri/ftp.rb2
-rw-r--r--lib/uri/generic.rb18
-rw-r--r--lib/uri/http.rb4
-rw-r--r--lib/yaml/store.rb8
-rwxr-xr-xlibexec/bundle2
-rw-r--r--load.c152
-rw-r--r--main.c12
-rw-r--r--man/ruby.195
-rw-r--r--marshal.c163
-rw-r--r--memory_view.c6
-rw-r--r--method.h4
-rw-r--r--mini_builtin.c71
-rw-r--r--miniinit.c13
-rw-r--r--misc/call_fuzzer.rb372
-rwxr-xr-xmisc/call_fuzzer.sh13
-rw-r--r--misc/lldb_rb/utils.py467
-rw-r--r--misc/lldb_yjit.py47
-rwxr-xr-xmisc/yjit_perf.py116
-rw-r--r--missing/setproctitle.c68
-rw-r--r--node.c330
-rw-r--r--node.h27
-rw-r--r--node_dump.c111
-rw-r--r--numeric.c269
-rw-r--r--numeric.rb5
-rw-r--r--object.c183
-rw-r--r--pack.c6
-rw-r--r--pack.rb1
-rw-r--r--parse.y6912
-rw-r--r--parser_st.c1
-rw-r--r--prism/api_pack.c9
-rw-r--r--prism/config.yml1446
-rw-r--r--prism/defines.h131
-rw-r--r--prism/diagnostic.c291
-rw-r--r--prism/diagnostic.h265
-rw-r--r--prism/enc/pm_big5.c53
-rw-r--r--prism/enc/pm_encoding.h186
-rw-r--r--prism/enc/pm_euc_jp.c59
-rw-r--r--prism/enc/pm_gbk.c62
-rw-r--r--prism/enc/pm_shift_jis.c57
-rw-r--r--prism/enc/pm_tables.c743
-rw-r--r--prism/enc/pm_unicode.c2369
-rw-r--r--prism/enc/pm_windows_31j.c57
-rw-r--r--prism/encoding.c5235
-rw-r--r--prism/encoding.h283
-rw-r--r--prism/extension.c599
-rw-r--r--prism/extension.h9
-rw-r--r--prism/node.h106
-rw-r--r--prism/options.c114
-rw-r--r--prism/options.h141
-rw-r--r--prism/pack.c50
-rw-r--r--prism/pack.h11
-rw-r--r--prism/parser.h333
-rw-r--r--prism/prettyprint.h8
-rw-r--r--prism/prism.c9684
-rw-r--r--prism/prism.h96
-rw-r--r--prism/regexp.c222
-rw-r--r--prism/regexp.h27
-rw-r--r--prism/static_literals.c617
-rw-r--r--prism/static_literals.h121
-rw-r--r--prism/templates/ext/prism/api_node.c.erb148
-rw-r--r--prism/templates/include/prism/ast.h.erb41
-rw-r--r--prism/templates/include/prism/diagnostic.h.erb130
-rw-r--r--prism/templates/lib/prism/compiler.rb.erb2
-rw-r--r--prism/templates/lib/prism/dot_visitor.rb.erb32
-rw-r--r--prism/templates/lib/prism/dsl.rb.erb20
-rw-r--r--prism/templates/lib/prism/inspect_visitor.rb.erb132
-rw-r--r--prism/templates/lib/prism/mutation_compiler.rb.erb4
-rw-r--r--prism/templates/lib/prism/node.rb.erb309
-rw-r--r--prism/templates/lib/prism/reflection.rb.erb137
-rw-r--r--prism/templates/lib/prism/serialize.rb.erb266
-rw-r--r--prism/templates/lib/prism/visitor.rb.erb3
-rw-r--r--prism/templates/src/diagnostic.c.erb508
-rw-r--r--prism/templates/src/node.c.erb336
-rw-r--r--prism/templates/src/prettyprint.c.erb115
-rw-r--r--prism/templates/src/serialize.c.erb173
-rw-r--r--prism/templates/src/token_type.c.erb357
-rwxr-xr-xprism/templates/template.rb885
-rw-r--r--prism/util/pm_buffer.c183
-rw-r--r--prism/util/pm_buffer.h86
-rw-r--r--prism/util/pm_char.c8
-rw-r--r--prism/util/pm_char.h3
-rw-r--r--prism/util/pm_constant_pool.c102
-rw-r--r--prism/util/pm_constant_pool.h45
-rw-r--r--prism/util/pm_integer.c670
-rw-r--r--prism/util/pm_integer.h126
-rw-r--r--prism/util/pm_list.c2
-rw-r--r--prism/util/pm_list.h2
-rw-r--r--prism/util/pm_memchr.c2
-rw-r--r--prism/util/pm_memchr.h4
-rw-r--r--prism/util/pm_newline_list.c40
-rw-r--r--prism/util/pm_newline_list.h24
-rw-r--r--prism/util/pm_state_stack.c25
-rw-r--r--prism/util/pm_state_stack.h42
-rw-r--r--prism/util/pm_string.c148
-rw-r--r--prism/util/pm_string.h28
-rw-r--r--prism/util/pm_string_list.c28
-rw-r--r--prism/util/pm_string_list.h44
-rw-r--r--prism/util/pm_strpbrk.c162
-rw-r--r--prism/util/pm_strpbrk.h9
-rw-r--r--prism/version.h6
-rw-r--r--prism_compile.c10797
-rw-r--r--prism_compile.h78
-rw-r--r--proc.c133
-rw-r--r--process.c232
-rw-r--r--ractor.c248
-rw-r--r--ractor.rb126
-rw-r--r--random.c51
-rw-r--r--range.c130
-rw-r--r--rational.c48
-rw-r--r--re.c222
-rw-r--r--regcomp.c8
-rw-r--r--regenc.c2
-rw-r--r--regexec.c303
-rw-r--r--regint.h20
-rw-r--r--regparse.c11
-rw-r--r--rjit.c88
-rw-r--r--rjit.h14
-rw-r--r--rjit.rb6
-rw-r--r--rjit_c.c4
-rw-r--r--rjit_c.h2
-rw-r--r--rjit_c.rb135
-rw-r--r--ruby-runner.c4
-rw-r--r--ruby.c784
-rw-r--r--ruby_parser.c1302
-rw-r--r--rubyparser.h627
-rw-r--r--sample/find_calls.rb105
-rw-r--r--sample/find_comments.rb100
-rw-r--r--sample/getoptlong/abbrev.rb9
-rw-r--r--sample/getoptlong/aliases.rb8
-rw-r--r--sample/getoptlong/argv.rb12
-rw-r--r--sample/getoptlong/each.rb12
-rw-r--r--sample/getoptlong/fibonacci.rb62
-rw-r--r--sample/getoptlong/permute.rb12
-rw-r--r--sample/getoptlong/require_order.rb13
-rw-r--r--sample/getoptlong/return_in_order.rb13
-rw-r--r--sample/getoptlong/simple.rb7
-rw-r--r--sample/getoptlong/types.rb10
-rw-r--r--sample/locate_nodes.rb84
-rw-r--r--sample/net-imap.rb167
-rw-r--r--sample/visit_nodes.rb63
-rw-r--r--sample/win32ole/excel1.rb (renamed from ext/win32ole/sample/excel1.rb)0
-rw-r--r--sample/win32ole/excel2.rb (renamed from ext/win32ole/sample/excel2.rb)0
-rw-r--r--sample/win32ole/excel3.rb (renamed from ext/win32ole/sample/excel3.rb)0
-rw-r--r--sample/win32ole/ie.rb (renamed from ext/win32ole/sample/ie.rb)0
-rw-r--r--sample/win32ole/ieconst.rb (renamed from ext/win32ole/sample/ieconst.rb)0
-rw-r--r--sample/win32ole/ienavi.rb (renamed from ext/win32ole/sample/ienavi.rb)0
-rw-r--r--sample/win32ole/ienavi2.rb (renamed from ext/win32ole/sample/ienavi2.rb)0
-rw-r--r--sample/win32ole/oledirs.rb (renamed from ext/win32ole/sample/oledirs.rb)0
-rw-r--r--sample/win32ole/olegen.rb348
-rw-r--r--sample/win32ole/xml.rb (renamed from ext/win32ole/sample/xml.rb)0
-rw-r--r--scheduler.c18
-rw-r--r--shape.c509
-rw-r--r--shape.h24
-rw-r--r--signal.c38
-rw-r--r--spec/bundled_gems.mspec6
-rw-r--r--spec/bundler/bundler/bundler_spec.rb10
-rw-r--r--spec/bundler/bundler/ci_detector_spec.rb21
-rw-r--r--spec/bundler/bundler/cli_spec.rb32
-rw-r--r--spec/bundler/bundler/compact_index_client/parser_spec.rb259
-rw-r--r--spec/bundler/bundler/compact_index_client/updater_spec.rb189
-rw-r--r--spec/bundler/bundler/definition_spec.rb93
-rw-r--r--spec/bundler/bundler/dependency_spec.rb221
-rw-r--r--spec/bundler/bundler/digest_spec.rb2
-rw-r--r--spec/bundler/bundler/dsl_spec.rb108
-rw-r--r--spec/bundler/bundler/endpoint_specification_spec.rb6
-rw-r--r--spec/bundler/bundler/env_spec.rb14
-rw-r--r--spec/bundler/bundler/environment_preserver_spec.rb16
-rw-r--r--spec/bundler/bundler/fetcher/base_spec.rb11
-rw-r--r--spec/bundler/bundler/fetcher/compact_index_spec.rb18
-rw-r--r--spec/bundler/bundler/fetcher/dependency_spec.rb25
-rw-r--r--spec/bundler/bundler/fetcher/downloader_spec.rb66
-rw-r--r--spec/bundler/bundler/fetcher/index_spec.rb7
-rw-r--r--spec/bundler/bundler/fetcher_spec.rb48
-rw-r--r--spec/bundler/bundler/friendly_errors_spec.rb6
-rw-r--r--spec/bundler/bundler/gem_helper_spec.rb42
-rw-r--r--spec/bundler/bundler/gem_version_promoter_spec.rb56
-rw-r--r--spec/bundler/bundler/installer/gem_installer_spec.rb12
-rw-r--r--spec/bundler/bundler/installer/spec_installation_spec.rb18
-rw-r--r--spec/bundler/bundler/lockfile_parser_spec.rb23
-rw-r--r--spec/bundler/bundler/mirror_spec.rb16
-rw-r--r--spec/bundler/bundler/plugin/dsl_spec.rb6
-rw-r--r--spec/bundler/bundler/plugin/installer_spec.rb21
-rw-r--r--spec/bundler/bundler/plugin_spec.rb10
-rw-r--r--spec/bundler/bundler/remote_specification_spec.rb12
-rw-r--r--spec/bundler/bundler/resolver/candidate_spec.rb6
-rw-r--r--spec/bundler/bundler/ruby_dsl_spec.rb42
-rw-r--r--spec/bundler/bundler/rubygems_integration_spec.rb29
-rw-r--r--spec/bundler/bundler/settings_spec.rb39
-rw-r--r--spec/bundler/bundler/shared_helpers_spec.rb34
-rw-r--r--spec/bundler/bundler/source/git/git_proxy_spec.rb18
-rw-r--r--spec/bundler/bundler/source/git_spec.rb4
-rw-r--r--spec/bundler/bundler/source/rubygems/remote_spec.rb20
-rw-r--r--spec/bundler/bundler/source_list_spec.rb6
-rw-r--r--spec/bundler/bundler/source_spec.rb20
-rw-r--r--spec/bundler/bundler/uri_credentials_filter_spec.rb10
-rw-r--r--spec/bundler/bundler/yaml_serializer_spec.rb15
-rw-r--r--spec/bundler/cache/gems_spec.rb163
-rw-r--r--spec/bundler/cache/git_spec.rb12
-rw-r--r--spec/bundler/cache/path_spec.rb10
-rw-r--r--spec/bundler/cache/platform_spec.rb2
-rw-r--r--spec/bundler/commands/add_spec.rb79
-rw-r--r--spec/bundler/commands/binstubs_spec.rb50
-rw-r--r--spec/bundler/commands/cache_spec.rb72
-rw-r--r--spec/bundler/commands/check_spec.rb75
-rw-r--r--spec/bundler/commands/clean_spec.rb44
-rw-r--r--spec/bundler/commands/config_spec.rb50
-rw-r--r--spec/bundler/commands/console_spec.rb2
-rw-r--r--spec/bundler/commands/exec_spec.rb88
-rw-r--r--spec/bundler/commands/help_spec.rb9
-rw-r--r--spec/bundler/commands/info_spec.rb24
-rw-r--r--spec/bundler/commands/init_spec.rb30
-rw-r--r--spec/bundler/commands/inject_spec.rb8
-rw-r--r--spec/bundler/commands/install_spec.rb290
-rw-r--r--spec/bundler/commands/list_spec.rb14
-rw-r--r--spec/bundler/commands/lock_spec.rb480
-rw-r--r--spec/bundler/commands/newgem_spec.rb239
-rw-r--r--spec/bundler/commands/open_spec.rb55
-rw-r--r--spec/bundler/commands/outdated_spec.rb176
-rw-r--r--spec/bundler/commands/platform_spec.rb132
-rw-r--r--spec/bundler/commands/post_bundle_message_spec.rb14
-rw-r--r--spec/bundler/commands/pristine_spec.rb20
-rw-r--r--spec/bundler/commands/remove_spec.rb24
-rw-r--r--spec/bundler/commands/show_spec.rb22
-rw-r--r--spec/bundler/commands/update_spec.rb414
-rw-r--r--spec/bundler/commands/version_spec.rb12
-rw-r--r--spec/bundler/commands/viz_spec.rb10
-rw-r--r--spec/bundler/install/allow_offline_install_spec.rb16
-rw-r--r--spec/bundler/install/bundler_spec.rb10
-rw-r--r--spec/bundler/install/deploy_spec.rb118
-rw-r--r--spec/bundler/install/failure_spec.rb4
-rw-r--r--spec/bundler/install/gemfile/eval_gemfile_spec.rb8
-rw-r--r--spec/bundler/install/gemfile/force_ruby_platform_spec.rb8
-rw-r--r--spec/bundler/install/gemfile/gemspec_spec.rb225
-rw-r--r--spec/bundler/install/gemfile/git_spec.rb183
-rw-r--r--spec/bundler/install/gemfile/groups_spec.rb42
-rw-r--r--spec/bundler/install/gemfile/install_if_spec.rb15
-rw-r--r--spec/bundler/install/gemfile/lockfile_spec.rb5
-rw-r--r--spec/bundler/install/gemfile/path_spec.rb231
-rw-r--r--spec/bundler/install/gemfile/platform_spec.rb70
-rw-r--r--spec/bundler/install/gemfile/ruby_spec.rb36
-rw-r--r--spec/bundler/install/gemfile/sources_spec.rb428
-rw-r--r--spec/bundler/install/gemfile/specific_platform_spec.rb399
-rw-r--r--spec/bundler/install/gemfile_spec.rb10
-rw-r--r--spec/bundler/install/gems/compact_index_spec.rb329
-rw-r--r--spec/bundler/install/gems/dependency_api_spec.rb136
-rw-r--r--spec/bundler/install/gems/flex_spec.rb30
-rw-r--r--spec/bundler/install/gems/native_extensions_spec.rb8
-rw-r--r--spec/bundler/install/gems/resolving_spec.rb71
-rw-r--r--spec/bundler/install/gems/standalone_spec.rb60
-rw-r--r--spec/bundler/install/gemspecs_spec.rb30
-rw-r--r--spec/bundler/install/git_spec.rb56
-rw-r--r--spec/bundler/install/global_cache_spec.rb38
-rw-r--r--spec/bundler/install/path_spec.rb36
-rw-r--r--spec/bundler/install/redownload_spec.rb2
-rw-r--r--spec/bundler/install/security_policy_spec.rb12
-rw-r--r--spec/bundler/install/yanked_spec.rb18
-rw-r--r--spec/bundler/lock/git_spec.rb6
-rw-r--r--spec/bundler/lock/lockfile_spec.rb471
-rw-r--r--spec/bundler/other/cli_dispatch_spec.rb6
-rw-r--r--spec/bundler/other/ext_spec.rb24
-rw-r--r--spec/bundler/other/major_deprecation_spec.rb198
-rw-r--r--spec/bundler/plugins/command_spec.rb2
-rw-r--r--spec/bundler/plugins/hook_spec.rb99
-rw-r--r--spec/bundler/plugins/install_spec.rb91
-rw-r--r--spec/bundler/plugins/source/example_spec.rb20
-rw-r--r--spec/bundler/quality_spec.rb5
-rw-r--r--spec/bundler/realworld/dependency_api_spec.rb16
-rw-r--r--spec/bundler/realworld/double_check_spec.rb6
-rw-r--r--spec/bundler/realworld/edgecases_spec.rb150
-rw-r--r--spec/bundler/realworld/ffi_spec.rb2
-rw-r--r--spec/bundler/realworld/fixtures/warbler/Gemfile2
-rw-r--r--spec/bundler/realworld/gemfile_source_header_spec.rb18
-rw-r--r--spec/bundler/realworld/git_spec.rb2
-rw-r--r--spec/bundler/realworld/mirror_probe_spec.rb22
-rw-r--r--spec/bundler/realworld/parallel_spec.rb8
-rw-r--r--spec/bundler/realworld/slow_perf_spec.rb117
-rw-r--r--spec/bundler/runtime/executable_spec.rb22
-rw-r--r--spec/bundler/runtime/gem_tasks_spec.rb14
-rw-r--r--spec/bundler/runtime/inline_spec.rb95
-rw-r--r--spec/bundler/runtime/load_spec.rb2
-rw-r--r--spec/bundler/runtime/platform_spec.rb25
-rw-r--r--spec/bundler/runtime/require_spec.rb36
-rw-r--r--spec/bundler/runtime/requiring_spec.rb4
-rw-r--r--spec/bundler/runtime/self_management_spec.rb20
-rw-r--r--spec/bundler/runtime/setup_spec.rb188
-rw-r--r--spec/bundler/runtime/with_unbundled_env_spec.rb14
-rw-r--r--spec/bundler/spec_helper.rb2
-rw-r--r--spec/bundler/support/activate.rb2
-rw-r--r--spec/bundler/support/artifice/compact_index_checksum_mismatch.rb4
-rw-r--r--spec/bundler/support/artifice/compact_index_concurrent_download.rb7
-rw-r--r--spec/bundler/support/artifice/compact_index_etag_match.rb16
-rw-r--r--spec/bundler/support/artifice/compact_index_host_redirect.rb2
-rw-r--r--spec/bundler/support/artifice/compact_index_partial_update.rb2
-rw-r--r--spec/bundler/support/artifice/compact_index_partial_update_bad_digest.rb40
-rw-r--r--spec/bundler/support/artifice/compact_index_partial_update_no_digest_not_incremental.rb42
-rw-r--r--spec/bundler/support/artifice/compact_index_partial_update_no_etag_not_incremental.rb40
-rw-r--r--spec/bundler/support/artifice/compact_index_range_ignored.rb40
-rw-r--r--spec/bundler/support/artifice/endpoint_500.rb2
-rw-r--r--spec/bundler/support/artifice/endpoint_host_redirect.rb2
-rw-r--r--spec/bundler/support/artifice/endpoint_mirror_source.rb2
-rw-r--r--spec/bundler/support/artifice/fail.rb10
-rw-r--r--spec/bundler/support/artifice/helpers/artifice.rb6
-rw-r--r--spec/bundler/support/artifice/helpers/compact_index.rb15
-rw-r--r--spec/bundler/support/artifice/helpers/endpoint.rb10
-rw-r--r--spec/bundler/support/artifice/helpers/rack_request.rb24
-rw-r--r--spec/bundler/support/artifice/vcr.rb10
-rw-r--r--spec/bundler/support/artifice/windows.rb2
-rw-r--r--spec/bundler/support/build_metadata.rb14
-rw-r--r--spec/bundler/support/builders.rb101
-rw-r--r--spec/bundler/support/checksums.rb68
-rw-r--r--spec/bundler/support/command_execution.rb48
-rw-r--r--spec/bundler/support/env.rb9
-rw-r--r--spec/bundler/support/filters.rb24
-rw-r--r--spec/bundler/support/helpers.rb146
-rw-r--r--spec/bundler/support/indexes.rb8
-rw-r--r--spec/bundler/support/matchers.rb12
-rw-r--r--spec/bundler/support/options.rb15
-rw-r--r--spec/bundler/support/path.rb51
-rw-r--r--spec/bundler/support/platforms.rb2
-rw-r--r--spec/bundler/support/rubygems_ext.rb21
-rw-r--r--spec/bundler/support/rubygems_version_manager.rb38
-rw-r--r--spec/bundler/support/subprocess.rb106
-rw-r--r--spec/bundler/update/gemfile_spec.rb10
-rw-r--r--spec/bundler/update/gems/fund_spec.rb2
-rw-r--r--spec/bundler/update/gems/post_install_spec.rb4
-rw-r--r--spec/bundler/update/git_spec.rb75
-rw-r--r--spec/bundler/update/path_spec.rb4
-rw-r--r--spec/bundler/update/redownload_spec.rb6
-rw-r--r--spec/default.mspec26
-rw-r--r--spec/mspec/lib/mspec/helpers/tmp.rb3
-rw-r--r--spec/mspec/lib/mspec/mocks/mock.rb25
-rw-r--r--spec/mspec/lib/mspec/runner/actions/leakchecker.rb58
-rw-r--r--spec/mspec/lib/mspec/runner/actions/timeout.rb30
-rw-r--r--spec/mspec/lib/mspec/runner/formatters/base.rb8
-rw-r--r--spec/mspec/spec/integration/run_spec.rb9
-rw-r--r--spec/mspec/spec/integration/tag_spec.rb9
-rw-r--r--spec/mspec/spec/mocks/mock_spec.rb21
-rw-r--r--spec/mspec/spec/spec_helper.rb2
-rw-r--r--spec/ruby/.rubocop.yml6
-rw-r--r--spec/ruby/.rubocop_todo.yml1
-rw-r--r--spec/ruby/command_line/backtrace_limit_spec.rb87
-rw-r--r--spec/ruby/command_line/dash_r_spec.rb5
-rw-r--r--spec/ruby/command_line/dash_v_spec.rb5
-rw-r--r--spec/ruby/command_line/fixtures/string_literal_frozen_comment.rb4
-rw-r--r--spec/ruby/command_line/fixtures/string_literal_mutable_comment.rb4
-rw-r--r--spec/ruby/command_line/fixtures/string_literal_raw.rb3
-rw-r--r--spec/ruby/command_line/frozen_strings_spec.rb36
-rw-r--r--spec/ruby/command_line/rubyopt_spec.rb4
-rw-r--r--spec/ruby/command_line/syntax_error_spec.rb10
-rw-r--r--spec/ruby/core/argf/readpartial_spec.rb2
-rw-r--r--spec/ruby/core/argf/shared/getc.rb2
-rw-r--r--spec/ruby/core/argf/shared/read.rb4
-rw-r--r--spec/ruby/core/array/assoc_spec.rb12
-rw-r--r--spec/ruby/core/array/fill_spec.rb2
-rw-r--r--spec/ruby/core/array/fixtures/encoded_strings.rb18
-rw-r--r--spec/ruby/core/array/pack/buffer_spec.rb12
-rw-r--r--spec/ruby/core/array/pack/shared/string.rb2
-rw-r--r--spec/ruby/core/array/rassoc_spec.rb14
-rw-r--r--spec/ruby/core/array/shared/inspect.rb6
-rw-r--r--spec/ruby/core/basicobject/singleton_method_added_spec.rb8
-rw-r--r--spec/ruby/core/binding/clone_spec.rb6
-rw-r--r--spec/ruby/core/binding/dup_spec.rb23
-rw-r--r--spec/ruby/core/binding/fixtures/irbrc1
-rw-r--r--spec/ruby/core/binding/irb_spec.rb15
-rw-r--r--spec/ruby/core/binding/shared/clone.rb22
-rw-r--r--spec/ruby/core/class/attached_object_spec.rb8
-rw-r--r--spec/ruby/core/class/subclasses_spec.rb29
-rw-r--r--spec/ruby/core/complex/inspect_spec.rb6
-rw-r--r--spec/ruby/core/complex/to_r_spec.rb12
-rw-r--r--spec/ruby/core/complex/to_s_spec.rb3
-rw-r--r--spec/ruby/core/conditionvariable/broadcast_spec.rb1
-rw-r--r--spec/ruby/core/conditionvariable/marshal_dump_spec.rb1
-rw-r--r--spec/ruby/core/conditionvariable/signal_spec.rb1
-rw-r--r--spec/ruby/core/conditionvariable/wait_spec.rb1
-rw-r--r--spec/ruby/core/data/initialize_spec.rb7
-rw-r--r--spec/ruby/core/data/with_spec.rb35
-rw-r--r--spec/ruby/core/dir/children_spec.rb17
-rw-r--r--spec/ruby/core/dir/each_child_spec.rb13
-rw-r--r--spec/ruby/core/dir/each_spec.rb11
-rw-r--r--spec/ruby/core/dir/entries_spec.rb2
-rw-r--r--spec/ruby/core/dir/shared/glob.rb2
-rw-r--r--spec/ruby/core/encoding/compatible_spec.rb74
-rw-r--r--spec/ruby/core/encoding/converter/convert_spec.rb15
-rw-r--r--spec/ruby/core/encoding/converter/finish_spec.rb4
-rw-r--r--spec/ruby/core/encoding/converter/last_error_spec.rb16
-rw-r--r--spec/ruby/core/encoding/converter/new_spec.rb2
-rw-r--r--spec/ruby/core/encoding/converter/primitive_convert_spec.rb1
-rw-r--r--spec/ruby/core/encoding/converter/primitive_errinfo_spec.rb1
-rw-r--r--spec/ruby/core/encoding/converter/putback_spec.rb14
-rw-r--r--spec/ruby/core/encoding/converter/replacement_spec.rb20
-rw-r--r--spec/ruby/core/encoding/inspect_spec.rb20
-rw-r--r--spec/ruby/core/encoding/invalid_byte_sequence_error/incomplete_input_spec.rb4
-rw-r--r--spec/ruby/core/encoding/invalid_byte_sequence_error/readagain_bytes_spec.rb4
-rw-r--r--spec/ruby/core/encoding/replicate_spec.rb23
-rw-r--r--spec/ruby/core/enumerable/fixtures/classes.rb6
-rw-r--r--spec/ruby/core/enumerable/to_set_spec.rb29
-rw-r--r--spec/ruby/core/enumerator/next_values_spec.rb8
-rw-r--r--spec/ruby/core/enumerator/peek_values_spec.rb8
-rw-r--r--spec/ruby/core/enumerator/product/each_spec.rb2
-rw-r--r--spec/ruby/core/enumerator/product/size_spec.rb8
-rw-r--r--spec/ruby/core/enumerator/product_spec.rb2
-rw-r--r--spec/ruby/core/exception/backtrace_spec.rb27
-rw-r--r--spec/ruby/core/exception/fixtures/syntax_error.rb3
-rw-r--r--spec/ruby/core/exception/frozen_error_spec.rb16
-rw-r--r--spec/ruby/core/exception/full_message_spec.rb49
-rw-r--r--spec/ruby/core/exception/interrupt_spec.rb2
-rw-r--r--spec/ruby/core/exception/no_method_error_spec.rb6
-rw-r--r--spec/ruby/core/exception/set_backtrace_spec.rb28
-rw-r--r--spec/ruby/core/exception/syntax_error_spec.rb27
-rw-r--r--spec/ruby/core/exception/to_s_spec.rb2
-rw-r--r--spec/ruby/core/exception/top_level_spec.rb30
-rw-r--r--spec/ruby/core/fiber/raise_spec.rb34
-rw-r--r--spec/ruby/core/file/atime_spec.rb3
-rw-r--r--spec/ruby/core/file/ctime_spec.rb3
-rw-r--r--spec/ruby/core/file/expand_path_spec.rb2
-rw-r--r--spec/ruby/core/file/lutime_spec.rb9
-rw-r--r--spec/ruby/core/file/mtime_spec.rb3
-rw-r--r--spec/ruby/core/file/new_spec.rb2
-rw-r--r--spec/ruby/core/file/open_spec.rb6
-rw-r--r--spec/ruby/core/file/shared/path.rb4
-rw-r--r--spec/ruby/core/file/shared/update_time.rb105
-rw-r--r--spec/ruby/core/file/utime_spec.rb100
-rw-r--r--spec/ruby/core/filetest/exist_spec.rb8
-rw-r--r--spec/ruby/core/hash/assoc_spec.rb6
-rw-r--r--spec/ruby/core/hash/compare_by_identity_spec.rb19
-rw-r--r--spec/ruby/core/hash/delete_spec.rb18
-rw-r--r--spec/ruby/core/hash/element_reference_spec.rb2
-rw-r--r--spec/ruby/core/hash/hash_spec.rb2
-rw-r--r--spec/ruby/core/hash/rehash_spec.rb30
-rw-r--r--spec/ruby/core/hash/shared/store.rb8
-rw-r--r--spec/ruby/core/hash/shared/to_s.rb4
-rw-r--r--spec/ruby/core/integer/coerce_spec.rb13
-rw-r--r--spec/ruby/core/integer/div_spec.rb8
-rw-r--r--spec/ruby/core/io/close_read_spec.rb3
-rw-r--r--spec/ruby/core/io/close_write_spec.rb14
-rw-r--r--spec/ruby/core/io/ioctl_spec.rb2
-rw-r--r--spec/ruby/core/io/lineno_spec.rb6
-rw-r--r--spec/ruby/core/io/pread_spec.rb19
-rw-r--r--spec/ruby/core/io/puts_spec.rb2
-rw-r--r--spec/ruby/core/io/pwrite_spec.rb2
-rw-r--r--spec/ruby/core/io/read_nonblock_spec.rb8
-rw-r--r--spec/ruby/core/io/read_spec.rb47
-rw-r--r--spec/ruby/core/io/readpartial_spec.rb9
-rw-r--r--spec/ruby/core/io/select_spec.rb33
-rw-r--r--spec/ruby/core/io/shared/readlines.rb2
-rw-r--r--spec/ruby/core/io/stat_spec.rb3
-rw-r--r--spec/ruby/core/io/sysread_spec.rb23
-rw-r--r--spec/ruby/core/kernel/Float_spec.rb2
-rw-r--r--spec/ruby/core/kernel/Integer_spec.rb15
-rw-r--r--spec/ruby/core/kernel/String_spec.rb2
-rw-r--r--spec/ruby/core/kernel/caller_locations_spec.rb30
-rw-r--r--spec/ruby/core/kernel/caller_spec.rb10
-rw-r--r--spec/ruby/core/kernel/catch_spec.rb2
-rw-r--r--spec/ruby/core/kernel/class_spec.rb2
-rw-r--r--spec/ruby/core/kernel/eval_spec.rb38
-rw-r--r--spec/ruby/core/kernel/not_match_spec.rb14
-rw-r--r--spec/ruby/core/kernel/public_send_spec.rb4
-rw-r--r--spec/ruby/core/kernel/require_spec.rb2
-rw-r--r--spec/ruby/core/kernel/shared/sprintf_encoding.rb8
-rw-r--r--spec/ruby/core/kernel/system_spec.rb17
-rw-r--r--spec/ruby/core/marshal/dump_spec.rb42
-rw-r--r--spec/ruby/core/marshal/fixtures/marshal_data.rb8
-rw-r--r--spec/ruby/core/marshal/shared/load.rb32
-rw-r--r--spec/ruby/core/matchdata/begin_spec.rb28
-rw-r--r--spec/ruby/core/matchdata/byteoffset_spec.rb4
-rw-r--r--spec/ruby/core/matchdata/element_reference_spec.rb2
-rw-r--r--spec/ruby/core/matchdata/post_match_spec.rb4
-rw-r--r--spec/ruby/core/matchdata/pre_match_spec.rb4
-rw-r--r--spec/ruby/core/matchdata/string_spec.rb5
-rw-r--r--spec/ruby/core/method/clone_spec.rb15
-rw-r--r--spec/ruby/core/method/dup_spec.rb15
-rw-r--r--spec/ruby/core/method/parameters_spec.rb47
-rw-r--r--spec/ruby/core/method/shared/dup.rb32
-rw-r--r--spec/ruby/core/method/to_proc_spec.rb2
-rw-r--r--spec/ruby/core/module/attr_accessor_spec.rb3
-rw-r--r--spec/ruby/core/module/attr_reader_spec.rb3
-rw-r--r--spec/ruby/core/module/attr_spec.rb3
-rw-r--r--spec/ruby/core/module/attr_writer_spec.rb3
-rw-r--r--spec/ruby/core/module/autoload_spec.rb103
-rw-r--r--spec/ruby/core/module/const_source_location_spec.rb12
-rw-r--r--spec/ruby/core/module/fixtures/autoload_const_source_location.rb6
-rw-r--r--spec/ruby/core/module/fixtures/autoload_during_autoload_after_define.rb6
-rw-r--r--spec/ruby/core/module/include_spec.rb28
-rw-r--r--spec/ruby/core/module/prepend_spec.rb92
-rw-r--r--spec/ruby/core/module/ruby2_keywords_spec.rb3
-rw-r--r--spec/ruby/core/module/shared/attr_added.rb34
-rw-r--r--spec/ruby/core/module/undef_method_spec.rb10
-rw-r--r--spec/ruby/core/module/using_spec.rb2
-rw-r--r--spec/ruby/core/objectspace/define_finalizer_spec.rb8
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/element_set_spec.rb2
-rw-r--r--spec/ruby/core/proc/arity_spec.rb16
-rw-r--r--spec/ruby/core/proc/clone_spec.rb9
-rw-r--r--spec/ruby/core/proc/dup_spec.rb7
-rw-r--r--spec/ruby/core/proc/fixtures/proc_aref.rb1
-rw-r--r--spec/ruby/core/proc/parameters_spec.rb43
-rw-r--r--spec/ruby/core/proc/shared/dup.rb23
-rw-r--r--spec/ruby/core/proc/shared/to_s.rb14
-rw-r--r--spec/ruby/core/process/fixtures/kill.rb2
-rw-r--r--spec/ruby/core/process/status/termsig_spec.rb2
-rw-r--r--spec/ruby/core/process/waitpid_spec.rb3
-rw-r--r--spec/ruby/core/range/bsearch_spec.rb44
-rw-r--r--spec/ruby/core/range/size_spec.rb62
-rw-r--r--spec/ruby/core/rational/coerce_spec.rb6
-rw-r--r--spec/ruby/core/refinement/import_methods_spec.rb4
-rw-r--r--spec/ruby/core/regexp/shared/new.rb44
-rw-r--r--spec/ruby/core/regexp/shared/quote.rb10
-rw-r--r--spec/ruby/core/signal/trap_spec.rb12
-rw-r--r--spec/ruby/core/string/ascii_only_spec.rb23
-rw-r--r--spec/ruby/core/string/b_spec.rb1
-rw-r--r--spec/ruby/core/string/byteindex_spec.rb4
-rw-r--r--spec/ruby/core/string/byterindex_spec.rb4
-rw-r--r--spec/ruby/core/string/bytes_spec.rb2
-rw-r--r--spec/ruby/core/string/bytesize_spec.rb10
-rw-r--r--spec/ruby/core/string/byteslice_spec.rb8
-rw-r--r--spec/ruby/core/string/bytesplice_spec.rb1
-rw-r--r--spec/ruby/core/string/capitalize_spec.rb24
-rw-r--r--spec/ruby/core/string/center_spec.rb4
-rw-r--r--spec/ruby/core/string/chilled_string_spec.rb71
-rw-r--r--spec/ruby/core/string/chomp_spec.rb1
-rw-r--r--spec/ruby/core/string/chop_spec.rb1
-rw-r--r--spec/ruby/core/string/clear_spec.rb1
-rw-r--r--spec/ruby/core/string/codepoints_spec.rb2
-rw-r--r--spec/ruby/core/string/comparison_spec.rb8
-rw-r--r--spec/ruby/core/string/concat_spec.rb6
-rw-r--r--spec/ruby/core/string/delete_prefix_spec.rb1
-rw-r--r--spec/ruby/core/string/delete_spec.rb1
-rw-r--r--spec/ruby/core/string/delete_suffix_spec.rb1
-rw-r--r--spec/ruby/core/string/downcase_spec.rb1
-rw-r--r--spec/ruby/core/string/dup_spec.rb2
-rw-r--r--spec/ruby/core/string/each_byte_spec.rb16
-rw-r--r--spec/ruby/core/string/element_set_spec.rb1
-rw-r--r--spec/ruby/core/string/encode_spec.rb22
-rw-r--r--spec/ruby/core/string/encoding_spec.rb24
-rw-r--r--spec/ruby/core/string/fixtures/utf-8-encoding.rb7
-rw-r--r--spec/ruby/core/string/force_encoding_spec.rb1
-rw-r--r--spec/ruby/core/string/freeze_spec.rb1
-rw-r--r--spec/ruby/core/string/gsub_spec.rb1
-rw-r--r--spec/ruby/core/string/include_spec.rb12
-rw-r--r--spec/ruby/core/string/index_spec.rb19
-rw-r--r--spec/ruby/core/string/insert_spec.rb2
-rw-r--r--spec/ruby/core/string/inspect_spec.rb2
-rw-r--r--spec/ruby/core/string/ljust_spec.rb4
-rw-r--r--spec/ruby/core/string/lstrip_spec.rb1
-rw-r--r--spec/ruby/core/string/modulo_spec.rb65
-rw-r--r--spec/ruby/core/string/ord_spec.rb2
-rw-r--r--spec/ruby/core/string/partition_spec.rb4
-rw-r--r--spec/ruby/core/string/prepend_spec.rb1
-rw-r--r--spec/ruby/core/string/reverse_spec.rb1
-rw-r--r--spec/ruby/core/string/rindex_spec.rb9
-rw-r--r--spec/ruby/core/string/rjust_spec.rb4
-rw-r--r--spec/ruby/core/string/rpartition_spec.rb4
-rw-r--r--spec/ruby/core/string/rstrip_spec.rb1
-rw-r--r--spec/ruby/core/string/scrub_spec.rb1
-rw-r--r--spec/ruby/core/string/setbyte_spec.rb1
-rw-r--r--spec/ruby/core/string/shared/chars.rb12
-rw-r--r--spec/ruby/core/string/shared/codepoints.rb6
-rw-r--r--spec/ruby/core/string/shared/concat.rb1
-rw-r--r--spec/ruby/core/string/shared/dedup.rb1
-rw-r--r--spec/ruby/core/string/shared/each_codepoint_without_block.rb4
-rw-r--r--spec/ruby/core/string/shared/each_line.rb2
-rw-r--r--spec/ruby/core/string/shared/encode.rb1
-rw-r--r--spec/ruby/core/string/shared/eql.rb8
-rw-r--r--spec/ruby/core/string/shared/length.rb10
-rw-r--r--spec/ruby/core/string/shared/replace.rb1
-rw-r--r--spec/ruby/core/string/shared/slice.rb4
-rw-r--r--spec/ruby/core/string/shared/succ.rb1
-rw-r--r--spec/ruby/core/string/shared/to_sym.rb4
-rw-r--r--spec/ruby/core/string/slice_spec.rb2
-rw-r--r--spec/ruby/core/string/split_spec.rb8
-rw-r--r--spec/ruby/core/string/squeeze_spec.rb1
-rw-r--r--spec/ruby/core/string/strip_spec.rb1
-rw-r--r--spec/ruby/core/string/sub_spec.rb1
-rw-r--r--spec/ruby/core/string/swapcase_spec.rb1
-rw-r--r--spec/ruby/core/string/to_i_spec.rb12
-rw-r--r--spec/ruby/core/string/tr_s_spec.rb1
-rw-r--r--spec/ruby/core/string/tr_spec.rb1
-rw-r--r--spec/ruby/core/string/unicode_normalize_spec.rb1
-rw-r--r--spec/ruby/core/string/unicode_normalized_spec.rb1
-rw-r--r--spec/ruby/core/string/unpack/a_spec.rb2
-rw-r--r--spec/ruby/core/string/unpack/b_spec.rb4
-rw-r--r--spec/ruby/core/string/unpack/u_spec.rb2
-rw-r--r--spec/ruby/core/string/upcase_spec.rb1
-rw-r--r--spec/ruby/core/string/uplus_spec.rb1
-rw-r--r--spec/ruby/core/string/upto_spec.rb4
-rw-r--r--spec/ruby/core/string/valid_encoding_spec.rb22
-rw-r--r--spec/ruby/core/struct/new_spec.rb2
-rw-r--r--spec/ruby/core/symbol/to_proc_spec.rb8
-rw-r--r--spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb2
-rw-r--r--spec/ruby/core/thread/backtrace/location/label_spec.rb10
-rw-r--r--spec/ruby/core/thread/backtrace/location/lineno_spec.rb2
-rw-r--r--spec/ruby/core/thread/backtrace_locations_spec.rb2
-rw-r--r--spec/ruby/core/thread/backtrace_spec.rb2
-rw-r--r--spec/ruby/core/thread/each_caller_location_spec.rb4
-rw-r--r--spec/ruby/core/thread/fetch_spec.rb30
-rw-r--r--spec/ruby/core/thread/report_on_exception_spec.rb10
-rw-r--r--spec/ruby/core/thread/thread_variable_get_spec.rb2
-rw-r--r--spec/ruby/core/time/_load_spec.rb3
-rw-r--r--spec/ruby/core/time/at_spec.rb9
-rw-r--r--spec/ruby/core/time/deconstruct_keys_spec.rb5
-rw-r--r--spec/ruby/core/time/fixtures/classes.rb1
-rw-r--r--spec/ruby/core/time/new_spec.rb16
-rw-r--r--spec/ruby/core/tracepoint/inspect_spec.rb6
-rw-r--r--spec/ruby/core/unboundmethod/clone_spec.rb13
-rw-r--r--spec/ruby/core/unboundmethod/dup_spec.rb15
-rw-r--r--spec/ruby/core/unboundmethod/shared/dup.rb32
-rw-r--r--spec/ruby/core/warning/element_reference_spec.rb4
-rw-r--r--spec/ruby/core/warning/performance_warning_spec.rb28
-rw-r--r--spec/ruby/default.mspec1
-rw-r--r--spec/ruby/language/assignments_spec.rb529
-rw-r--r--spec/ruby/language/block_spec.rb112
-rw-r--r--spec/ruby/language/break_spec.rb21
-rw-r--r--spec/ruby/language/case_spec.rb46
-rw-r--r--spec/ruby/language/def_spec.rb28
-rw-r--r--spec/ruby/language/defined_spec.rb121
-rw-r--r--spec/ruby/language/delegation_spec.rb36
-rw-r--r--spec/ruby/language/encoding_spec.rb8
-rw-r--r--spec/ruby/language/ensure_spec.rb17
-rw-r--r--spec/ruby/language/execution_spec.rb78
-rw-r--r--spec/ruby/language/fixtures/rescue/top_level.rb7
-rw-r--r--spec/ruby/language/fixtures/super.rb48
-rw-r--r--spec/ruby/language/hash_spec.rb80
-rw-r--r--spec/ruby/language/if_spec.rb10
-rw-r--r--spec/ruby/language/keyword_arguments_spec.rb43
-rw-r--r--spec/ruby/language/lambda_spec.rb23
-rw-r--r--spec/ruby/language/method_spec.rb3
-rw-r--r--spec/ruby/language/numbered_parameters_spec.rb15
-rw-r--r--spec/ruby/language/optional_assignments_spec.rb294
-rw-r--r--spec/ruby/language/pattern_matching_spec.rb222
-rw-r--r--spec/ruby/language/predefined_spec.rb18
-rw-r--r--spec/ruby/language/regexp/back-references_spec.rb9
-rw-r--r--spec/ruby/language/regexp/encoding_spec.rb42
-rw-r--r--spec/ruby/language/regexp_spec.rb2
-rw-r--r--spec/ruby/language/rescue_spec.rb91
-rw-r--r--spec/ruby/language/retry_spec.rb5
-rw-r--r--spec/ruby/language/safe_navigator_spec.rb80
-rw-r--r--spec/ruby/language/send_spec.rb2
-rw-r--r--spec/ruby/language/singleton_class_spec.rb9
-rw-r--r--spec/ruby/language/string_spec.rb18
-rw-r--r--spec/ruby/language/super_spec.rb7
-rw-r--r--spec/ruby/language/symbol_spec.rb14
-rw-r--r--spec/ruby/language/variables_spec.rb11
-rw-r--r--spec/ruby/language/yield_spec.rb12
-rw-r--r--spec/ruby/library/bigdecimal/core_spec.rb59
-rw-r--r--spec/ruby/library/bigdecimal/sqrt_spec.rb6
-rw-r--r--spec/ruby/library/bigmath/log_spec.rb10
-rw-r--r--spec/ruby/library/cgi/escapeURIComponent_spec.rb2
-rw-r--r--spec/ruby/library/coverage/result_spec.rb266
-rw-r--r--spec/ruby/library/coverage/start_spec.rb81
-rw-r--r--spec/ruby/library/csv/generate_spec.rb2
-rw-r--r--spec/ruby/library/date/iso8601_spec.rb21
-rw-r--r--spec/ruby/library/date/shared/parse.rb4
-rw-r--r--spec/ruby/library/date/shared/parse_eu.rb8
-rw-r--r--spec/ruby/library/date/shared/parse_us.rb8
-rw-r--r--spec/ruby/library/date/time/to_date_spec.rb42
-rw-r--r--spec/ruby/library/datetime/time/to_datetime_spec.rb42
-rw-r--r--spec/ruby/library/digest/instance/shared/update.rb2
-rw-r--r--spec/ruby/library/drb/start_service_spec.rb47
-rw-r--r--spec/ruby/library/erb/run_spec.rb2
-rw-r--r--spec/ruby/library/etc/uname_spec.rb14
-rw-r--r--spec/ruby/library/io-wait/wait_spec.rb37
-rw-r--r--spec/ruby/library/matrix/I_spec.rb9
-rw-r--r--spec/ruby/library/matrix/antisymmetric_spec.rb54
-rw-r--r--spec/ruby/library/matrix/build_spec.rb117
-rw-r--r--spec/ruby/library/matrix/clone_spec.rb37
-rw-r--r--spec/ruby/library/matrix/coerce_spec.rb11
-rw-r--r--spec/ruby/library/matrix/collect_spec.rb9
-rw-r--r--spec/ruby/library/matrix/column_size_spec.rb19
-rw-r--r--spec/ruby/library/matrix/column_spec.rb53
-rw-r--r--spec/ruby/library/matrix/column_vector_spec.rb37
-rw-r--r--spec/ruby/library/matrix/column_vectors_spec.rb37
-rw-r--r--spec/ruby/library/matrix/columns_spec.rb67
-rw-r--r--spec/ruby/library/matrix/conj_spec.rb9
-rw-r--r--spec/ruby/library/matrix/conjugate_spec.rb9
-rw-r--r--spec/ruby/library/matrix/constructor_spec.rb103
-rw-r--r--spec/ruby/library/matrix/det_spec.rb11
-rw-r--r--spec/ruby/library/matrix/determinant_spec.rb11
-rw-r--r--spec/ruby/library/matrix/diagonal_spec.rb105
-rw-r--r--spec/ruby/library/matrix/divide_spec.rb83
-rw-r--r--spec/ruby/library/matrix/each_spec.rb119
-rw-r--r--spec/ruby/library/matrix/each_with_index_spec.rb133
-rw-r--r--spec/ruby/library/matrix/eigenvalue_decomposition/eigenvalue_matrix_spec.rb13
-rw-r--r--spec/ruby/library/matrix/eigenvalue_decomposition/eigenvalues_spec.rb35
-rw-r--r--spec/ruby/library/matrix/eigenvalue_decomposition/eigenvector_matrix_spec.rb33
-rw-r--r--spec/ruby/library/matrix/eigenvalue_decomposition/eigenvectors_spec.rb37
-rw-r--r--spec/ruby/library/matrix/eigenvalue_decomposition/initialize_spec.rb39
-rw-r--r--spec/ruby/library/matrix/eigenvalue_decomposition/to_a_spec.rb27
-rw-r--r--spec/ruby/library/matrix/element_reference_spec.rb31
-rw-r--r--spec/ruby/library/matrix/empty_spec.rb107
-rw-r--r--spec/ruby/library/matrix/eql_spec.rb15
-rw-r--r--spec/ruby/library/matrix/equal_value_spec.rb15
-rw-r--r--spec/ruby/library/matrix/exponent_spec.rb93
-rw-r--r--spec/ruby/library/matrix/find_index_spec.rb221
-rw-r--r--spec/ruby/library/matrix/hash_spec.rb21
-rw-r--r--spec/ruby/library/matrix/hermitian_spec.rb53
-rw-r--r--spec/ruby/library/matrix/identity_spec.rb9
-rw-r--r--spec/ruby/library/matrix/imag_spec.rb9
-rw-r--r--spec/ruby/library/matrix/imaginary_spec.rb9
-rw-r--r--spec/ruby/library/matrix/inspect_spec.rb39
-rw-r--r--spec/ruby/library/matrix/inv_spec.rb11
-rw-r--r--spec/ruby/library/matrix/inverse_from_spec.rb9
-rw-r--r--spec/ruby/library/matrix/inverse_spec.rb11
-rw-r--r--spec/ruby/library/matrix/lower_triangular_spec.rb39
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/determinant_spec.rb33
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/initialize_spec.rb21
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/l_spec.rb27
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/p_spec.rb27
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/solve_spec.rb85
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/to_a_spec.rb53
-rw-r--r--spec/ruby/library/matrix/lup_decomposition/u_spec.rb27
-rw-r--r--spec/ruby/library/matrix/map_spec.rb9
-rw-r--r--spec/ruby/library/matrix/minor_spec.rb135
-rw-r--r--spec/ruby/library/matrix/minus_spec.rb65
-rw-r--r--spec/ruby/library/matrix/multiply_spec.rb104
-rw-r--r--spec/ruby/library/matrix/new_spec.rb11
-rw-r--r--spec/ruby/library/matrix/normal_spec.rb41
-rw-r--r--spec/ruby/library/matrix/orthogonal_spec.rb41
-rw-r--r--spec/ruby/library/matrix/permutation_spec.rb51
-rw-r--r--spec/ruby/library/matrix/plus_spec.rb65
-rw-r--r--spec/ruby/library/matrix/rank_spec.rb29
-rw-r--r--spec/ruby/library/matrix/real_spec.rb63
-rw-r--r--spec/ruby/library/matrix/rect_spec.rb9
-rw-r--r--spec/ruby/library/matrix/rectangular_spec.rb9
-rw-r--r--spec/ruby/library/matrix/regular_spec.rb45
-rw-r--r--spec/ruby/library/matrix/round_spec.rb31
-rw-r--r--spec/ruby/library/matrix/row_size_spec.rb19
-rw-r--r--spec/ruby/library/matrix/row_spec.rb55
-rw-r--r--spec/ruby/library/matrix/row_vector_spec.rb33
-rw-r--r--spec/ruby/library/matrix/row_vectors_spec.rb37
-rw-r--r--spec/ruby/library/matrix/rows_spec.rb65
-rw-r--r--spec/ruby/library/matrix/scalar/Fail_spec.rb9
-rw-r--r--spec/ruby/library/matrix/scalar/Raise_spec.rb9
-rw-r--r--spec/ruby/library/matrix/scalar/divide_spec.rb9
-rw-r--r--spec/ruby/library/matrix/scalar/exponent_spec.rb9
-rw-r--r--spec/ruby/library/matrix/scalar/included_spec.rb9
-rw-r--r--spec/ruby/library/matrix/scalar/initialize_spec.rb9
-rw-r--r--spec/ruby/library/matrix/scalar/minus_spec.rb9
-rw-r--r--spec/ruby/library/matrix/scalar/multiply_spec.rb9
-rw-r--r--spec/ruby/library/matrix/scalar/plus_spec.rb9
-rw-r--r--spec/ruby/library/matrix/scalar_spec.rb93
-rw-r--r--spec/ruby/library/matrix/singular_spec.rb47
-rw-r--r--spec/ruby/library/matrix/square_spec.rb41
-rw-r--r--spec/ruby/library/matrix/symmetric_spec.rb45
-rw-r--r--spec/ruby/library/matrix/t_spec.rb9
-rw-r--r--spec/ruby/library/matrix/to_a_spec.rb17
-rw-r--r--spec/ruby/library/matrix/to_s_spec.rb9
-rw-r--r--spec/ruby/library/matrix/tr_spec.rb11
-rw-r--r--spec/ruby/library/matrix/trace_spec.rb11
-rw-r--r--spec/ruby/library/matrix/transpose_spec.rb9
-rw-r--r--spec/ruby/library/matrix/unit_spec.rb9
-rw-r--r--spec/ruby/library/matrix/unitary_spec.rb48
-rw-r--r--spec/ruby/library/matrix/upper_triangular_spec.rb39
-rw-r--r--spec/ruby/library/matrix/vector/cross_product_spec.rb21
-rw-r--r--spec/ruby/library/matrix/vector/each2_spec.rb81
-rw-r--r--spec/ruby/library/matrix/vector/eql_spec.rb23
-rw-r--r--spec/ruby/library/matrix/vector/inner_product_spec.rb33
-rw-r--r--spec/ruby/library/matrix/vector/normalize_spec.rb29
-rw-r--r--spec/ruby/library/matrix/zero_spec.rb75
-rw-r--r--spec/ruby/library/net-ftp/FTPError_spec.rb8
-rw-r--r--spec/ruby/library/net-ftp/FTPPermError_spec.rb12
-rw-r--r--spec/ruby/library/net-ftp/FTPProtoError_spec.rb12
-rw-r--r--spec/ruby/library/net-ftp/FTPReplyError_spec.rb12
-rw-r--r--spec/ruby/library/net-ftp/FTPTempError_spec.rb12
-rw-r--r--spec/ruby/library/net-ftp/abort_spec.rb62
-rw-r--r--spec/ruby/library/net-ftp/acct_spec.rb58
-rw-r--r--spec/ruby/library/net-ftp/binary_spec.rb24
-rw-r--r--spec/ruby/library/net-ftp/chdir_spec.rb99
-rw-r--r--spec/ruby/library/net-ftp/close_spec.rb30
-rw-r--r--spec/ruby/library/net-ftp/closed_spec.rb21
-rw-r--r--spec/ruby/library/net-ftp/connect_spec.rb51
-rw-r--r--spec/ruby/library/net-ftp/debug_mode_spec.rb23
-rw-r--r--spec/ruby/library/net-ftp/default_passive_spec.rb8
-rw-r--r--spec/ruby/library/net-ftp/delete_spec.rb59
-rw-r--r--spec/ruby/library/net-ftp/dir_spec.rb8
-rw-r--r--spec/ruby/library/net-ftp/fixtures/default_passive.rb (renamed from spec/ruby/library/net/ftp/fixtures/default_passive.rb)0
-rw-r--r--spec/ruby/library/net-ftp/fixtures/passive.rb (renamed from spec/ruby/library/net/ftp/fixtures/passive.rb)0
-rw-r--r--spec/ruby/library/net-ftp/fixtures/putbinaryfile (renamed from spec/ruby/library/net/ftp/fixtures/putbinaryfile)0
-rw-r--r--spec/ruby/library/net-ftp/fixtures/puttextfile (renamed from spec/ruby/library/net/ftp/fixtures/puttextfile)0
-rw-r--r--spec/ruby/library/net-ftp/fixtures/server.rb (renamed from spec/ruby/library/net/ftp/fixtures/server.rb)0
-rw-r--r--spec/ruby/library/net-ftp/get_spec.rb21
-rw-r--r--spec/ruby/library/net-ftp/getbinaryfile_spec.rb8
-rw-r--r--spec/ruby/library/net-ftp/getdir_spec.rb7
-rw-r--r--spec/ruby/library/net-ftp/gettextfile_spec.rb8
-rw-r--r--spec/ruby/library/net-ftp/help_spec.rb66
-rw-r--r--spec/ruby/library/net-ftp/initialize_spec.rb405
-rw-r--r--spec/ruby/library/net-ftp/last_response_code_spec.rb8
-rw-r--r--spec/ruby/library/net-ftp/last_response_spec.rb25
-rw-r--r--spec/ruby/library/net-ftp/lastresp_spec.rb8
-rw-r--r--spec/ruby/library/net-ftp/list_spec.rb8
-rw-r--r--spec/ruby/library/net-ftp/login_spec.rb195
-rw-r--r--spec/ruby/library/net-ftp/ls_spec.rb8
-rw-r--r--spec/ruby/library/net-ftp/mdtm_spec.rb38
-rw-r--r--spec/ruby/library/net-ftp/mkdir_spec.rb61
-rw-r--r--spec/ruby/library/net-ftp/mtime_spec.rb50
-rw-r--r--spec/ruby/library/net-ftp/nlst_spec.rb92
-rw-r--r--spec/ruby/library/net-ftp/noop_spec.rb38
-rw-r--r--spec/ruby/library/net-ftp/open_spec.rb55
-rw-r--r--spec/ruby/library/net-ftp/passive_spec.rb28
-rw-r--r--spec/ruby/library/net-ftp/put_spec.rb21
-rw-r--r--spec/ruby/library/net-ftp/putbinaryfile_spec.rb8
-rw-r--r--spec/ruby/library/net-ftp/puttextfile_spec.rb8
-rw-r--r--spec/ruby/library/net-ftp/pwd_spec.rb53
-rw-r--r--spec/ruby/library/net-ftp/quit_spec.rb33
-rw-r--r--spec/ruby/library/net-ftp/rename_spec.rb94
-rw-r--r--spec/ruby/library/net-ftp/resume_spec.rb23
-rw-r--r--spec/ruby/library/net-ftp/retrbinary_spec.rb30
-rw-r--r--spec/ruby/library/net-ftp/retrlines_spec.rb34
-rw-r--r--spec/ruby/library/net-ftp/return_code_spec.rb24
-rw-r--r--spec/ruby/library/net-ftp/rmdir_spec.rb58
-rw-r--r--spec/ruby/library/net-ftp/sendcmd_spec.rb54
-rw-r--r--spec/ruby/library/net-ftp/set_socket_spec.rb8
-rw-r--r--spec/ruby/library/net-ftp/shared/getbinaryfile.rb (renamed from spec/ruby/library/net/ftp/shared/getbinaryfile.rb)0
-rw-r--r--spec/ruby/library/net-ftp/shared/gettextfile.rb (renamed from spec/ruby/library/net/ftp/shared/gettextfile.rb)0
-rw-r--r--spec/ruby/library/net-ftp/shared/last_response_code.rb (renamed from spec/ruby/library/net/ftp/shared/last_response_code.rb)0
-rw-r--r--spec/ruby/library/net-ftp/shared/list.rb (renamed from spec/ruby/library/net/ftp/shared/list.rb)0
-rw-r--r--spec/ruby/library/net-ftp/shared/putbinaryfile.rb (renamed from spec/ruby/library/net/ftp/shared/putbinaryfile.rb)0
-rw-r--r--spec/ruby/library/net-ftp/shared/puttextfile.rb120
-rw-r--r--spec/ruby/library/net-ftp/shared/pwd.rb (renamed from spec/ruby/library/net/ftp/shared/pwd.rb)0
-rw-r--r--spec/ruby/library/net-ftp/site_spec.rb53
-rw-r--r--spec/ruby/library/net-ftp/size_spec.rb48
-rw-r--r--spec/ruby/library/net-ftp/spec_helper.rb (renamed from spec/ruby/library/net/ftp/spec_helper.rb)0
-rw-r--r--spec/ruby/library/net-ftp/status_spec.rb67
-rw-r--r--spec/ruby/library/net-ftp/storbinary_spec.rb49
-rw-r--r--spec/ruby/library/net-ftp/storlines_spec.rb44
-rw-r--r--spec/ruby/library/net-ftp/system_spec.rb48
-rw-r--r--spec/ruby/library/net-ftp/voidcmd_spec.rb54
-rw-r--r--spec/ruby/library/net-ftp/welcome_spec.rb25
-rw-r--r--spec/ruby/library/net-http/HTTPBadResponse_spec.rb8
-rw-r--r--spec/ruby/library/net-http/HTTPClientExcepton_spec.rb12
-rw-r--r--spec/ruby/library/net-http/HTTPError_spec.rb12
-rw-r--r--spec/ruby/library/net-http/HTTPFatalError_spec.rb12
-rw-r--r--spec/ruby/library/net-http/HTTPHeaderSyntaxError_spec.rb8
-rw-r--r--spec/ruby/library/net-http/HTTPRetriableError_spec.rb12
-rw-r--r--spec/ruby/library/net-http/HTTPServerException_spec.rb12
-rw-r--r--spec/ruby/library/net-http/http/Proxy_spec.rb35
-rw-r--r--spec/ruby/library/net-http/http/active_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/address_spec.rb9
-rw-r--r--spec/ruby/library/net-http/http/close_on_empty_response_spec.rb10
-rw-r--r--spec/ruby/library/net-http/http/copy_spec.rb21
-rw-r--r--spec/ruby/library/net-http/http/default_port_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/delete_spec.rb21
-rw-r--r--spec/ruby/library/net-http/http/finish_spec.rb29
-rw-r--r--spec/ruby/library/net-http/http/fixtures/http_server.rb (renamed from spec/ruby/library/net/http/http/fixtures/http_server.rb)0
-rw-r--r--spec/ruby/library/net-http/http/get2_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/get_print_spec.rb30
-rw-r--r--spec/ruby/library/net-http/http/get_response_spec.rb30
-rw-r--r--spec/ruby/library/net-http/http/get_spec.rb94
-rw-r--r--spec/ruby/library/net-http/http/head2_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/head_spec.rb25
-rw-r--r--spec/ruby/library/net-http/http/http_default_port_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/https_default_port_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/initialize_spec.rb46
-rw-r--r--spec/ruby/library/net-http/http/inspect_spec.rb24
-rw-r--r--spec/ruby/library/net-http/http/is_version_1_1_spec.rb7
-rw-r--r--spec/ruby/library/net-http/http/is_version_1_2_spec.rb7
-rw-r--r--spec/ruby/library/net-http/http/lock_spec.rb21
-rw-r--r--spec/ruby/library/net-http/http/mkcol_spec.rb21
-rw-r--r--spec/ruby/library/net-http/http/move_spec.rb25
-rw-r--r--spec/ruby/library/net-http/http/new_spec.rb86
-rw-r--r--spec/ruby/library/net-http/http/newobj_spec.rb48
-rw-r--r--spec/ruby/library/net-http/http/open_timeout_spec.rb24
-rw-r--r--spec/ruby/library/net-http/http/options_spec.rb25
-rw-r--r--spec/ruby/library/net-http/http/port_spec.rb9
-rw-r--r--spec/ruby/library/net-http/http/post2_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/post_form_spec.rb22
-rw-r--r--spec/ruby/library/net-http/http/post_spec.rb74
-rw-r--r--spec/ruby/library/net-http/http/propfind_spec.rb24
-rw-r--r--spec/ruby/library/net-http/http/proppatch_spec.rb24
-rw-r--r--spec/ruby/library/net-http/http/proxy_address_spec.rb31
-rw-r--r--spec/ruby/library/net-http/http/proxy_class_spec.rb9
-rw-r--r--spec/ruby/library/net-http/http/proxy_pass_spec.rb39
-rw-r--r--spec/ruby/library/net-http/http/proxy_port_spec.rb39
-rw-r--r--spec/ruby/library/net-http/http/proxy_user_spec.rb39
-rw-r--r--spec/ruby/library/net-http/http/put2_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/put_spec.rb24
-rw-r--r--spec/ruby/library/net-http/http/read_timeout_spec.rb24
-rw-r--r--spec/ruby/library/net-http/http/request_get_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/request_head_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/request_post_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/request_put_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/request_spec.rb109
-rw-r--r--spec/ruby/library/net-http/http/request_types_spec.rb254
-rw-r--r--spec/ruby/library/net-http/http/send_request_spec.rb61
-rw-r--r--spec/ruby/library/net-http/http/set_debug_output_spec.rb33
-rw-r--r--spec/ruby/library/net-http/http/shared/request_get.rb (renamed from spec/ruby/library/net/http/http/shared/request_get.rb)0
-rw-r--r--spec/ruby/library/net-http/http/shared/request_head.rb (renamed from spec/ruby/library/net/http/http/shared/request_head.rb)0
-rw-r--r--spec/ruby/library/net-http/http/shared/request_post.rb (renamed from spec/ruby/library/net/http/http/shared/request_post.rb)0
-rw-r--r--spec/ruby/library/net-http/http/shared/request_put.rb (renamed from spec/ruby/library/net/http/http/shared/request_put.rb)0
-rw-r--r--spec/ruby/library/net-http/http/shared/started.rb (renamed from spec/ruby/library/net/http/http/shared/started.rb)0
-rw-r--r--spec/ruby/library/net-http/http/shared/version_1_1.rb (renamed from spec/ruby/library/net/http/http/shared/version_1_1.rb)0
-rw-r--r--spec/ruby/library/net-http/http/shared/version_1_2.rb (renamed from spec/ruby/library/net/http/http/shared/version_1_2.rb)0
-rw-r--r--spec/ruby/library/net-http/http/socket_type_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/start_spec.rb111
-rw-r--r--spec/ruby/library/net-http/http/started_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/trace_spec.rb24
-rw-r--r--spec/ruby/library/net-http/http/unlock_spec.rb24
-rw-r--r--spec/ruby/library/net-http/http/use_ssl_spec.rb9
-rw-r--r--spec/ruby/library/net-http/http/version_1_1_spec.rb7
-rw-r--r--spec/ruby/library/net-http/http/version_1_2_spec.rb20
-rw-r--r--spec/ruby/library/net-http/httpexceptions/fixtures/classes.rb (renamed from spec/ruby/library/net/http/httpexceptions/fixtures/classes.rb)0
-rw-r--r--spec/ruby/library/net-http/httpexceptions/initialize_spec.rb17
-rw-r--r--spec/ruby/library/net-http/httpexceptions/response_spec.rb10
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/body_exist_spec.rb21
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/body_spec.rb30
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/body_stream_spec.rb32
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/exec_spec.rb131
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/inspect_spec.rb25
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/method_spec.rb15
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/path_spec.rb12
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/request_body_permitted_spec.rb12
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/response_body_permitted_spec.rb12
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/set_body_internal_spec.rb21
-rw-r--r--spec/ruby/library/net-http/httpheader/add_field_spec.rb31
-rw-r--r--spec/ruby/library/net-http/httpheader/basic_auth_spec.rb14
-rw-r--r--spec/ruby/library/net-http/httpheader/canonical_each_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/chunked_spec.rb22
-rw-r--r--spec/ruby/library/net-http/httpheader/content_length_spec.rb54
-rw-r--r--spec/ruby/library/net-http/httpheader/content_range_spec.rb32
-rw-r--r--spec/ruby/library/net-http/httpheader/content_type_spec.rb26
-rw-r--r--spec/ruby/library/net-http/httpheader/delete_spec.rb30
-rw-r--r--spec/ruby/library/net-http/httpheader/each_capitalized_name_spec.rb35
-rw-r--r--spec/ruby/library/net-http/httpheader/each_capitalized_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/each_header_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/each_key_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/each_name_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/each_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/each_value_spec.rb35
-rw-r--r--spec/ruby/library/net-http/httpheader/element_reference_spec.rb39
-rw-r--r--spec/ruby/library/net-http/httpheader/element_set_spec.rb41
-rw-r--r--spec/ruby/library/net-http/httpheader/fetch_spec.rb68
-rw-r--r--spec/ruby/library/net-http/httpheader/fixtures/classes.rb (renamed from spec/ruby/library/net/http/httpheader/fixtures/classes.rb)0
-rw-r--r--spec/ruby/library/net-http/httpheader/form_data_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/get_fields_spec.rb39
-rw-r--r--spec/ruby/library/net-http/httpheader/initialize_http_header_spec.rb21
-rw-r--r--spec/ruby/library/net-http/httpheader/key_spec.rb21
-rw-r--r--spec/ruby/library/net-http/httpheader/length_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/main_type_spec.rb24
-rw-r--r--spec/ruby/library/net-http/httpheader/proxy_basic_auth_spec.rb14
-rw-r--r--spec/ruby/library/net-http/httpheader/range_length_spec.rb32
-rw-r--r--spec/ruby/library/net-http/httpheader/range_spec.rb48
-rw-r--r--spec/ruby/library/net-http/httpheader/set_content_type_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/set_form_data_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/set_range_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/shared/each_capitalized.rb (renamed from spec/ruby/library/net/http/httpheader/shared/each_capitalized.rb)0
-rw-r--r--spec/ruby/library/net-http/httpheader/shared/each_header.rb (renamed from spec/ruby/library/net/http/httpheader/shared/each_header.rb)0
-rw-r--r--spec/ruby/library/net-http/httpheader/shared/each_name.rb (renamed from spec/ruby/library/net/http/httpheader/shared/each_name.rb)0
-rw-r--r--spec/ruby/library/net-http/httpheader/shared/set_content_type.rb (renamed from spec/ruby/library/net/http/httpheader/shared/set_content_type.rb)0
-rw-r--r--spec/ruby/library/net-http/httpheader/shared/set_form_data.rb (renamed from spec/ruby/library/net/http/httpheader/shared/set_form_data.rb)0
-rw-r--r--spec/ruby/library/net-http/httpheader/shared/set_range.rb (renamed from spec/ruby/library/net/http/httpheader/shared/set_range.rb)0
-rw-r--r--spec/ruby/library/net-http/httpheader/shared/size.rb (renamed from spec/ruby/library/net/http/httpheader/shared/size.rb)0
-rw-r--r--spec/ruby/library/net-http/httpheader/size_spec.rb8
-rw-r--r--spec/ruby/library/net-http/httpheader/sub_type_spec.rb32
-rw-r--r--spec/ruby/library/net-http/httpheader/to_hash_spec.rb25
-rw-r--r--spec/ruby/library/net-http/httpheader/type_params_spec.rb24
-rw-r--r--spec/ruby/library/net-http/httprequest/initialize_spec.rb45
-rw-r--r--spec/ruby/library/net-http/httpresponse/body_permitted_spec.rb13
-rw-r--r--spec/ruby/library/net-http/httpresponse/body_spec.rb7
-rw-r--r--spec/ruby/library/net-http/httpresponse/code_spec.rb24
-rw-r--r--spec/ruby/library/net-http/httpresponse/code_type_spec.rb24
-rw-r--r--spec/ruby/library/net-http/httpresponse/entity_spec.rb7
-rw-r--r--spec/ruby/library/net-http/httpresponse/error_spec.rb24
-rw-r--r--spec/ruby/library/net-http/httpresponse/error_type_spec.rb24
-rw-r--r--spec/ruby/library/net-http/httpresponse/exception_type_spec.rb13
-rw-r--r--spec/ruby/library/net-http/httpresponse/header_spec.rb9
-rw-r--r--spec/ruby/library/net-http/httpresponse/http_version_spec.rb12
-rw-r--r--spec/ruby/library/net-http/httpresponse/initialize_spec.rb11
-rw-r--r--spec/ruby/library/net-http/httpresponse/inspect_spec.rb15
-rw-r--r--spec/ruby/library/net-http/httpresponse/message_spec.rb9
-rw-r--r--spec/ruby/library/net-http/httpresponse/msg_spec.rb9
-rw-r--r--spec/ruby/library/net-http/httpresponse/read_body_spec.rb86
-rw-r--r--spec/ruby/library/net-http/httpresponse/read_header_spec.rb9
-rw-r--r--spec/ruby/library/net-http/httpresponse/read_new_spec.rb23
-rw-r--r--spec/ruby/library/net-http/httpresponse/reading_body_spec.rb58
-rw-r--r--spec/ruby/library/net-http/httpresponse/response_spec.rb9
-rw-r--r--spec/ruby/library/net-http/httpresponse/shared/body.rb (renamed from spec/ruby/library/net/http/httpresponse/shared/body.rb)0
-rw-r--r--spec/ruby/library/net-http/httpresponse/value_spec.rb24
-rw-r--r--spec/ruby/library/net/FTPError_spec.rb11
-rw-r--r--spec/ruby/library/net/FTPPermError_spec.rb15
-rw-r--r--spec/ruby/library/net/FTPProtoError_spec.rb15
-rw-r--r--spec/ruby/library/net/FTPReplyError_spec.rb15
-rw-r--r--spec/ruby/library/net/FTPTempError_spec.rb15
-rw-r--r--spec/ruby/library/net/ftp/abort_spec.rb65
-rw-r--r--spec/ruby/library/net/ftp/acct_spec.rb61
-rw-r--r--spec/ruby/library/net/ftp/binary_spec.rb27
-rw-r--r--spec/ruby/library/net/ftp/chdir_spec.rb102
-rw-r--r--spec/ruby/library/net/ftp/close_spec.rb33
-rw-r--r--spec/ruby/library/net/ftp/closed_spec.rb24
-rw-r--r--spec/ruby/library/net/ftp/connect_spec.rb52
-rw-r--r--spec/ruby/library/net/ftp/debug_mode_spec.rb26
-rw-r--r--spec/ruby/library/net/ftp/default_passive_spec.rb11
-rw-r--r--spec/ruby/library/net/ftp/delete_spec.rb62
-rw-r--r--spec/ruby/library/net/ftp/dir_spec.rb11
-rw-r--r--spec/ruby/library/net/ftp/get_spec.rb24
-rw-r--r--spec/ruby/library/net/ftp/getbinaryfile_spec.rb11
-rw-r--r--spec/ruby/library/net/ftp/getdir_spec.rb10
-rw-r--r--spec/ruby/library/net/ftp/gettextfile_spec.rb11
-rw-r--r--spec/ruby/library/net/ftp/help_spec.rb69
-rw-r--r--spec/ruby/library/net/ftp/initialize_spec.rb408
-rw-r--r--spec/ruby/library/net/ftp/last_response_code_spec.rb11
-rw-r--r--spec/ruby/library/net/ftp/last_response_spec.rb28
-rw-r--r--spec/ruby/library/net/ftp/lastresp_spec.rb11
-rw-r--r--spec/ruby/library/net/ftp/list_spec.rb11
-rw-r--r--spec/ruby/library/net/ftp/login_spec.rb198
-rw-r--r--spec/ruby/library/net/ftp/ls_spec.rb11
-rw-r--r--spec/ruby/library/net/ftp/mdtm_spec.rb41
-rw-r--r--spec/ruby/library/net/ftp/mkdir_spec.rb64
-rw-r--r--spec/ruby/library/net/ftp/mtime_spec.rb53
-rw-r--r--spec/ruby/library/net/ftp/nlst_spec.rb95
-rw-r--r--spec/ruby/library/net/ftp/noop_spec.rb41
-rw-r--r--spec/ruby/library/net/ftp/open_spec.rb58
-rw-r--r--spec/ruby/library/net/ftp/passive_spec.rb31
-rw-r--r--spec/ruby/library/net/ftp/put_spec.rb24
-rw-r--r--spec/ruby/library/net/ftp/putbinaryfile_spec.rb11
-rw-r--r--spec/ruby/library/net/ftp/puttextfile_spec.rb11
-rw-r--r--spec/ruby/library/net/ftp/pwd_spec.rb56
-rw-r--r--spec/ruby/library/net/ftp/quit_spec.rb36
-rw-r--r--spec/ruby/library/net/ftp/rename_spec.rb97
-rw-r--r--spec/ruby/library/net/ftp/resume_spec.rb26
-rw-r--r--spec/ruby/library/net/ftp/retrbinary_spec.rb33
-rw-r--r--spec/ruby/library/net/ftp/retrlines_spec.rb37
-rw-r--r--spec/ruby/library/net/ftp/return_code_spec.rb27
-rw-r--r--spec/ruby/library/net/ftp/rmdir_spec.rb61
-rw-r--r--spec/ruby/library/net/ftp/sendcmd_spec.rb57
-rw-r--r--spec/ruby/library/net/ftp/set_socket_spec.rb11
-rw-r--r--spec/ruby/library/net/ftp/shared/puttextfile.rb120
-rw-r--r--spec/ruby/library/net/ftp/site_spec.rb56
-rw-r--r--spec/ruby/library/net/ftp/size_spec.rb51
-rw-r--r--spec/ruby/library/net/ftp/status_spec.rb70
-rw-r--r--spec/ruby/library/net/ftp/storbinary_spec.rb51
-rw-r--r--spec/ruby/library/net/ftp/storlines_spec.rb46
-rw-r--r--spec/ruby/library/net/ftp/system_spec.rb51
-rw-r--r--spec/ruby/library/net/ftp/voidcmd_spec.rb57
-rw-r--r--spec/ruby/library/net/ftp/welcome_spec.rb28
-rw-r--r--spec/ruby/library/net/http/HTTPBadResponse_spec.rb8
-rw-r--r--spec/ruby/library/net/http/HTTPClientExcepton_spec.rb12
-rw-r--r--spec/ruby/library/net/http/HTTPError_spec.rb12
-rw-r--r--spec/ruby/library/net/http/HTTPFatalError_spec.rb12
-rw-r--r--spec/ruby/library/net/http/HTTPHeaderSyntaxError_spec.rb8
-rw-r--r--spec/ruby/library/net/http/HTTPRetriableError_spec.rb12
-rw-r--r--spec/ruby/library/net/http/HTTPServerException_spec.rb12
-rw-r--r--spec/ruby/library/net/http/http/Proxy_spec.rb35
-rw-r--r--spec/ruby/library/net/http/http/active_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/address_spec.rb9
-rw-r--r--spec/ruby/library/net/http/http/close_on_empty_response_spec.rb10
-rw-r--r--spec/ruby/library/net/http/http/copy_spec.rb21
-rw-r--r--spec/ruby/library/net/http/http/default_port_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/delete_spec.rb21
-rw-r--r--spec/ruby/library/net/http/http/finish_spec.rb29
-rw-r--r--spec/ruby/library/net/http/http/get2_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/get_print_spec.rb30
-rw-r--r--spec/ruby/library/net/http/http/get_response_spec.rb30
-rw-r--r--spec/ruby/library/net/http/http/get_spec.rb94
-rw-r--r--spec/ruby/library/net/http/http/head2_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/head_spec.rb25
-rw-r--r--spec/ruby/library/net/http/http/http_default_port_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/https_default_port_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/initialize_spec.rb46
-rw-r--r--spec/ruby/library/net/http/http/inspect_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/is_version_1_1_spec.rb7
-rw-r--r--spec/ruby/library/net/http/http/is_version_1_2_spec.rb7
-rw-r--r--spec/ruby/library/net/http/http/lock_spec.rb21
-rw-r--r--spec/ruby/library/net/http/http/mkcol_spec.rb21
-rw-r--r--spec/ruby/library/net/http/http/move_spec.rb25
-rw-r--r--spec/ruby/library/net/http/http/new_spec.rb86
-rw-r--r--spec/ruby/library/net/http/http/newobj_spec.rb48
-rw-r--r--spec/ruby/library/net/http/http/open_timeout_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/options_spec.rb25
-rw-r--r--spec/ruby/library/net/http/http/port_spec.rb9
-rw-r--r--spec/ruby/library/net/http/http/post2_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/post_form_spec.rb22
-rw-r--r--spec/ruby/library/net/http/http/post_spec.rb74
-rw-r--r--spec/ruby/library/net/http/http/propfind_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/proppatch_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/proxy_address_spec.rb31
-rw-r--r--spec/ruby/library/net/http/http/proxy_class_spec.rb9
-rw-r--r--spec/ruby/library/net/http/http/proxy_pass_spec.rb39
-rw-r--r--spec/ruby/library/net/http/http/proxy_port_spec.rb39
-rw-r--r--spec/ruby/library/net/http/http/proxy_user_spec.rb39
-rw-r--r--spec/ruby/library/net/http/http/put2_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/put_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/read_timeout_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/request_get_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/request_head_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/request_post_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/request_put_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/request_spec.rb109
-rw-r--r--spec/ruby/library/net/http/http/request_types_spec.rb254
-rw-r--r--spec/ruby/library/net/http/http/send_request_spec.rb61
-rw-r--r--spec/ruby/library/net/http/http/set_debug_output_spec.rb33
-rw-r--r--spec/ruby/library/net/http/http/socket_type_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/start_spec.rb111
-rw-r--r--spec/ruby/library/net/http/http/started_spec.rb8
-rw-r--r--spec/ruby/library/net/http/http/trace_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/unlock_spec.rb24
-rw-r--r--spec/ruby/library/net/http/http/use_ssl_spec.rb9
-rw-r--r--spec/ruby/library/net/http/http/version_1_1_spec.rb7
-rw-r--r--spec/ruby/library/net/http/http/version_1_2_spec.rb20
-rw-r--r--spec/ruby/library/net/http/httpexceptions/initialize_spec.rb17
-rw-r--r--spec/ruby/library/net/http/httpexceptions/response_spec.rb10
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/body_exist_spec.rb21
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/body_spec.rb30
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/body_stream_spec.rb32
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/exec_spec.rb131
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/inspect_spec.rb25
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/method_spec.rb15
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/path_spec.rb12
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/request_body_permitted_spec.rb12
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/response_body_permitted_spec.rb12
-rw-r--r--spec/ruby/library/net/http/httpgenericrequest/set_body_internal_spec.rb21
-rw-r--r--spec/ruby/library/net/http/httpheader/add_field_spec.rb31
-rw-r--r--spec/ruby/library/net/http/httpheader/basic_auth_spec.rb14
-rw-r--r--spec/ruby/library/net/http/httpheader/canonical_each_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/chunked_spec.rb22
-rw-r--r--spec/ruby/library/net/http/httpheader/content_length_spec.rb54
-rw-r--r--spec/ruby/library/net/http/httpheader/content_range_spec.rb32
-rw-r--r--spec/ruby/library/net/http/httpheader/content_type_spec.rb26
-rw-r--r--spec/ruby/library/net/http/httpheader/delete_spec.rb30
-rw-r--r--spec/ruby/library/net/http/httpheader/each_capitalized_name_spec.rb35
-rw-r--r--spec/ruby/library/net/http/httpheader/each_capitalized_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/each_header_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/each_key_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/each_name_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/each_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/each_value_spec.rb35
-rw-r--r--spec/ruby/library/net/http/httpheader/element_reference_spec.rb39
-rw-r--r--spec/ruby/library/net/http/httpheader/element_set_spec.rb41
-rw-r--r--spec/ruby/library/net/http/httpheader/fetch_spec.rb68
-rw-r--r--spec/ruby/library/net/http/httpheader/form_data_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/get_fields_spec.rb39
-rw-r--r--spec/ruby/library/net/http/httpheader/initialize_http_header_spec.rb21
-rw-r--r--spec/ruby/library/net/http/httpheader/key_spec.rb21
-rw-r--r--spec/ruby/library/net/http/httpheader/length_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/main_type_spec.rb24
-rw-r--r--spec/ruby/library/net/http/httpheader/proxy_basic_auth_spec.rb14
-rw-r--r--spec/ruby/library/net/http/httpheader/range_length_spec.rb32
-rw-r--r--spec/ruby/library/net/http/httpheader/range_spec.rb48
-rw-r--r--spec/ruby/library/net/http/httpheader/set_content_type_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/set_form_data_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/set_range_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/size_spec.rb8
-rw-r--r--spec/ruby/library/net/http/httpheader/sub_type_spec.rb32
-rw-r--r--spec/ruby/library/net/http/httpheader/to_hash_spec.rb25
-rw-r--r--spec/ruby/library/net/http/httpheader/type_params_spec.rb24
-rw-r--r--spec/ruby/library/net/http/httprequest/initialize_spec.rb45
-rw-r--r--spec/ruby/library/net/http/httpresponse/body_permitted_spec.rb13
-rw-r--r--spec/ruby/library/net/http/httpresponse/body_spec.rb7
-rw-r--r--spec/ruby/library/net/http/httpresponse/code_spec.rb24
-rw-r--r--spec/ruby/library/net/http/httpresponse/code_type_spec.rb24
-rw-r--r--spec/ruby/library/net/http/httpresponse/entity_spec.rb7
-rw-r--r--spec/ruby/library/net/http/httpresponse/error_spec.rb24
-rw-r--r--spec/ruby/library/net/http/httpresponse/error_type_spec.rb24
-rw-r--r--spec/ruby/library/net/http/httpresponse/exception_type_spec.rb13
-rw-r--r--spec/ruby/library/net/http/httpresponse/header_spec.rb9
-rw-r--r--spec/ruby/library/net/http/httpresponse/http_version_spec.rb12
-rw-r--r--spec/ruby/library/net/http/httpresponse/initialize_spec.rb11
-rw-r--r--spec/ruby/library/net/http/httpresponse/inspect_spec.rb15
-rw-r--r--spec/ruby/library/net/http/httpresponse/message_spec.rb9
-rw-r--r--spec/ruby/library/net/http/httpresponse/msg_spec.rb9
-rw-r--r--spec/ruby/library/net/http/httpresponse/read_body_spec.rb86
-rw-r--r--spec/ruby/library/net/http/httpresponse/read_header_spec.rb9
-rw-r--r--spec/ruby/library/net/http/httpresponse/read_new_spec.rb23
-rw-r--r--spec/ruby/library/net/http/httpresponse/reading_body_spec.rb58
-rw-r--r--spec/ruby/library/net/http/httpresponse/response_spec.rb9
-rw-r--r--spec/ruby/library/net/http/httpresponse/value_spec.rb24
-rw-r--r--spec/ruby/library/objectspace/fixtures/trace.rb1
-rw-r--r--spec/ruby/library/objectspace/reachable_objects_from_spec.rb2
-rw-r--r--spec/ruby/library/objectspace/trace_spec.rb4
-rw-r--r--spec/ruby/library/openssl/fixed_length_secure_compare_spec.rb42
-rw-r--r--spec/ruby/library/openssl/kdf/pbkdf2_hmac_spec.rb17
-rw-r--r--spec/ruby/library/openssl/secure_compare_spec.rb38
-rw-r--r--spec/ruby/library/openssl/x509/name/verify_spec.rb78
-rw-r--r--spec/ruby/library/openssl/x509/store/verify_spec.rb78
-rw-r--r--spec/ruby/library/prime/each_spec.rb247
-rw-r--r--spec/ruby/library/prime/instance_spec.rb31
-rw-r--r--spec/ruby/library/prime/int_from_prime_division_spec.rb19
-rw-r--r--spec/ruby/library/prime/integer/each_prime_spec.rb19
-rw-r--r--spec/ruby/library/prime/integer/from_prime_division_spec.rb19
-rw-r--r--spec/ruby/library/prime/integer/prime_division_spec.rb31
-rw-r--r--spec/ruby/library/prime/integer/prime_spec.rb27
-rw-r--r--spec/ruby/library/prime/next_spec.rb11
-rw-r--r--spec/ruby/library/prime/prime_division_spec.rb37
-rw-r--r--spec/ruby/library/prime/prime_spec.rb27
-rw-r--r--spec/ruby/library/prime/succ_spec.rb11
-rw-r--r--spec/ruby/library/set/compare_by_identity_spec.rb2
-rw-r--r--spec/ruby/library/set/flatten_spec.rb9
-rw-r--r--spec/ruby/library/set/proper_subset_spec.rb9
-rw-r--r--spec/ruby/library/set/set_spec.rb12
-rw-r--r--spec/ruby/library/set/subset_spec.rb9
-rw-r--r--spec/ruby/library/shellwords/shellwords_spec.rb15
-rw-r--r--spec/ruby/library/socket/basicsocket/read_nonblock_spec.rb32
-rw-r--r--spec/ruby/library/socket/basicsocket/read_spec.rb47
-rw-r--r--spec/ruby/library/socket/basicsocket/recv_nonblock_spec.rb16
-rw-r--r--spec/ruby/library/socket/basicsocket/recv_spec.rb22
-rw-r--r--spec/ruby/library/socket/basicsocket/send_spec.rb4
-rw-r--r--spec/ruby/library/socket/shared/pack_sockaddr.rb3
-rw-r--r--spec/ruby/library/socket/socket/getnameinfo_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/pack_sockaddr_in_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/pair_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/recvfrom_nonblock_spec.rb21
-rw-r--r--spec/ruby/library/socket/socket/socketpair_spec.rb2
-rw-r--r--spec/ruby/library/socket/tcpserver/accept_spec.rb15
-rw-r--r--spec/ruby/library/socket/tcpsocket/initialize_spec.rb13
-rw-r--r--spec/ruby/library/socket/udpsocket/initialize_spec.rb13
-rw-r--r--spec/ruby/library/socket/udpsocket/recvfrom_nonblock_spec.rb9
-rw-r--r--spec/ruby/library/socket/udpsocket/send_spec.rb2
-rw-r--r--spec/ruby/library/socket/unixserver/accept_spec.rb11
-rw-r--r--spec/ruby/library/socket/unixserver/for_fd_spec.rb2
-rw-r--r--spec/ruby/library/socket/unixsocket/initialize_spec.rb10
-rw-r--r--spec/ruby/library/socket/unixsocket/pair_spec.rb2
-rw-r--r--spec/ruby/library/socket/unixsocket/recvfrom_spec.rb23
-rw-r--r--spec/ruby/library/stringio/append_spec.rb8
-rw-r--r--spec/ruby/library/stringio/binmode_spec.rb2
-rw-r--r--spec/ruby/library/stringio/close_read_spec.rb4
-rw-r--r--spec/ruby/library/stringio/close_write_spec.rb6
-rw-r--r--spec/ruby/library/stringio/closed_read_spec.rb2
-rw-r--r--spec/ruby/library/stringio/closed_spec.rb4
-rw-r--r--spec/ruby/library/stringio/closed_write_spec.rb2
-rw-r--r--spec/ruby/library/stringio/flush_spec.rb2
-rw-r--r--spec/ruby/library/stringio/fsync_spec.rb2
-rw-r--r--spec/ruby/library/stringio/gets_spec.rb2
-rw-r--r--spec/ruby/library/stringio/initialize_spec.rb90
-rw-r--r--spec/ruby/library/stringio/open_spec.rb60
-rw-r--r--spec/ruby/library/stringio/print_spec.rb8
-rw-r--r--spec/ruby/library/stringio/printf_spec.rb8
-rw-r--r--spec/ruby/library/stringio/putc_spec.rb10
-rw-r--r--spec/ruby/library/stringio/puts_spec.rb8
-rw-r--r--spec/ruby/library/stringio/read_nonblock_spec.rb4
-rw-r--r--spec/ruby/library/stringio/read_spec.rb2
-rw-r--r--spec/ruby/library/stringio/readline_spec.rb2
-rw-r--r--spec/ruby/library/stringio/readlines_spec.rb2
-rw-r--r--spec/ruby/library/stringio/readpartial_spec.rb6
-rw-r--r--spec/ruby/library/stringio/reopen_spec.rb38
-rw-r--r--spec/ruby/library/stringio/shared/codepoints.rb2
-rw-r--r--spec/ruby/library/stringio/shared/each.rb2
-rw-r--r--spec/ruby/library/stringio/shared/each_byte.rb2
-rw-r--r--spec/ruby/library/stringio/shared/each_char.rb2
-rw-r--r--spec/ruby/library/stringio/shared/getc.rb2
-rw-r--r--spec/ruby/library/stringio/shared/isatty.rb2
-rw-r--r--spec/ruby/library/stringio/shared/read.rb30
-rw-r--r--spec/ruby/library/stringio/shared/readchar.rb2
-rw-r--r--spec/ruby/library/stringio/shared/write.rb10
-rw-r--r--spec/ruby/library/stringio/truncate_spec.rb8
-rw-r--r--spec/ruby/library/stringio/ungetc_spec.rb10
-rw-r--r--spec/ruby/library/stringio/write_nonblock_spec.rb2
-rw-r--r--spec/ruby/library/stringscanner/getch_spec.rb2
-rw-r--r--spec/ruby/library/stringscanner/shared/concat.rb2
-rw-r--r--spec/ruby/library/stringscanner/string_spec.rb2
-rw-r--r--spec/ruby/library/time/to_date_spec.rb42
-rw-r--r--spec/ruby/library/time/to_datetime_spec.rb42
-rw-r--r--spec/ruby/library/yaml/dump_spec.rb14
-rw-r--r--spec/ruby/library/yaml/dump_stream_spec.rb3
-rw-r--r--spec/ruby/library/yaml/fixtures/common.rb4
-rw-r--r--spec/ruby/library/yaml/fixtures/strings.rb56
-rw-r--r--spec/ruby/library/yaml/load_file_spec.rb13
-rw-r--r--spec/ruby/library/yaml/load_stream_spec.rb3
-rw-r--r--spec/ruby/library/yaml/parse_file_spec.rb8
-rw-r--r--spec/ruby/library/yaml/parse_spec.rb7
-rw-r--r--spec/ruby/library/yaml/shared/each_document.rb5
-rw-r--r--spec/ruby/library/yaml/shared/load.rb12
-rw-r--r--spec/ruby/library/yaml/to_yaml_spec.rb20
-rw-r--r--spec/ruby/library/zlib/deflate/deflate_spec.rb4
-rw-r--r--spec/ruby/library/zlib/deflate/params_spec.rb2
-rw-r--r--spec/ruby/library/zlib/inflate/inflate_spec.rb8
-rw-r--r--spec/ruby/optional/capi/array_spec.rb34
-rw-r--r--spec/ruby/optional/capi/class_spec.rb12
-rw-r--r--spec/ruby/optional/capi/data_spec.rb73
-rw-r--r--spec/ruby/optional/capi/debug_spec.rb9
-rw-r--r--spec/ruby/optional/capi/encoding_spec.rb32
-rw-r--r--spec/ruby/optional/capi/ext/array_spec.c28
-rw-r--r--spec/ruby/optional/capi/ext/class_spec.c5
-rw-r--r--spec/ruby/optional/capi/ext/data_spec.c4
-rw-r--r--spec/ruby/optional/capi/ext/encoding_spec.c5
-rw-r--r--spec/ruby/optional/capi/ext/gc_spec.c64
-rw-r--r--spec/ruby/optional/capi/ext/io_spec.c28
-rw-r--r--spec/ruby/optional/capi/ext/kernel_spec.c10
-rw-r--r--spec/ruby/optional/capi/ext/object_spec.c52
-rw-r--r--spec/ruby/optional/capi/ext/rbasic_spec.c54
-rw-r--r--spec/ruby/optional/capi/ext/rubyspec.h27
-rw-r--r--spec/ruby/optional/capi/ext/string_spec.c36
-rw-r--r--spec/ruby/optional/capi/ext/thread_spec.c8
-rw-r--r--spec/ruby/optional/capi/ext/typed_data_spec.c14
-rw-r--r--spec/ruby/optional/capi/ext/util_spec.c17
-rw-r--r--spec/ruby/optional/capi/file_spec.rb2
-rw-r--r--spec/ruby/optional/capi/fixtures/kernel.rb6
-rw-r--r--spec/ruby/optional/capi/gc_spec.rb35
-rw-r--r--spec/ruby/optional/capi/integer_spec.rb17
-rw-r--r--spec/ruby/optional/capi/io_spec.rb19
-rw-r--r--spec/ruby/optional/capi/kernel_spec.rb43
-rw-r--r--spec/ruby/optional/capi/object_spec.rb10
-rw-r--r--spec/ruby/optional/capi/rbasic_spec.rb56
-rw-r--r--spec/ruby/optional/capi/shared/rbasic.rb1
-rw-r--r--spec/ruby/optional/capi/string_spec.rb129
-rw-r--r--spec/ruby/optional/capi/typed_data_spec.rb12
-rw-r--r--spec/ruby/optional/capi/util_spec.rb2
-rw-r--r--spec/ruby/security/cve_2010_1330_spec.rb2
-rw-r--r--spec/ruby/security/cve_2019_8323_spec.rb14
-rw-r--r--spec/ruby/shared/kernel/at_exit.rb11
-rw-r--r--spec/ruby/shared/kernel/object_id.rb28
-rw-r--r--spec/ruby/shared/kernel/raise.rb11
-rw-r--r--spec/ruby/shared/queue/deque.rb34
-rw-r--r--spec/ruby/shared/rational/coerce.rb34
-rw-r--r--spec/ruby/shared/sizedqueue/enque.rb36
-rw-r--r--spec/ruby/shared/string/end_with.rb4
-rw-r--r--spec/ruby/shared/string/times.rb2
-rw-r--r--spec/syntax_suggest/integration/ruby_command_line_spec.rb6
-rw-r--r--spec/syntax_suggest/integration/syntax_suggest_spec.rb16
-rw-r--r--spec/syntax_suggest/unit/api_spec.rb6
-rw-r--r--spec/syntax_suggest/unit/around_block_scan_spec.rb2
-rw-r--r--spec/syntax_suggest/unit/block_expand_spec.rb4
-rw-r--r--spec/syntax_suggest/unit/capture/before_after_keyword_ends_spec.rb4
-rw-r--r--spec/syntax_suggest/unit/capture/falling_indent_lines_spec.rb4
-rw-r--r--spec/syntax_suggest/unit/capture_code_context_spec.rb32
-rw-r--r--spec/syntax_suggest/unit/clean_document_spec.rb14
-rw-r--r--spec/syntax_suggest/unit/code_line_spec.rb12
-rw-r--r--spec/syntax_suggest/unit/code_search_spec.rb82
-rw-r--r--spec/syntax_suggest/unit/core_ext_spec.rb2
-rw-r--r--spec/syntax_suggest/unit/explain_syntax_spec.rb4
-rw-r--r--spec/syntax_suggest/unit/lex_all_spec.rb3
-rw-r--r--spec/syntax_suggest/unit/scan_history_spec.rb6
-rw-r--r--sprintf.c4
-rw-r--r--st.c46
-rw-r--r--string.c647
-rw-r--r--string.rb42
-rw-r--r--struct.c33
-rw-r--r--symbol.c87
-rw-r--r--symbol.h7
-rw-r--r--symbol.rb15
-rw-r--r--template/Doxyfile.tmpl6
-rw-r--r--template/GNUmakefile.in12
-rw-r--r--template/Makefile.in58
-rw-r--r--template/encdb.h.tmpl36
-rw-r--r--template/extinit.c.tmpl2
-rw-r--r--template/exts.mk.tmpl9
-rw-r--r--template/known_errors.inc.tmpl8
-rw-r--r--template/prelude.c.tmpl78
-rw-r--r--template/transdb.h.tmpl39
-rw-r--r--test/-ext-/bug_reporter/test_bug_reporter.rb2
-rw-r--r--test/-ext-/debug/test_debug.rb2
-rw-r--r--test/-ext-/debug/test_profile_frames.rb4
-rw-r--r--test/-ext-/integer/test_my_integer.rb34
-rw-r--r--test/-ext-/load/test_resolve_symbol.rb27
-rw-r--r--test/-ext-/load/test_stringify_symbols.rb35
-rw-r--r--test/-ext-/marshal/test_internal_ivar.rb2
-rw-r--r--test/-ext-/postponed_job/test_postponed_job.rb72
-rw-r--r--test/-ext-/string/test_fstring.rb16
-rw-r--r--test/-ext-/symbol/test_type.rb5
-rw-r--r--test/-ext-/test_bug-3571.rb4
-rw-r--r--test/-ext-/thread/helper.rb51
-rw-r--r--test/-ext-/thread/test_instrumentation_api.rb281
-rw-r--r--test/-ext-/thread/test_lock_native_thread.rb50
-rw-r--r--test/-ext-/tracepoint/test_tracepoint.rb1
-rw-r--r--test/.excludes-prism/TestM17N.rb1
-rw-r--r--test/.excludes-prism/TestMixedUnicodeEscape.rb1
-rw-r--r--test/.excludes-prism/TestRubyLiteral.rb1
-rw-r--r--test/base64/test_base64.rb115
-rw-r--r--test/bigdecimal/helper.rb39
-rw-r--r--test/bigdecimal/test_bigdecimal.rb2310
-rw-r--r--test/bigdecimal/test_bigdecimal_util.rb141
-rw-r--r--test/bigdecimal/test_bigmath.rb81
-rw-r--r--test/bigdecimal/test_ractor.rb23
-rw-r--r--test/cgi/test_cgi_util.rb18
-rw-r--r--test/coverage/test_coverage.rb55
-rw-r--r--test/csv/helper.rb42
-rw-r--r--test/csv/interface/test_delegation.rb47
-rw-r--r--test/csv/interface/test_read.rb381
-rw-r--r--test/csv/interface/test_read_write.rb124
-rw-r--r--test/csv/interface/test_write.rb217
-rw-r--r--test/csv/line_endings.gzbin59 -> 0 bytes-rw-r--r--test/csv/parse/test_column_separator.rb40
-rw-r--r--test/csv/parse/test_convert.rb165
-rw-r--r--test/csv/parse/test_each.rb23
-rw-r--r--test/csv/parse/test_general.rb348
-rw-r--r--test/csv/parse/test_header.rb342
-rw-r--r--test/csv/parse/test_inputs_scanner.rb63
-rw-r--r--test/csv/parse/test_invalid.rb52
-rw-r--r--test/csv/parse/test_liberal_parsing.rb171
-rw-r--r--test/csv/parse/test_quote_char_nil.rb93
-rw-r--r--test/csv/parse/test_read.rb27
-rw-r--r--test/csv/parse/test_rewind.rb40
-rw-r--r--test/csv/parse/test_row_separator.rb16
-rw-r--r--test/csv/parse/test_skip_lines.rb126
-rw-r--r--test/csv/parse/test_strip.rb112
-rw-r--r--test/csv/parse/test_unconverted_fields.rb117
-rw-r--r--test/csv/test_data_converters.rb190
-rw-r--r--test/csv/test_encodings.rb403
-rw-r--r--test/csv/test_features.rb359
-rw-r--r--test/csv/test_patterns.rb27
-rw-r--r--test/csv/test_row.rb435
-rw-r--r--test/csv/test_table.rb691
-rw-r--r--test/csv/write/test_converters.rb53
-rw-r--r--test/csv/write/test_force_quotes.rb78
-rw-r--r--test/csv/write/test_general.rb246
-rw-r--r--test/csv/write/test_quote_empty.rb70
-rw-r--r--test/date/test_date_parse.rb24
-rw-r--r--test/did_you_mean/core_ext/test_name_error_extension.rb2
-rw-r--r--test/drb/drbtest.rb396
-rw-r--r--test/drb/ignore_test_drb.rb14
-rw-r--r--test/drb/test_acl.rb207
-rw-r--r--test/drb/test_drb.rb371
-rw-r--r--test/drb/test_drbobject.rb69
-rw-r--r--test/drb/test_drbssl.rb84
-rw-r--r--test/drb/test_drbunix.rb60
-rw-r--r--test/drb/ut_array.rb17
-rw-r--r--test/drb/ut_array_drbssl.rb43
-rw-r--r--test/drb/ut_array_drbunix.rb17
-rw-r--r--test/drb/ut_drb.rb189
-rw-r--r--test/drb/ut_drb_drbssl.rb40
-rw-r--r--test/drb/ut_drb_drbunix.rb18
-rw-r--r--test/drb/ut_eq.rb37
-rw-r--r--test/drb/ut_large.rb62
-rw-r--r--test/drb/ut_port.rb16
-rw-r--r--test/drb/ut_safe1.rb17
-rw-r--r--test/drb/ut_timerholder.rb74
-rw-r--r--test/error_highlight/test_error_highlight.rb29
-rw-r--r--test/fiber/scheduler.rb22
-rw-r--r--test/fiber/test_address_resolve.rb2
-rw-r--r--test/fiber/test_enumerator.rb8
-rw-r--r--test/fiber/test_mutex.rb2
-rw-r--r--test/fiber/test_process.rb8
-rw-r--r--test/fiddle/test_handle.rb3
-rw-r--r--test/io/console/test_io_console.rb20
-rw-r--r--test/io/wait/test_io_wait.rb1
-rw-r--r--test/irb/command/test_custom_command.rb149
-rw-r--r--test/irb/command/test_disable_irb.rb28
-rw-r--r--test/irb/command/test_force_exit.rb51
-rw-r--r--test/irb/command/test_help.rb75
-rw-r--r--test/irb/command/test_multi_irb_commands.rb50
-rw-r--r--test/irb/command/test_show_source.rb397
-rw-r--r--test/irb/helper.rb22
-rw-r--r--test/irb/test_cmd.rb974
-rw-r--r--test/irb/test_color.rb3
-rw-r--r--test/irb/test_color_printer.rb1
-rw-r--r--test/irb/test_command.rb971
-rw-r--r--test/irb/test_completion.rb23
-rw-r--r--test/irb/test_context.rb275
-rw-r--r--test/irb/test_debug_cmd.rb440
-rw-r--r--test/irb/test_debugger_integration.rb496
-rw-r--r--test/irb/test_eval_history.rb5
-rw-r--r--test/irb/test_helper_method.rb134
-rw-r--r--test/irb/test_history.rb240
-rw-r--r--test/irb/test_init.rb241
-rw-r--r--test/irb/test_input_method.rb18
-rw-r--r--test/irb/test_irb.rb190
-rw-r--r--test/irb/test_nesting_parser.rb38
-rw-r--r--test/irb/test_raise_exception.rb74
-rw-r--r--test/irb/test_raise_no_backtrace_exception.rb56
-rw-r--r--test/irb/test_ruby_lex.rb4
-rw-r--r--test/irb/test_tracer.rb90
-rw-r--r--test/irb/test_type_completor.rb88
-rw-r--r--test/irb/test_workspace.rb3
-rw-r--r--test/irb/type_completion/test_scope.rb114
-rw-r--r--test/irb/type_completion/test_type_analyze.rb699
-rw-r--r--test/irb/type_completion/test_type_completor.rb183
-rw-r--r--test/irb/type_completion/test_types.rb91
-rw-r--r--test/irb/yamatanooroti/test_rendering.rb175
-rw-r--r--test/json/json_addition_test.rb2
-rw-r--r--test/json/json_common_interface_test.rb32
-rw-r--r--test/json/json_encoding_test.rb3
-rw-r--r--test/json/json_ext_parser_test.rb19
-rwxr-xr-xtest/json/json_generator_test.rb38
-rw-r--r--test/json/json_generic_object_test.rb2
-rw-r--r--test/json/json_parser_test.rb71
-rw-r--r--test/json/ractor_test.rb6
-rw-r--r--test/logger/test_logperiod.rb83
-rw-r--r--test/mkmf/test_config.rb27
-rw-r--r--test/monitor/test_monitor.rb2
-rw-r--r--test/net/fixtures/Makefile6
-rw-r--r--test/net/fixtures/cacert.pem44
-rw-r--r--test/net/fixtures/server.crt99
-rw-r--r--test/net/fixtures/server.key55
-rw-r--r--test/net/http/test_http.rb10
-rw-r--r--test/net/http/test_https.rb4
-rw-r--r--test/nkf/test_kconv.rb82
-rw-r--r--test/nkf/test_nkf.rb23
-rw-r--r--test/objspace/test_objspace.rb16
-rw-r--r--test/objspace/test_ractor.rb24
-rw-r--r--test/open-uri/test_open-uri.rb19
-rw-r--r--test/openssl/fixtures/pkey/dh1024.pem5
-rw-r--r--test/openssl/fixtures/pkey/dh2048_ffdhe2048.pem8
-rw-r--r--test/openssl/fixtures/pkey/dsa2048.pem15
-rw-r--r--test/openssl/test_asn1.rb8
-rw-r--r--test/openssl/test_cipher.rb16
-rw-r--r--test/openssl/test_digest.rb20
-rw-r--r--test/openssl/test_ocsp.rb2
-rw-r--r--test/openssl/test_pair.rb20
-rw-r--r--test/openssl/test_pkcs12.rb31
-rw-r--r--test/openssl/test_pkcs7.rb21
-rw-r--r--test/openssl/test_pkey_dh.rb64
-rw-r--r--test/openssl/test_pkey_dsa.rb40
-rw-r--r--test/openssl/test_provider.rb15
-rw-r--r--test/openssl/test_ssl.rb44
-rw-r--r--test/openssl/test_ts.rb2
-rw-r--r--test/openssl/test_x509cert.rb9
-rw-r--r--test/openssl/test_x509req.rb7
-rw-r--r--test/openssl/utils.rb6
-rw-r--r--test/optparse/test_acceptable.rb5
-rw-r--r--test/optparse/test_optarg.rb16
-rw-r--r--test/optparse/test_optparse.rb88
-rw-r--r--test/optparse/test_placearg.rb20
-rw-r--r--test/optparse/test_reqarg.rb6
-rw-r--r--test/prism/api/command_line_test.rb111
-rw-r--r--test/prism/api/dump_test.rb56
-rw-r--r--test/prism/api/parse_comments_test.rb33
-rw-r--r--test/prism/api/parse_stream_test.rb73
-rw-r--r--test/prism/api/parse_success_test.rb16
-rw-r--r--test/prism/api/parse_test.rb66
-rw-r--r--test/prism/bom_test.rb2
-rw-r--r--test/prism/comments_test.rb152
-rw-r--r--test/prism/compiler_test.rb30
-rw-r--r--test/prism/constant_path_node_test.rb29
-rw-r--r--test/prism/desugar_compiler_test.rb86
-rw-r--r--test/prism/dispatcher_test.rb46
-rw-r--r--test/prism/encoding/encodings_test.rb101
-rw-r--r--test/prism/encoding/regular_expression_encoding_test.rb131
-rw-r--r--test/prism/encoding/string_encoding_test.rb136
-rw-r--r--test/prism/encoding/symbol_encoding_test.rb108
-rw-r--r--test/prism/encoding_test.rb106
-rw-r--r--test/prism/errors_test.rb1464
-rw-r--r--test/prism/fixtures/arrays.txt16
-rw-r--r--test/prism/fixtures/break.txt22
-rw-r--r--test/prism/fixtures/case.txt23
-rw-r--r--test/prism/fixtures/command_method_call.txt41
-rw-r--r--test/prism/fixtures/defined.txt3
-rw-r--r--test/prism/fixtures/dstring.txt29
-rw-r--r--test/prism/fixtures/dsym_str.txt2
-rw-r--r--test/prism/fixtures/emoji_method_calls.txt1
-rw-r--r--test/prism/fixtures/hashes.txt2
-rw-r--r--test/prism/fixtures/heredoc.txt2
-rw-r--r--test/prism/fixtures/heredoc_with_carriage_returns.txt2
-rw-r--r--test/prism/fixtures/heredoc_with_comment.txt3
-rw-r--r--test/prism/fixtures/heredocs_leading_whitespace.txt29
-rw-r--r--test/prism/fixtures/heredocs_nested.txt13
-rw-r--r--test/prism/fixtures/if.txt10
-rw-r--r--test/prism/fixtures/keywords.txt4
-rw-r--r--test/prism/fixtures/method_calls.txt9
-rw-r--r--test/prism/fixtures/methods.txt19
-rw-r--r--test/prism/fixtures/multi_write.txt4
-rw-r--r--test/prism/fixtures/next.txt26
-rw-r--r--test/prism/fixtures/patterns.txt24
-rw-r--r--test/prism/fixtures/ranges.txt32
-rw-r--r--test/prism/fixtures/regex.txt17
-rw-r--r--test/prism/fixtures/regex_char_width.txt3
-rw-r--r--test/prism/fixtures/repeat_parameters.txt38
-rw-r--r--test/prism/fixtures/rescue.txt8
-rw-r--r--test/prism/fixtures/seattlerb/README.rdoc6
-rw-r--r--test/prism/fixtures/seattlerb/block_break.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_next.txt1
-rw-r--r--test/prism/fixtures/seattlerb/dasgn_icky2.txt8
-rw-r--r--test/prism/fixtures/seattlerb/yield_arg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/yield_call_assocs.txt11
-rw-r--r--test/prism/fixtures/seattlerb/yield_empty_parens.txt1
-rw-r--r--test/prism/fixtures/single_method_call_with_bang.txt1
-rw-r--r--test/prism/fixtures/spanning_heredoc.txt8
-rw-r--r--test/prism/fixtures/spanning_heredoc_newlines.txt23
-rw-r--r--test/prism/fixtures/unless.txt4
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/control.txt15
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/flipflop.txt4
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/since/32.txt4
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/yield.txt3
-rw-r--r--test/prism/fixtures/unparser/corpus/semantic/opasgn.txt1
-rw-r--r--test/prism/fixtures/until.txt4
-rw-r--r--test/prism/fixtures/while.txt12
-rw-r--r--test/prism/fixtures/whitequark/args_assocs.txt11
-rw-r--r--test/prism/fixtures/whitequark/args_assocs_legacy.txt11
-rw-r--r--test/prism/fixtures/whitequark/break.txt7
-rw-r--r--test/prism/fixtures/whitequark/break_block.txt1
-rw-r--r--test/prism/fixtures/whitequark/class_definition_in_while_cond.txt7
-rw-r--r--test/prism/fixtures/whitequark/cond_eflipflop_with_beginless_range.txt1
-rw-r--r--test/prism/fixtures/whitequark/cond_eflipflop_with_endless_range.txt1
-rw-r--r--test/prism/fixtures/whitequark/cond_iflipflop_with_beginless_range.txt1
-rw-r--r--test/prism/fixtures/whitequark/cond_iflipflop_with_endless_range.txt1
-rw-r--r--test/prism/fixtures/whitequark/if_while_after_class__since_32.txt7
-rw-r--r--test/prism/fixtures/whitequark/next.txt7
-rw-r--r--test/prism/fixtures/whitequark/next_block.txt1
-rw-r--r--test/prism/fixtures/whitequark/numparam_ruby_bug_19025.txt1
-rw-r--r--test/prism/fixtures/whitequark/parser_bug_989.txt3
-rw-r--r--test/prism/fixtures/whitequark/redo.txt1
-rw-r--r--test/prism/fixtures/whitequark/retry.txt1
-rw-r--r--test/prism/fixtures/whitequark/yield.txt7
-rw-r--r--test/prism/fixtures/xstring.txt10
-rw-r--r--test/prism/fixtures/xstring_with_backslash.txt1
-rw-r--r--test/prism/fixtures/yield.txt8
-rw-r--r--test/prism/fixtures_test.rb21
-rw-r--r--test/prism/fuzzer_test.rb10
-rw-r--r--test/prism/heredoc_dedent_test.rb133
-rw-r--r--test/prism/lex_test.rb90
-rw-r--r--test/prism/library_symbols_test.rb31
-rw-r--r--test/prism/locals_test.rb256
-rw-r--r--test/prism/location_test.rb878
-rw-r--r--test/prism/magic_comment_test.rb117
-rw-r--r--test/prism/memsize_test.rb17
-rw-r--r--test/prism/newline_offsets_test.rb22
-rw-r--r--test/prism/newline_test.rb30
-rw-r--r--test/prism/onigmo_test.rb66
-rw-r--r--test/prism/parameters_signature_test.rb91
-rw-r--r--test/prism/parse_comments_test.rb21
-rw-r--r--test/prism/parse_test.rb262
-rw-r--r--test/prism/pattern_test.rb132
-rw-r--r--test/prism/regexp_test.rb126
-rw-r--r--test/prism/result/attribute_write_test.rb56
-rw-r--r--test/prism/result/comments_test.rb138
-rw-r--r--test/prism/result/constant_path_node_test.rb91
-rw-r--r--test/prism/result/equality_test.rb22
-rw-r--r--test/prism/result/heredoc_test.rb19
-rw-r--r--test/prism/result/index_write_test.rb89
-rw-r--r--test/prism/result/integer_base_flags_test.rb33
-rw-r--r--test/prism/result/integer_parse_test.rb41
-rw-r--r--test/prism/result/numeric_value_test.rb21
-rw-r--r--test/prism/result/overlap_test.rb43
-rw-r--r--test/prism/result/redundant_return_test.rb73
-rw-r--r--test/prism/result/regular_expression_options_test.rb25
-rw-r--r--test/prism/result/source_location_test.rb950
-rw-r--r--test/prism/result/static_inspect_test.rb89
-rw-r--r--test/prism/result/static_literals_test.rb92
-rw-r--r--test/prism/result/warnings_test.rb262
-rw-r--r--test/prism/ripper_compat_test.rb21
-rw-r--r--test/prism/ruby/compiler_test.rb31
-rw-r--r--test/prism/ruby/desugar_compiler_test.rb80
-rw-r--r--test/prism/ruby/dispatcher_test.rb46
-rw-r--r--test/prism/ruby/location_test.rb173
-rw-r--r--test/prism/ruby/parameters_signature_test.rb91
-rw-r--r--test/prism/ruby/parser_test.rb291
-rw-r--r--test/prism/ruby/pattern_test.rb132
-rw-r--r--test/prism/ruby/reflection_test.rb22
-rw-r--r--test/prism/ruby/ripper_test.rb62
-rw-r--r--test/prism/ruby/ruby_parser_test.rb127
-rw-r--r--test/prism/ruby/tunnel_test.rb26
-rw-r--r--test/prism/ruby_api_test.rb80
-rw-r--r--test/prism/snapshots/alias.txt24
-rw-r--r--test/prism/snapshots/arithmetic.txt283
-rw-r--r--test/prism/snapshots/arrays.txt1857
-rw-r--r--test/prism/snapshots/begin_ensure.txt197
-rw-r--r--test/prism/snapshots/begin_rescue.txt210
-rw-r--r--test/prism/snapshots/blocks.txt1171
-rw-r--r--test/prism/snapshots/boolean_operators.txt22
-rw-r--r--test/prism/snapshots/break.txt547
-rw-r--r--test/prism/snapshots/case.txt359
-rw-r--r--test/prism/snapshots/classes.txt101
-rw-r--r--test/prism/snapshots/command_method_call.txt755
-rw-r--r--test/prism/snapshots/comments.txt84
-rw-r--r--test/prism/snapshots/constants.txt902
-rw-r--r--test/prism/snapshots/dash_heredocs.txt170
-rw-r--r--test/prism/snapshots/defined.txt55
-rw-r--r--test/prism/snapshots/dos_endings.txt109
-rw-r--r--test/prism/snapshots/dstring.txt85
-rw-r--r--test/prism/snapshots/dsym_str.txt11
-rw-r--r--test/prism/snapshots/emoji_method_calls.txt31
-rw-r--r--test/prism/snapshots/endless_methods.txt58
-rw-r--r--test/prism/snapshots/endless_range_in_conditional.txt27
-rw-r--r--test/prism/snapshots/for.txt90
-rw-r--r--test/prism/snapshots/global_variables.txt23
-rw-r--r--test/prism/snapshots/hashes.txt311
-rw-r--r--test/prism/snapshots/heredoc.txt11
-rw-r--r--test/prism/snapshots/heredoc_with_carriage_returns.txt11
-rw-r--r--test/prism/snapshots/heredoc_with_comment.txt21
-rw-r--r--test/prism/snapshots/heredoc_with_escaped_newline_at_start.txt68
-rw-r--r--test/prism/snapshots/heredocs_leading_whitespace.txt63
-rw-r--r--test/prism/snapshots/heredocs_nested.txt119
-rw-r--r--test/prism/snapshots/heredocs_with_ignored_newlines.txt31
-rw-r--r--test/prism/snapshots/if.txt460
-rw-r--r--test/prism/snapshots/integer_operations.txt602
-rw-r--r--test/prism/snapshots/keyword_method_names.txt74
-rw-r--r--test/prism/snapshots/keywords.txt39
-rw-r--r--test/prism/snapshots/lambda.txt47
-rw-r--r--test/prism/snapshots/method_calls.txt3248
-rw-r--r--test/prism/snapshots/methods.txt836
-rw-r--r--test/prism/snapshots/modules.txt74
-rw-r--r--test/prism/snapshots/multi_write.txt93
-rw-r--r--test/prism/snapshots/newline_terminated.txt4
-rw-r--r--test/prism/snapshots/next.txt452
-rw-r--r--test/prism/snapshots/nils.txt6
-rw-r--r--test/prism/snapshots/non_alphanumeric_methods.txt8
-rw-r--r--test/prism/snapshots/not.txt194
-rw-r--r--test/prism/snapshots/numbers.txt129
-rw-r--r--test/prism/snapshots/patterns.txt3649
-rw-r--r--test/prism/snapshots/procs.txt69
-rw-r--r--test/prism/snapshots/range_begin_open_exclusive.txt7
-rw-r--r--test/prism/snapshots/range_begin_open_inclusive.txt7
-rw-r--r--test/prism/snapshots/range_end_open_exclusive.txt7
-rw-r--r--test/prism/snapshots/range_end_open_inclusive.txt7
-rw-r--r--test/prism/snapshots/ranges.txt488
-rw-r--r--test/prism/snapshots/regex.txt457
-rw-r--r--test/prism/snapshots/regex_char_width.txt50
-rw-r--r--test/prism/snapshots/repeat_parameters.txt473
-rw-r--r--test/prism/snapshots/rescue.txt579
-rw-r--r--test/prism/snapshots/return.txt214
-rw-r--r--test/prism/snapshots/seattlerb/BEGIN.txt3
-rw-r--r--test/prism/snapshots/seattlerb/TestRubyParserShared.txt96
-rw-r--r--test/prism/snapshots/seattlerb/alias_resword.txt2
-rw-r--r--test/prism/snapshots/seattlerb/and_multi.txt6
-rw-r--r--test/prism/snapshots/seattlerb/aref_args_assocs.txt8
-rw-r--r--test/prism/snapshots/seattlerb/aref_args_lit_assocs.txt11
-rw-r--r--test/prism/snapshots/seattlerb/args_kw_block.txt5
-rw-r--r--test/prism/snapshots/seattlerb/array_line_breaks.txt4
-rw-r--r--test/prism/snapshots/seattlerb/array_lits_trailing_calls.txt14
-rw-r--r--test/prism/snapshots/seattlerb/assoc__bare.txt7
-rw-r--r--test/prism/snapshots/seattlerb/assoc_label.txt39
-rw-r--r--test/prism/snapshots/seattlerb/attr_asgn_colon_id.txt15
-rw-r--r--test/prism/snapshots/seattlerb/attrasgn_array_arg.txt40
-rw-r--r--test/prism/snapshots/seattlerb/attrasgn_array_lhs.txt118
-rw-r--r--test/prism/snapshots/seattlerb/attrasgn_primary_dot_constant.txt21
-rw-r--r--test/prism/snapshots/seattlerb/backticks_interpolation_line.txt50
-rw-r--r--test/prism/snapshots/seattlerb/bang_eq.txt18
-rw-r--r--test/prism/snapshots/seattlerb/bdot2.txt23
-rw-r--r--test/prism/snapshots/seattlerb/bdot3.txt23
-rw-r--r--test/prism/snapshots/seattlerb/begin_rescue_else_ensure_bodies.txt12
-rw-r--r--test/prism/snapshots/seattlerb/block_arg__bare.txt3
-rw-r--r--test/prism/snapshots/seattlerb/block_arg_kwsplat.txt53
-rw-r--r--test/prism/snapshots/seattlerb/block_arg_opt_arg_block.txt79
-rw-r--r--test/prism/snapshots/seattlerb/block_arg_opt_splat.txt74
-rw-r--r--test/prism/snapshots/seattlerb/block_arg_opt_splat_arg_block_omfg.txt88
-rw-r--r--test/prism/snapshots/seattlerb/block_arg_optional.txt60
-rw-r--r--test/prism/snapshots/seattlerb/block_arg_scope.txt54
-rw-r--r--test/prism/snapshots/seattlerb/block_arg_scope2.txt59
-rw-r--r--test/prism/snapshots/seattlerb/block_arg_splat_arg.txt63
-rw-r--r--test/prism/snapshots/seattlerb/block_args_kwargs.txt63
-rw-r--r--test/prism/snapshots/seattlerb/block_args_no_kwargs.txt50
-rw-r--r--test/prism/snapshots/seattlerb/block_args_opt1.txt90
-rw-r--r--test/prism/snapshots/seattlerb/block_args_opt2.txt76
-rw-r--r--test/prism/snapshots/seattlerb/block_args_opt2_2.txt112
-rw-r--r--test/prism/snapshots/seattlerb/block_args_opt3.txt127
-rw-r--r--test/prism/snapshots/seattlerb/block_break.txt55
-rw-r--r--test/prism/snapshots/seattlerb/block_call_defn_call_block_call.txt105
-rw-r--r--test/prism/snapshots/seattlerb/block_call_dot_op2_brace_block.txt145
-rw-r--r--test/prism/snapshots/seattlerb/block_call_dot_op2_cmd_args_do_block.txt169
-rw-r--r--test/prism/snapshots/seattlerb/block_call_operation_colon.txt54
-rw-r--r--test/prism/snapshots/seattlerb/block_call_operation_dot.txt54
-rw-r--r--test/prism/snapshots/seattlerb/block_call_paren_call_block_call.txt66
-rw-r--r--test/prism/snapshots/seattlerb/block_command_operation_colon.txt54
-rw-r--r--test/prism/snapshots/seattlerb/block_command_operation_dot.txt54
-rw-r--r--test/prism/snapshots/seattlerb/block_decomp_anon_splat_arg.txt67
-rw-r--r--test/prism/snapshots/seattlerb/block_decomp_arg_splat.txt67
-rw-r--r--test/prism/snapshots/seattlerb/block_decomp_arg_splat_arg.txt77
-rw-r--r--test/prism/snapshots/seattlerb/block_decomp_splat.txt67
-rw-r--r--test/prism/snapshots/seattlerb/block_kw.txt58
-rw-r--r--test/prism/snapshots/seattlerb/block_kw__required.txt51
-rw-r--r--test/prism/snapshots/seattlerb/block_kwarg_lvar.txt74
-rw-r--r--test/prism/snapshots/seattlerb/block_kwarg_lvar_multiple.txt94
-rw-r--r--test/prism/snapshots/seattlerb/block_next.txt55
-rw-r--r--test/prism/snapshots/seattlerb/block_opt_arg.txt65
-rw-r--r--test/prism/snapshots/seattlerb/block_opt_splat.txt69
-rw-r--r--test/prism/snapshots/seattlerb/block_opt_splat_arg_block_omfg.txt83
-rw-r--r--test/prism/snapshots/seattlerb/block_optarg.txt66
-rw-r--r--test/prism/snapshots/seattlerb/block_paren_splat.txt72
-rw-r--r--test/prism/snapshots/seattlerb/block_reg_optarg.txt71
-rw-r--r--test/prism/snapshots/seattlerb/block_return.txt94
-rw-r--r--test/prism/snapshots/seattlerb/block_scope.txt33
-rw-r--r--test/prism/snapshots/seattlerb/block_splat_reg.txt58
-rw-r--r--test/prism/snapshots/seattlerb/bug169.txt30
-rw-r--r--test/prism/snapshots/seattlerb/bug179.txt30
-rw-r--r--test/prism/snapshots/seattlerb/bug190.txt4
-rw-r--r--test/prism/snapshots/seattlerb/bug191.txt26
-rw-r--r--test/prism/snapshots/seattlerb/bug202.txt6
-rw-r--r--test/prism/snapshots/seattlerb/bug236.txt103
-rw-r--r--test/prism/snapshots/seattlerb/bug290.txt6
-rw-r--r--test/prism/snapshots/seattlerb/bug_187.txt92
-rw-r--r--test/prism/snapshots/seattlerb/bug_215.txt1
-rw-r--r--test/prism/snapshots/seattlerb/bug_249.txt144
-rw-r--r--test/prism/snapshots/seattlerb/bug_and.txt1
-rw-r--r--test/prism/snapshots/seattlerb/bug_args__19.txt90
-rw-r--r--test/prism/snapshots/seattlerb/bug_args_masgn.txt71
-rw-r--r--test/prism/snapshots/seattlerb/bug_args_masgn2.txt88
-rw-r--r--test/prism/snapshots/seattlerb/bug_args_masgn_outer_parens__19.txt83
-rw-r--r--test/prism/snapshots/seattlerb/bug_call_arglist_parens.txt96
-rw-r--r--test/prism/snapshots/seattlerb/bug_case_when_regexp.txt8
-rw-r--r--test/prism/snapshots/seattlerb/bug_comma.txt43
-rw-r--r--test/prism/snapshots/seattlerb/bug_cond_pct.txt5
-rw-r--r--test/prism/snapshots/seattlerb/bug_hash_args.txt47
-rw-r--r--test/prism/snapshots/seattlerb/bug_hash_args_trailing_comma.txt47
-rw-r--r--test/prism/snapshots/seattlerb/bug_hash_interp_array.txt1
-rw-r--r--test/prism/snapshots/seattlerb/bug_masgn_right.txt71
-rw-r--r--test/prism/snapshots/seattlerb/bug_not_parens.txt12
-rw-r--r--test/prism/snapshots/seattlerb/bug_op_asgn_rescue.txt6
-rw-r--r--test/prism/snapshots/seattlerb/call_and.txt18
-rw-r--r--test/prism/snapshots/seattlerb/call_arg_assoc.txt38
-rw-r--r--test/prism/snapshots/seattlerb/call_arg_assoc_kwsplat.txt55
-rw-r--r--test/prism/snapshots/seattlerb/call_arg_kwsplat.txt46
-rw-r--r--test/prism/snapshots/seattlerb/call_args_assoc_quoted.txt146
-rw-r--r--test/prism/snapshots/seattlerb/call_args_assoc_trailing_comma.txt38
-rw-r--r--test/prism/snapshots/seattlerb/call_args_command.txt67
-rw-r--r--test/prism/snapshots/seattlerb/call_array_arg.txt44
-rw-r--r--test/prism/snapshots/seattlerb/call_array_block_call.txt53
-rw-r--r--test/prism/snapshots/seattlerb/call_array_lambda_block_call.txt55
-rw-r--r--test/prism/snapshots/seattlerb/call_array_lit_inline_hash.txt59
-rw-r--r--test/prism/snapshots/seattlerb/call_assoc.txt33
-rw-r--r--test/prism/snapshots/seattlerb/call_assoc_new.txt39
-rw-r--r--test/prism/snapshots/seattlerb/call_assoc_new_if_multiline.txt84
-rw-r--r--test/prism/snapshots/seattlerb/call_assoc_trailing_comma.txt33
-rw-r--r--test/prism/snapshots/seattlerb/call_bang_command_call.txt27
-rw-r--r--test/prism/snapshots/seattlerb/call_bang_squiggle.txt18
-rw-r--r--test/prism/snapshots/seattlerb/call_begin_call_block_call.txt80
-rw-r--r--test/prism/snapshots/seattlerb/call_block_arg_named.txt32
-rw-r--r--test/prism/snapshots/seattlerb/call_carat.txt18
-rw-r--r--test/prism/snapshots/seattlerb/call_colon2.txt6
-rw-r--r--test/prism/snapshots/seattlerb/call_colon_parens.txt9
-rw-r--r--test/prism/snapshots/seattlerb/call_div.txt18
-rw-r--r--test/prism/snapshots/seattlerb/call_dot_parens.txt9
-rw-r--r--test/prism/snapshots/seattlerb/call_env.txt12
-rw-r--r--test/prism/snapshots/seattlerb/call_eq3.txt18
-rw-r--r--test/prism/snapshots/seattlerb/call_gt.txt18
-rw-r--r--test/prism/snapshots/seattlerb/call_kwsplat.txt26
-rw-r--r--test/prism/snapshots/seattlerb/call_leading_dots.txt18
-rw-r--r--test/prism/snapshots/seattlerb/call_leading_dots_comment.txt18
-rw-r--r--test/prism/snapshots/seattlerb/call_lt.txt18
-rw-r--r--test/prism/snapshots/seattlerb/call_lte.txt18
-rw-r--r--test/prism/snapshots/seattlerb/call_not.txt9
-rw-r--r--test/prism/snapshots/seattlerb/call_pipe.txt18
-rw-r--r--test/prism/snapshots/seattlerb/call_rshift.txt18
-rw-r--r--test/prism/snapshots/seattlerb/call_self_brackets.txt15
-rw-r--r--test/prism/snapshots/seattlerb/call_spaceship.txt18
-rw-r--r--test/prism/snapshots/seattlerb/call_stabby_do_end_with_block.txt54
-rw-r--r--test/prism/snapshots/seattlerb/call_stabby_with_braces_block.txt54
-rw-r--r--test/prism/snapshots/seattlerb/call_star.txt18
-rw-r--r--test/prism/snapshots/seattlerb/call_star2.txt18
-rw-r--r--test/prism/snapshots/seattlerb/call_trailing_comma.txt15
-rw-r--r--test/prism/snapshots/seattlerb/call_trailing_dots.txt18
-rw-r--r--test/prism/snapshots/seattlerb/call_unary_bang.txt9
-rw-r--r--test/prism/snapshots/seattlerb/case_in.txt228
-rw-r--r--test/prism/snapshots/seattlerb/case_in_31.txt5
-rw-r--r--test/prism/snapshots/seattlerb/case_in_37.txt5
-rw-r--r--test/prism/snapshots/seattlerb/case_in_42.txt4
-rw-r--r--test/prism/snapshots/seattlerb/case_in_42_2.txt3
-rw-r--r--test/prism/snapshots/seattlerb/case_in_47.txt6
-rw-r--r--test/prism/snapshots/seattlerb/case_in_67.txt10
-rw-r--r--test/prism/snapshots/seattlerb/case_in_86.txt12
-rw-r--r--test/prism/snapshots/seattlerb/case_in_86_2.txt12
-rw-r--r--test/prism/snapshots/seattlerb/case_in_array_pat_const.txt4
-rw-r--r--test/prism/snapshots/seattlerb/case_in_array_pat_const2.txt11
-rw-r--r--test/prism/snapshots/seattlerb/case_in_array_pat_paren_assign.txt4
-rw-r--r--test/prism/snapshots/seattlerb/case_in_const.txt3
-rw-r--r--test/prism/snapshots/seattlerb/case_in_else.txt4
-rw-r--r--test/prism/snapshots/seattlerb/case_in_find.txt4
-rw-r--r--test/prism/snapshots/seattlerb/case_in_find_array.txt4
-rw-r--r--test/prism/snapshots/seattlerb/case_in_hash_pat.txt6
-rw-r--r--test/prism/snapshots/seattlerb/case_in_hash_pat_assign.txt14
-rw-r--r--test/prism/snapshots/seattlerb/case_in_hash_pat_paren_assign.txt8
-rw-r--r--test/prism/snapshots/seattlerb/case_in_hash_pat_paren_true.txt5
-rw-r--r--test/prism/snapshots/seattlerb/case_in_hash_pat_rest.txt41
-rw-r--r--test/prism/snapshots/seattlerb/case_in_hash_pat_rest_solo.txt4
-rw-r--r--test/prism/snapshots/seattlerb/case_in_if_unless_post_mod.txt7
-rw-r--r--test/prism/snapshots/seattlerb/case_in_multiple.txt19
-rw-r--r--test/prism/snapshots/seattlerb/case_in_or.txt4
-rw-r--r--test/prism/snapshots/seattlerb/cond_unary_minus.txt4
-rw-r--r--test/prism/snapshots/seattlerb/const_2_op_asgn_or2.txt17
-rw-r--r--test/prism/snapshots/seattlerb/const_3_op_asgn_or.txt10
-rw-r--r--test/prism/snapshots/seattlerb/const_op_asgn_and1.txt14
-rw-r--r--test/prism/snapshots/seattlerb/const_op_asgn_and2.txt10
-rw-r--r--test/prism/snapshots/seattlerb/const_op_asgn_or.txt10
-rw-r--r--test/prism/snapshots/seattlerb/dasgn_icky2.txt61
-rw-r--r--test/prism/snapshots/seattlerb/defined_eh_parens.txt3
-rw-r--r--test/prism/snapshots/seattlerb/defn_arg_asplat_arg.txt5
-rw-r--r--test/prism/snapshots/seattlerb/defn_arg_forward_args.txt21
-rw-r--r--test/prism/snapshots/seattlerb/defn_args_forward_args.txt34
-rw-r--r--test/prism/snapshots/seattlerb/defn_endless_command.txt15
-rw-r--r--test/prism/snapshots/seattlerb/defn_endless_command_rescue.txt44
-rw-r--r--test/prism/snapshots/seattlerb/defn_forward_args.txt14
-rw-r--r--test/prism/snapshots/seattlerb/defn_forward_args__no_parens.txt14
-rw-r--r--test/prism/snapshots/seattlerb/defn_kwarg_env.txt28
-rw-r--r--test/prism/snapshots/seattlerb/defn_kwarg_kwarg.txt9
-rw-r--r--test/prism/snapshots/seattlerb/defn_kwarg_kwsplat.txt5
-rw-r--r--test/prism/snapshots/seattlerb/defn_kwarg_kwsplat_anon.txt7
-rw-r--r--test/prism/snapshots/seattlerb/defn_kwarg_lvar.txt2
-rw-r--r--test/prism/snapshots/seattlerb/defn_kwarg_no_parens.txt4
-rw-r--r--test/prism/snapshots/seattlerb/defn_kwarg_val.txt5
-rw-r--r--test/prism/snapshots/seattlerb/defn_oneliner.txt17
-rw-r--r--test/prism/snapshots/seattlerb/defn_oneliner_eq2.txt4
-rw-r--r--test/prism/snapshots/seattlerb/defn_oneliner_noargs.txt6
-rw-r--r--test/prism/snapshots/seattlerb/defn_oneliner_noargs_parentheses.txt6
-rw-r--r--test/prism/snapshots/seattlerb/defn_oneliner_rescue.txt53
-rw-r--r--test/prism/snapshots/seattlerb/defn_opt_last_arg.txt1
-rw-r--r--test/prism/snapshots/seattlerb/defn_opt_reg.txt2
-rw-r--r--test/prism/snapshots/seattlerb/defn_opt_splat_arg.txt6
-rw-r--r--test/prism/snapshots/seattlerb/defn_powarg.txt1
-rw-r--r--test/prism/snapshots/seattlerb/defn_reg_opt_reg.txt4
-rw-r--r--test/prism/snapshots/seattlerb/defn_splat_arg.txt4
-rw-r--r--test/prism/snapshots/seattlerb/defn_unary_not.txt2
-rw-r--r--test/prism/snapshots/seattlerb/defs_as_arg_with_do_block_inside.txt94
-rw-r--r--test/prism/snapshots/seattlerb/defs_endless_command.txt21
-rw-r--r--test/prism/snapshots/seattlerb/defs_endless_command_rescue.txt50
-rw-r--r--test/prism/snapshots/seattlerb/defs_kwarg.txt4
-rw-r--r--test/prism/snapshots/seattlerb/defs_oneliner.txt17
-rw-r--r--test/prism/snapshots/seattlerb/defs_oneliner_eq2.txt4
-rw-r--r--test/prism/snapshots/seattlerb/defs_oneliner_rescue.txt53
-rw-r--r--test/prism/snapshots/seattlerb/difficult0_.txt119
-rw-r--r--test/prism/snapshots/seattlerb/difficult1_line_numbers.txt219
-rw-r--r--test/prism/snapshots/seattlerb/difficult1_line_numbers2.txt51
-rw-r--r--test/prism/snapshots/seattlerb/difficult2_.txt68
-rw-r--r--test/prism/snapshots/seattlerb/difficult3_.txt77
-rw-r--r--test/prism/snapshots/seattlerb/difficult3_2.txt58
-rw-r--r--test/prism/snapshots/seattlerb/difficult3_3.txt67
-rw-r--r--test/prism/snapshots/seattlerb/difficult3_4.txt7
-rw-r--r--test/prism/snapshots/seattlerb/difficult3_5.txt70
-rw-r--r--test/prism/snapshots/seattlerb/difficult3__10.txt77
-rw-r--r--test/prism/snapshots/seattlerb/difficult3__11.txt67
-rw-r--r--test/prism/snapshots/seattlerb/difficult3__12.txt72
-rw-r--r--test/prism/snapshots/seattlerb/difficult3__6.txt82
-rw-r--r--test/prism/snapshots/seattlerb/difficult3__7.txt72
-rw-r--r--test/prism/snapshots/seattlerb/difficult3__8.txt77
-rw-r--r--test/prism/snapshots/seattlerb/difficult3__9.txt72
-rw-r--r--test/prism/snapshots/seattlerb/difficult4__leading_dots.txt12
-rw-r--r--test/prism/snapshots/seattlerb/difficult4__leading_dots2.txt10
-rw-r--r--test/prism/snapshots/seattlerb/difficult6_.txt33
-rw-r--r--test/prism/snapshots/seattlerb/difficult6__7.txt69
-rw-r--r--test/prism/snapshots/seattlerb/difficult6__8.txt69
-rw-r--r--test/prism/snapshots/seattlerb/difficult7_.txt113
-rw-r--r--test/prism/snapshots/seattlerb/do_bug.txt70
-rw-r--r--test/prism/snapshots/seattlerb/dot2_nil__26.txt10
-rw-r--r--test/prism/snapshots/seattlerb/dot3_nil__26.txt10
-rw-r--r--test/prism/snapshots/seattlerb/dstr_evstr.txt9
-rw-r--r--test/prism/snapshots/seattlerb/dstr_evstr_empty_end.txt6
-rw-r--r--test/prism/snapshots/seattlerb/dstr_lex_state.txt22
-rw-r--r--test/prism/snapshots/seattlerb/dstr_str.txt5
-rw-r--r--test/prism/snapshots/seattlerb/dsym_esc_to_sym.txt1
-rw-r--r--test/prism/snapshots/seattlerb/dsym_to_sym.txt4
-rw-r--r--test/prism/snapshots/seattlerb/eq_begin_line_numbers.txt6
-rw-r--r--test/prism/snapshots/seattlerb/eq_begin_why_wont_people_use_their_spacebar.txt59
-rw-r--r--test/prism/snapshots/seattlerb/evstr_evstr.txt13
-rw-r--r--test/prism/snapshots/seattlerb/evstr_str.txt9
-rw-r--r--test/prism/snapshots/seattlerb/expr_not_bang.txt36
-rw-r--r--test/prism/snapshots/seattlerb/f_kw.txt4
-rw-r--r--test/prism/snapshots/seattlerb/f_kw__required.txt1
-rw-r--r--test/prism/snapshots/seattlerb/flip2_env_lvar.txt17
-rw-r--r--test/prism/snapshots/seattlerb/float_with_if_modifier.txt2
-rw-r--r--test/prism/snapshots/seattlerb/heredoc__backslash_dos_format.txt2
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_bad_hex_escape.txt2
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_bad_oct_escape.txt2
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_comma_arg.txt2
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_lineno.txt3
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_nested.txt11
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_squiggly.txt7
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_squiggly_blank_line_plus_interpolation.txt95
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_squiggly_blank_lines.txt7
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_squiggly_interp.txt12
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_squiggly_tabs.txt5
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_squiggly_tabs_extra.txt5
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_squiggly_visually_blank_lines.txt7
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_trailing_slash_continued_call.txt6
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_with_carriage_return_escapes_windows.txt2
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_with_extra_carriage_horrible_mix.txt2
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_with_extra_carriage_returns.txt2
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_with_extra_carriage_returns_windows.txt2
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_with_interpolation_and_carriage_return_escapes.txt5
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_with_interpolation_and_carriage_return_escapes_windows.txt7
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_with_only_carriage_returns.txt2
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_with_only_carriage_returns_windows.txt2
-rw-r--r--test/prism/snapshots/seattlerb/if_elsif.txt8
-rw-r--r--test/prism/snapshots/seattlerb/if_symbol.txt22
-rw-r--r--test/prism/snapshots/seattlerb/index_0.txt36
-rw-r--r--test/prism/snapshots/seattlerb/index_0_opasgn.txt18
-rw-r--r--test/prism/snapshots/seattlerb/integer_with_if_modifier.txt4
-rw-r--r--test/prism/snapshots/seattlerb/interpolated_symbol_array_line_breaks.txt6
-rw-r--r--test/prism/snapshots/seattlerb/interpolated_word_array_line_breaks.txt4
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_1.txt54
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_10_1.txt74
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_10_2.txt83
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_11_1.txt79
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_11_2.txt88
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_2__19.txt66
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_3.txt76
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_4.txt63
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_5.txt58
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_6.txt70
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_7_1.txt69
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_7_2.txt78
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_8_1.txt74
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_8_2.txt83
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_9_1.txt65
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_9_2.txt74
-rw-r--r--test/prism/snapshots/seattlerb/iter_kwarg.txt58
-rw-r--r--test/prism/snapshots/seattlerb/iter_kwarg_kwsplat.txt67
-rw-r--r--test/prism/snapshots/seattlerb/label_vs_string.txt28
-rw-r--r--test/prism/snapshots/seattlerb/lambda_do_vs_brace.txt116
-rw-r--r--test/prism/snapshots/seattlerb/lasgn_arg_rescue_arg.txt6
-rw-r--r--test/prism/snapshots/seattlerb/lasgn_call_bracket_rescue_arg.txt18
-rw-r--r--test/prism/snapshots/seattlerb/lasgn_call_nobracket_rescue_arg.txt44
-rw-r--r--test/prism/snapshots/seattlerb/lasgn_command.txt21
-rw-r--r--test/prism/snapshots/seattlerb/lasgn_env.txt3
-rw-r--r--test/prism/snapshots/seattlerb/lasgn_ivar_env.txt3
-rw-r--r--test/prism/snapshots/seattlerb/lasgn_lasgn_command_call.txt15
-rw-r--r--test/prism/snapshots/seattlerb/lasgn_middle_splat.txt19
-rw-r--r--test/prism/snapshots/seattlerb/magic_encoding_comment.txt1
-rw-r--r--test/prism/snapshots/seattlerb/masgn_anon_splat_arg.txt6
-rw-r--r--test/prism/snapshots/seattlerb/masgn_arg_colon_arg.txt24
-rw-r--r--test/prism/snapshots/seattlerb/masgn_arg_ident.txt24
-rw-r--r--test/prism/snapshots/seattlerb/masgn_arg_splat_arg.txt6
-rw-r--r--test/prism/snapshots/seattlerb/masgn_colon2.txt20
-rw-r--r--test/prism/snapshots/seattlerb/masgn_colon3.txt21
-rw-r--r--test/prism/snapshots/seattlerb/masgn_command_call.txt25
-rw-r--r--test/prism/snapshots/seattlerb/masgn_double_paren.txt6
-rw-r--r--test/prism/snapshots/seattlerb/masgn_lhs_splat.txt10
-rw-r--r--test/prism/snapshots/seattlerb/masgn_paren.txt12
-rw-r--r--test/prism/snapshots/seattlerb/masgn_splat_arg.txt6
-rw-r--r--test/prism/snapshots/seattlerb/masgn_splat_arg_arg.txt6
-rw-r--r--test/prism/snapshots/seattlerb/masgn_star.txt3
-rw-r--r--test/prism/snapshots/seattlerb/masgn_var_star_var.txt6
-rw-r--r--test/prism/snapshots/seattlerb/messy_op_asgn_lineno.txt93
-rw-r--r--test/prism/snapshots/seattlerb/method_call_assoc_trailing_comma.txt39
-rw-r--r--test/prism/snapshots/seattlerb/method_call_trailing_comma.txt21
-rw-r--r--test/prism/snapshots/seattlerb/mlhs_back_anonsplat.txt6
-rw-r--r--test/prism/snapshots/seattlerb/mlhs_back_splat.txt6
-rw-r--r--test/prism/snapshots/seattlerb/mlhs_front_anonsplat.txt6
-rw-r--r--test/prism/snapshots/seattlerb/mlhs_front_splat.txt6
-rw-r--r--test/prism/snapshots/seattlerb/mlhs_keyword.txt20
-rw-r--r--test/prism/snapshots/seattlerb/mlhs_mid_anonsplat.txt6
-rw-r--r--test/prism/snapshots/seattlerb/mlhs_mid_splat.txt6
-rw-r--r--test/prism/snapshots/seattlerb/mlhs_rescue.txt9
-rw-r--r--test/prism/snapshots/seattlerb/multiline_hash_declaration.txt126
-rw-r--r--test/prism/snapshots/seattlerb/non_interpolated_symbol_array_line_breaks.txt6
-rw-r--r--test/prism/snapshots/seattlerb/non_interpolated_word_array_line_breaks.txt4
-rw-r--r--test/prism/snapshots/seattlerb/op_asgn_command_call.txt21
-rw-r--r--test/prism/snapshots/seattlerb/op_asgn_dot_ident_command_call.txt17
-rw-r--r--test/prism/snapshots/seattlerb/op_asgn_index_command_call.txt43
-rw-r--r--test/prism/snapshots/seattlerb/op_asgn_primary_colon_const_command_call.txt41
-rw-r--r--test/prism/snapshots/seattlerb/op_asgn_primary_colon_identifier1.txt9
-rw-r--r--test/prism/snapshots/seattlerb/op_asgn_primary_colon_identifier_command_call.txt36
-rw-r--r--test/prism/snapshots/seattlerb/op_asgn_val_dot_ident_command_call.txt23
-rw-r--r--test/prism/snapshots/seattlerb/parse_if_not_canonical.txt19
-rw-r--r--test/prism/snapshots/seattlerb/parse_if_not_noncanonical.txt19
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_block.txt19
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_block_inline_comment.txt18
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_block_inline_comment_leading_newlines.txt18
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_block_inline_multiline_comment.txt18
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_call_ivar_arg_no_parens_line_break.txt14
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_call_ivar_line_break_paren.txt14
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_call_no_args.txt96
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_defn_complex.txt35
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_defn_no_parens_args.txt1
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_dot2.txt32
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_dot2_open.txt23
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_dot3.txt32
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_dot3_open.txt23
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_dstr_escaped_newline.txt3
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_dstr_soft_newline.txt3
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_evstr_after_break.txt61
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_hash_lit.txt4
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_heredoc.txt22
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_heredoc_evstr.txt11
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_heredoc_regexp_chars.txt16
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_iter_call_no_parens.txt120
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_iter_call_parens.txt120
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_multiline_str.txt3
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_multiline_str_literal_n.txt3
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_op_asgn.txt16
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_postexe.txt6
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_preexe.txt6
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_rescue.txt18
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_return.txt11
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_str_with_newline_escape.txt24
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_to_ary.txt12
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_trailing_newlines.txt12
-rw-r--r--test/prism/snapshots/seattlerb/parse_opt_call_args_assocs_comma.txt36
-rw-r--r--test/prism/snapshots/seattlerb/parse_opt_call_args_lit_comma.txt18
-rw-r--r--test/prism/snapshots/seattlerb/parse_pattern_019.txt15
-rw-r--r--test/prism/snapshots/seattlerb/parse_pattern_044.txt8
-rw-r--r--test/prism/snapshots/seattlerb/parse_pattern_051.txt21
-rw-r--r--test/prism/snapshots/seattlerb/parse_pattern_058.txt45
-rw-r--r--test/prism/snapshots/seattlerb/parse_pattern_058_2.txt41
-rw-r--r--test/prism/snapshots/seattlerb/parse_pattern_069.txt10
-rw-r--r--test/prism/snapshots/seattlerb/parse_pattern_076.txt40
-rw-r--r--test/prism/snapshots/seattlerb/parse_until_not_canonical.txt38
-rw-r--r--test/prism/snapshots/seattlerb/parse_until_not_noncanonical.txt38
-rw-r--r--test/prism/snapshots/seattlerb/parse_while_not_canonical.txt38
-rw-r--r--test/prism/snapshots/seattlerb/parse_while_not_noncanonical.txt38
-rw-r--r--test/prism/snapshots/seattlerb/pctW_lineno.txt1
-rw-r--r--test/prism/snapshots/seattlerb/pct_w_heredoc_interp_nested.txt4
-rw-r--r--test/prism/snapshots/seattlerb/pipe_semicolon.txt39
-rw-r--r--test/prism/snapshots/seattlerb/pipe_space.txt34
-rw-r--r--test/prism/snapshots/seattlerb/qWords_space.txt1
-rw-r--r--test/prism/snapshots/seattlerb/qsymbols.txt4
-rw-r--r--test/prism/snapshots/seattlerb/qsymbols_empty.txt1
-rw-r--r--test/prism/snapshots/seattlerb/qsymbols_empty_space.txt1
-rw-r--r--test/prism/snapshots/seattlerb/qsymbols_interp.txt23
-rw-r--r--test/prism/snapshots/seattlerb/quoted_symbol_hash_arg.txt42
-rw-r--r--test/prism/snapshots/seattlerb/quoted_symbol_keys.txt2
-rw-r--r--test/prism/snapshots/seattlerb/qwords_empty.txt1
-rw-r--r--test/prism/snapshots/seattlerb/read_escape_unicode_curlies.txt2
-rw-r--r--test/prism/snapshots/seattlerb/read_escape_unicode_h4.txt2
-rw-r--r--test/prism/snapshots/seattlerb/regexp.txt20
-rw-r--r--test/prism/snapshots/seattlerb/regexp_esc_C_slash.txt4
-rw-r--r--test/prism/snapshots/seattlerb/regexp_esc_u.txt4
-rw-r--r--test/prism/snapshots/seattlerb/regexp_escape_extended.txt4
-rw-r--r--test/prism/snapshots/seattlerb/regexp_unicode_curlies.txt8
-rw-r--r--test/prism/snapshots/seattlerb/required_kwarg_no_value.txt2
-rw-r--r--test/prism/snapshots/seattlerb/rescue_do_end_ensure_result.txt76
-rw-r--r--test/prism/snapshots/seattlerb/rescue_do_end_no_raise.txt122
-rw-r--r--test/prism/snapshots/seattlerb/rescue_do_end_raised.txt79
-rw-r--r--test/prism/snapshots/seattlerb/rescue_do_end_rescued.txt131
-rw-r--r--test/prism/snapshots/seattlerb/rescue_in_block.txt70
-rw-r--r--test/prism/snapshots/seattlerb/rescue_parens.txt70
-rw-r--r--test/prism/snapshots/seattlerb/return_call_assocs.txt351
-rw-r--r--test/prism/snapshots/seattlerb/rhs_asgn.txt3
-rw-r--r--test/prism/snapshots/seattlerb/ruby21_numbers.txt16
-rw-r--r--test/prism/snapshots/seattlerb/safe_attrasgn.txt21
-rw-r--r--test/prism/snapshots/seattlerb/safe_attrasgn_constant.txt21
-rw-r--r--test/prism/snapshots/seattlerb/safe_call.txt12
-rw-r--r--test/prism/snapshots/seattlerb/safe_call_after_newline.txt12
-rw-r--r--test/prism/snapshots/seattlerb/safe_call_dot_parens.txt12
-rw-r--r--test/prism/snapshots/seattlerb/safe_call_newline.txt12
-rw-r--r--test/prism/snapshots/seattlerb/safe_call_operator.txt21
-rw-r--r--test/prism/snapshots/seattlerb/safe_call_rhs_newline.txt12
-rw-r--r--test/prism/snapshots/seattlerb/safe_calls.txt27
-rw-r--r--test/prism/snapshots/seattlerb/safe_op_asgn.txt27
-rw-r--r--test/prism/snapshots/seattlerb/safe_op_asgn2.txt14
-rw-r--r--test/prism/snapshots/seattlerb/slashy_newlines_within_string.txt58
-rw-r--r--test/prism/snapshots/seattlerb/stabby_arg_no_paren.txt1
-rw-r--r--test/prism/snapshots/seattlerb/stabby_arg_opt_splat_arg_block_omfg.txt8
-rw-r--r--test/prism/snapshots/seattlerb/stabby_block_iter_call.txt90
-rw-r--r--test/prism/snapshots/seattlerb/stabby_block_iter_call_no_target_with_arg.txt81
-rw-r--r--test/prism/snapshots/seattlerb/stabby_block_kw.txt4
-rw-r--r--test/prism/snapshots/seattlerb/stabby_block_kw__required.txt1
-rw-r--r--test/prism/snapshots/seattlerb/stabby_proc_scope.txt2
-rw-r--r--test/prism/snapshots/seattlerb/str_backslashes.txt22
-rw-r--r--test/prism/snapshots/seattlerb/str_double_double_escaped_newline.txt28
-rw-r--r--test/prism/snapshots/seattlerb/str_double_escaped_newline.txt28
-rw-r--r--test/prism/snapshots/seattlerb/str_double_newline.txt28
-rw-r--r--test/prism/snapshots/seattlerb/str_evstr.txt9
-rw-r--r--test/prism/snapshots/seattlerb/str_evstr_escape.txt11
-rw-r--r--test/prism/snapshots/seattlerb/str_heredoc_interp.txt9
-rw-r--r--test/prism/snapshots/seattlerb/str_interp_ternary_or_label.txt66
-rw-r--r--test/prism/snapshots/seattlerb/str_lit_concat_bad_encodings.txt32
-rw-r--r--test/prism/snapshots/seattlerb/str_newline_hash_line_number.txt3
-rw-r--r--test/prism/snapshots/seattlerb/str_pct_Q_nested.txt11
-rw-r--r--test/prism/snapshots/seattlerb/str_pct_nested_nested.txt9
-rw-r--r--test/prism/snapshots/seattlerb/str_single_double_escaped_newline.txt28
-rw-r--r--test/prism/snapshots/seattlerb/str_single_escaped_newline.txt28
-rw-r--r--test/prism/snapshots/seattlerb/str_single_newline.txt28
-rw-r--r--test/prism/snapshots/seattlerb/str_str.txt5
-rw-r--r--test/prism/snapshots/seattlerb/str_str_str.txt7
-rw-r--r--test/prism/snapshots/seattlerb/super_arg.txt9
-rw-r--r--test/prism/snapshots/seattlerb/symbol_empty.txt1
-rw-r--r--test/prism/snapshots/seattlerb/symbol_list.txt13
-rw-r--r--test/prism/snapshots/seattlerb/symbols.txt4
-rw-r--r--test/prism/snapshots/seattlerb/symbols_empty.txt1
-rw-r--r--test/prism/snapshots/seattlerb/symbols_empty_space.txt1
-rw-r--r--test/prism/snapshots/seattlerb/symbols_interp.txt4
-rw-r--r--test/prism/snapshots/seattlerb/thingy.txt42
-rw-r--r--test/prism/snapshots/seattlerb/uminus_float.txt1
-rw-r--r--test/prism/snapshots/seattlerb/unary_minus.txt12
-rw-r--r--test/prism/snapshots/seattlerb/unary_plus.txt12
-rw-r--r--test/prism/snapshots/seattlerb/unary_plus_on_literal.txt7
-rw-r--r--test/prism/snapshots/seattlerb/unary_tilde.txt12
-rw-r--r--test/prism/snapshots/seattlerb/utf8_bom.txt15
-rw-r--r--test/prism/snapshots/seattlerb/when_splat.txt15
-rw-r--r--test/prism/snapshots/seattlerb/words_interp.txt7
-rw-r--r--test/prism/snapshots/seattlerb/yield_arg.txt15
-rw-r--r--test/prism/snapshots/seattlerb/yield_call_assocs.txt203
-rw-r--r--test/prism/snapshots/seattlerb/yield_empty_parens.txt10
-rw-r--r--test/prism/snapshots/single_method_call_with_bang.txt15
-rw-r--r--test/prism/snapshots/spanning_heredoc.txt624
-rw-r--r--test/prism/snapshots/spanning_heredoc_newlines.txt155
-rw-r--r--test/prism/snapshots/strings.txt99
-rw-r--r--test/prism/snapshots/super.txt77
-rw-r--r--test/prism/snapshots/symbols.txt103
-rw-r--r--test/prism/snapshots/ternary_operator.txt98
-rw-r--r--test/prism/snapshots/tilde_heredocs.txt118
-rw-r--r--test/prism/snapshots/undef.txt16
-rw-r--r--test/prism/snapshots/unescaping.txt5
-rw-r--r--test/prism/snapshots/unless.txt142
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/alias.txt2
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/assignment.txt770
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/block.txt2198
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/case.txt209
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/class.txt102
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/control.txt135
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/def.txt207
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/defined.txt7
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/defs.txt150
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/dstr.txt289
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/flipflop.txt284
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/for.txt122
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/hookexe.txt18
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/if.txt134
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/kwbegin.txt105
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/lambda.txt88
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/literal.txt535
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/module.txt56
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/opasgn.txt402
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/pattern.txt96
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/pragma.txt7
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/range.txt34
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/rescue.txt74
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/send.txt2344
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/since/27.txt27
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/since/30.txt15
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/since/31.txt31
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/since/32.txt161
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/super.txt260
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/unary.txt129
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/undef.txt3
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/variables.txt34
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/while.txt887
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/yield.txt56
-rw-r--r--test/prism/snapshots/unparser/corpus/semantic/and.txt130
-rw-r--r--test/prism/snapshots/unparser/corpus/semantic/block.txt282
-rw-r--r--test/prism/snapshots/unparser/corpus/semantic/def.txt42
-rw-r--r--test/prism/snapshots/unparser/corpus/semantic/dstr.txt367
-rw-r--r--test/prism/snapshots/unparser/corpus/semantic/kwbegin.txt60
-rw-r--r--test/prism/snapshots/unparser/corpus/semantic/literal.txt92
-rw-r--r--test/prism/snapshots/unparser/corpus/semantic/opasgn.txt69
-rw-r--r--test/prism/snapshots/unparser/corpus/semantic/send.txt195
-rw-r--r--test/prism/snapshots/unparser/corpus/semantic/undef.txt3
-rw-r--r--test/prism/snapshots/unparser/corpus/semantic/while.txt322
-rw-r--r--test/prism/snapshots/until.txt217
-rw-r--r--test/prism/snapshots/variables.txt128
-rw-r--r--test/prism/snapshots/while.txt672
-rw-r--r--test/prism/snapshots/whitequark/alias.txt2
-rw-r--r--test/prism/snapshots/whitequark/ambiuous_quoted_label_in_ternary_operator.txt35
-rw-r--r--test/prism/snapshots/whitequark/and.txt24
-rw-r--r--test/prism/snapshots/whitequark/and_asgn.txt36
-rw-r--r--test/prism/snapshots/whitequark/and_or_masgn.txt24
-rw-r--r--test/prism/snapshots/whitequark/anonymous_blockarg.txt15
-rw-r--r--test/prism/snapshots/whitequark/arg.txt3
-rw-r--r--test/prism/snapshots/whitequark/arg_duplicate_ignored.txt4
-rw-r--r--test/prism/snapshots/whitequark/arg_label.txt111
-rw-r--r--test/prism/snapshots/whitequark/arg_scope.txt43
-rw-r--r--test/prism/snapshots/whitequark/args.txt108
-rw-r--r--test/prism/snapshots/whitequark/args_args_assocs.txt144
-rw-r--r--test/prism/snapshots/whitequark/args_args_assocs_comma.txt65
-rw-r--r--test/prism/snapshots/whitequark/args_args_comma.txt36
-rw-r--r--test/prism/snapshots/whitequark/args_args_star.txt138
-rw-r--r--test/prism/snapshots/whitequark/args_assocs.txt177
-rw-r--r--test/prism/snapshots/whitequark/args_assocs_comma.txt45
-rw-r--r--test/prism/snapshots/whitequark/args_assocs_legacy.txt177
-rw-r--r--test/prism/snapshots/whitequark/args_block_pass.txt32
-rw-r--r--test/prism/snapshots/whitequark/args_cmd.txt56
-rw-r--r--test/prism/snapshots/whitequark/args_star.txt98
-rw-r--r--test/prism/snapshots/whitequark/array_assocs.txt19
-rw-r--r--test/prism/snapshots/whitequark/array_plain.txt7
-rw-r--r--test/prism/snapshots/whitequark/array_splat.txt30
-rw-r--r--test/prism/snapshots/whitequark/array_symbols.txt3
-rw-r--r--test/prism/snapshots/whitequark/array_symbols_empty.txt2
-rw-r--r--test/prism/snapshots/whitequark/array_symbols_interp.txt17
-rw-r--r--test/prism/snapshots/whitequark/array_words.txt1
-rw-r--r--test/prism/snapshots/whitequark/array_words_empty.txt2
-rw-r--r--test/prism/snapshots/whitequark/array_words_interp.txt18
-rw-r--r--test/prism/snapshots/whitequark/asgn_cmd.txt32
-rw-r--r--test/prism/snapshots/whitequark/asgn_mrhs.txt30
-rw-r--r--test/prism/snapshots/whitequark/bang.txt12
-rw-r--r--test/prism/snapshots/whitequark/bang_cmd.txt36
-rw-r--r--test/prism/snapshots/whitequark/begin_cmdarg.txt74
-rw-r--r--test/prism/snapshots/whitequark/beginless_erange_after_newline.txt13
-rw-r--r--test/prism/snapshots/whitequark/beginless_irange_after_newline.txt13
-rw-r--r--test/prism/snapshots/whitequark/beginless_range.txt14
-rw-r--r--test/prism/snapshots/whitequark/blockarg.txt1
-rw-r--r--test/prism/snapshots/whitequark/blockargs.txt2098
-rw-r--r--test/prism/snapshots/whitequark/break.txt56
-rw-r--r--test/prism/snapshots/whitequark/break_block.txt40
-rw-r--r--test/prism/snapshots/whitequark/bug_435.txt2
-rw-r--r--test/prism/snapshots/whitequark/bug_447.txt67
-rw-r--r--test/prism/snapshots/whitequark/bug_452.txt71
-rw-r--r--test/prism/snapshots/whitequark/bug_466.txt111
-rw-r--r--test/prism/snapshots/whitequark/bug_473.txt40
-rw-r--r--test/prism/snapshots/whitequark/bug_480.txt47
-rw-r--r--test/prism/snapshots/whitequark/bug_481.txt57
-rw-r--r--test/prism/snapshots/whitequark/bug_ascii_8bit_in_literal.txt2
-rw-r--r--test/prism/snapshots/whitequark/bug_cmd_string_lookahead.txt34
-rw-r--r--test/prism/snapshots/whitequark/bug_cmdarg.txt150
-rw-r--r--test/prism/snapshots/whitequark/bug_do_block_in_call_args.txt74
-rw-r--r--test/prism/snapshots/whitequark/bug_do_block_in_cmdarg.txt54
-rw-r--r--test/prism/snapshots/whitequark/bug_do_block_in_hash_brace.txt663
-rw-r--r--test/prism/snapshots/whitequark/bug_heredoc_do.txt34
-rw-r--r--test/prism/snapshots/whitequark/bug_interp_single.txt9
-rw-r--r--test/prism/snapshots/whitequark/bug_lambda_leakage.txt7
-rw-r--r--test/prism/snapshots/whitequark/bug_regex_verification.txt4
-rw-r--r--test/prism/snapshots/whitequark/bug_while_not_parens_do.txt10
-rw-r--r--test/prism/snapshots/whitequark/case_cond.txt7
-rw-r--r--test/prism/snapshots/whitequark/case_cond_else.txt7
-rw-r--r--test/prism/snapshots/whitequark/case_expr.txt15
-rw-r--r--test/prism/snapshots/whitequark/case_expr_else.txt21
-rw-r--r--test/prism/snapshots/whitequark/casgn_scoped.txt10
-rw-r--r--test/prism/snapshots/whitequark/casgn_toplevel.txt10
-rw-r--r--test/prism/snapshots/whitequark/casgn_unscoped.txt3
-rw-r--r--test/prism/snapshots/whitequark/class_definition_in_while_cond.txt171
-rw-r--r--test/prism/snapshots/whitequark/class_super_label.txt21
-rw-r--r--test/prism/snapshots/whitequark/comments_before_leading_dot__27.txt48
-rw-r--r--test/prism/snapshots/whitequark/complex.txt15
-rw-r--r--test/prism/snapshots/whitequark/cond_begin.txt13
-rw-r--r--test/prism/snapshots/whitequark/cond_begin_masgn.txt13
-rw-r--r--test/prism/snapshots/whitequark/cond_eflipflop.txt39
-rw-r--r--test/prism/snapshots/whitequark/cond_eflipflop_with_beginless_range.txt27
-rw-r--r--test/prism/snapshots/whitequark/cond_eflipflop_with_endless_range.txt27
-rw-r--r--test/prism/snapshots/whitequark/cond_iflipflop.txt39
-rw-r--r--test/prism/snapshots/whitequark/cond_iflipflop_with_beginless_range.txt27
-rw-r--r--test/prism/snapshots/whitequark/cond_iflipflop_with_endless_range.txt27
-rw-r--r--test/prism/snapshots/whitequark/cond_match_current_line.txt15
-rw-r--r--test/prism/snapshots/whitequark/const_op_asgn.txt55
-rw-r--r--test/prism/snapshots/whitequark/const_scoped.txt7
-rw-r--r--test/prism/snapshots/whitequark/const_toplevel.txt7
-rw-r--r--test/prism/snapshots/whitequark/cpath.txt14
-rw-r--r--test/prism/snapshots/whitequark/cvasgn.txt3
-rw-r--r--test/prism/snapshots/whitequark/dedenting_heredoc.txt715
-rw-r--r--test/prism/snapshots/whitequark/dedenting_interpolating_heredoc_fake_line_continuation.txt5
-rw-r--r--test/prism/snapshots/whitequark/dedenting_non_interpolating_heredoc_line_continuation.txt5
-rw-r--r--test/prism/snapshots/whitequark/defined.txt12
-rw-r--r--test/prism/snapshots/whitequark/defs.txt6
-rw-r--r--test/prism/snapshots/whitequark/endless_comparison_method.txt42
-rw-r--r--test/prism/snapshots/whitequark/endless_method.txt50
-rw-r--r--test/prism/snapshots/whitequark/endless_method_command_syntax.txt312
-rw-r--r--test/prism/snapshots/whitequark/endless_method_forwarded_args_legacy.txt14
-rw-r--r--test/prism/snapshots/whitequark/endless_method_with_rescue_mod.txt12
-rw-r--r--test/prism/snapshots/whitequark/endless_method_without_args.txt12
-rw-r--r--test/prism/snapshots/whitequark/ensure.txt12
-rw-r--r--test/prism/snapshots/whitequark/float.txt2
-rw-r--r--test/prism/snapshots/whitequark/for.txt48
-rw-r--r--test/prism/snapshots/whitequark/for_mlhs.txt32
-rw-r--r--test/prism/snapshots/whitequark/forward_arg.txt14
-rw-r--r--test/prism/snapshots/whitequark/forward_arg_with_open_args.txt132
-rw-r--r--test/prism/snapshots/whitequark/forward_args_legacy.txt24
-rw-r--r--test/prism/snapshots/whitequark/forwarded_argument_with_kwrestarg.txt31
-rw-r--r--test/prism/snapshots/whitequark/forwarded_argument_with_restarg.txt26
-rw-r--r--test/prism/snapshots/whitequark/forwarded_kwrestarg.txt24
-rw-r--r--test/prism/snapshots/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt45
-rw-r--r--test/prism/snapshots/whitequark/forwarded_restarg.txt19
-rw-r--r--test/prism/snapshots/whitequark/gvasgn.txt3
-rw-r--r--test/prism/snapshots/whitequark/hash_hashrocket.txt13
-rw-r--r--test/prism/snapshots/whitequark/hash_kwsplat.txt10
-rw-r--r--test/prism/snapshots/whitequark/hash_label.txt4
-rw-r--r--test/prism/snapshots/whitequark/hash_label_end.txt85
-rw-r--r--test/prism/snapshots/whitequark/hash_pair_value_omission.txt22
-rw-r--r--test/prism/snapshots/whitequark/heredoc.txt1
-rw-r--r--test/prism/snapshots/whitequark/if.txt26
-rw-r--r--test/prism/snapshots/whitequark/if_else.txt38
-rw-r--r--test/prism/snapshots/whitequark/if_elsif.txt26
-rw-r--r--test/prism/snapshots/whitequark/if_masgn__24.txt7
-rw-r--r--test/prism/snapshots/whitequark/if_mod.txt13
-rw-r--r--test/prism/snapshots/whitequark/if_nl_then.txt13
-rw-r--r--test/prism/snapshots/whitequark/if_while_after_class__since_32.txt117
-rw-r--r--test/prism/snapshots/whitequark/int.txt9
-rw-r--r--test/prism/snapshots/whitequark/interp_digit_var.txt40
-rw-r--r--test/prism/snapshots/whitequark/ivasgn.txt3
-rw-r--r--test/prism/snapshots/whitequark/keyword_argument_omission.txt101
-rw-r--r--test/prism/snapshots/whitequark/kwarg.txt1
-rw-r--r--test/prism/snapshots/whitequark/kwbegin_compstmt.txt12
-rw-r--r--test/prism/snapshots/whitequark/kwnilarg.txt50
-rw-r--r--test/prism/snapshots/whitequark/kwoptarg.txt4
-rw-r--r--test/prism/snapshots/whitequark/kwoptarg_with_kwrestarg_and_forwarded_args.txt25
-rw-r--r--test/prism/snapshots/whitequark/kwrestarg_named.txt1
-rw-r--r--test/prism/snapshots/whitequark/kwrestarg_unnamed.txt3
-rw-r--r--test/prism/snapshots/whitequark/lbrace_arg_after_command_args.txt81
-rw-r--r--test/prism/snapshots/whitequark/lparenarg_after_lvar__since_25.txt90
-rw-r--r--test/prism/snapshots/whitequark/lvar.txt6
-rw-r--r--test/prism/snapshots/whitequark/lvar_injecting_match.txt31
-rw-r--r--test/prism/snapshots/whitequark/lvasgn.txt3
-rw-r--r--test/prism/snapshots/whitequark/masgn.txt21
-rw-r--r--test/prism/snapshots/whitequark/masgn_attr.txt59
-rw-r--r--test/prism/snapshots/whitequark/masgn_cmd.txt16
-rw-r--r--test/prism/snapshots/whitequark/masgn_const.txt14
-rw-r--r--test/prism/snapshots/whitequark/masgn_nested.txt16
-rw-r--r--test/prism/snapshots/whitequark/masgn_splat.txt68
-rw-r--r--test/prism/snapshots/whitequark/method_definition_in_while_cond.txt130
-rw-r--r--test/prism/snapshots/whitequark/multiple_pattern_matches.txt48
-rw-r--r--test/prism/snapshots/whitequark/newline_in_hash_argument.txt120
-rw-r--r--test/prism/snapshots/whitequark/next.txt56
-rw-r--r--test/prism/snapshots/whitequark/next_block.txt40
-rw-r--r--test/prism/snapshots/whitequark/non_lvar_injecting_match.txt31
-rw-r--r--test/prism/snapshots/whitequark/not.txt30
-rw-r--r--test/prism/snapshots/whitequark/not_cmd.txt36
-rw-r--r--test/prism/snapshots/whitequark/not_masgn__24.txt12
-rw-r--r--test/prism/snapshots/whitequark/numbered_args_after_27.txt164
-rw-r--r--test/prism/snapshots/whitequark/numparam_outside_block.txt36
-rw-r--r--test/prism/snapshots/whitequark/numparam_ruby_bug_19025.txt49
-rw-r--r--test/prism/snapshots/whitequark/op_asgn.txt45
-rw-r--r--test/prism/snapshots/whitequark/op_asgn_cmd.txt173
-rw-r--r--test/prism/snapshots/whitequark/op_asgn_index.txt29
-rw-r--r--test/prism/snapshots/whitequark/op_asgn_index_cmd.txt56
-rw-r--r--test/prism/snapshots/whitequark/optarg.txt12
-rw-r--r--test/prism/snapshots/whitequark/or.txt24
-rw-r--r--test/prism/snapshots/whitequark/or_asgn.txt36
-rw-r--r--test/prism/snapshots/whitequark/parser_bug_272.txt57
-rw-r--r--test/prism/snapshots/whitequark/parser_bug_507.txt1
-rw-r--r--test/prism/snapshots/whitequark/parser_bug_525.txt102
-rw-r--r--test/prism/snapshots/whitequark/parser_bug_604.txt88
-rw-r--r--test/prism/snapshots/whitequark/parser_bug_640.txt19
-rw-r--r--test/prism/snapshots/whitequark/parser_bug_645.txt1
-rw-r--r--test/prism/snapshots/whitequark/parser_bug_830.txt4
-rw-r--r--test/prism/snapshots/whitequark/parser_bug_989.txt11
-rw-r--r--test/prism/snapshots/whitequark/parser_drops_truncated_parts_of_squiggly_heredoc.txt3
-rw-r--r--test/prism/snapshots/whitequark/parser_slash_slash_n_escaping_in_literals.txt20
-rw-r--r--test/prism/snapshots/whitequark/pattern_matching__FILE__LINE_literals.txt20
-rw-r--r--test/prism/snapshots/whitequark/pattern_matching_blank_else.txt11
-rw-r--r--test/prism/snapshots/whitequark/pattern_matching_else.txt14
-rw-r--r--test/prism/snapshots/whitequark/pattern_matching_single_line.txt6
-rw-r--r--test/prism/snapshots/whitequark/pattern_matching_single_line_allowed_omission_of_parentheses.txt44
-rw-r--r--test/prism/snapshots/whitequark/postexe.txt3
-rw-r--r--test/prism/snapshots/whitequark/preexe.txt3
-rw-r--r--test/prism/snapshots/whitequark/procarg0.txt115
-rw-r--r--test/prism/snapshots/whitequark/range_exclusive.txt10
-rw-r--r--test/prism/snapshots/whitequark/range_inclusive.txt10
-rw-r--r--test/prism/snapshots/whitequark/rational.txt11
-rw-r--r--test/prism/snapshots/whitequark/redo.txt6
-rw-r--r--test/prism/snapshots/whitequark/regex_interp.txt14
-rw-r--r--test/prism/snapshots/whitequark/regex_plain.txt4
-rw-r--r--test/prism/snapshots/whitequark/resbody_list.txt12
-rw-r--r--test/prism/snapshots/whitequark/resbody_list_mrhs.txt18
-rw-r--r--test/prism/snapshots/whitequark/resbody_list_var.txt18
-rw-r--r--test/prism/snapshots/whitequark/resbody_var.txt24
-rw-r--r--test/prism/snapshots/whitequark/rescue.txt12
-rw-r--r--test/prism/snapshots/whitequark/rescue_else.txt18
-rw-r--r--test/prism/snapshots/whitequark/rescue_else_ensure.txt24
-rw-r--r--test/prism/snapshots/whitequark/rescue_ensure.txt18
-rw-r--r--test/prism/snapshots/whitequark/rescue_in_lambda_block.txt2
-rw-r--r--test/prism/snapshots/whitequark/rescue_mod.txt12
-rw-r--r--test/prism/snapshots/whitequark/rescue_mod_asgn.txt12
-rw-r--r--test/prism/snapshots/whitequark/rescue_mod_masgn.txt13
-rw-r--r--test/prism/snapshots/whitequark/rescue_mod_op_assign.txt16
-rw-r--r--test/prism/snapshots/whitequark/rescue_without_begin_end.txt94
-rw-r--r--test/prism/snapshots/whitequark/restarg_named.txt1
-rw-r--r--test/prism/snapshots/whitequark/restarg_unnamed.txt3
-rw-r--r--test/prism/snapshots/whitequark/retry.txt6
-rw-r--r--test/prism/snapshots/whitequark/return.txt76
-rw-r--r--test/prism/snapshots/whitequark/return_block.txt63
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_10279.txt5
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_10653.txt166
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_11107.txt70
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_11380.txt80
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_11873.txt1332
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_11873_a.txt2112
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_11873_b.txt170
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_11989.txt22
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_11990.txt42
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_12073.txt80
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_12402.txt690
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_12669.txt100
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_12686.txt52
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_13547.txt24
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_14690.txt92
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_15789.txt192
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_9669.txt6
-rw-r--r--test/prism/snapshots/whitequark/sclass.txt6
-rw-r--r--test/prism/snapshots/whitequark/send_attr_asgn.txt79
-rw-r--r--test/prism/snapshots/whitequark/send_attr_asgn_conditional.txt21
-rw-r--r--test/prism/snapshots/whitequark/send_binary_op.txt441
-rw-r--r--test/prism/snapshots/whitequark/send_block_chain_cmd.txt411
-rw-r--r--test/prism/snapshots/whitequark/send_block_conditional.txt24
-rw-r--r--test/prism/snapshots/whitequark/send_call.txt42
-rw-r--r--test/prism/snapshots/whitequark/send_conditional.txt12
-rw-r--r--test/prism/snapshots/whitequark/send_index.txt26
-rw-r--r--test/prism/snapshots/whitequark/send_index_asgn.txt31
-rw-r--r--test/prism/snapshots/whitequark/send_index_asgn_legacy.txt31
-rw-r--r--test/prism/snapshots/whitequark/send_index_cmd.txt62
-rw-r--r--test/prism/snapshots/whitequark/send_index_legacy.txt26
-rw-r--r--test/prism/snapshots/whitequark/send_lambda.txt1
-rw-r--r--test/prism/snapshots/whitequark/send_lambda_args.txt2
-rw-r--r--test/prism/snapshots/whitequark/send_lambda_args_noparen.txt5
-rw-r--r--test/prism/snapshots/whitequark/send_lambda_args_shadow.txt3
-rw-r--r--test/prism/snapshots/whitequark/send_op_asgn_conditional.txt11
-rw-r--r--test/prism/snapshots/whitequark/send_plain.txt36
-rw-r--r--test/prism/snapshots/whitequark/send_plain_cmd.txt108
-rw-r--r--test/prism/snapshots/whitequark/send_self.txt27
-rw-r--r--test/prism/snapshots/whitequark/send_self_block.txt81
-rw-r--r--test/prism/snapshots/whitequark/send_unary_op.txt36
-rw-r--r--test/prism/snapshots/whitequark/slash_newline_in_heredocs.txt19
-rw-r--r--test/prism/snapshots/whitequark/space_args_arg.txt27
-rw-r--r--test/prism/snapshots/whitequark/space_args_arg_block.txt129
-rw-r--r--test/prism/snapshots/whitequark/space_args_arg_call.txt47
-rw-r--r--test/prism/snapshots/whitequark/space_args_arg_newline.txt27
-rw-r--r--test/prism/snapshots/whitequark/space_args_block.txt30
-rw-r--r--test/prism/snapshots/whitequark/space_args_cmd.txt68
-rw-r--r--test/prism/snapshots/whitequark/string___FILE__.txt1
-rw-r--r--test/prism/snapshots/whitequark/string_concat.txt51
-rw-r--r--test/prism/snapshots/whitequark/string_dvar.txt5
-rw-r--r--test/prism/snapshots/whitequark/string_interp.txt11
-rw-r--r--test/prism/snapshots/whitequark/super.txt48
-rw-r--r--test/prism/snapshots/whitequark/super_block.txt44
-rw-r--r--test/prism/snapshots/whitequark/symbol_interp.txt10
-rw-r--r--test/prism/snapshots/whitequark/symbol_plain.txt2
-rw-r--r--test/prism/snapshots/whitequark/ternary.txt13
-rw-r--r--test/prism/snapshots/whitequark/ternary_ambiguous_symbol.txt10
-rw-r--r--test/prism/snapshots/whitequark/trailing_forward_arg.txt27
-rw-r--r--test/prism/snapshots/whitequark/unary_num_pow_precedence.txt62
-rw-r--r--test/prism/snapshots/whitequark/undef.txt7
-rw-r--r--test/prism/snapshots/whitequark/unless.txt26
-rw-r--r--test/prism/snapshots/whitequark/unless_else.txt38
-rw-r--r--test/prism/snapshots/whitequark/unless_mod.txt13
-rw-r--r--test/prism/snapshots/whitequark/until.txt68
-rw-r--r--test/prism/snapshots/whitequark/until_mod.txt34
-rw-r--r--test/prism/snapshots/whitequark/until_post.txt52
-rw-r--r--test/prism/snapshots/whitequark/var_and_asgn.txt3
-rw-r--r--test/prism/snapshots/whitequark/var_op_asgn.txt28
-rw-r--r--test/prism/snapshots/whitequark/var_op_asgn_cmd.txt20
-rw-r--r--test/prism/snapshots/whitequark/var_or_asgn.txt3
-rw-r--r--test/prism/snapshots/whitequark/when_multi.txt17
-rw-r--r--test/prism/snapshots/whitequark/when_splat.txt29
-rw-r--r--test/prism/snapshots/whitequark/when_then.txt15
-rw-r--r--test/prism/snapshots/whitequark/while.txt68
-rw-r--r--test/prism/snapshots/whitequark/while_mod.txt34
-rw-r--r--test/prism/snapshots/whitequark/while_post.txt52
-rw-r--r--test/prism/snapshots/whitequark/xstring_interp.txt10
-rw-r--r--test/prism/snapshots/whitequark/xstring_plain.txt1
-rw-r--r--test/prism/snapshots/whitequark/yield.txt51
-rw-r--r--test/prism/snapshots/xstring.txt47
-rw-r--r--test/prism/snapshots/xstring_with_backslash.txt11
-rw-r--r--test/prism/snapshots/yield.txt134
-rw-r--r--test/prism/snapshots_test.rb73
-rw-r--r--test/prism/snippets_test.rb42
-rw-r--r--test/prism/test_helper.rb244
-rw-r--r--test/prism/unescape_test.rb4
-rw-r--r--test/psych/test_object_references.rb8
-rw-r--r--test/psych/test_psych.rb26
-rw-r--r--test/psych/test_scalar_scanner.rb2
-rw-r--r--test/psych/test_set.rb7
-rw-r--r--test/psych/test_string.rb12
-rw-r--r--test/psych/visitors/test_to_ruby.rb2
-rw-r--r--test/rdoc/test_rdoc_context.rb6
-rw-r--r--test/rdoc/test_rdoc_markdown.rb19
-rw-r--r--test/rdoc/test_rdoc_markup_formatter.rb6
-rw-r--r--test/rdoc/test_rdoc_markup_to_html.rb36
-rw-r--r--test/rdoc/test_rdoc_markup_to_html_crossref.rb12
-rw-r--r--test/rdoc/test_rdoc_markup_to_markdown.rb7
-rw-r--r--test/rdoc/test_rdoc_markup_to_rdoc.rb18
-rw-r--r--test/rdoc/test_rdoc_options.rb23
-rw-r--r--test/rdoc/test_rdoc_parser.rb14
-rw-r--r--test/rdoc/test_rdoc_parser_c.rb43
-rw-r--r--test/rdoc/test_rdoc_parser_ruby.rb22
-rw-r--r--test/rdoc/test_rdoc_rdoc.rb14
-rw-r--r--test/rdoc/test_rdoc_token_stream.rb52
-rw-r--r--test/rdoc/xref_data.rb12
-rw-r--r--test/reline/helper.rb53
-rw-r--r--test/reline/test_ansi_with_terminfo.rb6
-rw-r--r--test/reline/test_ansi_without_terminfo.rb4
-rw-r--r--test/reline/test_config.rb168
-rw-r--r--test/reline/test_key_actor_emacs.rb2044
-rw-r--r--test/reline/test_key_actor_vi.rb1332
-rw-r--r--test/reline/test_key_stroke.rb56
-rw-r--r--test/reline/test_line_editor.rb186
-rw-r--r--test/reline/test_macro.rb1
-rw-r--r--test/reline/test_reline.rb62
-rw-r--r--test/reline/test_reline_key.rb51
-rw-r--r--test/reline/test_string_processing.rb12
-rw-r--r--test/reline/test_terminfo.rb2
-rw-r--r--test/reline/test_unicode.rb31
-rw-r--r--test/reline/test_within_pipe.rb1
-rwxr-xr-xtest/reline/yamatanooroti/multiline_repl19
-rw-r--r--test/reline/yamatanooroti/test_rendering.rb254
-rw-r--r--test/resolv/test_dns.rb243
-rw-r--r--test/resolv/test_resource.rb68
-rw-r--r--test/resolv/test_svcb_https.rb231
-rw-r--r--test/rinda/test_rinda.rb912
-rw-r--r--test/rinda/test_tuplebag.rb173
-rw-r--r--test/ripper/test_lexer.rb138
-rw-r--r--test/ripper/test_parser_events.rb64
-rw-r--r--test/ripper/test_ripper.rb10
-rw-r--r--test/ripper/test_scanner_events.rb14
-rw-r--r--test/ripper/test_sexp.rb28
-rw-r--r--test/ruby/enc/test_case_mapping.rb10
-rw-r--r--test/ruby/enc/test_case_options.rb12
-rw-r--r--test/ruby/rjit/test_assembler.rb14
-rw-r--r--test/ruby/test_allocation.rb777
-rw-r--r--test/ruby/test_argf.rb110
-rw-r--r--test/ruby/test_array.rb32
-rw-r--r--test/ruby/test_ast.rb74
-rw-r--r--test/ruby/test_backtrace.rb56
-rw-r--r--test/ruby/test_beginendblock.rb5
-rw-r--r--test/ruby/test_bignum.rb8
-rw-r--r--test/ruby/test_call.rb234
-rw-r--r--test/ruby/test_class.rb6
-rw-r--r--test/ruby/test_clone.rb7
-rw-r--r--test/ruby/test_compile_prism.rb1748
-rw-r--r--test/ruby/test_complex.rb128
-rw-r--r--test/ruby/test_continuation.rb4
-rw-r--r--test/ruby/test_data.rb17
-rw-r--r--test/ruby/test_default_gems.rb4
-rw-r--r--test/ruby/test_defined.rb12
-rw-r--r--test/ruby/test_dir.rb55
-rw-r--r--test/ruby/test_dir_m17n.rb46
-rw-r--r--test/ruby/test_enum.rb2
-rw-r--r--test/ruby/test_enumerator.rb43
-rw-r--r--test/ruby/test_env.rb4
-rw-r--r--test/ruby/test_exception.rb124
-rw-r--r--test/ruby/test_fiber.rb16
-rw-r--r--test/ruby/test_file.rb279
-rw-r--r--test/ruby/test_gc.rb46
-rw-r--r--test/ruby/test_gc_compact.rb138
-rw-r--r--test/ruby/test_hash.rb832
-rw-r--r--test/ruby/test_integer.rb8
-rw-r--r--test/ruby/test_io.rb9
-rw-r--r--test/ruby/test_io_buffer.rb55
-rw-r--r--test/ruby/test_iseq.rb94
-rw-r--r--test/ruby/test_keyword.rb117
-rw-r--r--test/ruby/test_literal.rb35
-rw-r--r--test/ruby/test_m17n.rb4
-rw-r--r--test/ruby/test_marshal.rb12
-rw-r--r--test/ruby/test_method.rb108
-rw-r--r--test/ruby/test_module.rb25
-rw-r--r--test/ruby/test_nomethod_error.rb2
-rw-r--r--test/ruby/test_object.rb43
-rw-r--r--test/ruby/test_objectspace.rb5
-rw-r--r--test/ruby/test_optimization.rb72
-rw-r--r--test/ruby/test_pack.rb18
-rw-r--r--test/ruby/test_parse.rb341
-rw-r--r--test/ruby/test_pattern_matching.rb10
-rw-r--r--test/ruby/test_proc.rb1
-rw-r--r--test/ruby/test_process.rb207
-rw-r--r--test/ruby/test_range.rb64
-rw-r--r--test/ruby/test_refinement.rb70
-rw-r--r--test/ruby/test_regexp.rb123
-rw-r--r--test/ruby/test_require.rb26
-rw-r--r--test/ruby/test_rubyoptions.rb186
-rw-r--r--test/ruby/test_rubyvm.rb9
-rw-r--r--test/ruby/test_settracefunc.rb167
-rw-r--r--test/ruby/test_shapes.rb353
-rw-r--r--test/ruby/test_sprintf.rb11
-rw-r--r--test/ruby/test_string.rb221
-rw-r--r--test/ruby/test_struct.rb14
-rw-r--r--test/ruby/test_super.rb12
-rw-r--r--test/ruby/test_symbol.rb9
-rw-r--r--test/ruby/test_syntax.rb404
-rw-r--r--test/ruby/test_thread.rb16
-rw-r--r--test/ruby/test_time.rb1
-rw-r--r--test/ruby/test_time_tz.rb8
-rw-r--r--test/ruby/test_transcode.rb2
-rw-r--r--test/ruby/test_vm_dump.rb7
-rw-r--r--test/ruby/test_weakkeymap.rb7
-rw-r--r--test/ruby/test_weakmap.rb5
-rw-r--r--test/ruby/test_whileuntil.rb18
-rw-r--r--test/ruby/test_yjit.rb245
-rw-r--r--test/rubygems/bundler_test_gem.rb16
-rw-r--r--test/rubygems/helper.rb112
-rw-r--r--test/rubygems/installer_test_case.rb8
-rw-r--r--test/rubygems/specifications/rubyforge-0.0.1.gemspec21
-rw-r--r--test/rubygems/test_bundled_ca.rb6
-rw-r--r--test/rubygems/test_gem.rb51
-rw-r--r--test/rubygems/test_gem_ci_detector.rb32
-rw-r--r--test/rubygems/test_gem_command.rb2
-rw-r--r--test/rubygems/test_gem_commands_build_command.rb2
-rw-r--r--test/rubygems/test_gem_commands_cleanup_command.rb10
-rw-r--r--test/rubygems/test_gem_commands_environment_command.rb2
-rw-r--r--test/rubygems/test_gem_commands_exec_command.rb8
-rw-r--r--test/rubygems/test_gem_commands_generate_index_command.rb81
-rw-r--r--test/rubygems/test_gem_commands_install_command.rb27
-rw-r--r--test/rubygems/test_gem_commands_owner_command.rb10
-rw-r--r--test/rubygems/test_gem_commands_pristine_command.rb16
-rw-r--r--test/rubygems/test_gem_commands_push_command.rb16
-rw-r--r--test/rubygems/test_gem_commands_rebuild_command.rb154
-rw-r--r--test/rubygems/test_gem_commands_setup_command.rb25
-rw-r--r--test/rubygems/test_gem_commands_signin_command.rb75
-rw-r--r--test/rubygems/test_gem_commands_stale_command.rb4
-rw-r--r--test/rubygems/test_gem_commands_uninstall_command.rb8
-rw-r--r--test/rubygems/test_gem_commands_update_command.rb62
-rw-r--r--test/rubygems/test_gem_commands_yank_command.rb2
-rw-r--r--test/rubygems/test_gem_config_file.rb42
-rw-r--r--test/rubygems/test_gem_console_ui.rb19
-rw-r--r--test/rubygems/test_gem_dependency.rb10
-rw-r--r--test/rubygems/test_gem_dependency_installer.rb80
-rw-r--r--test/rubygems/test_gem_ext_builder.rb21
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder.rb4
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock16
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml2
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock16
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml2
-rw-r--r--test/rubygems/test_gem_gemcutter_utilities.rb8
-rw-r--r--test/rubygems/test_gem_indexer.rb380
-rw-r--r--test/rubygems/test_gem_install_update_options.rb50
-rw-r--r--test/rubygems/test_gem_installer.rb125
-rw-r--r--test/rubygems/test_gem_local_remote_options.rb12
-rw-r--r--test/rubygems/test_gem_package_tar_header.rb75
-rw-r--r--test/rubygems/test_gem_package_task.rb4
-rw-r--r--test/rubygems/test_gem_platform.rb3
-rw-r--r--test/rubygems/test_gem_remote_fetcher.rb99
-rw-r--r--test/rubygems/test_gem_request.rb60
-rw-r--r--test/rubygems/test_gem_request_connection_pools.rb20
-rw-r--r--test/rubygems/test_gem_request_set.rb20
-rw-r--r--test/rubygems/test_gem_request_set_gem_dependency_api.rb94
-rw-r--r--test/rubygems/test_gem_requirement.rb14
-rw-r--r--test/rubygems/test_gem_resolver.rb2
-rw-r--r--test/rubygems/test_gem_resolver_api_set.rb50
-rw-r--r--test/rubygems/test_gem_resolver_api_specification.rb68
-rw-r--r--test/rubygems/test_gem_resolver_best_set.rb6
-rw-r--r--test/rubygems/test_gem_resolver_specification.rb2
-rw-r--r--test/rubygems/test_gem_safe_marshal.rb55
-rw-r--r--test/rubygems/test_gem_safe_yaml.rb24
-rw-r--r--test/rubygems/test_gem_security_policy.rb24
-rw-r--r--test/rubygems/test_gem_security_signer.rb4
-rw-r--r--test/rubygems/test_gem_security_trust_dir.rb2
-rw-r--r--test/rubygems/test_gem_silent_ui.rb1
-rw-r--r--test/rubygems/test_gem_source.rb19
-rw-r--r--test/rubygems/test_gem_source_git.rb2
-rw-r--r--test/rubygems/test_gem_source_list.rb4
-rw-r--r--test/rubygems/test_gem_source_lock.rb2
-rw-r--r--test/rubygems/test_gem_source_subpath_problem.rb4
-rw-r--r--test/rubygems/test_gem_spec_fetcher.rb2
-rw-r--r--test/rubygems/test_gem_specification.rb163
-rw-r--r--test/rubygems/test_gem_stream_ui.rb14
-rw-r--r--test/rubygems/test_gem_uninstaller.rb161
-rw-r--r--test/rubygems/test_gem_update_suggestion.rb2
-rw-r--r--test/rubygems/test_gem_version_option.rb48
-rw-r--r--test/rubygems/test_kernel.rb16
-rw-r--r--test/rubygems/test_require.rb70
-rw-r--r--test/rubygems/test_rubygems.rb8
-rw-r--r--test/rubygems/test_webauthn_listener.rb32
-rw-r--r--test/rubygems/test_webauthn_poller.rb20
-rw-r--r--test/rubygems/utilities.rb30
-rw-r--r--test/runner.rb6
-rw-r--r--test/socket/test_addrinfo.rb4
-rw-r--r--test/socket/test_socket.rb253
-rw-r--r--test/stringio/test_ractor.rb2
-rw-r--r--test/stringio/test_stringio.rb75
-rw-r--r--test/strscan/test_stringscanner.rb47
-rw-r--r--test/syslog/test_syslog_logger.rb588
-rw-r--r--test/test_abbrev.rb55
-rw-r--r--test/test_delegate.rb9
-rw-r--r--test/test_extlibs.rb5
-rw-r--r--test/test_forwardable.rb2
-rw-r--r--test/test_getoptlong.rb163
-rw-r--r--test/test_ipaddr.rb75
-rw-r--r--test/test_mutex_m.rb79
-rw-r--r--test/test_observer.rb66
-rw-r--r--test/test_pp.rb44
-rw-r--r--test/test_syslog.rb193
-rw-r--r--test/test_tempfile.rb50
-rw-r--r--test/test_timeout.rb4
-rw-r--r--test/test_trick.rb38
-rw-r--r--test/uri/test_generic.rb11
-rw-r--r--test/win32/test_registry.rb97
-rw-r--r--test/win32ole/available_ole.rb14
-rw-r--r--test/win32ole/err_in_callback.rb4
-rw-r--r--test/win32ole/test_err_in_callback.rb4
-rw-r--r--test/win32ole/test_folderitem2_invokeverb.rb2
-rw-r--r--test/win32ole/test_nil2vtempty.rb2
-rw-r--r--test/win32ole/test_propertyputref.rb2
-rw-r--r--test/win32ole/test_thread.rb2
-rw-r--r--test/win32ole/test_win32ole.rb41
-rw-r--r--test/win32ole/test_win32ole_event.rb70
-rw-r--r--test/win32ole/test_win32ole_method.rb48
-rw-r--r--test/win32ole/test_win32ole_method_event.rb10
-rw-r--r--test/win32ole/test_win32ole_param.rb42
-rw-r--r--test/win32ole/test_win32ole_param_event.rb2
-rw-r--r--test/win32ole/test_win32ole_record.rb60
-rw-r--r--test/win32ole/test_win32ole_type.rb67
-rw-r--r--test/win32ole/test_win32ole_type_event.rb4
-rw-r--r--test/win32ole/test_win32ole_typelib.rb66
-rw-r--r--test/win32ole/test_win32ole_variable.rb16
-rw-r--r--test/win32ole/test_win32ole_variant.rb308
-rw-r--r--test/win32ole/test_win32ole_variant_m.rb5
-rw-r--r--test/win32ole/test_win32ole_variant_outarg.rb6
-rw-r--r--test/win32ole/test_word.rb2
-rw-r--r--test/yaml/test_store.rb2
-rw-r--r--test/zlib/test_zlib.rb62
-rw-r--r--thread.c451
-rw-r--r--thread_none.c15
-rw-r--r--thread_pthread.c200
-rw-r--r--thread_pthread.h2
-rw-r--r--thread_pthread_mn.c284
-rw-r--r--thread_sync.c12
-rw-r--r--thread_win32.c23
-rw-r--r--time.c88
-rw-r--r--timev.rb103
-rw-r--r--tool/bundler/dev_gems.rb8
-rw-r--r--tool/bundler/test_gems.rb12
-rw-r--r--tool/bundler/vendor_gems.rb15
-rw-r--r--tool/downloader.rb34
-rwxr-xr-xtool/fetch-bundled_gems.rb15
-rwxr-xr-xtool/format-release4
-rwxr-xr-xtool/gen-github-release.rb19
-rw-r--r--tool/generic_erb.rb6
-rwxr-xr-xtool/leaked-globals30
-rw-r--r--tool/lib/_tmpdir.rb100
-rw-r--r--tool/lib/bundled_gem.rb12
-rw-r--r--tool/lib/colorize.rb33
-rw-r--r--tool/lib/core_assertions.rb8
-rw-r--r--tool/lib/envutil.rb27
-rw-r--r--tool/lib/iseq_loader_checker.rb9
-rw-r--r--tool/lib/output.rb13
-rw-r--r--tool/lib/path.rb101
-rw-r--r--tool/lib/test/unit.rb238
-rw-r--r--tool/lib/test/unit/assertions.rb9
-rw-r--r--tool/lib/test/unit/parallel.rb10
-rw-r--r--tool/lib/test/unit/testcase.rb3
-rw-r--r--tool/lib/vcs.rb9
-rw-r--r--tool/lib/webrick/httprequest.rb2
-rwxr-xr-xtool/ln_sr.rb2
-rw-r--r--tool/lrama/LEGAL.md1
-rw-r--r--tool/lrama/NEWS.md382
-rw-r--r--tool/lrama/lib/lrama.rb1
-rw-r--r--tool/lrama/lib/lrama/command.rb33
-rw-r--r--tool/lrama/lib/lrama/context.rb38
-rw-r--r--tool/lrama/lib/lrama/counterexamples.rb3
-rw-r--r--tool/lrama/lib/lrama/counterexamples/example.rb4
-rw-r--r--tool/lrama/lib/lrama/counterexamples/path.rb46
-rw-r--r--tool/lrama/lib/lrama/counterexamples/production_path.rb17
-rw-r--r--tool/lrama/lib/lrama/counterexamples/start_path.rb21
-rw-r--r--tool/lrama/lib/lrama/counterexamples/transition_path.rb17
-rw-r--r--tool/lrama/lib/lrama/grammar.rb631
-rw-r--r--tool/lrama/lib/lrama/grammar/binding.rb24
-rw-r--r--tool/lrama/lib/lrama/grammar/code.rb117
-rw-r--r--tool/lrama/lib/lrama/grammar/code/destructor_code.rb40
-rw-r--r--tool/lrama/lib/lrama/grammar/code/initial_action_code.rb34
-rw-r--r--tool/lrama/lib/lrama/grammar/code/no_reference_code.rb28
-rw-r--r--tool/lrama/lib/lrama/grammar/code/printer_code.rb40
-rw-r--r--tool/lrama/lib/lrama/grammar/code/rule_action.rb88
-rw-r--r--tool/lrama/lib/lrama/grammar/counter.rb15
-rw-r--r--tool/lrama/lib/lrama/grammar/destructor.rb9
-rw-r--r--tool/lrama/lib/lrama/grammar/error_token.rb6
-rw-r--r--tool/lrama/lib/lrama/grammar/parameterizing_rule.rb3
-rw-r--r--tool/lrama/lib/lrama/grammar/parameterizing_rule/resolver.rb56
-rw-r--r--tool/lrama/lib/lrama/grammar/parameterizing_rule/rhs.rb37
-rw-r--r--tool/lrama/lib/lrama/grammar/parameterizing_rule/rule.rb18
-rw-r--r--tool/lrama/lib/lrama/grammar/percent_code.rb6
-rw-r--r--tool/lrama/lib/lrama/grammar/printer.rb6
-rw-r--r--tool/lrama/lib/lrama/grammar/reference.rb24
-rw-r--r--tool/lrama/lib/lrama/grammar/rule.rb29
-rw-r--r--tool/lrama/lib/lrama/grammar/rule_builder.rb268
-rw-r--r--tool/lrama/lib/lrama/grammar/stdlib.y122
-rw-r--r--tool/lrama/lib/lrama/grammar/symbol.rb20
-rw-r--r--tool/lrama/lib/lrama/grammar/symbols.rb1
-rw-r--r--tool/lrama/lib/lrama/grammar/symbols/resolver.rb293
-rw-r--r--tool/lrama/lib/lrama/grammar/type.rb18
-rw-r--r--tool/lrama/lib/lrama/lexer.rb95
-rw-r--r--tool/lrama/lib/lrama/lexer/grammar_file.rb31
-rw-r--r--tool/lrama/lib/lrama/lexer/location.rb97
-rw-r--r--tool/lrama/lib/lrama/lexer/token.rb50
-rw-r--r--tool/lrama/lib/lrama/lexer/token/instantiate_rule.rb23
-rw-r--r--tool/lrama/lib/lrama/lexer/token/parameterizing.rb19
-rw-r--r--tool/lrama/lib/lrama/lexer/token/tag.rb4
-rw-r--r--tool/lrama/lib/lrama/lexer/token/user_code.rb71
-rw-r--r--tool/lrama/lib/lrama/option_parser.rb38
-rw-r--r--tool/lrama/lib/lrama/options.rb4
-rw-r--r--tool/lrama/lib/lrama/output.rb85
-rw-r--r--tool/lrama/lib/lrama/parser.rb1326
-rw-r--r--tool/lrama/lib/lrama/report/profile.rb13
-rw-r--r--tool/lrama/lib/lrama/state.rb36
-rw-r--r--tool/lrama/lib/lrama/states/item.rb36
-rw-r--r--tool/lrama/lib/lrama/states_reporter.rb24
-rw-r--r--tool/lrama/lib/lrama/type.rb4
-rw-r--r--tool/lrama/lib/lrama/version.rb2
-rw-r--r--tool/lrama/template/bison/yacc.c20
-rw-r--r--tool/m4/ruby_check_header.m48
-rw-r--r--tool/m4/ruby_default_arch.m425
-rw-r--r--tool/m4/ruby_shared_gc.m419
-rw-r--r--tool/m4/ruby_try_cflags.m413
-rw-r--r--tool/m4/ruby_universal_arch.m42
-rw-r--r--tool/m4/ruby_wasm_tools.m43
-rwxr-xr-xtool/merger.rb183
-rwxr-xr-xtool/missing-baseruby.bat19
-rw-r--r--tool/mk_builtin_loader.rb15
-rwxr-xr-xtool/mkrunnable.rb99
-rwxr-xr-xtool/outdate-bundled-gems.rb101
-rwxr-xr-xtool/rbinstall.rb674
-rw-r--r--tool/rbs_skip_tests34
-rwxr-xr-xtool/rbuninstall.rb36
-rwxr-xr-xtool/rdoc-srcdir20
-rwxr-xr-xtool/redmine-backporter.rb143
-rwxr-xr-xtool/release.sh5
-rwxr-xr-xtool/rjit/bindgen.rb20
-rw-r--r--tool/ruby_vm/helpers/dumper.rb6
-rw-r--r--tool/rubyspec_temp.rb13
-rwxr-xr-xtool/runruby.rb6
-rwxr-xr-xtool/sync_default_gems.rb57
-rw-r--r--tool/test-bundled-gems.rb5
-rw-r--r--tool/test/init.rb18
-rw-r--r--tool/test/runner.rb11
-rwxr-xr-xtool/test/test_sync_default_gems.rb32
-rw-r--r--tool/test/testunit/test_assertion.rb13
-rw-r--r--tool/test/testunit/test_launchable.rb69
-rw-r--r--tool/test/testunit/test_parallel.rb2
-rw-r--r--tool/test/testunit/tests_for_parallel/slow_helper.rb3
-rw-r--r--tool/test/webrick/test_cgi.rb32
-rw-r--r--tool/test/webrick/test_filehandler.rb10
-rw-r--r--tool/test/webrick/utils.rb20
-rwxr-xr-x[-rw-r--r--]tool/test/webrick/webrick.cgi4
-rw-r--r--tool/test_for_warn_bundled_gems/.gitignore1
-rw-r--r--tool/test_for_warn_bundled_gems/Gemfile0
-rw-r--r--tool/test_for_warn_bundled_gems/Gemfile.lock11
-rw-r--r--tool/test_for_warn_bundled_gems/README.md3
-rwxr-xr-xtool/test_for_warn_bundled_gems/test.sh53
-rw-r--r--tool/test_for_warn_bundled_gems/test_no_warn_dash_gem.rb8
-rw-r--r--tool/test_for_warn_bundled_gems/test_no_warn_dependency.rb10
-rw-r--r--tool/test_for_warn_bundled_gems/test_no_warn_sub_feature.rb8
-rw-r--r--tool/test_for_warn_bundled_gems/test_warn_bootsnap.rb11
-rw-r--r--tool/test_for_warn_bundled_gems/test_warn_bootsnap_rubyarchdir_gem.rb11
-rw-r--r--tool/test_for_warn_bundled_gems/test_warn_bundle_exec.rb1
-rwxr-xr-xtool/test_for_warn_bundled_gems/test_warn_bundle_exec_shebang.rb3
-rw-r--r--tool/test_for_warn_bundled_gems/test_warn_bundled_gems.rb8
-rw-r--r--tool/test_for_warn_bundled_gems/test_warn_dash_gem.rb7
-rw-r--r--tool/test_for_warn_bundled_gems/test_warn_dependency.rb8
-rw-r--r--tool/test_for_warn_bundled_gems/test_warn_sub_feature.rb7
-rw-r--r--tool/test_for_warn_bundled_gems/test_warn_zeitwerk.rb12
-rw-r--r--tool/transcode-tblgen.rb6
-rw-r--r--tool/update-NEWS-refs.rb7
-rwxr-xr-xtool/update-deps2
-rw-r--r--trace_point.rb14
-rw-r--r--transcode.c22
-rw-r--r--universal_parser.c171
-rw-r--r--util.c48
-rw-r--r--variable.c369
-rw-r--r--variable.h2
-rw-r--r--vcpkg.json11
-rw-r--r--version.c5
-rw-r--r--vm.c550
-rw-r--r--vm_args.c201
-rw-r--r--vm_backtrace.c446
-rw-r--r--vm_callinfo.h49
-rw-r--r--vm_core.h91
-rw-r--r--vm_debug.h2
-rw-r--r--vm_dump.c8
-rw-r--r--vm_eval.c337
-rw-r--r--vm_exec.c2
-rw-r--r--vm_exec.h6
-rw-r--r--vm_insnhelper.c431
-rw-r--r--vm_insnhelper.h31
-rw-r--r--vm_method.c235
-rw-r--r--vm_opts.h2
-rw-r--r--vm_trace.c325
-rw-r--r--vsnprintf.c2
-rw-r--r--warning.rb2
-rw-r--r--wasm/runtime.c7
-rw-r--r--wasm/setjmp.c6
-rw-r--r--weakmap.c264
-rw-r--r--win32/Makefile.sub55
-rwxr-xr-xwin32/configure.bat11
-rw-r--r--win32/file.c6
-rwxr-xr-xwin32/mkexports.rb2
-rw-r--r--win32/setup.mak17
-rw-r--r--win32/win32.c73
-rw-r--r--yjit.c121
-rw-r--r--yjit.h15
-rw-r--r--yjit.rb131
-rw-r--r--yjit/Cargo.lock8
-rw-r--r--yjit/Cargo.toml2
-rw-r--r--yjit/bindgen/Cargo.lock4
-rw-r--r--yjit/bindgen/src/main.rs31
-rw-r--r--yjit/src/asm/arm64/inst/smulh.rs2
-rw-r--r--yjit/src/asm/arm64/mod.rs66
-rw-r--r--yjit/src/asm/mod.rs21
-rw-r--r--yjit/src/asm/x86_64/mod.rs1
-rw-r--r--yjit/src/backend/arm64/mod.rs147
-rw-r--r--yjit/src/backend/ir.rs122
-rw-r--r--yjit/src/backend/tests.rs2
-rw-r--r--yjit/src/backend/x86_64/mod.rs57
-rw-r--r--yjit/src/codegen.rs3531
-rw-r--r--yjit/src/core.rs1262
-rw-r--r--yjit/src/cruby.rs80
-rw-r--r--yjit/src/cruby_bindings.inc.rs494
-rw-r--r--yjit/src/invariants.rs176
-rw-r--r--yjit/src/lib.rs3
-rw-r--r--yjit/src/options.rs110
-rw-r--r--yjit/src/stats.rs292
-rw-r--r--yjit/src/yjit.rs37
-rw-r--r--yjit/yjit.mk4
4171 files changed, 200595 insertions, 172090 deletions
diff --git a/.appveyor.yml b/.appveyor.yml
deleted file mode 100644
index 0a25dceab4..0000000000
--- a/.appveyor.yml
+++ /dev/null
@@ -1,133 +0,0 @@
----
-version: '{build}'
-init:
- - git config --global user.name git
- - git config --global user.email svn-admin@ruby-lang.org
- - git config --global core.autocrlf false
- - git config --global core.eol lf
- - git config --global advice.detachedHead 0
-shallow_clone: true
-clone_depth: 10
-platform:
- - x64
-skip_commits:
- message: /\[DOC\]/
- files:
- - doc/*
- - '**/*.md'
- - '**/*.rdoc'
- - '**/.document'
- - '**/*.[1-8]'
- - '**/*.ronn'
-environment:
- ruby_version: "25-%Platform%"
- matrix:
- # Test only the oldest supported version because AppVeyor is unstable, its concurrency
- # is limited, and compatibility issues that happen only in newer versions are rare.
- # You may test some other stuff on GitHub Actions instead.
- - build: vs
- vs: 120 # Visual Studio 2013
- ssl: OpenSSL-v111
- # The worker image name. This is NOT the Visual Studio version we're using here.
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
- GEMS_FOR_TEST: ""
- RELINE_TEST_ENCODING: "UTF-8"
-cache:
- - c:\Tools\vcpkg\installed\
-for:
--
- matrix:
- only:
- - build: vs
- install:
- - ver
- - chcp
- - SET BITS=%Platform:x86=32%
- - SET BITS=%BITS:x=%
- - SET OPENSSL_DIR=C:\%ssl%-Win%BITS%
- - cd C:\Tools\vcpkg
- - git pull -q
- - .\bootstrap-vcpkg.bat
- - cd %APPVEYOR_BUILD_FOLDER%
- - vcpkg --triplet %Platform%-windows install --x-use-aria2 libffi libyaml readline zlib
- - CALL SET vcvars=%%^VS%VS%COMNTOOLS^%%..\..\VC\vcvarsall.bat
- - SET vcvars
- - '"%vcvars%" %Platform:x64=amd64%'
- - SET ruby_path=C:\Ruby%ruby_version:-x86=%
- - SET PATH=\usr\local\bin;%ruby_path%\bin;%PATH%;C:\msys64\mingw64\bin;C:\msys64\usr\bin
- - ruby --version
- - 'cl'
- - echo> Makefile srcdir=.
- - echo>> Makefile MSC_VER=0
- - echo>> Makefile RT=none
- - echo>> Makefile RT_VER=0
- - echo>> Makefile BUILTIN_ENCOBJS=nul
- - type win32\Makefile.sub >> Makefile
- - nmake %mflags% up VCSUP="echo Update OK"
- - nmake %mflags% extract-extlibs
- - del Makefile
- - mkdir \usr\local\bin
- - mkdir \usr\local\include
- - mkdir \usr\local\lib
- - for %%I in (%OPENSSL_DIR%\*.dll) do mklink /h \usr\local\bin\%%~nxI %%I
- - for %%I in (c:\Tools\vcpkg\installed\%Platform%-windows\bin\*.dll) do (
- if not %%~nI == readline mklink \usr\local\bin\%%~nxI %%I
- )
- - attrib +r /s /d
- - mkdir %Platform%-mswin_%vs%
- build_script:
- - set HAVE_GIT=no
- - cd %APPVEYOR_BUILD_FOLDER%
- - cd %Platform%-mswin_%vs%
- - >-
- ..\win32\configure.bat
- --with-opt-dir="/usr/local;c:/Tools/vcpkg/installed/%Platform%-windows"
- --with-openssl-dir=%OPENSSL_DIR:\=/%
- - nmake -l
- - nmake install-nodoc
- - \usr\bin\ruby -v -e "p :locale => Encoding.find('locale'), :filesystem => Encoding.find('filesystem')"
- - if not "%GEMS_FOR_TEST%" == "" \usr\bin\gem install --no-document %GEMS_FOR_TEST%
- - \usr\bin\ruby -ropenssl -e "puts 'Build ' + OpenSSL::OPENSSL_VERSION, 'Runtime ' + OpenSSL::OPENSSL_LIBRARY_VERSION"
- test_script:
- - set /a JOBS=%NUMBER_OF_PROCESSORS%
- - nmake -l "TESTOPTS=-v -q" btest
- - nmake -l "TESTOPTS=-v -q" test-basic
- - >-
- nmake -l "TESTOPTS=--timeout-scale=3.0
- --excludes=../test/.excludes/_appveyor -j%JOBS%
- --exclude win32ole
- --exclude test_bignum
- --exclude test_syntax
- --exclude test_open-uri
- --exclude test_bundled_ca
- " test-all
- # separately execute tests without -j which may crash worker with -j.
- - >-
- nmake -l
- "TESTOPTS=--timeout-scale=3.0 --excludes=../test/.excludes/_appveyor"
- TESTS="
- ../test/win32ole
- ../test/ruby/test_bignum.rb
- ../test/ruby/test_syntax.rb
- ../test/open-uri/test_open-uri.rb
- ../test/rubygems/test_bundled_ca.rb
- " test-all
- - nmake -l test-spec # not using `-j` because sometimes `mspec -j` silently dies on Windows
-notifications:
- - provider: Webhook
- method: POST
- url:
- secure: CcFlJNDJ/a6to7u3Z4Fnz6dScEPNx7hTha2GkSRlV+1U6dqmxY/7uBcLXYb9gR3jfQk6w+2o/HrjNAyXMNGU/JOka3s2WRI4VKitzM+lQ08owvJIh0R7LxrGH0J2e81U # ruby-lang slack: ruby/simpler-alerts-bot
- body: >-
- {{^isPullRequest}}
- {
- "ci": "AppVeyor CI",
- "env": "Visual Studio 2013",
- "url": "{{buildUrl}}",
- "commit": "{{commitId}}",
- "branch": "{{branch}}"
- }
- {{/isPullRequest}}
- on_build_success: false
- on_build_failure: true
- on_build_status_changed: false
diff --git a/.document b/.document
index e875e42546..0665d415b9 100644
--- a/.document
+++ b/.document
@@ -31,6 +31,9 @@ trace_point.rb
warning.rb
yjit.rb
+# Errno::*
+known_errors.inc
+
# the lib/ directory (which has its own .document file)
lib
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index 1bf7db40ad..1cafd3df75 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -26,3 +26,7 @@ fc4acf8cae82e5196186d3278d831f2438479d91
# Make prism_compile.c indentation consistent
40b2c8e5e7e6e5f83cee9276dc9c1922a69292d6
d2c5867357ed88eccc28c2b3bd4a46e206e7ff85
+
+# Miss-and-revived commits
+a0f7de814ae5c299d6ce99bed5fb308a05d50ba0
+d4e24021d39e1f80f0055b55d91f8d5f22e15084
diff --git a/.github/actions/launchable/setup/action.yml b/.github/actions/launchable/setup/action.yml
new file mode 100644
index 0000000000..6d50318ded
--- /dev/null
+++ b/.github/actions/launchable/setup/action.yml
@@ -0,0 +1,144 @@
+name: Set up Launchable
+description: >-
+ Install the required dependencies and execute the necessary Launchable commands for test recording
+
+inputs:
+ report-path:
+ default: launchable_reports.json
+ required: true
+ description: The file path of the test report for uploading to Launchable
+
+ os:
+ required: true
+ description: The operating system that CI runs on. This value is used in Launchable flavor.
+
+ test-opts:
+ default: none
+ required: false
+ description: >-
+ Test options that determine how tests are run.
+ This value is used in the Launchable flavor.
+
+ launchable-token:
+ required: false
+ description: >-
+ Launchable token is needed if you want to run Launchable on your forked repository.
+ See https://github.com/ruby/ruby/wiki/CI-Servers#launchable-ci for details.
+
+ builddir:
+ required: false
+ default: ${{ github.workspace }}
+ description: >-
+ Directory to create Launchable report file.
+
+ srcdir:
+ required: false
+ default: ${{ github.workspace }}
+ description: >-
+ Directory to (re-)checkout source codes. Launchable retrives the commit information
+ from the directory.
+
+runs:
+ using: composite
+
+ steps:
+ - name: Enable Launchable conditionally
+ id: enable-launchable
+ run: echo "enable-launchable=true" >> $GITHUB_OUTPUT
+ shell: bash
+ if: >-
+ ${{
+ (github.repository == 'ruby/ruby' ||
+ (github.repository != 'ruby/ruby' && env.LAUNCHABLE_TOKEN)) &&
+ (matrix.test_task == 'check' || matrix.test_task == 'test-all')
+ }}
+
+ # Launchable CLI requires Python and Java.
+ # https://www.launchableinc.com/docs/resources/cli-reference/
+ - name: Set up Python
+ uses: actions/setup-python@871daa956ca9ea99f3c3e30acb424b7960676734 # v5.0.0
+ with:
+ python-version: "3.x"
+ if: steps.enable-launchable.outputs.enable-launchable
+
+ - name: Set up Java
+ uses: actions/setup-java@7a445ee88d4e23b52c33fdc7601e40278616c7f8 # v4.0.0
+ with:
+ distribution: 'temurin'
+ java-version: '17'
+ if: steps.enable-launchable.outputs.enable-launchable
+
+ - name: Set environment variables for Launchable
+ shell: bash
+ run: |
+ : # GITHUB_PULL_REQUEST_URL are used for commenting test reports in Launchable Github App.
+ : # https://github.com/launchableinc/cli/blob/v1.80.1/launchable/utils/link.py#L42
+ echo "GITHUB_PULL_REQUEST_URL=${{ github.event.pull_request.html_url }}" >> $GITHUB_ENV
+ : # The following envs are necessary in Launchable tokenless authentication.
+ : # https://github.com/launchableinc/cli/blob/v1.80.1/launchable/utils/authentication.py#L20
+ echo "LAUNCHABLE_ORGANIZATION=${{ github.repository_owner }}" >> $GITHUB_ENV
+ echo "LAUNCHABLE_WORKSPACE=${{ github.event.repository.name }}" >> $GITHUB_ENV
+ : # https://github.com/launchableinc/cli/blob/v1.80.1/launchable/utils/authentication.py#L71
+ echo "GITHUB_PR_HEAD_SHA=${{ github.event.pull_request.head.sha || github.sha }}" >> $GITHUB_ENV
+ echo "LAUNCHABLE_TOKEN=${{ inputs.launchable-token }}" >> $GITHUB_ENV
+ if: steps.enable-launchable.outputs.enable-launchable
+
+ - name: Set up Launchable
+ shell: bash
+ working-directory: ${{ inputs.srcdir }}
+ run: |
+ set -x
+ PATH=$PATH:$(python -msite --user-base)/bin
+ echo "PATH=$PATH" >> $GITHUB_ENV
+ pip install --user launchable
+ launchable verify || true
+ : # The build name cannot include a slash, so we replace the string here.
+ github_ref="${{ github.ref }}"
+ github_ref="${github_ref//\//_}"
+ : # With the --name option, we need to configure a unique identifier for this build.
+ : # To avoid setting the same build name as the CI which runs on other branches, we use the branch name here.
+ : #
+ : # FIXME: Need to fix `WARNING: Failed to process a change to a file`.
+ : # https://github.com/launchableinc/cli/issues/786
+ launchable record build --name ${github_ref}_${GITHUB_PR_HEAD_SHA}
+ echo "TESTS=${TESTS} --launchable-test-reports=${{ inputs.report-path }}" >> $GITHUB_ENV
+ if: steps.enable-launchable.outputs.enable-launchable
+
+ - name: Variables to report Launchable
+ id: variables
+ shell: bash
+ run: |
+ set -x
+ : # flavor
+ test_opts="${{ inputs.test-opts }}"
+ test_opts="${test_opts// /}"
+ test_opts="${test_opts//=/:}"
+ echo test-opts="$test_opts" >> $GITHUB_OUTPUT
+ : # report-path from srcdir
+ if [ "${srcdir}" = "${{ github.workspace }}" ]; then
+ dir=
+ else
+ # srcdir must be equal to or under workspace
+ dir=$(echo ${srcdir:+${srcdir}/} | sed 's:[^/][^/]*/:../:g')
+ fi
+ report_path="${dir}${builddir:+${builddir}/}${report_path}"
+ echo report-path="${report_path}" >> $GITHUB_OUTPUT
+ if: steps.enable-launchable.outputs.enable-launchable
+ env:
+ srcdir: ${{ inputs.srcdir }}
+ builddir: ${{ inputs.builddir }}
+ report_path: ${{ inputs.report-path }}
+
+ - name: Record test results in Launchable
+ uses: gacts/run-and-post-run@674528335da98a7afc80915ff2b4b860a0b3553a # v1.4.0
+ with:
+ shell: bash
+ working-directory: ${{ inputs.srcdir }}
+ post: |
+ : # record
+ launchable record tests --flavor os=${{ inputs.os }} --flavor test_task=${{ matrix.test_task }} --flavor test_opts=${test_opts} raw ${report_path}
+ rm -f ${report_path}
+ if: ${{ always() && steps.enable-launchable.outputs.enable-launchable }}
+ env:
+ test_opts: ${{ steps.variables.outputs.test-opts }}
+ report_path: ${{ steps.variables.outputs.report-path }}
diff --git a/.github/actions/setup/directories/action.yml b/.github/actions/setup/directories/action.yml
index 359e5c0d37..5264e0e969 100644
--- a/.github/actions/setup/directories/action.yml
+++ b/.github/actions/setup/directories/action.yml
@@ -44,6 +44,18 @@ inputs:
description: >-
If set to true, creates dummy files in build dir.
+ fetch-depth:
+ required: false
+ default: '1'
+ description: The depth of commit history fetched from the remote repository
+
+ clean:
+ required: false
+ type: boolean
+ default: ''
+ description: >-
+ If set to true, clean build directory.
+
outputs: {} # nothing?
runs:
@@ -76,11 +88,12 @@ runs:
git config --global init.defaultBranch garbage
- if: inputs.checkout
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
path: ${{ inputs.srcdir }}
+ fetch-depth: ${{ inputs.fetch-depth }}
- - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1
+ - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
with:
path: ${{ inputs.srcdir }}/.downloaded-cache
key: downloaded-cache
@@ -129,9 +142,33 @@ runs:
- if: inputs.dummy-files == 'true'
shell: bash
+ id: dummy-files
working-directory: ${{ inputs.builddir }}
run: |
: Create dummy files in build dir
- for basename in {a..z} {A..Z} {0..9} foo bar test zzz; do
- echo > ${basename}.rb "raise %(do not load ${basename}.rb)"
+ set {{a..z},{A..Z},{0..9},foo,bar,test,zzz}.rb
+ for file; do \
+ echo > $file "raise 'do not load $file'"; \
done
+ # drop {a..z}.rb if case-insensitive filesystem
+ grep -F A.rb a.rb > /dev/null && set "${@:27}"
+ echo clean="cd ${{ inputs.builddir }} && rm $*" >> $GITHUB_OUTPUT
+
+ - if: inputs.clean == 'true'
+ shell: bash
+ id: clean
+ run: |
+ echo distclean='make -C ${{ inputs.builddir }} distclean' >> $GITHUB_OUTPUT
+ echo remained-files='find ${{ inputs.builddir }} -ls' >> $GITHUB_OUTPUT
+ [ "${{ inputs.builddir }}" = "${{ inputs.srcdir }}" ] ||
+ echo final='rmdir ${{ inputs.builddir }}' >> $GITHUB_OUTPUT
+
+ - name: clean
+ uses: gacts/run-and-post-run@7aec950f3b114c4fcf6012070c3709ecff0eb6f8 # v1.4.0
+ with:
+ working-directory:
+ post: |
+ ${{ steps.dummy-files.outputs.clean }}
+ ${{ steps.clean.outputs.distclean }}
+ ${{ steps.clean.outputs.remained-files }}
+ ${{ steps.clean.outputs.final }}
diff --git a/.github/actions/setup/macos/action.yml b/.github/actions/setup/macos/action.yml
index 3649a64876..b96e959aa6 100644
--- a/.github/actions/setup/macos/action.yml
+++ b/.github/actions/setup/macos/action.yml
@@ -13,12 +13,16 @@ runs:
- name: brew
shell: bash
run: |
- brew install --quiet gmp libffi openssl@1.1 zlib autoconf automake libtool readline
+ brew install --quiet gmp libffi openssl@1.1 zlib autoconf automake libtool
- name: Set ENV
shell: bash
run: |
- for lib in openssl@1.1 readline; do
+ for lib in gmp; do
+ ruby_configure_args="${ruby_configure_args:+$ruby_configure_args }--with-${lib%@*}-dir=$(brew --prefix $lib)"
+ done
+ for lib in openssl@1.1; do
CONFIGURE_ARGS="${CONFIGURE_ARGS:+$CONFIGURE_ARGS }--with-${lib%@*}-dir=$(brew --prefix $lib)"
done
+ echo ruby_configure_args="${ruby_configure_args}" >> $GITHUB_ENV
echo CONFIGURE_ARGS="${CONFIGURE_ARGS}" >> $GITHUB_ENV
diff --git a/.github/actions/slack/action.yml b/.github/actions/slack/action.yml
index c98be085a8..f0481f5bc2 100644
--- a/.github/actions/slack/action.yml
+++ b/.github/actions/slack/action.yml
@@ -24,7 +24,7 @@ runs:
using: composite
steps:
- - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
+ - uses: ruby/action-slack@54175162371f1f7c8eb94d7c8644ee2479fcd375 # v3.2.2
with:
payload: |
{
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 70a73430d7..426893be2a 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -1,6 +1,18 @@
version: 2
updates:
- package-ecosystem: 'github-actions'
- directory: '/.github'
+ directory: '/'
+ schedule:
+ interval: 'daily'
+ - package-ecosystem: 'github-actions'
+ directory: '/.github/actions/slack'
+ schedule:
+ interval: 'daily'
+ - package-ecosystem: 'github-actions'
+ directory: '/.github/actions/setup/directories'
+ schedule:
+ interval: 'daily'
+ - package-ecosystem: 'cargo'
+ directory: '/yjit'
schedule:
interval: 'daily'
diff --git a/.github/workflows/annocheck.yml b/.github/workflows/annocheck.yml
index 582285afa8..9b0cefdbdd 100644
--- a/.github/workflows/annocheck.yml
+++ b/.github/workflows/annocheck.yml
@@ -4,24 +4,20 @@ on:
push:
paths-ignore:
- 'doc/**'
- - '**/man'
+ - '**/man/*'
- '**.md'
- '**.rdoc'
- '**/.document'
+ - '.*.yml'
pull_request:
paths-ignore:
- 'doc/**'
- - '**/man'
+ - '**/man/*'
- '**.md'
- '**.rdoc'
- '**/.document'
+ - '.*.yml'
merge_group:
- paths-ignore:
- - 'doc/**'
- - '**/man'
- - '**.md'
- - '**.rdoc'
- - '**/.document'
concurrency:
group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
@@ -32,7 +28,7 @@ permissions:
jobs:
compile:
- name: gcc-11 annocheck
+ name: test-annocheck
runs-on: ubuntu-latest
@@ -43,8 +39,10 @@ jobs:
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || contains(github.event.pull_request.title, 'Document')
+ || contains(github.event.pull_request.labels.*.name, 'Document')
|| (github.event_name == 'push' && github.actor == 'dependabot[bot]')
)}}
@@ -65,7 +63,7 @@ jobs:
- run: id
working-directory:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
sparse-checkout-cone-mode: false
sparse-checkout: /.github
@@ -76,6 +74,11 @@ jobs:
builddir: build
makeup: true
+ - uses: ruby/setup-ruby@78c01b705fd9d5ad960d432d3a0cfa341d50e410 # v1.179.1
+ with:
+ ruby-version: '3.0'
+ bundler: none
+
# Minimal flags to pass the check.
# -g0 disables backtraces when SEGV. Do not set that.
- name: Run configure
@@ -97,20 +100,6 @@ jobs:
- run: make
- - run: make test
-
- - run: make install
-
- - run: make test-tool
-
- ### test-all doesn't work: https://github.com/ruby/ruby/actions/runs/4340112185/jobs/7578344307
- # - run: make test-all TESTS='-- ruby -ext-'
-
- ### test-spec doesn't work: https://github.com/ruby/ruby/actions/runs/4340193212/jobs/7578505652
- # - run: make test-spec
- # env:
- # CHECK_LEAKS: true
-
- run: make test-annocheck
- uses: ./.github/actions/slack
diff --git a/.github/workflows/auto_request_review.yml b/.github/workflows/auto_request_review.yml
index d9eb774e3f..ca27244b46 100644
--- a/.github/workflows/auto_request_review.yml
+++ b/.github/workflows/auto_request_review.yml
@@ -10,10 +10,10 @@ jobs:
auto-request-review:
name: Auto Request Review
runs-on: ubuntu-latest
- if: ${{ github.repository == 'ruby/ruby' }}
+ if: ${{ github.repository == 'ruby/ruby' && github.base_ref == 'master' }}
steps:
- name: Request review based on files changes and/or groups the author belongs to
- uses: necojackarc/auto-request-review@6a51cebffe2c084705d9a7b394abd802e0119633 # v0.12.0
+ uses: necojackarc/auto-request-review@e89da1a8cd7c8c16d9de9c6e763290b6b0e3d424 # v0.13.0
with:
# scope: public_repo
token: ${{ secrets.MATZBOT_GITHUB_TOKEN }}
diff --git a/.github/workflows/baseruby.yml b/.github/workflows/baseruby.yml
index 6102c61ad0..e7a245e1dc 100644
--- a/.github/workflows/baseruby.yml
+++ b/.github/workflows/baseruby.yml
@@ -4,24 +4,20 @@ on:
push:
paths-ignore:
- 'doc/**'
- - '**/man'
+ - '**/man/*'
- '**.md'
- '**.rdoc'
- '**/.document'
+ - '.*.yml'
pull_request:
paths-ignore:
- 'doc/**'
- - '**/man'
+ - '**/man/*'
- '**.md'
- '**.rdoc'
- '**/.document'
+ - '.*.yml'
merge_group:
- paths-ignore:
- - 'doc/**'
- - '**/man'
- - '**.md'
- - '**.rdoc'
- - '**/.document'
concurrency:
group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
@@ -39,28 +35,28 @@ jobs:
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || contains(github.event.pull_request.title, 'Document')
+ || contains(github.event.pull_request.labels.*.name, 'Document')
|| (github.event_name == 'push' && github.actor == 'dependabot[bot]')
)}}
strategy:
matrix:
ruby:
- - ruby-2.5
-# - ruby-2.6
-# - ruby-2.7
- ruby-3.0
- ruby-3.1
- ruby-3.2
+ - ruby-3.3
steps:
- - uses: ruby/setup-ruby@036ef458ddccddb148a2b9fb67e95a22fdbf728b # v1.160.0
+ - uses: ruby/setup-ruby@78c01b705fd9d5ad960d432d3a0cfa341d50e410 # v1.179.1
with:
ruby-version: ${{ matrix.ruby }}
bundler: none
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- uses: ./.github/actions/setup/ubuntu
diff --git a/.github/workflows/bundled_gems.yml b/.github/workflows/bundled_gems.yml
index 943140e9ef..6f06451a99 100644
--- a/.github/workflows/bundled_gems.yml
+++ b/.github/workflows/bundled_gems.yml
@@ -12,10 +12,6 @@ on:
- '.github/workflows/bundled_gems.yml'
- 'gems/bundled_gems'
merge_group:
- branches: ['master']
- paths:
- - '.github/workflows/bundled_gems.yml'
- - 'gems/bundled_gems'
schedule:
- cron: '45 6 * * *'
workflow_dispatch:
@@ -35,7 +31,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
@@ -60,6 +56,13 @@ jobs:
run: |
ruby -i~ tool/update-bundled_gems.rb gems/bundled_gems >> $GITHUB_OUTPUT
+ - name: Update spec/bundler/support/builders.rb
+ run: |
+ #!ruby
+ rake_version = File.read("gems/bundled_gems")[/^rake\s+(\S+)/, 1]
+ print ARGF.read.sub(/^ *def rake_version\s*\K".*?"/) {rake_version.dump}
+ shell: ruby -i~ {0} spec/bundler/support/builders.rb
+
- name: Maintain updated gems list in NEWS
run: |
ruby tool/update-NEWS-gemlist.rb bundled
@@ -73,6 +76,7 @@ jobs:
git diff --color --no-ext-diff --ignore-submodules --exit-code -- gems/bundled_gems ||
gems=true
git add -- NEWS.md gems/bundled_gems
+ git add -- spec/bundler/support/builders.rb
echo news=$news >> $GITHUB_OUTPUT
echo gems=$gems >> $GITHUB_OUTPUT
echo update=${news:-$gems} >> $GITHUB_OUTPUT
diff --git a/.github/workflows/check_dependencies.yml b/.github/workflows/check_dependencies.yml
index 4da0b3696c..9fb52444de 100644
--- a/.github/workflows/check_dependencies.yml
+++ b/.github/workflows/check_dependencies.yml
@@ -3,24 +3,20 @@ on:
push:
paths-ignore:
- 'doc/**'
- - '**/man'
+ - '**/man/*'
- '**.md'
- '**.rdoc'
- '**/.document'
+ - '.*.yml'
pull_request:
paths-ignore:
- 'doc/**'
- - '**/man'
+ - '**/man/*'
- '**.md'
- '**.rdoc'
- '**/.document'
+ - '.*.yml'
merge_group:
- paths-ignore:
- - 'doc/**'
- - '**/man'
- - '**.md'
- - '**.rdoc'
- - '**/.document'
concurrency:
group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
@@ -41,13 +37,15 @@ jobs:
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || contains(github.event.pull_request.title, 'Document')
+ || contains(github.event.pull_request.labels.*.name, 'Document')
|| (github.event_name == 'push' && github.actor == 'dependabot[bot]')
)}}
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- uses: ./.github/actions/setup/ubuntu
if: ${{ contains(matrix.os, 'ubuntu') }}
@@ -57,6 +55,11 @@ jobs:
- uses: ./.github/actions/setup/directories
+ - uses: ruby/setup-ruby@78c01b705fd9d5ad960d432d3a0cfa341d50e410 # v1.179.1
+ with:
+ ruby-version: '3.0'
+ bundler: none
+
- name: Run configure
run: ./configure -C --disable-install-doc --disable-rubygems --with-gcc 'optflags=-O0' 'debugflags=-save-temps=obj -g'
diff --git a/.github/workflows/check_misc.yml b/.github/workflows/check_misc.yml
index d8f73d26ec..f26319f448 100644
--- a/.github/workflows/check_misc.yml
+++ b/.github/workflows/check_misc.yml
@@ -1,4 +1,4 @@
-name: Miscellaneous checks
+name: Misc
on: [push, pull_request, merge_group]
concurrency:
@@ -10,13 +10,15 @@ permissions:
jobs:
checks:
+ name: Miscellaneous checks
+
permissions:
contents: write # for Git to git push
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 4c6e9fd639..f733234906 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -5,17 +5,19 @@ on:
branches: ['master']
paths-ignore:
- 'doc/**'
- - '**/man'
+ - '**/man/*'
- '**.md'
- '**.rdoc'
- '**/.document'
+ - '.*.yml'
pull_request:
paths-ignore:
- 'doc/**'
- - '**/man'
+ - '**/man/*'
- '**.md'
- '**.rdoc'
- '**/.document'
+ - '.*.yml'
schedule:
- cron: '0 12 * * *'
workflow_dispatch:
@@ -30,7 +32,7 @@ permissions: # added using https://github.com/step-security/secure-workflows
jobs:
analyze:
name: Analyze
- runs-on: ubuntu-latest
+ runs-on: ${{ matrix.os }}
permissions:
actions: read # for github/codeql-action/init to get workflow details
contents: read # for actions/checkout to fetch code
@@ -39,8 +41,10 @@ jobs:
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || contains(github.event.pull_request.title, 'Document')
+ || contains(github.event.pull_request.labels.*.name, 'Document')
|| (github.event_name == 'push' && github.actor == 'dependabot[bot]')
)}}
@@ -50,41 +54,48 @@ jobs:
strategy:
fail-fast: false
matrix:
- language: ['cpp', 'ruby']
+ include:
+ - language: cpp
+ os: ubuntu-latest
+ # ruby analysis used large memory. We need to use a larger runner.
+ - language: ruby
+ os: ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'ubuntu-latest' }}
steps:
- name: Checkout repository
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- name: Install libraries
+ if: ${{ contains(matrix.os, 'macos') }}
+ uses: ./.github/actions/setup/macos
+
+ - name: Install libraries
+ if : ${{ matrix.os == 'ubuntu-latest' }}
uses: ./.github/actions/setup/ubuntu
- uses: ./.github/actions/setup/directories
- name: Remove an obsolete rubygems vendored file
+ if: ${{ matrix.os == 'ubuntu-latest' }}
run: sudo rm /usr/lib/ruby/vendor_ruby/rubygems/defaults/operating_system.rb
- name: Initialize CodeQL
- uses: github/codeql-action/init@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4
+ uses: github/codeql-action/init@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
with:
languages: ${{ matrix.language }}
- name: Autobuild
- uses: github/codeql-action/autobuild@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4
+ uses: github/codeql-action/autobuild@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4
+ uses: github/codeql-action/analyze@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
with:
category: '/language:${{ matrix.language }}'
upload: False
output: sarif-results
- ram: 8192
- # CodeQL randomly hits `OutOfMemoryError "Java heap space"`.
- # GitHub recommends running a larger runner to fix it, but we don't pay for it.
- continue-on-error: true
- name: filter-sarif
- uses: advanced-security/filter-sarif@f3b8118a9349d88f7b1c0c488476411145b6270d # v1.0
+ uses: advanced-security/filter-sarif@f3b8118a9349d88f7b1c0c488476411145b6270d # v1.0.1
with:
patterns: |
+**/*.rb
@@ -104,8 +115,10 @@ jobs:
input: sarif-results/${{ matrix.language }}.sarif
output: sarif-results/${{ matrix.language }}.sarif
if: ${{ matrix.language == 'ruby' }}
+ continue-on-error: true
- name: Upload SARIF
- uses: github/codeql-action/upload-sarif@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4
+ uses: github/codeql-action/upload-sarif@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
with:
sarif_file: sarif-results/${{ matrix.language }}.sarif
+ continue-on-error: true
diff --git a/.github/workflows/compilers.yml b/.github/workflows/compilers.yml
index 0262c70ef8..85769bd879 100644
--- a/.github/workflows/compilers.yml
+++ b/.github/workflows/compilers.yml
@@ -1,27 +1,24 @@
+# Some tests depending on this name 'Compilations' via $GITHUB_WORKFLOW. Make sure to update such tests when renaming this workflow.
name: Compilations
on:
push:
paths-ignore:
- 'doc/**'
- - '**/man'
+ - '**/man/*'
- '**.md'
- '**.rdoc'
- '**/.document'
+ - '.*.yml'
pull_request:
paths-ignore:
- 'doc/**'
- - '**/man'
+ - '**/man/*'
- '**.md'
- '**.rdoc'
- '**/.document'
+ - '.*.yml'
merge_group:
- paths-ignore:
- - 'doc/**'
- - '**/man'
- - '**.md'
- - '**.rdoc'
- - '**/.document'
concurrency:
group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
@@ -31,7 +28,7 @@ concurrency:
# environment variables (plus the "echo $GITHUB_ENV" hack) is to reroute that
# restriction.
env:
- default_cc: clang-17
+ default_cc: clang-18
append_cc: ''
# -O1 is faster than -O3 in our tests... Majority of time are consumed trying
@@ -85,6 +82,7 @@ jobs:
optflags: '-O2'
shared: disable
# check: true
+ - { name: clang-19, env: { default_cc: clang-19 } }
- { name: clang-18, env: { default_cc: clang-18 } }
- { name: clang-17, env: { default_cc: clang-17 } }
- { name: clang-16, env: { default_cc: clang-16 } }
@@ -107,7 +105,7 @@ jobs:
shared: disable
# check: true
- - { name: ext/Setup }
+ - { name: ext/Setup, static-exts: 'etc,json/*,*/escape' }
# - { name: aarch64-linux-gnu, crosshost: aarch64-linux-gnu, container: crossbuild-essential-arm64 }
# - { name: arm-linux-gnueabi, crosshost: arm-linux-gnueabi }
@@ -139,7 +137,7 @@ jobs:
- { name: '-O0', env: { optflags: '-O0 -march=x86-64 -mtune=generic' } }
# - { name: '-O3', env: { optflags: '-O3 -march=x86-64 -mtune=generic' }, check: true }
- - { name: gmp, env: { append_configure: '--with-gmp' } }
+ - { name: gmp, env: { append_configure: '--with-gmp' }, check: true }
- { name: jemalloc, env: { append_configure: '--with-jemalloc' } }
- { name: valgrind, env: { append_configure: '--with-valgrind' } }
- { name: 'coroutine=ucontext', env: { append_configure: '--with-coroutine=ucontext' } }
@@ -150,9 +148,9 @@ jobs:
- { name: disable-rubygems, env: { append_configure: '--disable-rubygems' } }
- { name: RUBY_DEVEL, env: { append_configure: '--enable-devel' } }
+ - { name: OPT_THREADED_CODE=0, env: { cppflags: '-DOPT_THREADED_CODE=0' } }
- { name: OPT_THREADED_CODE=1, env: { cppflags: '-DOPT_THREADED_CODE=1' } }
- { name: OPT_THREADED_CODE=2, env: { cppflags: '-DOPT_THREADED_CODE=2' } }
- - { name: OPT_THREADED_CODE=3, env: { cppflags: '-DOPT_THREADED_CODE=3' } }
- { name: NDEBUG, env: { cppflags: '-DNDEBUG' } }
- { name: RUBY_DEBUG, env: { cppflags: '-DRUBY_DEBUG' } }
@@ -217,14 +215,16 @@ jobs:
runs-on: ubuntu-latest
container:
- image: ghcr.io/ruby/ruby-ci-image:${{ matrix.entry.container || matrix.entry.env.default_cc || 'clang-17' }}
+ image: ghcr.io/ruby/ruby-ci-image:${{ matrix.entry.container || matrix.entry.env.default_cc || 'clang-18' }}
options: --user root
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || contains(github.event.pull_request.title, 'Document')
+ || contains(github.event.pull_request.labels.*.name, 'Document')
|| (github.event_name == 'push' && github.actor == 'dependabot[bot]')
)}}
@@ -234,7 +234,7 @@ jobs:
- run: id
working-directory:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
sparse-checkout-cone-mode: false
sparse-checkout: /.github
@@ -244,6 +244,7 @@ jobs:
srcdir: src
builddir: build
makeup: true
+ clean: true
- name: Run configure
run: >
@@ -255,9 +256,23 @@ jobs:
}}
--${{ matrix.entry.shared || 'enable' }}-shared
- - name: Add to ext/Setup # statically link just the etc extension
- run: mkdir ext && echo etc >> ext/Setup
- if: ${{ matrix.entry.name == 'ext/Setup' }}
+ - name: Add to ext/Setup
+ id: ext-setup
+ run: |
+ mkdir ext
+ cd ext
+ for ext in {${{ matrix.entry.static-exts }}}; do
+ echo "${ext}"
+ done >> Setup
+ if: ${{ (matrix.entry.static-exts || '') != '' }}
+
+ - name: Clean up ext/Setup
+ uses: gacts/run-and-post-run@7aec950f3b114c4fcf6012070c3709ecff0eb6f8 # v1.4.0
+ with:
+ shell: bash
+ working-directory: build
+ post: rm ext/Setup
+ if: ${{ steps.ext-setup.outcome == 'success' }}
- run: make showflags
@@ -279,9 +294,6 @@ jobs:
CHECK_LEAKS: true
if: ${{ matrix.entry.check }}
- - run: make test-annocheck
- if: ${{ matrix.entry.check && endsWith(matrix.entry.name, 'annocheck') }}
-
- uses: ./.github/actions/slack
with:
label: ${{ matrix.entry.name }}
diff --git a/.github/workflows/dependabot_automerge.yml b/.github/workflows/dependabot_automerge.yml
index 6259199b11..80112a0af3 100644
--- a/.github/workflows/dependabot_automerge.yml
+++ b/.github/workflows/dependabot_automerge.yml
@@ -11,11 +11,11 @@ jobs:
steps:
- name: Dependabot metadata
- uses: dependabot/fetch-metadata@c9c4182bf1b97f5224aee3906fd373f6b61b4526 # v1.6.0
+ uses: dependabot/fetch-metadata@5e5f99653a5b510e8555840e80cbf1514ad4af38 # v2.1.0
id: metadata
- name: Wait for status checks
- uses: lewagon/wait-on-check-action@e106e5c43e8ca1edea6383a39a01c5ca495fd812 # v1.3.1
+ uses: lewagon/wait-on-check-action@ccfb013c15c8afb7bf2b7c028fb74dc5a068cccc # v1.3.4
with:
repo-token: ${{ secrets.MATZBOT_GITHUB_TOKEN }}
ref: ${{ github.event.pull_request.head.sha || github.sha }}
diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml
index 363ef8566e..b565833e74 100644
--- a/.github/workflows/macos.yml
+++ b/.github/workflows/macos.yml
@@ -3,20 +3,15 @@ on:
push:
paths-ignore:
- 'doc/**'
- - '**/man'
+ - '**/man/*'
- '**.md'
- '**.rdoc'
- '**/.document'
+ - '.*.yml'
pull_request:
# Do not use paths-ignore for required status checks
# https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks
merge_group:
- paths-ignore:
- - 'doc/**'
- - '**/man'
- - '**.md'
- - '**.rdoc'
- - '**/.document'
concurrency:
group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
@@ -29,26 +24,35 @@ jobs:
make:
strategy:
matrix:
- test_task: ['check']
- configure: ['']
- os: ${{ fromJSON(format('["macos-11","macos-12"{0}]', (github.repository == 'ruby/ruby' && ',"macos-arm-oss"' || ''))) }}
+ include:
+ - test_task: check
+ - test_task: test-all
+ test_opts: --repeat-count=2
+ - test_task: test-bundler-parallel
+ - test_task: test-bundled-gems
+ - test_task: check
+ os: macos-12
+ - test_task: check
+ os: macos-13
fail-fast: false
env:
GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
- runs-on: ${{ matrix.os }}
+ runs-on: ${{ matrix.os || (github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-14')}}
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || contains(github.event.pull_request.title, 'Document')
+ || contains(github.event.pull_request.labels.*.name, 'Document')
|| (github.event_name == 'push' && github.actor == 'dependabot[bot]')
)}}
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
sparse-checkout-cone-mode: false
sparse-checkout: /.github
@@ -61,43 +65,88 @@ jobs:
srcdir: src
builddir: build
makeup: true
+ clean: true
dummy-files: ${{ matrix.test_task == 'check' }}
+ # Set fetch-depth: 0 so that Launchable can receive commits information.
+ fetch-depth: 10
+
+ - name: make sure that kern.coredump=1
+ run: |
+ sysctl -n kern.coredump
+ sudo sysctl -w kern.coredump=1
+ sudo chmod -R +rwx /cores/
- name: Run configure
- run: ../src/configure -C --disable-install-doc ${{ matrix.configure }}
+ run: ../src/configure -C --disable-install-doc ${ruby_configure_args}
- run: make prepare-gems
if: ${{ matrix.test_task == 'test-bundled-gems' }}
- run: make
+ - name: Set test options for skipped tests
+ run: |
+ set -x
+ TESTS="$(echo "${{ matrix.skipped_tests }}" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|')"
+ echo "TESTS=${TESTS}" >> $GITHUB_ENV
+ if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }}
+
+ - name: Set up Launchable
+ uses: ./.github/actions/launchable/setup
+ with:
+ os: ${{ matrix.os || (github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-14')}}
+ test-opts: ${{ matrix.test_opts }}
+ launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }}
+ builddir: build
+ srcdir: src
+ continue-on-error: true
+
+ - name: Set extra test options
+ run: echo "TESTS=$TESTS ${{ matrix.test_opts }}" >> $GITHUB_ENV
+ if: matrix.test_opts
+
- name: make ${{ matrix.test_task }}
run: |
- make -s ${{ matrix.test_task }} ${TESTS:+TESTS=`echo "$TESTS" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|'`}
+ ulimit -c unlimited
+ make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"}
timeout-minutes: 60
env:
RUBY_TESTOPTS: '-q --tty=no'
- TESTS: ${{ matrix.test_task == 'check' && matrix.skipped_tests || '' }}
TEST_BUNDLED_GEMS_ALLOW_FAILURES: ''
PRECHECK_BUNDLED_GEMS: 'no'
- name: make skipped tests
run: |
- make -s test-all TESTS=`echo "$TESTS" | sed 's| |$$/ -n/|g;s|^|-n/|;s|$|$$/|'`
+ make -s test-all TESTS="${TESTS//-n!\//-n/}"
env:
GNUMAKEFLAGS: ''
RUBY_TESTOPTS: '-v --tty=no'
- TESTS: ${{ matrix.skipped_tests }}
PRECHECK_BUNDLED_GEMS: 'no'
- if: ${{ matrix.test_task == 'check' && matrix.skipped_tests != '' }}
+ if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }}
continue-on-error: ${{ matrix.continue-on-skipped_tests || false }}
- uses: ./.github/actions/slack
with:
- label: ${{ matrix.os }} / ${{ matrix.test_task }} ${{ matrix.configure }}
+ label: ${{ matrix.os }} / ${{ matrix.test_task }}
SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
if: ${{ failure() }}
+ - name: Resolve job ID
+ id: job_id
+ uses: actions/github-script@main
+ env:
+ matrix: ${{ toJson(matrix) }}
+ with:
+ script: |
+ const { data: workflow_run } = await github.rest.actions.listJobsForWorkflowRun({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ run_id: context.runId
+ });
+ const matrix = JSON.parse(process.env.matrix);
+ const job_name = `${context.job}${matrix ? ` (${Object.values(matrix).join(", ")})` : ""}`;
+ return workflow_run.jobs.find((job) => job.name === job_name).id;
+
result:
if: ${{ always() }}
name: ${{ github.workflow }} result
@@ -105,6 +154,7 @@ jobs:
needs: [make]
steps:
- run: exit 1
+ working-directory:
if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
defaults:
diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml
index 5ddcb59e76..8f38fd1e7b 100644
--- a/.github/workflows/mingw.yml
+++ b/.github/workflows/mingw.yml
@@ -3,24 +3,20 @@ on:
push:
paths-ignore:
- 'doc/**'
- - '**/man'
+ - '**/man/*'
- '**.md'
- '**.rdoc'
- '**/.document'
+ - '.*.yml'
pull_request:
paths-ignore:
- 'doc/**'
- - '**/man'
+ - '**/man/*'
- '**.md'
- '**.rdoc'
- '**/.document'
+ - '.*.yml'
merge_group:
- paths-ignore:
- - 'doc/**'
- - '**/man'
- - '**.md'
- - '**.rdoc'
- - '**/.document'
concurrency:
group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
@@ -53,7 +49,7 @@ jobs:
include:
# To mitigate flakiness of MinGW CI, we test only one runtime that newer MSYS2 uses.
- msystem: 'UCRT64'
- base_ruby: head
+ baseruby: '3.0'
test_task: 'check'
test-all-opts: '--name=!/TestObjSpace#test_reachable_objects_during_iteration/'
fail-fast: false
@@ -61,16 +57,18 @@ jobs:
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || contains(github.event.pull_request.title, 'Document')
+ || contains(github.event.pull_request.labels.*.name, 'Document')
|| (github.event_name == 'push' && github.actor == 'dependabot[bot]')
)}}
steps:
- name: Set up Ruby & MSYS2
- uses: ruby/setup-ruby@036ef458ddccddb148a2b9fb67e95a22fdbf728b # v1.160.0
+ uses: ruby/setup-ruby@78c01b705fd9d5ad960d432d3a0cfa341d50e410 # v1.179.1
with:
- ruby-version: ${{ matrix.base_ruby }}
+ ruby-version: ${{ matrix.baseruby }}
- name: where check
run: |
@@ -99,7 +97,7 @@ jobs:
$result
working-directory:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
sparse-checkout-cone-mode: false
sparse-checkout: /.github
@@ -125,6 +123,7 @@ jobs:
- name: test
timeout-minutes: 30
run: make test
+ shell: cmd
env:
GNUMAKEFLAGS: ''
RUBY_TESTOPTS: '-v --tty=no'
@@ -132,9 +131,8 @@ jobs:
- name: test-all
timeout-minutes: 45
+ shell: cmd
run: |
- # Actions uses UTF8, causes test failures, similar to normal OS setup
- chcp.com 437
make ${{ StartsWith(matrix.test_task, 'test/') && matrix.test_task || 'test-all' }}
env:
RUBY_TESTOPTS: >-
@@ -147,6 +145,7 @@ jobs:
timeout-minutes: 10
run: |
make ${{ StartsWith(matrix.test_task, 'spec/') && matrix.test_task || 'test-spec' }}
+ shell: cmd
if: ${{ matrix.test_task == 'check' || matrix.test_task == 'test-spec' || StartsWith(matrix.test_task, 'spec/') }}
- uses: ./src/.github/actions/slack
diff --git a/.github/workflows/pr-playground.yml b/.github/workflows/pr-playground.yml
new file mode 100644
index 0000000000..cc06006142
--- /dev/null
+++ b/.github/workflows/pr-playground.yml
@@ -0,0 +1,127 @@
+name: Post Playground link to PR
+on:
+ pull_request_target:
+ types: [labeled]
+ workflow_run:
+ workflows: ["WebAssembly"]
+ types: [completed]
+
+jobs:
+ post-summary:
+ name: Post Playground link
+ runs-on: ubuntu-latest
+ permissions:
+ pull-requests: write
+ # Post a comment only if the PR status check is passed and the PR is labeled with `Playground`.
+ # Triggered twice: when the PR is labeled and when PR build is passed.
+ if: >-
+ ${{ false
+ || (true
+ && github.event_name == 'pull_request_target'
+ && contains(github.event.pull_request.labels.*.name, 'Playground'))
+ || (true
+ && github.event_name == 'workflow_run'
+ && github.event.workflow_run.conclusion == 'success'
+ && github.event.workflow_run.event == 'pull_request')
+ }}
+ steps:
+ - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ const fs = require('fs/promises');
+
+ const buildWorkflowPath = '.github/workflows/wasm.yml';
+ const findSuccessfuBuildRun = async (pr) => {
+ const opts = github.rest.actions.listWorkflowRunsForRepo.endpoint.merge({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ status: 'success',
+ branch: pr.head.ref,
+ });
+ const runs = await github.paginate(opts);
+ const buildRun = runs.find(run => run.path == buildWorkflowPath);
+ return buildRun;
+ }
+
+ const postComment = async (body, pr) => {
+ const { data: comments } = await github.rest.issues.listComments({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: pr.number,
+ });
+
+ const commentOpts = { owner: context.repo.owner, repo: context.repo.repo, body: comment };
+
+ const existingComment = comments.find(comment => comment.body.startsWith(magicComment));
+ if (existingComment) {
+ core.info(`Updating existing comment: ${existingComment.html_url}`);
+ await github.rest.issues.updateComment({
+ ...commentOpts, comment_id: existingComment.id
+ });
+ } else {
+ await github.rest.issues.createComment({
+ ...commentOpts, issue_number: pr.number
+ });
+ }
+ }
+
+ const derivePRNumber = async () => {
+ if (context.payload.pull_request) {
+ return context.payload.pull_request.number;
+ }
+ // Workaround for https://github.com/orgs/community/discussions/25220
+
+ const { data: { artifacts } } = await github.rest.actions.listWorkflowRunArtifacts({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ run_id: context.payload.workflow_run.id,
+ });
+ const artifact = artifacts.find(artifact => artifact.name == 'github-pr-info');
+ if (!artifact) {
+ throw new Error('Cannot find github-pr-info.txt artifact');
+ }
+
+ const { data } = await github.rest.actions.downloadArtifact({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ artifact_id: artifact.id,
+ archive_format: 'zip',
+ });
+
+ await fs.writeFile('pr-info.zip', Buffer.from(data));
+ await exec.exec('unzip', ['pr-info.zip']);
+ return await fs.readFile('github-pr-info.txt', 'utf8');
+ }
+
+ const prNumber = await derivePRNumber();
+
+ const { data: pr } = await github.rest.pulls.get({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ pull_number: prNumber,
+ });
+
+ core.info(`Checking if the PR ${prNumber} is labeled with Playground...`);
+ if (!pr.labels.some(label => label.name == 'Playground')) {
+ core.info(`The PR is not labeled with Playground.`);
+ return;
+ }
+
+ core.info(`Checking if the build is successful for ${pr.head.ref} in ${pr.head.repo.owner.login}/${pr.head.repo.name}...`);
+ const buildRun = await findSuccessfuBuildRun(pr);
+ if (!buildRun) {
+ core.info(`No successful build run found for ${buildWorkflowPath} on ${pr.head.ref} yet.`);
+ return;
+ }
+ core.info(`Found a successful build run: ${buildRun.html_url}`);
+
+ const runLink = `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`;
+ const magicComment = `<!-- AUTO-GENERATED-COMMENT-PR-PLAYGROUND -->`;
+ const comment = `${magicComment}
+ **Try on Playground**: https://ruby.github.io/play-ruby?run=${buildRun.id}
+ This is an automated comment by [\`pr-playground.yml\`](${runLink}) workflow.
+ `;
+ core.info(`Comment: ${comment}`);
+ await postComment(comment, pr);
+
diff --git a/.github/workflows/prism.yml b/.github/workflows/prism.yml
new file mode 100644
index 0000000000..56d7298193
--- /dev/null
+++ b/.github/workflows/prism.yml
@@ -0,0 +1,114 @@
+name: Prism
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '**.[1-8]'
+ - '**.ronn'
+ - '.*.yml'
+ pull_request:
+ paths-ignore:
+ - 'doc/**'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '**.[1-8]'
+ - '**.ronn'
+ - '.*.yml'
+ merge_group:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ make:
+ strategy:
+ matrix:
+ # main variables included in the job name
+ test_task: [check]
+ run_opts: ['--parser=prism']
+ arch: ['']
+ fail-fast: false
+
+ env:
+ GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
+ RUBY_DEBUG: ci
+ SETARCH: ${{ matrix.arch && format('setarch {0}', matrix.arch) }}
+
+ runs-on: ubuntu-22.04
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.head_commit.message, 'Document')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.title, 'Document')
+ || contains(github.event.pull_request.labels.*.name, 'Document')
+ || (github.event_name == 'push' && github.actor == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ with:
+ sparse-checkout-cone-mode: false
+ sparse-checkout: /.github
+
+ - uses: ./.github/actions/setup/ubuntu
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ srcdir: src
+ builddir: build
+ makeup: true
+
+ - name: Run configure
+ env:
+ arch: ${{ matrix.arch }}
+ run: >-
+ $SETARCH ../src/configure -C --disable-install-doc cppflags=-DRUBY_DEBUG
+ ${arch:+--target=$arch-$OSTYPE --host=$arch-$OSTYPE}
+
+ - run: $SETARCH make
+
+ - name: make test
+ run: |
+ $SETARCH make -s test RUN_OPTS="$RUN_OPTS"
+ timeout-minutes: 30
+ env:
+ GNUMAKEFLAGS: ''
+ RUBY_TESTOPTS: '-v --tty=no'
+ RUN_OPTS: ${{ matrix.run_opts }}
+
+ - name: make test-all
+ run: |
+ $SETARCH make -s test-all RUN_OPTS="$RUN_OPTS"
+ timeout-minutes: 40
+ env:
+ GNUMAKEFLAGS: ''
+ RUBY_TESTOPTS: '-q --tty=no --excludes-dir="../src/test/.excludes-prism" --exclude="error_highlight/test_error_highlight.rb"'
+ RUN_OPTS: ${{ matrix.run_opts }}
+
+ - name: make test-spec
+ run: |
+ $SETARCH make -s test-spec SPECOPTS="$SPECOPTS"
+ timeout-minutes: 10
+ env:
+ GNUMAKEFLAGS: ''
+ SPECOPTS: "-T -W:no-experimental -T --parser=prism"
+
+ - uses: ./.github/actions/slack
+ with:
+ label: ${{ matrix.run_opts }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
+
+defaults:
+ run:
+ working-directory: build
diff --git a/.github/workflows/rjit-bindgen.yml b/.github/workflows/rjit-bindgen.yml
index 8da2815b06..97c99ea829 100644
--- a/.github/workflows/rjit-bindgen.yml
+++ b/.github/workflows/rjit-bindgen.yml
@@ -3,24 +3,20 @@ on:
push:
paths-ignore:
- 'doc/**'
- - '**/man'
+ - '**/man/*'
- '**.md'
- '**.rdoc'
- '**/.document'
+ - '.*.yml'
pull_request:
paths-ignore:
- 'doc/**'
- - '**/man'
+ - '**/man/*'
- '**.md'
- '**.rdoc'
- '**/.document'
+ - '.*.yml'
merge_group:
- paths-ignore:
- - 'doc/**'
- - '**/man'
- - '**.md'
- - '**.rdoc'
- - '**/.document'
concurrency:
group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
@@ -42,18 +38,20 @@ jobs:
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || contains(github.event.pull_request.title, 'Document')
+ || contains(github.event.pull_request.labels.*.name, 'Document')
|| (github.event_name == 'push' && github.actor == 'dependabot[bot]')
)}}
steps:
- name: Set up Ruby
- uses: ruby/setup-ruby@036ef458ddccddb148a2b9fb67e95a22fdbf728b # v1.160.0
+ uses: ruby/setup-ruby@78c01b705fd9d5ad960d432d3a0cfa341d50e410 # v1.179.1
with:
ruby-version: '3.1'
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
sparse-checkout-cone-mode: false
sparse-checkout: /.github
diff --git a/.github/workflows/rjit.yml b/.github/workflows/rjit.yml
index 53c29959eb..21e697315b 100644
--- a/.github/workflows/rjit.yml
+++ b/.github/workflows/rjit.yml
@@ -8,6 +8,7 @@ on:
- '**/.document'
- '**.[1-8]'
- '**.ronn'
+ - '.*.yml'
pull_request:
paths-ignore:
- 'doc/**'
@@ -16,14 +17,8 @@ on:
- '**/.document'
- '**.[1-8]'
- '**.ronn'
+ - '.*.yml'
merge_group:
- paths-ignore:
- - 'doc/**'
- - '**.md'
- - '**.rdoc'
- - '**/.document'
- - '**.[1-8]'
- - '**.ronn'
concurrency:
group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
@@ -52,13 +47,15 @@ jobs:
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || contains(github.event.pull_request.title, 'Document')
+ || contains(github.event.pull_request.labels.*.name, 'Document')
|| (github.event_name == 'push' && github.actor == 'dependabot[bot]')
)}}
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
sparse-checkout-cone-mode: false
sparse-checkout: /.github
@@ -86,7 +83,7 @@ jobs:
timeout-minutes: 30
env:
GNUMAKEFLAGS: ''
- RUBY_TESTOPTS: '-v --tty=no'
+ RUBY_TESTOPTS: '--tty=no'
RUN_OPTS: ${{ matrix.run_opts }}
- name: make test-all
diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml
index 51ce54a518..51423a84f9 100644
--- a/.github/workflows/scorecards.yml
+++ b/.github/workflows/scorecards.yml
@@ -32,12 +32,12 @@ jobs:
steps:
- name: 'Checkout code'
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
persist-credentials: false
- name: 'Run analysis'
- uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
+ uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3
with:
results_file: results.sarif
results_format: sarif
@@ -67,6 +67,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: 'Upload to code-scanning'
- uses: github/codeql-action/upload-sarif@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.1.27
+ uses: github/codeql-action/upload-sarif@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v2.1.27
with:
sarif_file: results.sarif
diff --git a/.github/workflows/spec_guards.yml b/.github/workflows/spec_guards.yml
index e14e7818a6..4fde74ec46 100644
--- a/.github/workflows/spec_guards.yml
+++ b/.github/workflows/spec_guards.yml
@@ -6,13 +6,10 @@ on:
- 'spec/**'
- '!spec/*.md'
pull_request:
- paths-ignore:
+ paths:
- 'spec/**'
- '!spec/*.md'
merge_group:
- paths-ignore:
- - 'spec/**'
- - '!spec/*.md'
concurrency:
group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
@@ -30,8 +27,10 @@ jobs:
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || contains(github.event.pull_request.title, 'Document')
+ || contains(github.event.pull_request.labels.*.name, 'Document')
|| (github.event_name == 'push' && github.actor == 'dependabot[bot]')
)}}
@@ -43,11 +42,12 @@ jobs:
- ruby-3.0
- ruby-3.1
- ruby-3.2
+ - ruby-3.3
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- - uses: ruby/setup-ruby@036ef458ddccddb148a2b9fb67e95a22fdbf728b # v1.160.0
+ - uses: ruby/setup-ruby@78c01b705fd9d5ad960d432d3a0cfa341d50e410 # v1.179.1
with:
ruby-version: ${{ matrix.ruby }}
bundler: none
diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml
index fa9eb9fef6..cf2b1f73ab 100644
--- a/.github/workflows/ubuntu.yml
+++ b/.github/workflows/ubuntu.yml
@@ -3,20 +3,15 @@ on:
push:
paths-ignore:
- 'doc/**'
- - '**/man'
+ - '**/man/*'
- '**.md'
- '**.rdoc'
- '**/.document'
+ - '.*.yml'
pull_request:
# Do not use paths-ignore for required status checks
# https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks
merge_group:
- paths-ignore:
- - 'doc/**'
- - '**/man'
- - '**.md'
- - '**.rdoc'
- - '**/.document'
concurrency:
group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
@@ -29,40 +24,41 @@ jobs:
make:
strategy:
matrix:
- test_task: [check]
- arch: ['']
- configure: ['cppflags=-DVM_CHECK_MODE']
- # specifying other jobs with `include` to avoid redundant tests
include:
- test_task: check
+ configure: 'cppflags=-DVM_CHECK_MODE'
+ - test_task: check
arch: i686
- test_task: check
configure: '--disable-yjit'
- test_task: check
configure: '--enable-shared --enable-load-relative'
- - test_task: test-all TESTS=--repeat-count=2
- - test_task: test-all
- configure: 'cppflags=-DUNIVERSAL_PARSER'
+ - test_task: check
+ configure: '--with-shared-gc'
- test_task: test-bundler-parallel
- test_task: test-bundled-gems
+ - test_task: check
+ os: ubuntu-20.04
fail-fast: false
env:
GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
RUBY_DEBUG: ci
- runs-on: ubuntu-20.04
+ runs-on: ${{ matrix.os || 'ubuntu-22.04' }}
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || contains(github.event.pull_request.title, 'Document')
+ || contains(github.event.pull_request.labels.*.name, 'Document')
|| (github.event_name == 'push' && github.actor == 'dependabot[bot]')
)}}
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
sparse-checkout-cone-mode: false
sparse-checkout: /.github
@@ -71,12 +67,20 @@ jobs:
with:
arch: ${{ matrix.arch }}
+ - uses: ruby/setup-ruby@78c01b705fd9d5ad960d432d3a0cfa341d50e410 # v1.179.1
+ with:
+ ruby-version: '3.0'
+ bundler: none
+
- uses: ./.github/actions/setup/directories
with:
srcdir: src
builddir: build
makeup: true
+ clean: true
dummy-files: ${{ matrix.test_task == 'check' }}
+ # Set fetch-depth: 10 so that Launchable can receive commits information.
+ fetch-depth: 10
- name: Run configure
env:
@@ -91,26 +95,41 @@ jobs:
- run: $SETARCH make
+ - name: Set test options for skipped tests
+ run: |
+ set -x
+ TESTS="$(echo "${{ matrix.skipped_tests }}" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|')"
+ echo "TESTS=${TESTS}" >> $GITHUB_ENV
+ if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }}
+
+ - name: Set up Launchable
+ uses: ./.github/actions/launchable/setup
+ with:
+ os: ${{ matrix.os || 'ubuntu-22.04' }}
+ test-opts: ${{ matrix.configure }}
+ launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }}
+ builddir: build
+ srcdir: src
+ continue-on-error: true
+
- name: make ${{ matrix.test_task }}
run: >-
$SETARCH make -s ${{ matrix.test_task }}
- ${TESTS:+TESTS=`echo "$TESTS" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|'`}
+ ${TESTS:+TESTS="$TESTS"}
${{ !contains(matrix.test_task, 'bundle') && 'RUBYOPT=-w' || '' }}
timeout-minutes: 40
env:
RUBY_TESTOPTS: '-q --tty=no'
- TESTS: ${{ matrix.test_task == 'check' && matrix.skipped_tests || '' }}
TEST_BUNDLED_GEMS_ALLOW_FAILURES: ''
PRECHECK_BUNDLED_GEMS: 'no'
- name: make skipped tests
run: |
- $SETARCH make -s test-all TESTS=`echo "$TESTS" | sed 's| |$$/ -n/|g;s|^|-n/|;s|$|$$/|'`
+ $SETARCH make -s test-all TESTS="${TESTS//-n!\//-n/}"
env:
GNUMAKEFLAGS: ''
RUBY_TESTOPTS: '-v --tty=no'
- TESTS: ${{ matrix.skipped_tests }}
- if: ${{ matrix.test_task == 'check' && matrix.skipped_tests != '' }}
+ if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }}
continue-on-error: ${{ matrix.continue-on-skipped_tests || false }}
- uses: ./.github/actions/slack
@@ -126,6 +145,7 @@ jobs:
needs: [make]
steps:
- run: exit 1
+ working-directory:
if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
defaults:
diff --git a/.github/workflows/wasm.yml b/.github/workflows/wasm.yml
index 9f8f292b8b..e9ce787f12 100644
--- a/.github/workflows/wasm.yml
+++ b/.github/workflows/wasm.yml
@@ -3,24 +3,20 @@ on:
push:
paths-ignore:
- 'doc/**'
- - '**/man'
+ - '**/man/*'
- '**.md'
- '**.rdoc'
- '**/.document'
+ - '.*.yml'
pull_request:
paths-ignore:
- 'doc/**'
- - '**/man'
+ - '**/man/*'
- '**.md'
- '**.rdoc'
- '**/.document'
+ - '.*.yml'
merge_group:
- paths-ignore:
- - 'doc/**'
- - '**/man'
- - '**.md'
- - '**.rdoc'
- - '**/.document'
concurrency:
group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
@@ -47,23 +43,25 @@ jobs:
env:
RUBY_TESTOPTS: '-q --tty=no'
GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
- WASI_SDK_VERSION_MAJOR: 14
+ WASI_SDK_VERSION_MAJOR: 20
WASI_SDK_VERSION_MINOR: 0
- BINARYEN_VERSION: 109
- WASMTIME_VERSION: v0.33.0
+ BINARYEN_VERSION: 113
+ WASMTIME_VERSION: v15.0.0
runs-on: ubuntu-20.04
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || contains(github.event.pull_request.title, 'Document')
+ || contains(github.event.pull_request.labels.*.name, 'Document')
|| (github.event_name == 'push' && github.actor == 'dependabot[bot]')
)}}
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
sparse-checkout-cone-mode: false
sparse-checkout: /.github
@@ -102,12 +100,27 @@ jobs:
run: |
echo "WASI_SDK_PATH=/opt/wasi-sdk" >> $GITHUB_ENV
+ - uses: ruby/setup-ruby@78c01b705fd9d5ad960d432d3a0cfa341d50e410 # v1.179.1
+ with:
+ ruby-version: '3.0'
+ bundler: none
+
+ - name: Build baseruby
+ run: |
+ set -ex
+ mkdir ../baseruby
+ pushd ../baseruby
+ ../src/configure --prefix=$PWD/install
+ make
+ make install
+
- name: Run configure
run: |
../src/configure \
--host wasm32-unknown-wasi \
+ --with-baseruby=$PWD/../baseruby/install/bin/ruby \
--with-static-linked-ext \
- --with-ext=bigdecimal,ripper,monitor,stringio,pathname \
+ --with-ext=cgi/escape,continuation,coverage,date,digest/bubblebabble,digest,digest/md5,digest/rmd160,digest/sha1,digest/sha2,etc,fcntl,json,json/generator,json/parser,objspace,pathname,rbconfig/sizeof,ripper,stringio,strscan,monitor \
LDFLAGS=" \
-Xlinker --stack-first \
-Xlinker -z -Xlinker stack-size=16777216 \
@@ -119,6 +132,18 @@ jobs:
# miniruby may not be built when cross-compling
- run: make mini ruby
+ - run: make install DESTDIR=$PWD/../install
+ - run: tar cfz ../install.tar.gz -C ../install .
+
+ - name: Upload artifacts
+ uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
+ with:
+ name: ruby-wasm-install
+ path: ${{ github.workspace }}/install.tar.gz
+ - name: Show Playground URL to try the build
+ run: |
+ echo "Try on Playground: https://ruby.github.io/play-ruby?run=$GITHUB_RUN_ID" >> $GITHUB_STEP_SUMMARY
+
- name: Run basictest
run: wasmtime run ./../build/miniruby --mapdir /::./ -- basictest/test.rb
working-directory: src
@@ -135,6 +160,16 @@ jobs:
SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
if: ${{ failure() }}
+ # Workaround for https://github.com/orgs/community/discussions/25220
+ - name: Save Pull Request number
+ if: ${{ github.event_name == 'pull_request' }}
+ run: echo "${{ github.event.pull_request.number }}" >> ${{ github.workspace }}/github-pr-info.txt
+ - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
+ if: ${{ github.event_name == 'pull_request' }}
+ with:
+ name: github-pr-info
+ path: ${{ github.workspace }}/github-pr-info.txt
+
defaults:
run:
working-directory: build
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 982f855345..0e778a48db 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -3,24 +3,20 @@ on:
push:
paths-ignore:
- 'doc/**'
- - '**/man'
+ - '**/man/*'
- '**.md'
- '**.rdoc'
- '**/.document'
+ - '.*.yml'
pull_request:
paths-ignore:
- 'doc/**'
- - '**/man'
+ - '**/man/*'
- '**.md'
- '**.rdoc'
- '**/.document'
+ - '.*.yml'
merge_group:
- paths-ignore:
- - 'doc/**'
- - '**/man'
- - '**.md'
- - '**.rdoc'
- - '**/.document'
concurrency:
group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
@@ -34,6 +30,9 @@ jobs:
strategy:
matrix:
include:
+ - vc: 2015
+ vs: 2019
+ vcvars: '10.0.14393.0 -vcvars_ver=14.0' # The oldest Windows 10 SDK w/ VC++ 2015 toolset (v140)
- vs: 2019
- vs: 2022
fail-fast: false
@@ -43,12 +42,14 @@ jobs:
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || contains(github.event.pull_request.title, 'Document')
+ || contains(github.event.pull_request.labels.*.name, 'Document')
|| (github.event_name == 'push' && github.actor == 'dependabot[bot]')
)}}
- name: VisualStudio ${{ matrix.vs }}
+ name: VisualStudio ${{ matrix.vc || matrix.vs }}
env:
GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
@@ -90,7 +91,13 @@ jobs:
${{ steps.find-tools.outputs.needs }}
if: ${{ steps.find-tools.outputs.needs != '' }}
- - uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
+ - uses: ruby/setup-ruby@78c01b705fd9d5ad960d432d3a0cfa341d50e410 # v1.179.1
+ with:
+ ruby-version: '3.0'
+ bundler: none
+ windows-toolchain: none
+
+ - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
with:
path: C:\vcpkg\downloads
key: ${{ runner.os }}-vcpkg-download-${{ env.OS_VER }}-${{ github.sha }}
@@ -98,7 +105,7 @@ jobs:
${{ runner.os }}-vcpkg-download-${{ env.OS_VER }}-
${{ runner.os }}-vcpkg-download-
- - uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
+ - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
with:
path: C:\vcpkg\installed
key: ${{ runner.os }}-vcpkg-installed-${{ env.OS_VER }}-${{ github.sha }}
@@ -108,7 +115,7 @@ jobs:
- name: Install libraries with vcpkg
run: |
- vcpkg --triplet x64-windows install libffi libyaml openssl readline zlib
+ vcpkg --triplet x64-windows install gmp libffi libyaml openssl zlib
- name: Install libraries with scoop
run: |
@@ -116,7 +123,7 @@ jobs:
Join-Path (Resolve-Path ~).Path "scoop\shims" >> $Env:GITHUB_PATH
shell: pwsh
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
sparse-checkout-cone-mode: false
sparse-checkout: /.github
@@ -127,17 +134,15 @@ jobs:
builddir: build
- name: setup env
+ # Available Ruby versions: https://github.com/actions/runner-images/blob/main/images/windows/Windows2019-Readme.md#ruby
# %TEMP% is inconsistent with %TMP% and test-all expects they are consistent.
# https://github.com/actions/virtual-environments/issues/712#issuecomment-613004302
run: |
set VS=${{ matrix.vs }}
- set VCVARS=${{ matrix.vcvars || '' }}
- if not "%VCVARS%" == "" goto :vcset
- set VCVARS="C:\Program Files (x86)\Microsoft Visual Studio\%VS%\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
- if not exist %VCVARS% set VCVARS="C:\Program Files\Microsoft Visual Studio\%VS%\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
- :vcset
+ set VCVARS="C:\Program Files (x86)\Microsoft Visual Studio\%VS%\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
+ if not exist %VCVARS% set VCVARS="C:\Program Files\Microsoft Visual Studio\%VS%\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
set | C:\msys64\usr\bin\sort > old.env
- call %VCVARS%
+ call %VCVARS% ${{ matrix.vcvars || '' }}
nmake -f nul
set TMP=%USERPROFILE%\AppData\Local\Temp
set TEMP=%USERPROFILE%\AppData\Local\Temp
@@ -147,6 +152,9 @@ jobs:
C:\msys64\usr\bin\comm -13 old.env new.env >> %GITHUB_ENV%
del *.env
+ - name: baseruby version
+ run: ruby -v
+
- name: compiler version
run: cl
@@ -173,6 +181,10 @@ jobs:
- run: nmake extract-extlibs
+ # On all other platforms, test-spec depending on extract-gems (in common.mk) is enough.
+ # But not for this Visual Studio workflow. So here we extract gems before building.
+ - run: nmake extract-gems
+
- run: nmake
- run: nmake test
@@ -188,7 +200,7 @@ jobs:
- uses: ./.github/actions/slack
with:
- label: VS${{ matrix.vs }} / ${{ matrix.test_task || 'check' }}
+ label: VS${{ matrix.vc || matrix.vs }} / ${{ matrix.test_task || 'check' }}
SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
if: ${{ failure() }}
diff --git a/.github/workflows/yjit-macos.yml b/.github/workflows/yjit-macos.yml
index c8f21cfa7e..9660572e99 100644
--- a/.github/workflows/yjit-macos.yml
+++ b/.github/workflows/yjit-macos.yml
@@ -3,20 +3,15 @@ on:
push:
paths-ignore:
- 'doc/**'
- - '**/man'
+ - '**/man/*'
- '**.md'
- '**.rdoc'
- '**/.document'
+ - '.*.yml'
pull_request:
# Do not use paths-ignore for required status checks
# https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks
merge_group:
- paths-ignore:
- - 'doc/**'
- - '**/man'
- - '**.md'
- - '**.rdoc'
- - '**/.document'
concurrency:
group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
@@ -29,19 +24,20 @@ jobs:
cargo:
name: cargo test
- runs-on: macos-arm-oss
+ runs-on: ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-14' }}
if: >-
- ${{github.repository == 'ruby/ruby' &&
- !(false
+ ${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || contains(github.event.pull_request.title, 'Document')
+ || contains(github.event.pull_request.labels.*.name, 'Document')
|| (github.event_name == 'push' && github.actor == 'dependabot[bot]')
)}}
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- run: RUST_BACKTRACE=1 cargo test
working-directory: yjit
@@ -64,25 +60,28 @@ jobs:
- test_task: 'check'
configure: '--enable-yjit=dev'
yjit_opts: '--yjit-call-threshold=1 --yjit-verify-ctx --yjit-code-gc'
+ specopts: '-T --yjit-call-threshold=1 -T --yjit-verify-ctx -T --yjit-code-gc'
fail-fast: false
env:
GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
RUN_OPTS: ${{ matrix.yjit_opts }}
+ SPECOPTS: ${{ matrix.specopts }}
- runs-on: macos-arm-oss
+ runs-on: ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-14' }}
if: >-
- ${{github.repository == 'ruby/ruby' &&
- !(false
+ ${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || contains(github.event.pull_request.title, 'Document')
+ || contains(github.event.pull_request.labels.*.name, 'Document')
|| (github.event_name == 'push' && github.actor == 'dependabot[bot]')
)}}
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
sparse-checkout-cone-mode: false
sparse-checkout: /.github
@@ -96,6 +95,8 @@ jobs:
builddir: build
makeup: true
dummy-files: ${{ matrix.test_task == 'check' }}
+ # Set fetch-depth: 10 so that Launchable can receive commits information.
+ fetch-depth: 10
- name: Run configure
run: ../src/configure -C --disable-install-doc ${{ matrix.configure }}
@@ -108,25 +109,44 @@ jobs:
- name: Enable YJIT through ENV
run: echo "RUBY_YJIT_ENABLE=1" >> $GITHUB_ENV
- - name: make ${{ matrix.test_task }}
+ - name: Set test options for skipped tests
run: |
- make -s ${{ matrix.test_task }} ${TESTS:+TESTS=`echo "$TESTS" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|'`}
+ set -x
+ TESTS="$(echo "${{ matrix.skipped_tests }}" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|')"
+ echo "TESTS=${TESTS}" >> $GITHUB_ENV
+ if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }}
+
+ - name: Set up Launchable
+ uses: ./.github/actions/launchable/setup
+ with:
+ os: ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-14' }}
+ test-opts: ${{ matrix.configure }}
+ launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }}
+ builddir: build
+ srcdir: src
+ continue-on-error: true
+
+ - name: make ${{ matrix.test_task }}
+ run: >-
+ make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"}
+ RUN_OPTS="$RUN_OPTS"
+ SPECOPTS="$SPECOPTS"
timeout-minutes: 60
env:
RUBY_TESTOPTS: '-q --tty=no'
- TESTS: ${{ matrix.test_task == 'check' && matrix.skipped_tests || '' }}
TEST_BUNDLED_GEMS_ALLOW_FAILURES: ''
+ SYNTAX_SUGGEST_TIMEOUT: '5'
PRECHECK_BUNDLED_GEMS: 'no'
+ continue-on-error: ${{ matrix.continue-on-test_task || false }}
- name: make skipped tests
run: |
- make -s test-all TESTS=`echo "$TESTS" | sed 's| |$$/ -n/|g;s|^|-n/|;s|$|$$/|'`
+ make -s test-all TESTS="${TESTS//-n!\//-n/}"
env:
GNUMAKEFLAGS: ''
RUBY_TESTOPTS: '-v --tty=no'
- TESTS: ${{ matrix.skipped_tests }}
PRECHECK_BUNDLED_GEMS: 'no'
- if: ${{ matrix.test_task == 'check' && matrix.skipped_tests != '' }}
+ if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }}
continue-on-error: ${{ matrix.continue-on-skipped_tests || false }}
- uses: ./.github/actions/slack
@@ -136,12 +156,13 @@ jobs:
if: ${{ failure() }}
result:
- if: ${{ always() && github.repository == 'ruby/ruby' }}
+ if: ${{ always() }}
name: ${{ github.workflow }} result
- runs-on: macos-arm-oss
+ runs-on: ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-14' }}
needs: [make]
steps:
- run: exit 1
+ working-directory:
if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
defaults:
diff --git a/.github/workflows/yjit-ubuntu.yml b/.github/workflows/yjit-ubuntu.yml
index d29aaccdfb..7f6f3393ef 100644
--- a/.github/workflows/yjit-ubuntu.yml
+++ b/.github/workflows/yjit-ubuntu.yml
@@ -3,20 +3,15 @@ on:
push:
paths-ignore:
- 'doc/**'
- - '**/man'
+ - '**/man/*'
- '**.md'
- '**.rdoc'
- '**/.document'
+ - '.*.yml'
pull_request:
# Do not use paths-ignore for required status checks
# https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks
merge_group:
- paths-ignore:
- - 'doc/**'
- - '**/man'
- - '**.md'
- - '**.rdoc'
- - '**/.document'
concurrency:
group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
@@ -36,12 +31,12 @@ jobs:
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || contains(github.event.pull_request.labels.*.name, 'Document')
|| (github.event_name == 'push' && github.actor == 'dependabot[bot]')
)}}
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
# For now we can't run cargo test --offline because it complains about the
# capstone dependency, even though the dependency is optional
@@ -68,12 +63,12 @@ jobs:
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || contains(github.event.pull_request.labels.*.name, 'Document')
|| (github.event_name == 'push' && github.actor == 'dependabot[bot]')
)}}
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
# Check that we don't have linting errors in release mode, too
- run: cargo clippy --all-targets --all-features
@@ -100,6 +95,7 @@ jobs:
- test_task: 'check'
configure: '--enable-yjit=dev'
yjit_opts: '--yjit-call-threshold=1 --yjit-verify-ctx --yjit-code-gc'
+ specopts: '-T --yjit-call-threshold=1 -T --yjit-verify-ctx -T --yjit-code-gc'
- test_task: 'test-bundled-gems'
configure: '--enable-yjit=dev'
@@ -107,11 +103,13 @@ jobs:
- test_task: 'yjit-bench'
configure: '--enable-yjit=dev'
yjit_bench_opts: '--yjit-stats'
+ continue-on-test_task: true
env:
GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
RUN_OPTS: ${{ matrix.yjit_opts }}
YJIT_BENCH_OPTS: ${{ matrix.yjit_bench_opts }}
+ SPECOPTS: ${{ matrix.specopts }}
RUBY_DEBUG: ci
BUNDLE_JOBS: 8 # for yjit-bench
RUST_BACKTRACE: 1
@@ -121,25 +119,34 @@ jobs:
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || contains(github.event.pull_request.title, 'Document')
+ || contains(github.event.pull_request.labels.*.name, 'Document')
|| (github.event_name == 'push' && github.actor == 'dependabot[bot]')
)}}
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
sparse-checkout-cone-mode: false
sparse-checkout: /.github
- uses: ./.github/actions/setup/ubuntu
+ - uses: ruby/setup-ruby@78c01b705fd9d5ad960d432d3a0cfa341d50e410 # v1.179.1
+ with:
+ ruby-version: '3.0'
+ bundler: none
+
- uses: ./.github/actions/setup/directories
with:
srcdir: src
builddir: build
makeup: true
dummy-files: ${{ matrix.test_task == 'check' }}
+ # Set fetch-depth: 10 so that Launchable can receive commits information.
+ fetch-depth: 10
- name: Install Rust
if: ${{ matrix.rust_version }}
@@ -162,16 +169,29 @@ jobs:
- name: Check YJIT enabled
run: ./miniruby --yjit -v | grep "+YJIT"
+ - name: Set up Launchable
+ uses: ./.github/actions/launchable/setup
+ with:
+ os: ubuntu-20.04
+ test-opts: ${{ matrix.configure }}
+ launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }}
+ builddir: build
+ srcdir: src
+ continue-on-error: true
+
- name: make ${{ matrix.test_task }}
- run: make -s -j ${{ matrix.test_task }} RUN_OPTS="$RUN_OPTS" MSPECOPT=--debug YJIT_BENCH_OPTS="$YJIT_BENCH_OPTS" YJIT_BINDGEN_DIFF_OPTS="$YJIT_BINDGEN_DIFF_OPTS"
- timeout-minutes: 60
+ run: >-
+ make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"}
+ RUN_OPTS="$RUN_OPTS" MSPECOPT=--debug SPECOPTS="$SPECOPTS"
+ YJIT_BENCH_OPTS="$YJIT_BENCH_OPTS" YJIT_BINDGEN_DIFF_OPTS="$YJIT_BINDGEN_DIFF_OPTS"
+ timeout-minutes: 90
env:
RUBY_TESTOPTS: '-q --tty=no'
- TEST_BUNDLED_GEMS_ALLOW_FAILURES: 'rbs'
+ TEST_BUNDLED_GEMS_ALLOW_FAILURES: ''
PRECHECK_BUNDLED_GEMS: 'no'
SYNTAX_SUGGEST_TIMEOUT: '5'
YJIT_BINDGEN_DIFF_OPTS: '--exit-code'
- continue-on-error: ${{ matrix.test_task == 'yjit-bench' }}
+ continue-on-error: ${{ matrix.continue-on-test_task || false }}
- name: Show ${{ github.event.pull_request.base.ref }} GitHub URL for yjit-bench comparison
run: echo "https://github.com/${BASE_REPO}/commit/${BASE_SHA}"
@@ -193,6 +213,7 @@ jobs:
needs: [make]
steps:
- run: exit 1
+ working-directory:
if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
defaults:
diff --git a/.gitignore b/.gitignore
index f30842adb5..b6beba3b3e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -138,6 +138,7 @@ lcov*.info
/test.rb
/test-coverage.dat
/tmp
+/vcpkg_installed
/transdb.h
/uncommon.mk
/verconf.h
@@ -166,6 +167,7 @@ lcov*.info
# /coroutine/
!/coroutine/**/*.s
+!/coroutine/**/*.S
# /enc/trans/
/enc/trans/*.c
@@ -258,13 +260,18 @@ lcov*.info
# prism
/lib/prism/compiler.rb
/lib/prism/dispatcher.rb
+/lib/prism/dot_visitor.rb
/lib/prism/dsl.rb
+/lib/prism/inspect_visitor.rb
/lib/prism/mutation_compiler.rb
/lib/prism/node.rb
+/lib/prism/reflection.rb
/lib/prism/serialize.rb
/lib/prism/visitor.rb
/prism/api_node.c
/prism/ast.h
+/prism/diagnostic.c
+/prism/diagnostic.h
/prism/node.c
/prism/prettyprint.c
/prism/serialize.c
diff --git a/.mailmap b/.mailmap
new file mode 100644
index 0000000000..213a0f4916
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1,431 @@
+git[bot] <svn-admin@ruby-lang.org>
+git[bot] <svn-admin@ruby-lang.org> git <svn@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+svn[bot] <svn-admin@ruby-lang.org> svn <svn@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# a_matsuda
+Akira Matsuda <ronnie@dio.jp>
+Akira Matsuda <ronnie@dio.jp> <a_matsuda@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# aamine
+Minero Aoki <aamine@loveruby.net>
+Minero Aoki <aamine@loveruby.net> <aamine@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# akira
+akira yamada <akira@ruby-lang.org>
+## akira yamada <akira@ruby-lang.org> <akira@rice.p.arika.org>
+akira yamada <akira@ruby-lang.org> <akira@arika.org>
+akira yamada <akira@ruby-lang.org> <akira@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# akiyoshi
+AKIYOSHI, Masamichi <masamichi.akiyoshi@hp.com>
+AKIYOSHI, Masamichi <masamichi.akiyoshi@hp.com> <akiyoshi@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# akr
+Tanaka Akira <akr@fsij.org>
+Tanaka Akira <akr@fsij.org> <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# arai
+Koji Arai <jca02266@nifty.ne.jp>
+Koji Arai <jca02266@nifty.ne.jp> <arai@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# arton
+Akio Tajima <artonx@yahoo.co.jp>
+Akio Tajima <artonx@yahoo.co.jp> <arton@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# aycabta
+aycabta <aycabta@gmail.com>
+aycabta <aycabta@gmail.com> <aycabta@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# ayumin
+Ayumu AIZAWA <ayumu.aizawa@gmail.com>
+Ayumu AIZAWA <ayumu.aizawa@gmail.com> <ayumin@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# azav
+Alexander Zavorine <alexandre.zavorine@nokia.com>
+Alexander Zavorine <alexandre.zavorine@nokia.com> <azav@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# charliesome
+Charlie Somerville <charliesome@ruby-lang.org>
+Charlie Somerville <charliesome@ruby-lang.org> <charliesome@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# dave
+Dave Thomas <dave@pragprog.com>
+Dave Thomas <dave@pragprog.com> <dave@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# davidflanagan
+David Flanagan <davidflanagan@ruby-lang.org>
+David Flanagan <davidflanagan@ruby-lang.org> <david@think32>
+David Flanagan <davidflanagan@ruby-lang.org> <david@davidflanagan.com>
+David Flanagan <davidflanagan@ruby-lang.org> <davidflanagan@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# dblack
+David A. Black <dblack@rubypal.com>
+David A. Black <dblack@rubypal.com> <dblack@wobblini.net>
+David A. Black <dblack@rubypal.com> <dblack@superlink.net>
+David A. Black <dblack@rubypal.com> <dblack@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# drbrain
+Eric Hodel <drbrain@segment7.net>
+Eric Hodel <drbrain@segment7.net> <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# duerst
+Martin Dürst <duerst@it.aoyama.ac.jp>
+Martin Dürst <duerst@it.aoyama.ac.jp> <duerst@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# eban
+WATANABE Hirofumi <eban@ruby-lang.org>
+WATANABE Hirofumi <eban@ruby-lang.org> <eban@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# emboss
+Martin Bosslet <Martin.Bosslet@gmail.com>
+Martin Bosslet <Martin.Bosslet@gmail.com> <Martin.Bosslet@googlemail.com>
+Martin Bosslet <Martin.Bosslet@gmail.com> <emboss@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# eregon
+Benoit Daloze <eregontp@gmail.com>
+Benoit Daloze <eregontp@gmail.com> <eregon@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# evan
+Evan Phoenix <evan@ruby-lang.org>
+Evan Phoenix <evan@ruby-lang.org> <evan@fallingsnow.net>
+Evan Phoenix <evan@ruby-lang.org> <evan@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# glass
+Masaki Matsushita <glass.saga@gmail.com>
+Masaki Matsushita <glass.saga@gmail.com> <glass@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# gogotanaka
+Kazuki Tanaka <gogotanaka@ruby-lang.org>
+Kazuki Tanaka <gogotanaka@ruby-lang.org> <gogotanaka@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# gotoken
+Kentaro Goto <gotoken@gmail.com>
+Kentaro Goto <gotoken@gmail.com> <gotoken@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# gotoyuzo
+GOTOU Yuuzou <gotoyuzo@notwork.org>
+GOTOU Yuuzou <gotoyuzo@notwork.org> <gotoyuzo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# gsinclair
+Gavin Sinclair <gsinclair@soyabean.com.au>
+Gavin Sinclair <gsinclair@soyabean.com.au> <gsinclair@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# H_Konishi
+KONISHI Hiromasa <konishih@fd6.so-net.ne.jp>
+KONISHI Hiromasa <konishih@fd6.so-net.ne.jp> <H_Konishi@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# headius
+Charles Oliver Nutter <headius@headius.com>
+Charles Oliver Nutter <headius@headius.com> <headius@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# hone
+Terence Lee <hone@heroku.com>
+Terence Lee <hone@heroku.com> <hone@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# hsbt
+Hiroshi SHIBATA <hsbt@ruby-lang.org>
+Hiroshi SHIBATA <hsbt@ruby-lang.org> <hsbt@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# iwamatsu
+Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
+Nobuhiro Iwamatsu <iwamatsu@nigauri.org> <iwamatsu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# jeg2
+James Edward Gray II <james@graysoftinc.com>
+James Edward Gray II <james@graysoftinc.com> <jeg2@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# jim
+Jim Weirich <jim@tardis.local>
+Jim Weirich <jim@tardis.local> <jim@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# k0kubun
+Takashi Kokubun <takashikkbn@gmail.com>
+Takashi Kokubun <takashikkbn@gmail.com> <k0kubun@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# kanemoto
+Yutaka Kanemoto <kanemoto@ruby-lang.org>
+Yutaka Kanemoto <kanemoto@ruby-lang.org> <kanemoto@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# katsu
+UENO Katsuhiro <katsu@blue.sky.or.jp>
+UENO Katsuhiro <katsu@blue.sky.or.jp> <katsu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# kazu
+Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+Kazuhiro NISHIYAMA <zn@mbf.nifty.com> <kazu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# keiju
+Keiju Ishitsuka <keiju@ishitsuka.com>
+Keiju Ishitsuka <keiju@ishitsuka.com> <keiju@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# knu
+Akinori MUSHA <knu@iDaemons.org>
+Akinori MUSHA <knu@iDaemons.org> <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# ko1
+Koichi Sasada <ko1@atdot.net>
+Koichi Sasada <ko1@atdot.net> <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# kosaki
+KOSAKI Motohiro <kosaki.motohiro@gmail.com>
+KOSAKI Motohiro <kosaki.motohiro@gmail.com> <kosaki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# kosako
+K.Kosako <sndgk393@ybb.ne.jp>
+K.Kosako <sndgk393@ybb.ne.jp> <kosako@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# kou
+Sutou Kouhei <kou@clear-code.com>
+Sutou Kouhei <kou@clear-code.com> <kou@cozmixng.org>
+Sutou Kouhei <kou@clear-code.com> <kou@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# kouji
+Kouji Takao <kouji.takao@gmail.com>
+Kouji Takao <kouji.takao@gmail.com> <kouji@takao7.net>
+Kouji Takao <kouji.takao@gmail.com> <kouji@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# ksaito
+Kazuo Saito <ksaito@uranus.dti.ne.jp>
+Kazuo Saito <ksaito@uranus.dti.ne.jp> <ksaito@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# ktsj
+Kazuki Tsujimoto <kazuki@callcc.net>
+Kazuki Tsujimoto <kazuki@callcc.net> <ktsj@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# luislavena
+Luis Lavena <luislavena@gmail.com>
+Luis Lavena <luislavena@gmail.com> <luislavena@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# mame
+Yusuke Endoh <mame@ruby-lang.org>
+## Yusuke Endoh <mame@ruby-lang.org> <mame@tsg.ne.jp>
+Yusuke Endoh <mame@ruby-lang.org> <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# marcandre
+Marc-Andre Lafortune <github@marc-andre.ca>
+Marc-Andre Lafortune <ruby-core@marc-andre.ca>
+Marc-Andre Lafortune <ruby-core@marc-andre.ca> <marcandre@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# matz
+Yukihiro "Matz" Matsumoto <matz@ruby.or.jp>
+Yukihiro "Matz" Matsumoto <matz@ruby.or.jp> <matz@ruby-lang.org>
+Yukihiro "Matz" Matsumoto <matz@ruby.or.jp> <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# michal
+Michal Rokos <michal@ruby-lang.org>
+Michal Rokos <michal@ruby-lang.org> <michal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# mneumann
+Michael Neumann <mneumann@ruby-lang.org>
+Michael Neumann <mneumann@ruby-lang.org> <mneumann@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# mrkn
+Kenta Murata <mrkn@mrkn.jp>
+Kenta Murata <mrkn@mrkn.jp> <muraken@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+Kenta Murata <mrkn@mrkn.jp> <3959+mrkn@users.noreply.github.com>
+Kenta Murata <mrkn@mrkn.jp> <mrkn@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# nagachika
+nagachika <nagachika@ruby-lang.org>
+nagachika <nagachika@ruby-lang.org> <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# nagai
+Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> <nagai@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# nahi
+Hiroshi Nakamura <nahi@ruby-lang.org>
+Hiroshi Nakamura <nahi@ruby-lang.org> <nahi@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# nari
+Narihiro Nakamura <authornari@gmail.com>
+Narihiro Nakamura <authornari@gmail.com> <nari@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# naruse
+NARUSE, Yui <naruse@airemix.jp>
+NARUSE, Yui <naruse@airemix.jp> <naruse@ruby-lang.org>
+NARUSE, Yui <naruse@airemix.jp> <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# ngoto
+Naohisa Goto <ngotogenome@gmail.com>
+Naohisa Goto <ngotogenome@gmail.com> <ngoto@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# nobu
+Nobuyoshi Nakada <nobu@ruby-lang.org>
+Nobuyoshi Nakada <nobu@ruby-lang.org> <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# normal
+Eric Wong <normal@ruby-lang.org>
+Eric Wong <normal@ruby-lang.org> <e@80x24.org>
+Eric Wong <normal@ruby-lang.org> <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# ntalbott
+Nathaniel Talbott <ntalbott@ruby-lang.org>
+Nathaniel Talbott <ntalbott@ruby-lang.org> <ntalbott@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# ocean
+Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
+Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp> <ocean@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# odaira
+Rei Odaira <rodaira@us.ibm.com>
+Rei Odaira <rodaira@us.ibm.com> <Rei.Odaira@gmail.com>
+Rei Odaira <rodaira@us.ibm.com> <odaira@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# okkez
+okkez <okkez000@gmail.com>
+okkez <okkez000@gmail.com> <okkez@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# rhe
+Kazuki Yamaguchi <k@rhe.jp>
+Kazuki Yamaguchi <k@rhe.jp> <rhe@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# ryan
+Ryan Davis <ryand-github@zenspider.com>
+Ryan Davis <ryand-github@zenspider.com> <ryand-ruby@zenspider.com>
+Ryan Davis <ryand-github@zenspider.com> <ryan@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# samuel
+Samuel Williams <samuel.williams@oriontransfer.co.nz>
+Samuel Williams <samuel.williams@oriontransfer.co.nz> <samuel@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# seki
+Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+Masatoshi SEKI <m_seki@mva.biglobe.ne.jp> <seki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# ser
+Sean Russell <ser@germane-software.com>
+Sean Russell <ser@germane-software.com> <ser@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# shigek
+Shigeo Kobayashi <shigek@ruby-lang.org>
+Shigeo Kobayashi <shigek@ruby-lang.org> <shigek@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# shirosaki
+Hiroshi Shirosaki <h.shirosaki@gmail.com>
+Hiroshi Shirosaki <h.shirosaki@gmail.com> <shirosaki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# sho-h
+Sho Hashimoto <sho-h@ruby-lang.org>
+Sho Hashimoto <sho-h@ruby-lang.org> <sho-h@netlab.jp>
+Sho Hashimoto <sho-h@ruby-lang.org> <sho.hsmt@gmail.com>
+Sho Hashimoto <sho-h@ruby-lang.org> <sho-h@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# shugo
+Shugo Maeda <shugo@ruby-lang.org>
+Shugo Maeda <shugo@ruby-lang.org> <shugo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# shyouhei
+åœéƒ¨æ˜Œå¹³ <shyouhei@ruby-lang.org>
+åœéƒ¨æ˜Œå¹³ <shyouhei@ruby-lang.org> <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# siena
+Siena. <siena@faculty.chiba-u.jp>
+Siena. <siena@faculty.chiba-u.jp> <siena@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# sonots
+sonots <sonots@gmail.com>
+sonots <sonots@gmail.com> <sonots@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# sorah
+Sorah Fukumori <her@sorah.jp>
+Sorah Fukumori <her@sorah.jp> <sorah@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# stomar
+Marcus Stollsteimer <sto.mar@web.de>
+Marcus Stollsteimer <sto.mar@web.de> <stomar@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# suke
+Masaki Suketa <masaki.suketa@nifty.ne.jp>
+Masaki Suketa <masaki.suketa@nifty.ne.jp> <suke@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# tadd
+Tadashi Saito <tad.a.digger@gmail.com>
+Tadashi Saito <tad.a.digger@gmail.com> <tadd@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# tadf
+Tadayoshi Funaba <tadf@dotrb.org>
+Tadayoshi Funaba <tadf@dotrb.org> <tadf@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# takano32
+TAKANO Mitsuhiro <takano32@gmail.com>
+TAKANO Mitsuhiro <takano32@gmail.com> <takano32@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# tarui
+Masaya Tarui <tarui@ruby-lang.org>
+Masaya Tarui <tarui@ruby-lang.org> <tarui@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# technorama
+Technorama Ltd. <oss-ruby@technorama.net>
+Technorama Ltd. <oss-ruby@technorama.net> <technorama@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# tenderlove
+Aaron Patterson <tenderlove@ruby-lang.org>
+Aaron Patterson <tenderlove@ruby-lang.org> <tenderlove@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# tmm1
+Aman Gupta <ruby@tmm1.net>
+Aman Gupta <ruby@tmm1.net> <tmm1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# ts
+Guy Decoux <ts@moulon.inra.fr>
+Guy Decoux <ts@moulon.inra.fr> <ts@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# ttate
+Takaaki Tateishi <ttate@ttsky.net>
+## Takaaki Tateishi <ttate@ttsky.net> <ttate@kt.jaist.ac.jp>
+Takaaki Tateishi <ttate@ttsky.net> <ttate@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# uema2
+Takaaki Uematsu <uema2x@jcom.home.ne.jp>
+Takaaki Uematsu <uema2x@jcom.home.ne.jp> <uema2@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# usa
+U.Nakamura <usa@ruby-lang.org>
+U.Nakamura <usa@ruby-lang.org> <usa@garbagecollect.jp>
+U.Nakamura <usa@ruby-lang.org> <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# wakou
+Wakou Aoyama <wakou@ruby-lang.org>
+Wakou Aoyama <wakou@ruby-lang.org> <wakou@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# wanabe
+wanabe <s.wanabe@gmail.com>
+wanabe <s.wanabe@gmail.com> <wanabe@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# watson1978
+Watson <watson1978@gmail.com>
+Watson <watson1978@gmail.com> <watson1978@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# wew
+William Webber <william@williamwebber.com>
+William Webber <william@williamwebber.com> <wew@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# why
+why the lucky stiff <why@ruby-lang.org>
+why the lucky stiff <why@ruby-lang.org> <why@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# xibbar
+Takeyuki FUJIOKA <xibbar@ruby-lang.org>
+Takeyuki FUJIOKA <xibbar@ruby-lang.org> <xibbar@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# yugui
+Yuki Yugui Sonoda <yugui@yugui.jp>
+Yuki Yugui Sonoda <yugui@yugui.jp> <yugui@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# yui-knk
+yui-knk <spiketeika@gmail.com>
+yui-knk <spiketeika@gmail.com> <yui-knk@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# yuki
+Yuki Nishijima <yuki24@hey.com>
+Yuki Nishijima <yuki24@hey.com> <mail@yukinishijima.net>
+Yuki Nishijima <yuki24@hey.com> <yuki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# zsombor
+Dee Zsombor <zsombor@ruby-lang.org>
+Dee Zsombor <zsombor@ruby-lang.org> <zsombor@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+
+# zzak
+zzak <zzakscott@gmail.com>
+zzak <zzakscott@gmail.com> <zzak@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
diff --git a/.rdoc_options b/.rdoc_options
index 760507c7a2..4dfbfa140c 100644
--- a/.rdoc_options
+++ b/.rdoc_options
@@ -1,4 +1,9 @@
---
page_dir: doc
+charset: UTF-8
+encoding: UTF-8
main_page: README.md
title: Documentation for Ruby development version
+visibility: :private
+rdoc_include:
+- doc
diff --git a/.travis.yml b/.travis.yml
index 6d942d1425..06de3dd493 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,7 +11,9 @@
# https://github.com/ruby/ruby/wiki/CI-Servers#travis-ci
# We enable Travis on the specific branches or forked repositories here.
-if: (repo = ruby/ruby AND (branch = master OR branch =~ /^ruby_\d_\d$/)) OR repo != ruby/ruby OR commit_message !~ /\[DOC\]/
+if: >-
+ (repo != ruby/ruby OR branch = master OR branch =~ /^ruby_\d_\d$/)
+ AND (commit_message !~ /\[DOC\]/)
language: c
@@ -112,13 +114,14 @@ matrix:
allow_failures:
# Allow failures for the unstable jobs.
# - name: arm64-linux
- # - name: ppc64le-linux
- # - name: s390x-linux
+ - name: ppc64le-linux
+ - name: s390x-linux
# The 2nd arm64 pipeline may be unstable.
# - name: arm32-linux
fast_finish: true
before_script:
+ - lscpu
- ./autogen.sh
- mkdir build
- cd build
@@ -133,7 +136,7 @@ before_script:
script:
- $SETARCH make -s test
- ../tool/travis_wait.sh $SETARCH make -s test-all RUBYOPT="-w"
- - $SETARCH make -s test-spec
+ - ../tool/travis_wait.sh $SETARCH make -s test-spec
# We want to be notified when something happens.
notifications:
@@ -144,4 +147,7 @@ notifications:
on_success: never
on_failure: always
email:
- - jaruga@ruby-lang.org
+ recipients:
+ - jaruga@ruby-lang.org
+ on_success: never
+ on_failure: always
diff --git a/LEGAL b/LEGAL
index e352c55ee5..162ba78483 100644
--- a/LEGAL
+++ b/LEGAL
@@ -58,12 +58,12 @@ mentioned below.
[ccan/list/list.h]
- This file is licensed under the {MIT License}[rdoc-label:label-MIT+License].
+ This file is licensed under the {MIT License}[rdoc-ref:@MIT+License].
[coroutine]
Unless otherwise specified, these files are licensed under the
- {MIT License}[rdoc-label:label-MIT+License].
+ {MIT License}[rdoc-ref:@MIT+License].
[include/ruby/onigmo.h]
[include/ruby/oniguruma.h]
@@ -546,7 +546,7 @@ mentioned below.
[vsnprintf.c]
- This file is under the {old-style BSD license}[rdoc-label:label-Old-style+BSD+license].
+ This file is under the {old-style BSD license}[rdoc-ref:@Old-style+BSD+license].
>>>
Copyright (c) 1990, 1993::
@@ -577,7 +577,7 @@ mentioned below.
[missing/crypt.c]
- This file is under the {old-style BSD license}[rdoc-label:label-Old-style+BSD+license].
+ This file is under the {old-style BSD license}[rdoc-ref:@Old-style+BSD+license].
>>>
Copyright (c) 1989, 1993::
@@ -588,7 +588,7 @@ mentioned below.
[missing/setproctitle.c]
- This file is under the {old-style BSD license}[rdoc-label:label-Old-style+BSD+license].
+ This file is under the {old-style BSD license}[rdoc-ref:@Old-style+BSD+license].
>>>
Copyright 2003:: Damien Miller
@@ -727,24 +727,6 @@ mentioned below.
for internal or external distribution as long as this notice
remains attached.
-[ext/nkf/nkf-utf8/config.h]
-[ext/nkf/nkf-utf8/nkf.c]
-[ext/nkf/nkf-utf8/utf8tbl.c]
-
- These files are under the following license. So to speak, it is
- copyrighted semi-public-domain software.
-
- >>>
- Copyright (C) 1987:: Fujitsu LTD. (Itaru ICHIKAWA)
-
- Everyone is permitted to do anything on this program
- including copying, modifying, improving,
- as long as you don't try to pretend that you wrote it.
- i.e., the above copyright notice has to appear in all copies.
- Binary distribution requires original version messages.
- You don't have to ask before copying, redistribution or publishing.
- THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE.
-
[ext/psych]
[test/psych]
@@ -879,7 +861,7 @@ mentioned below.
>>>
RubyGems is copyrighted free software by Chad Fowler, Rich Kilmer, Jim
Weirich and others. You can redistribute it and/or modify it under
- either the terms of the {MIT license}[rdoc-label:label-MIT+License], or the conditions
+ either the terms of the {MIT license}[rdoc-ref:@MIT+License], or the conditions
below:
1. You may make and give away verbatim copies of the source form of the
@@ -941,7 +923,7 @@ mentioned below.
Portions copyright (c) 2010:: Andre Arko
Portions copyright (c) 2009:: Engine Yard
- {MIT License}[rdoc-label:label-MIT+License]
+ {MIT License}[rdoc-ref:@MIT+License]
[lib/bundler/vendor/thor]
@@ -950,16 +932,16 @@ mentioned below.
>>>
Copyright (c) 2008 Yehuda Katz, Eric Hodel, et al.
- {MIT License}[rdoc-label:label-MIT+License]
+ {MIT License}[rdoc-ref:@MIT+License]
-[lib/rubygems/resolver/molinillo]
+[lib/rubygems/vendor/molinillo]
molinillo is under the following license.
>>>
Copyright (c) 2014 Samuel E. Giddins segiddins@segiddins.me
- {MIT License}[rdoc-label:label-MIT+License]
+ {MIT License}[rdoc-ref:@MIT+License]
[lib/bundler/vendor/pub_grub]
@@ -968,7 +950,7 @@ mentioned below.
>>>
Copyright (c) 2018 John Hawthorn
- {MIT License}[rdoc-label:label-MIT+License]
+ {MIT License}[rdoc-ref:@MIT+License]
[lib/bundler/vendor/connection_pool]
@@ -977,7 +959,7 @@ mentioned below.
>>>
Copyright (c) 2011 Mike Perham
- {MIT License}[rdoc-label:label-MIT+License]
+ {MIT License}[rdoc-ref:@MIT+License]
[lib/bundler/vendor/net-http-persistent]
@@ -986,7 +968,7 @@ mentioned below.
>>>
Copyright (c) Eric Hodel, Aaron Patterson
- {MIT License}[rdoc-label:label-MIT+License]
+ {MIT License}[rdoc-ref:@MIT+License]
[lib/did_you_mean]
[lib/did_you_mean.rb]
@@ -997,7 +979,7 @@ mentioned below.
>>>
Copyright (c) 2014-2016 Yuki Nishijima
- {MIT License}[rdoc-label:label-MIT+License]
+ {MIT License}[rdoc-ref:@MIT+License]
[lib/error_highlight]
[lib/error_highlight.rb]
@@ -1008,7 +990,7 @@ mentioned below.
>>>
Copyright (c) 2021 Yusuke Endoh
- {MIT License}[rdoc-label:label-MIT+License]
+ {MIT License}[rdoc-ref:@MIT+License]
[benchmark/so_ackermann.rb]
[benchmark/so_array.rb]
diff --git a/NEWS.md b/NEWS.md
index 240f6f4008..ac77cfae9d 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,314 +1,154 @@
-# NEWS for Ruby 3.3.0
+# NEWS for Ruby 3.4.0
This document is a list of user-visible feature changes
-since the **3.2.0** release, except for bug fixes.
+since the **3.3.0** release, except for bug fixes.
Note that each entry is kept to a minimum, see links for details.
## Language changes
-## Command line options
+* String literals in files without a `frozen_string_literal` comment now emit a deprecation warning
+ when they are mutated.
+ These warnings can be enabled with `-W:deprecated` or by setting `Warning[:deprecated] = true`.
+ To disable this change, you can run Ruby with the `--disable-frozen-string-literal`
+ command line argument. [[Feature #20205]]
-* A new `performance` warning category was introduced.
- They are not displayed by default even in verbose mode.
- Turn them on with `-W:performance` or `Warning[:performance] = true`. [[Feature #19538]]
-* The `RUBY_GC_HEAP_INIT_SLOTS` environment variable has been deprecated and
- removed. Environment variables `RUBY_GC_HEAP_%d_INIT_SLOTS` should be
- used instead. [[Feature #19785]]
+* `it` is added to reference a block parameter. [[Feature #18980]]
-## Core classes updates
-
-Note: We're only listing outstanding class updates.
-
-* Array
-
- * Array#pack now raises ArgumentError for unknown directives. [[Bug #19150]]
-
-* Dir
-
- * Dir.for_fd added for returning a Dir object for the directory specified
- by the provided directory file descriptor. [[Feature #19347]]
- * Dir.fchdir added for changing the directory to the directory specified
- by the provided directory file descriptor. [[Feature #19347]]
- * Dir#chdir added for changing the directory to the directory specified by
- the provided `Dir` object. [[Feature #19347]]
-
-* MatchData
-
- * MatchData#named_captures now accepts optional `symbolize_names`
- keyword. [[Feature #19591]]
+* Keyword splatting `nil` when calling methods is now supported.
+ `**nil` is treated similarly to `**{}`, passing no keywords,
+ and not calling any conversion methods. [[Bug #20064]]
-* Module
+* Block passing is no longer allowed in index assignment
+ (e.g. `a[0, &b] = 1`). [[Bug #19918]]
- * Module#set_temporary_name added for setting a temporary name for a
- module. [[Feature #19521]]
+* Keyword arguments are no longer allowed in index assignment
+ (e.g. `a[0, kw: 1] = 2`). [[Bug #20218]]
-* ObjectSpace::WeakKeyMap
-
- * New core class to build collections with weak references.
- The class use equality semantic to lookup keys like a regular hash,
- but it doesn't hold strong references on the keys. [[Feature #18498]]
-
-* Proc
- * Now Proc#dup and Proc#clone call `#initialize_dup` and `#initialize_clone`
- hooks respectively. [[Feature #19362]]
-
-* Process.warmup
+## Core classes updates
- * Notify the Ruby virtual machine that the boot sequence is finished,
- and that now is a good time to optimize the application. This is useful
- for long running applications. The actual optimizations performed are entirely
- implementation specific and may change in the future without notice. [[Feature #18885]]
+Note: We're only listing outstanding class updates.
-* Process::Status
+* Exception
- * Process::Status#& and Process::Status#>> are deprecated. [[Bug #19868]]
+ * Exception#set_backtrace now accepts arrays of `Thread::Backtrace::Location`.
+ `Kernel#raise`, `Thread#raise` and `Fiber#raise` also accept this new format. [[Feature #13557]]
* Range
- * Range#reverse_each can now process beginless ranges with an Integer endpoint. [[Feature #18515]]
-
-* Refinement
-
- * Add Refinement#target as an alternative of Refinement#refined_class.
- Refinement#refined_class is deprecated and will be removed in Ruby
- 3.4. [[Feature #19714]]
-
-* String
-
- * String#unpack now raises ArgumentError for unknown directives. [[Bug #19150]]
- * String#bytesplice now accepts new arguments index/length or range of the
- source string to be copied. [[Feature #19314]]
-
-* TracePoint
-
- * TracePoint supports `rescue` event. When the raised exception was rescued,
- the TracePoint will fire the hook. `rescue` event only supports Ruby-level
- `rescue`. [[Feature #19572]]
+ * Range#size now raises TypeError if the range is not iterable. [[Misc #18984]]
## Stdlib updates
-* RubyGems and Bundler warn if users require gem that is scheduled to become the bundled gems
- in the future version of Ruby. [[Feature #19351]] [[Feature #19776]] [[Feature #19843]]
+* Tempfile
- Targeted libraries are:
- * abbrev
- * base64
- * bigdecimal
- * csv
- * drb
- * getoptlong
- * mutex_m
- * nkf
- * observer
- * racc
- * resolv-replace
- * rinda
- * syslog
+ * The keyword argument `anonymous: true` is implemented for `Tempfile.create`.
+ `Tempfile.create(anonymous: true)` removes the created temporary file immediately.
+ So applications don't need to remove the file.
+ [[Feature #20497]]
-* Socket#recv and Socket#recv_nonblock returns `nil` instead of an empty string on closed
- connections. Socket#recvmsg and Socket#recvmsg_nonblock returns `nil` instead of an empty packet on closed
- connections. [[Bug #19012]]
+The following default gems are updated.
-* Random::Formatter#alphanumeric is extended to accept optional `chars`
- keyword argument. [[Feature #18183]]
+* RubyGems 3.6.0.dev
+* bundler 2.6.0.dev
+* erb 4.0.4
+* fiddle 1.1.3
+* io-console 0.7.2
+* irb 1.13.1
+* json 2.7.2
+* net-http 0.4.1
+* optparse 0.5.0
+* prism 0.30.0
+* rdoc 6.7.0
+* reline 0.5.8
+* resolv 0.4.0
+* stringio 3.1.1
+* strscan 3.1.1
-The following default gem is added.
+The following bundled gems are updated.
-* prism 0.17.1
+* minitest 5.23.1
+* rake 13.2.1
+* test-unit 3.6.2
+* rexml 3.2.8
+* net-ftp 0.3.5
+* net-imap 0.4.12
+* net-smtp 0.5.0
+* rbs 3.4.4
+* typeprof 0.21.11
+* debug 1.9.2
+* racc 1.8.0
-The following default gems are updated.
+The following bundled gems are promoted from default gems.
-* RubyGems 3.5.0.dev
-* base64 0.2.0
-* benchmark 0.3.0
-* bigdecimal 3.1.5
-* bundler 2.5.0.dev
-* cgi 0.4.0
-* csv 3.2.8
-* date 3.3.4
-* delegate 0.3.1
-* drb 2.2.0
-* english 0.8.0
-* erb 4.0.3
-* etc 1.4.3.dev.1
-* fcntl 1.1.0
-* fiddle 1.1.2
-* fileutils 1.7.2
-* find 0.2.0
-* getoptlong 0.2.1
-* io-console 0.6.1.dev.1
-* irb 1.9.0
-* logger 1.6.0
* mutex_m 0.2.0
-* net-http 0.4.0
-* net-protocol 0.2.2
-* nkf 0.1.3
+* getoptlong 0.2.1
+* base64 0.2.0
+* bigdecimal 3.1.8
* observer 0.1.2
-* open-uri 0.4.0
-* open3 0.2.0
-* openssl 3.2.0
-* optparse 0.4.0
-* ostruct 0.6.0
-* pathname 0.3.0
-* pp 0.5.0
-* prettyprint 0.2.0
-* pstore 0.1.3
-* psych 5.1.1.1
-* rdoc 6.6.0
-* reline 0.4.0
+* abbrev 0.1.2
+* resolv-replace 0.1.1
* rinda 0.2.0
-* securerandom 0.3.0
-* shellwords 0.2.0
-* singleton 0.2.0
-* stringio 3.1.0
-* strscan 3.0.8
-* syntax_suggest 1.1.0
-* tempfile 0.2.0
-* time 0.3.0
-* timeout 0.4.1
-* tmpdir 0.2.0
-* tsort 0.2.0
-* un 0.3.0
-* uri 0.13.0
-* weakref 0.1.3
-* win32ole 1.8.10
-* yaml 0.3.0
-* zlib 3.1.0
-
-The following bundled gem is promoted from default gems.
-
-* racc 1.7.3
-
-The following bundled gems are updated.
-
-* minitest 5.20.0
-* rake 13.1.0
-* test-unit 3.6.1
-* rexml 3.2.6
-* rss 0.3.0
-* net-imap 0.4.4
-* net-smtp 0.4.0
-* rbs 3.2.2
-* typeprof 0.21.8
-* debug 1.8.0
+* drb 2.2.1
+* nkf 0.2.0
+* syslog 0.1.2
+* csv 3.3.0
-See GitHub releases like [Logger](https://github.com/ruby/logger/releases) or
-changelog for details of the default gems or bundled gems.
+See GitHub releases like [GitHub Releases of Logger](https://github.com/ruby/logger/releases) or changelog for details of the default gems or bundled gems.
## Supported platforms
## Compatibility issues
-## Stdlib compatibility issues
+* Error messages and backtrace displays have been changed.
+ * Use a single quote instead of a backtick as a opening quote. [[Feature #16495]]
+ * Display a class name before a method name (only when the class has a permanent name). [[Feature #19117]]
+ * `Kernel#caller`, `Thread::Backtrace::Location`'s methods, etc. are also changed accordingly.
+ ```
+ Old:
+ test.rb:1:in `foo': undefined method `time' for an instance of Integer
+ from test.rb:2:in `<main>'
+
+ New:
+ test.rb:1:in 'Object#foo': undefined method 'time' for an instance of Integer
+ from test.rb:2:in `<main>'
+ ```
-* `racc` is promoted to bundled gems.
- * You need to add `racc` to your `Gemfile` if you use `racc` under bundler environment.
-* `ext/readline` is retired
- * We have `reline` that is pure Ruby implementation compatible with `ext/readline` API. We rely on `reline` in the future. If you need to use `ext/readline`, you can install `ext/readline` via rubygems.org with `gem install readline-ext`.
- * We no longer need to install libraries like `libreadline` or `libedit`.
+## Stdlib compatibility issues
## C API updates
+* `rb_newobj` and `rb_newobj_of` (and corresponding macros `RB_NEWOBJ`, `RB_NEWOBJ_OF`, `NEWOBJ`, `NEWOBJ_OF`) have been removed. [[Feature #20265]]
+* Removed deprecated function `rb_gc_force_recycle`. [[Feature #18290]]
+
## Implementation improvements
-* `defined?(@ivar)` is optimized with Object Shapes.
-* Name resolution such as `Socket.getaddrinfo` can now be interrupted. [[Feature #19965]]
-
-### YJIT
-
-* Major performance improvements over 3.2
- * Support for splat and rest arguments has been improved.
- * Registers are allocated for stack operations of the virtual machine.
- * More calls with optional arguments are compiled.
- * Exception handlers are also compiled.
- * Instance variables no longer exit to the interpreter
- with megamorphic object shapes.
- * Unsupported call types no longer exit to the interpreter.
- * `Integer#!=`, `String#!=`, `Kernel#block_given?`, `Kernel#is_a?`,
- `Kernel#instance_of?`, `Module#===` are specially optimized.
- * Now more than 3x faster than the interpreter on optcarrot!
-* Significantly improved memory usage over 3.2
- * Metadata for compiled code uses a lot less memory.
- * Generate more compact code on ARM64
-* Compilation speed is now slightly faster than 3.2.
-* Add `RubyVM::YJIT.enable` that can enable YJIT later
- * You can start YJIT without modifying command-line arguments or environment variables.
- * This can also be used to enable YJIT only once your application is
- done booting. `--yjit-disable` can be used if you want to use other
- YJIT options while disabling YJIT at boot.
-* Code GC now disabled by default, with `--yjit-exec-mem-size` treated as a hard limit
- * Can produce better copy-on-write behavior on forking web servers such as `unicorn`
- * Use the `--yjit-code-gc` option to automatically run code GC when YJIT reaches the size limit
-* `ratio_in_yjit` stat produced by `--yjit-stats` is now available in release builds,
- a special stats or dev build is no longer required to access most stats.
-* Exit tracing option now supports sampling
- * `--trace-exits-sample-rate=N`
-* More thorough testing and multiple bug fixes
-* `--yjit-stats=quiet` is added to avoid printing stats on exit.
-* `--yjit-perf` is added to facilitate profiling with Linux perf.
-
-### MJIT
-
-* MJIT is removed.
- * `--disable-jit-support` is removed. Consider using `--disable-yjit --disable-rjit` instead.
-
-### RJIT
-
-* Introduced a pure-Ruby JIT compiler RJIT.
- * RJIT supports only x86\_64 architecture on Unix platforms.
- * Unlike MJIT, it doesn't require a C compiler at runtime.
-* RJIT exists only for experimental purposes.
- * You should keep using YJIT in production.
-
-### M:N Therad scheduler
-
-* M:N Thread scheduler is introduced. [[Feature #19842]]
- * Background: Ruby 1.8 and before, M:1 thread scheduler (M Ruby threads
- with 1 native thread. Called as User level threads or Green threads)
- is used. Ruby 1.9 and later, 1:1 thread scheduler (1 Ruby thread with
- 1 native thread). M:1 threads takes lower resources compare with 1:1
- threads because it needs only 1 native threads. However it is difficult
- to support context switching for all of blocking operation so 1:1
- threads are employed from Ruby 1.9. M:N thread scheduler uses N native
- threads for M Ruby threads (N is small number in general). It doesn't
- need same number of native threads as Ruby threads (similar to the M:1
- thread scheduler). Also our M:N threads supports blocking operations
- well same as 1:1 threads. See the ticket for more details.
- Our M:N thread scheduler refers on the gorotuine scheduler in the
- Go language.
- * In a ractor, only 1 thread can run in a same time because of
- implementation. Therefore, applications that use only one Ractor
- (most applications) M:N thread scheduler works as M:1 thread scheduler
- with further extension from Ruby 1.8.
- * M:N thread scheduler can introduce incompatibility for C-extensions,
- so it is disabled by default on the main Ractors.
- `RUBY_MN_THREADS=1` environment variable will enable it.
- On non-main Ractors, M:N thread scheduler is enabled (and can not
- disable it now).
- * `N` (the number of native threads) can be specified with `RUBY_MAX_CPU`
- environment variable. The default is 8.
- Note that more than `N` native threads are used to support many kind of
- blocking operations.
-
-[Feature #18183]: https://bugs.ruby-lang.org/issues/18183
-[Feature #18498]: https://bugs.ruby-lang.org/issues/18498
-[Feature #18515]: https://bugs.ruby-lang.org/issues/18515
-[Feature #18885]: https://bugs.ruby-lang.org/issues/18885
-[Bug #19012]: https://bugs.ruby-lang.org/issues/19012
-[Bug #19150]: https://bugs.ruby-lang.org/issues/19150
-[Feature #19314]: https://bugs.ruby-lang.org/issues/19314
-[Feature #19347]: https://bugs.ruby-lang.org/issues/19347
-[Feature #19351]: https://bugs.ruby-lang.org/issues/19351
-[Feature #19362]: https://bugs.ruby-lang.org/issues/19362
-[Feature #19521]: https://bugs.ruby-lang.org/issues/19521
-[Feature #19538]: https://bugs.ruby-lang.org/issues/19538
-[Feature #19572]: https://bugs.ruby-lang.org/issues/19572
-[Feature #19591]: https://bugs.ruby-lang.org/issues/19591
-[Feature #19714]: https://bugs.ruby-lang.org/issues/19714
-[Feature #19776]: https://bugs.ruby-lang.org/issues/19776
-[Feature #19785]: https://bugs.ruby-lang.org/issues/19785
-[Feature #19842]: https://bugs.ruby-lang.org/issues/19842
-[Feature #19843]: https://bugs.ruby-lang.org/issues/19843
-[Bug #19868]: https://bugs.ruby-lang.org/issues/19868
-[Feature #19965]: https://bugs.ruby-lang.org/issues/19965
+* `Array#each` is rewritten in Ruby for better performance [[Feature #20182]].
+
+## JIT
+
+## Miscellaneous changes
+
+* Passing a block to a method which doesn't use the passed block will show
+ a warning on verbose mode (`-w`).
+ [[Feature #15554]]
+
+* Redefining some core methods that are specially optimized by the interpreter
+ and JIT like `String.freeze` or `Integer#+` now emits a performance class
+ warning (`-W:performance` or `Warning[:performance] = true`).
+ [[Feature #20429]]
+
+[Feature #13557]: https://bugs.ruby-lang.org/issues/13557
+[Feature #15554]: https://bugs.ruby-lang.org/issues/15554
+[Feature #16495]: https://bugs.ruby-lang.org/issues/16495
+[Feature #18290]: https://bugs.ruby-lang.org/issues/18290
+[Feature #18980]: https://bugs.ruby-lang.org/issues/18980
+[Misc #18984]: https://bugs.ruby-lang.org/issues/18984
+[Feature #19117]: https://bugs.ruby-lang.org/issues/19117
+[Bug #19918]: https://bugs.ruby-lang.org/issues/19918
+[Bug #20064]: https://bugs.ruby-lang.org/issues/20064
+[Feature #20182]: https://bugs.ruby-lang.org/issues/20182
+[Feature #20205]: https://bugs.ruby-lang.org/issues/20205
+[Bug #20218]: https://bugs.ruby-lang.org/issues/20218
+[Feature #20265]: https://bugs.ruby-lang.org/issues/20265
+[Feature #20429]: https://bugs.ruby-lang.org/issues/20429
diff --git a/README.ja.md b/README.ja.md
index 0d2d309fb8..49cf72b5fd 100644
--- a/README.ja.md
+++ b/README.ja.md
@@ -4,7 +4,6 @@
[![Actions Status: Windows](https://github.com/ruby/ruby/workflows/Windows/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"Windows")
[![AppVeyor status](https://ci.appveyor.com/api/projects/status/0sy8rrxut4o0k960/branch/master?svg=true)](https://ci.appveyor.com/project/ruby/ruby/branch/master)
[![Travis Status](https://app.travis-ci.com/ruby/ruby.svg?branch=master)](https://app.travis-ci.com/ruby/ruby)
-[![Cirrus Status](https://api.cirrus-ci.com/github/ruby/ruby.svg)](https://cirrus-ci.com/github/ruby/ruby/master)
# Rubyã¨ã¯
diff --git a/README.md b/README.md
index 8fb3786691..eb24a73ee3 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,6 @@
[![Actions Status: RJIT](https://github.com/ruby/ruby/workflows/RJIT/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"RJIT")
[![Actions Status: Ubuntu](https://github.com/ruby/ruby/workflows/Ubuntu/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"Ubuntu")
[![Actions Status: Windows](https://github.com/ruby/ruby/workflows/Windows/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"Windows")
-[![AppVeyor status](https://ci.appveyor.com/api/projects/status/0sy8rrxut4o0k960/branch/master?svg=true)](https://ci.appveyor.com/project/ruby/ruby/branch/master)
[![Travis Status](https://app.travis-ci.com/ruby/ruby.svg?branch=master)](https://app.travis-ci.com/ruby/ruby)
# What is Ruby?
diff --git a/addr2line.c b/addr2line.c
index 2a69dd0966..02a3e617a6 100644
--- a/addr2line.c
+++ b/addr2line.c
@@ -2384,13 +2384,14 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
goto fail;
}
else {
- kprintf("'%s' is not a "
# ifdef __LP64__
- "64"
+# define bitsize "64"
# else
- "32"
+# define bitsize "32"
# endif
+ kprintf("'%s' is not a " bitsize
"-bit Mach-O file!\n",binary_filename);
+# undef bitsize
close(fd);
goto fail;
}
diff --git a/array.c b/array.c
index 1032696308..dab933776f 100644
--- a/array.c
+++ b/array.c
@@ -28,6 +28,7 @@
#include "ruby/encoding.h"
#include "ruby/st.h"
#include "ruby/util.h"
+#include "vm_core.h"
#include "builtin.h"
#if !ARRAY_DEBUG
@@ -76,47 +77,47 @@ should_be_T_ARRAY(VALUE ary)
return RB_TYPE_P(ary, T_ARRAY);
}
-#define ARY_HEAP_PTR(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
-#define ARY_HEAP_LEN(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
-#define ARY_HEAP_CAPA(a) (assert(!ARY_EMBED_P(a)), assert(!ARY_SHARED_ROOT_P(a)), \
+#define ARY_HEAP_PTR(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
+#define ARY_HEAP_LEN(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
+#define ARY_HEAP_CAPA(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RUBY_ASSERT(!ARY_SHARED_ROOT_P(a)), \
RARRAY(a)->as.heap.aux.capa)
-#define ARY_EMBED_PTR(a) (assert(ARY_EMBED_P(a)), RARRAY(a)->as.ary)
+#define ARY_EMBED_PTR(a) (RUBY_ASSERT(ARY_EMBED_P(a)), RARRAY(a)->as.ary)
#define ARY_EMBED_LEN(a) \
- (assert(ARY_EMBED_P(a)), \
+ (RUBY_ASSERT(ARY_EMBED_P(a)), \
(long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
(RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
-#define ARY_HEAP_SIZE(a) (assert(!ARY_EMBED_P(a)), assert(ARY_OWNS_HEAP_P(a)), ARY_CAPA(a) * sizeof(VALUE))
+#define ARY_HEAP_SIZE(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RUBY_ASSERT(ARY_OWNS_HEAP_P(a)), ARY_CAPA(a) * sizeof(VALUE))
-#define ARY_OWNS_HEAP_P(a) (assert(should_be_T_ARRAY((VALUE)(a))), \
+#define ARY_OWNS_HEAP_P(a) (RUBY_ASSERT(should_be_T_ARRAY((VALUE)(a))), \
!FL_TEST_RAW((a), RARRAY_SHARED_FLAG|RARRAY_EMBED_FLAG))
#define FL_SET_EMBED(a) do { \
- assert(!ARY_SHARED_P(a)); \
+ RUBY_ASSERT(!ARY_SHARED_P(a)); \
FL_SET((a), RARRAY_EMBED_FLAG); \
ary_verify(a); \
} while (0)
#define FL_UNSET_EMBED(ary) FL_UNSET((ary), RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK)
#define FL_SET_SHARED(ary) do { \
- assert(!ARY_EMBED_P(ary)); \
+ RUBY_ASSERT(!ARY_EMBED_P(ary)); \
FL_SET((ary), RARRAY_SHARED_FLAG); \
} while (0)
#define FL_UNSET_SHARED(ary) FL_UNSET((ary), RARRAY_SHARED_FLAG)
#define ARY_SET_PTR(ary, p) do { \
- assert(!ARY_EMBED_P(ary)); \
- assert(!OBJ_FROZEN(ary)); \
+ RUBY_ASSERT(!ARY_EMBED_P(ary)); \
+ RUBY_ASSERT(!OBJ_FROZEN(ary)); \
RARRAY(ary)->as.heap.ptr = (p); \
} while (0)
#define ARY_SET_EMBED_LEN(ary, n) do { \
long tmp_n = (n); \
- assert(ARY_EMBED_P(ary)); \
+ RUBY_ASSERT(ARY_EMBED_P(ary)); \
RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
} while (0)
#define ARY_SET_HEAP_LEN(ary, n) do { \
- assert(!ARY_EMBED_P(ary)); \
+ RUBY_ASSERT(!ARY_EMBED_P(ary)); \
RARRAY(ary)->as.heap.len = (n); \
} while (0)
#define ARY_SET_LEN(ary, n) do { \
@@ -126,15 +127,15 @@ should_be_T_ARRAY(VALUE ary)
else { \
ARY_SET_HEAP_LEN((ary), (n)); \
} \
- assert(RARRAY_LEN(ary) == (n)); \
+ RUBY_ASSERT(RARRAY_LEN(ary) == (n)); \
} while (0)
#define ARY_INCREASE_PTR(ary, n) do { \
- assert(!ARY_EMBED_P(ary)); \
- assert(!OBJ_FROZEN(ary)); \
+ RUBY_ASSERT(!ARY_EMBED_P(ary)); \
+ RUBY_ASSERT(!OBJ_FROZEN(ary)); \
RARRAY(ary)->as.heap.ptr += (n); \
} while (0)
#define ARY_INCREASE_LEN(ary, n) do { \
- assert(!OBJ_FROZEN(ary)); \
+ RUBY_ASSERT(!OBJ_FROZEN(ary)); \
if (ARY_EMBED_P(ary)) { \
ARY_SET_EMBED_LEN((ary), RARRAY_LEN(ary)+(n)); \
} \
@@ -146,30 +147,30 @@ should_be_T_ARRAY(VALUE ary)
#define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? ary_embed_capa(ary) : \
ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : ARY_HEAP_CAPA(ary))
#define ARY_SET_CAPA(ary, n) do { \
- assert(!ARY_EMBED_P(ary)); \
- assert(!ARY_SHARED_P(ary)); \
- assert(!OBJ_FROZEN(ary)); \
+ RUBY_ASSERT(!ARY_EMBED_P(ary)); \
+ RUBY_ASSERT(!ARY_SHARED_P(ary)); \
+ RUBY_ASSERT(!OBJ_FROZEN(ary)); \
RARRAY(ary)->as.heap.aux.capa = (n); \
} while (0)
#define ARY_SHARED_ROOT_OCCUPIED(ary) (!OBJ_FROZEN(ary) && ARY_SHARED_ROOT_REFCNT(ary) == 1)
#define ARY_SET_SHARED_ROOT_REFCNT(ary, value) do { \
- assert(ARY_SHARED_ROOT_P(ary)); \
- assert(!OBJ_FROZEN(ary)); \
- assert((value) >= 0); \
+ RUBY_ASSERT(ARY_SHARED_ROOT_P(ary)); \
+ RUBY_ASSERT(!OBJ_FROZEN(ary)); \
+ RUBY_ASSERT((value) >= 0); \
RARRAY(ary)->as.heap.aux.capa = (value); \
} while (0)
#define FL_SET_SHARED_ROOT(ary) do { \
- assert(!OBJ_FROZEN(ary)); \
- assert(!ARY_EMBED_P(ary)); \
+ RUBY_ASSERT(!OBJ_FROZEN(ary)); \
+ RUBY_ASSERT(!ARY_EMBED_P(ary)); \
FL_SET((ary), RARRAY_SHARED_ROOT_FLAG); \
} while (0)
static inline void
ARY_SET(VALUE a, long i, VALUE v)
{
- assert(!ARY_SHARED_P(a));
- assert(!OBJ_FROZEN(a));
+ RUBY_ASSERT(!ARY_SHARED_P(a));
+ RUBY_ASSERT(!OBJ_FROZEN(a));
RARRAY_ASET(a, i, v);
}
@@ -179,7 +180,7 @@ static long
ary_embed_capa(VALUE ary)
{
size_t size = rb_gc_obj_slot_size(ary) - offsetof(struct RArray, as.ary);
- assert(size % sizeof(VALUE) == 0);
+ RUBY_ASSERT(size % sizeof(VALUE) == 0);
return size / sizeof(VALUE);
}
@@ -233,23 +234,22 @@ rb_ary_size_as_embedded(VALUE ary)
static VALUE
ary_verify_(VALUE ary, const char *file, int line)
{
- assert(RB_TYPE_P(ary, T_ARRAY));
+ RUBY_ASSERT(RB_TYPE_P(ary, T_ARRAY));
if (ARY_SHARED_P(ary)) {
VALUE root = ARY_SHARED_ROOT(ary);
const VALUE *ptr = ARY_HEAP_PTR(ary);
const VALUE *root_ptr = RARRAY_CONST_PTR(root);
long len = ARY_HEAP_LEN(ary), root_len = RARRAY_LEN(root);
- assert(ARY_SHARED_ROOT_P(root) || OBJ_FROZEN(root));
- assert(root_ptr <= ptr && ptr + len <= root_ptr + root_len);
+ RUBY_ASSERT(ARY_SHARED_ROOT_P(root) || OBJ_FROZEN(root));
+ RUBY_ASSERT(root_ptr <= ptr && ptr + len <= root_ptr + root_len);
ary_verify(root);
}
else if (ARY_EMBED_P(ary)) {
- assert(!ARY_SHARED_P(ary));
- assert(RARRAY_LEN(ary) <= ary_embed_capa(ary));
+ RUBY_ASSERT(!ARY_SHARED_P(ary));
+ RUBY_ASSERT(RARRAY_LEN(ary) <= ary_embed_capa(ary));
}
else {
-#if 1
const VALUE *ptr = RARRAY_CONST_PTR(ary);
long i, len = RARRAY_LEN(ary);
volatile VALUE v;
@@ -258,7 +258,6 @@ ary_verify_(VALUE ary, const char *file, int line)
v = ptr[i]; /* access check */
}
v = v;
-#endif
}
return ary;
@@ -326,7 +325,7 @@ ary_memfill(VALUE ary, long beg, long size, VALUE val)
static void
ary_memcpy0(VALUE ary, long beg, long argc, const VALUE *argv, VALUE buff_owner_ary)
{
- assert(!ARY_SHARED_P(buff_owner_ary));
+ RUBY_ASSERT(!ARY_SHARED_P(buff_owner_ary));
if (argc > (int)(128/sizeof(VALUE)) /* is magic number (cache line size) */) {
rb_gc_writebarrier_remember(buff_owner_ary);
@@ -351,7 +350,7 @@ ary_memcpy(VALUE ary, long beg, long argc, const VALUE *argv)
}
static VALUE *
-ary_heap_alloc(size_t capa)
+ary_heap_alloc_buffer(size_t capa)
{
return ALLOC_N(VALUE, capa);
}
@@ -380,7 +379,7 @@ ary_heap_realloc(VALUE ary, size_t new_capa)
void
rb_ary_make_embedded(VALUE ary)
{
- assert(rb_ary_embeddable_p(ary));
+ RUBY_ASSERT(rb_ary_embeddable_p(ary));
if (!ARY_EMBED_P(ary)) {
const VALUE *buf = ARY_HEAP_PTR(ary);
long len = ARY_HEAP_LEN(ary);
@@ -397,15 +396,15 @@ rb_ary_make_embedded(VALUE ary)
static void
ary_resize_capa(VALUE ary, long capacity)
{
- assert(RARRAY_LEN(ary) <= capacity);
- assert(!OBJ_FROZEN(ary));
- assert(!ARY_SHARED_P(ary));
+ RUBY_ASSERT(RARRAY_LEN(ary) <= capacity);
+ RUBY_ASSERT(!OBJ_FROZEN(ary));
+ RUBY_ASSERT(!ARY_SHARED_P(ary));
if (capacity > ary_embed_capa(ary)) {
size_t new_capa = capacity;
if (ARY_EMBED_P(ary)) {
long len = ARY_EMBED_LEN(ary);
- VALUE *ptr = ary_heap_alloc(capacity);
+ VALUE *ptr = ary_heap_alloc_buffer(capacity);
MEMCPY(ptr, ARY_EMBED_PTR(ary), VALUE, len);
FL_UNSET_EMBED(ary);
@@ -440,8 +439,8 @@ ary_shrink_capa(VALUE ary)
{
long capacity = ARY_HEAP_LEN(ary);
long old_capa = ARY_HEAP_CAPA(ary);
- assert(!ARY_SHARED_P(ary));
- assert(old_capa >= capacity);
+ RUBY_ASSERT(!ARY_SHARED_P(ary));
+ RUBY_ASSERT(old_capa >= capacity);
if (old_capa > capacity) ary_heap_realloc(ary, capacity);
ary_verify(ary);
@@ -500,7 +499,7 @@ rb_ary_increment_share(VALUE shared_root)
{
if (!OBJ_FROZEN(shared_root)) {
long num = ARY_SHARED_ROOT_REFCNT(shared_root);
- assert(num >= 0);
+ RUBY_ASSERT(num >= 0);
ARY_SET_SHARED_ROOT_REFCNT(shared_root, num + 1);
}
return shared_root;
@@ -509,9 +508,9 @@ rb_ary_increment_share(VALUE shared_root)
static void
rb_ary_set_shared(VALUE ary, VALUE shared_root)
{
- assert(!ARY_EMBED_P(ary));
- assert(!OBJ_FROZEN(ary));
- assert(ARY_SHARED_ROOT_P(shared_root) || OBJ_FROZEN(shared_root));
+ RUBY_ASSERT(!ARY_EMBED_P(ary));
+ RUBY_ASSERT(!OBJ_FROZEN(ary));
+ RUBY_ASSERT(ARY_SHARED_ROOT_P(shared_root) || OBJ_FROZEN(shared_root));
rb_ary_increment_share(shared_root);
FL_SET_SHARED(ary);
@@ -556,7 +555,7 @@ rb_ary_cancel_sharing(VALUE ary)
rb_ary_decrement_share(shared_root);
}
else {
- VALUE *ptr = ary_heap_alloc(len);
+ VALUE *ptr = ary_heap_alloc_buffer(len);
MEMCPY(ptr, ARY_HEAP_PTR(ary), VALUE, len);
rb_ary_unshare(ary);
ARY_SET_CAPA(ary, len);
@@ -634,7 +633,7 @@ ary_ensure_room_for_push(VALUE ary, long add_len)
* a.freeze
* a.frozen? # => true
*
- * An attempt to modify a frozen \Array raises FrozenError.
+ * An attempt to modify a frozen +Array+ raises FrozenError.
*/
VALUE
@@ -666,7 +665,7 @@ static VALUE
ary_alloc_embed(VALUE klass, long capa)
{
size_t size = ary_embed_size(capa);
- assert(rb_gc_size_allocatable_p(size));
+ RUBY_ASSERT(rb_gc_size_allocatable_p(size));
NEWOBJ_OF(ary, struct RArray, klass,
T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
size, 0);
@@ -713,9 +712,9 @@ ary_new(VALUE klass, long capa)
else {
ary = ary_alloc_heap(klass);
ARY_SET_CAPA(ary, capa);
- assert(!ARY_EMBED_P(ary));
+ RUBY_ASSERT(!ARY_EMBED_P(ary));
- ARY_SET_PTR(ary, ary_heap_alloc(capa));
+ ARY_SET_PTR(ary, ary_heap_alloc_buffer(capa));
ARY_SET_HEAP_LEN(ary, 0);
}
@@ -777,7 +776,7 @@ static VALUE
ec_ary_alloc_embed(rb_execution_context_t *ec, VALUE klass, long capa)
{
size_t size = ary_embed_size(capa);
- assert(rb_gc_size_allocatable_p(size));
+ RUBY_ASSERT(rb_gc_size_allocatable_p(size));
NEWOBJ_OF(ary, struct RArray, klass,
T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
size, ec);
@@ -817,9 +816,9 @@ ec_ary_new(rb_execution_context_t *ec, VALUE klass, long capa)
else {
ary = ec_ary_alloc_heap(ec, klass);
ARY_SET_CAPA(ary, capa);
- assert(!ARY_EMBED_P(ary));
+ RUBY_ASSERT(!ARY_EMBED_P(ary));
- ARY_SET_PTR(ary, ary_heap_alloc(capa));
+ ARY_SET_PTR(ary, ary_heap_alloc_buffer(capa));
ARY_SET_HEAP_LEN(ary, 0);
}
@@ -881,7 +880,20 @@ rb_ary_free(VALUE ary)
}
}
-RUBY_FUNC_EXPORTED size_t
+VALUE
+rb_setup_fake_ary(struct RArray *fake_ary, const VALUE *list, long len, bool freeze)
+{
+ fake_ary->basic.flags = T_ARRAY;
+ VALUE ary = (VALUE)fake_ary;
+ RBASIC_CLEAR_CLASS(ary);
+ ARY_SET_PTR(ary, list);
+ ARY_SET_HEAP_LEN(ary, len);
+ ARY_SET_CAPA(ary, len);
+ if (freeze) OBJ_FREEZE(ary);
+ return ary;
+}
+
+size_t
rb_ary_memsize(VALUE ary)
{
if (ARY_OWNS_HEAP_P(ary)) {
@@ -919,7 +931,7 @@ ary_make_shared(VALUE ary)
FL_SET_SHARED_ROOT(shared);
if (ARY_EMBED_P(ary)) {
- VALUE *ptr = ary_heap_alloc(capa);
+ VALUE *ptr = ary_heap_alloc_buffer(capa);
ARY_SET_PTR(shared, ptr);
ary_memcpy(shared, 0, len, RARRAY_CONST_PTR(ary));
@@ -949,7 +961,7 @@ ary_make_substitution(VALUE ary)
if (ary_embeddable_p(len)) {
VALUE subst = rb_ary_new_capa(len);
- assert(ARY_EMBED_P(subst));
+ RUBY_ASSERT(ARY_EMBED_P(subst));
ary_memcpy(subst, 0, len, RARRAY_CONST_PTR(ary));
ARY_SET_EMBED_LEN(subst, len);
@@ -995,14 +1007,14 @@ rb_to_array(VALUE ary)
* call-seq:
* Array.try_convert(object) -> object, new_array, or nil
*
- * If +object+ is an \Array object, returns +object+.
+ * If +object+ is an +Array+ object, returns +object+.
*
* Otherwise if +object+ responds to <tt>:to_ary</tt>,
* calls <tt>object.to_ary</tt> and returns the result.
*
* Returns +nil+ if +object+ does not respond to <tt>:to_ary</tt>
*
- * Raises an exception unless <tt>object.to_ary</tt> returns an \Array object.
+ * Raises an exception unless <tt>object.to_ary</tt> returns an +Array+ object.
*/
static VALUE
@@ -1043,33 +1055,33 @@ rb_ary_s_new(int argc, VALUE *argv, VALUE klass)
* Array.new(size, default_value) -> new_array
* Array.new(size) {|index| ... } -> new_array
*
- * Returns a new \Array.
+ * Returns a new +Array+.
*
- * With no block and no arguments, returns a new empty \Array object.
+ * With no block and no arguments, returns a new empty +Array+ object.
*
- * With no block and a single \Array argument +array+,
- * returns a new \Array formed from +array+:
+ * With no block and a single +Array+ argument +array+,
+ * returns a new +Array+ formed from +array+:
*
* a = Array.new([:foo, 'bar', 2])
* a.class # => Array
* a # => [:foo, "bar", 2]
*
* With no block and a single Integer argument +size+,
- * returns a new \Array of the given size
+ * returns a new +Array+ of the given size
* whose elements are all +nil+:
*
* a = Array.new(3)
* a # => [nil, nil, nil]
*
* With no block and arguments +size+ and +default_value+,
- * returns an \Array of the given size;
+ * returns an +Array+ of the given size;
* each element is that same +default_value+:
*
* a = Array.new(3, 'x')
* a # => ['x', 'x', 'x']
*
* With a block and argument +size+,
- * returns an \Array of the given size;
+ * returns an +Array+ of the given size;
* the block is called with each successive integer +index+;
* the element for that +index+ is the return value from the block:
*
@@ -1080,7 +1092,7 @@ rb_ary_s_new(int argc, VALUE *argv, VALUE klass)
*
* With a block and no argument,
* or a single argument +0+,
- * ignores the block and returns a new empty \Array.
+ * ignores the block and returns a new empty +Array+.
*/
static VALUE
@@ -1092,8 +1104,8 @@ rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
rb_ary_modify(ary);
if (argc == 0) {
rb_ary_reset(ary);
- assert(ARY_EMBED_P(ary));
- assert(ARY_EMBED_LEN(ary) == 0);
+ RUBY_ASSERT(ARY_EMBED_P(ary));
+ RUBY_ASSERT(ARY_EMBED_LEN(ary) == 0);
if (rb_block_given_p()) {
rb_warning("given block not used");
}
@@ -1190,9 +1202,9 @@ rb_ary_store(VALUE ary, long idx, VALUE val)
static VALUE
ary_make_partial(VALUE ary, VALUE klass, long offset, long len)
{
- assert(offset >= 0);
- assert(len >= 0);
- assert(offset+len <= RARRAY_LEN(ary));
+ RUBY_ASSERT(offset >= 0);
+ RUBY_ASSERT(len >= 0);
+ RUBY_ASSERT(offset+len <= RARRAY_LEN(ary));
VALUE result = ary_alloc_heap(klass);
size_t embed_capa = ary_embed_capa(result);
@@ -1204,7 +1216,10 @@ ary_make_partial(VALUE ary, VALUE klass, long offset, long len)
else {
VALUE shared = ary_make_shared(ary);
- assert(!ARY_EMBED_P(result));
+ /* The ary_make_shared call may allocate, which can trigger a GC
+ * compaction. This can cause the array to be embedded because it has
+ * a length of 0. */
+ FL_UNSET_EMBED(result);
ARY_SET_PTR(result, RARRAY_CONST_PTR(ary));
ARY_SET_LEN(result, RARRAY_LEN(ary));
@@ -1223,17 +1238,18 @@ ary_make_partial(VALUE ary, VALUE klass, long offset, long len)
static VALUE
ary_make_partial_step(VALUE ary, VALUE klass, long offset, long len, long step)
{
- assert(offset >= 0);
- assert(len >= 0);
- assert(offset+len <= RARRAY_LEN(ary));
- assert(step != 0);
+ RUBY_ASSERT(offset >= 0);
+ RUBY_ASSERT(len >= 0);
+ RUBY_ASSERT(offset+len <= RARRAY_LEN(ary));
+ RUBY_ASSERT(step != 0);
- const VALUE *values = RARRAY_CONST_PTR(ary);
const long orig_len = len;
if (step > 0 && step >= len) {
VALUE result = ary_new(klass, 1);
VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
+ const VALUE *values = RARRAY_CONST_PTR(ary);
+
RB_OBJ_WRITE(result, ptr, values[offset]);
ARY_SET_EMBED_LEN(result, 1);
return result;
@@ -1251,6 +1267,8 @@ ary_make_partial_step(VALUE ary, VALUE klass, long offset, long len, long step)
VALUE result = ary_new(klass, len);
if (ARY_EMBED_P(result)) {
VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
+ const VALUE *values = RARRAY_CONST_PTR(ary);
+
for (i = 0; i < len; ++i) {
RB_OBJ_WRITE(result, ptr+i, values[j]);
j += step;
@@ -1258,6 +1276,8 @@ ary_make_partial_step(VALUE ary, VALUE klass, long offset, long len, long step)
ARY_SET_EMBED_LEN(result, len);
}
else {
+ const VALUE *values = RARRAY_CONST_PTR(ary);
+
RARRAY_PTR_USE(result, ptr, {
for (i = 0; i < len; ++i) {
RB_OBJ_WRITE(result, ptr+i, values[j]);
@@ -1320,7 +1340,7 @@ ary_take_first_or_last(int argc, const VALUE *argv, VALUE ary, enum ary_take_pos
* a = [:foo, 'bar', 2]
* a << :baz # => [:foo, "bar", 2, :baz]
*
- * Appends +object+ as one element, even if it is another \Array:
+ * Appends +object+ as one element, even if it is another +Array+:
*
* a = [:foo, 'bar', 2]
* a1 = a << [3, 4]
@@ -1362,7 +1382,7 @@ rb_ary_cat(VALUE ary, const VALUE *argv, long len)
* a = [:foo, 'bar', 2]
* a.push(:baz, :bat) # => [:foo, "bar", 2, :baz, :bat]
*
- * Appends each argument as one element, even if it is another \Array:
+ * Appends each argument as one element, even if it is another +Array+:
*
* a = [:foo, 'bar', 2]
* a1 = a.push([:baz, :bat], [:bam, :bad])
@@ -1414,7 +1434,7 @@ rb_ary_pop(VALUE ary)
*
* When a non-negative Integer argument +n+ is given and is in range,
*
- * removes and returns the last +n+ elements in a new \Array:
+ * removes and returns the last +n+ elements in a new +Array+:
* a = [:foo, 'bar', 2]
* a.pop(2) # => ["bar", 2]
*
@@ -1477,19 +1497,19 @@ rb_ary_shift(VALUE ary)
* Returns +nil+ if +self+ is empty.
*
* When positive Integer argument +n+ is given, removes the first +n+ elements;
- * returns those elements in a new \Array:
+ * returns those elements in a new +Array+:
*
* a = [:foo, 'bar', 2]
* a.shift(2) # => [:foo, 'bar']
* a # => [2]
*
* If +n+ is as large as or larger than <tt>self.length</tt>,
- * removes all elements; returns those elements in a new \Array:
+ * removes all elements; returns those elements in a new +Array+:
*
* a = [:foo, 'bar', 2]
* a.shift(3) # => [:foo, 'bar', 2]
*
- * If +n+ is zero, returns a new empty \Array; +self+ is unmodified.
+ * If +n+ is zero, returns a new empty +Array+; +self+ is unmodified.
*
* Related: #push, #pop, #unshift.
*/
@@ -1556,7 +1576,7 @@ make_room_for_unshift(VALUE ary, const VALUE *head, VALUE *sharedp, int argc, lo
head = sharedp + argc + room;
}
ARY_SET_PTR(ary, head - argc);
- assert(ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary)));
+ RUBY_ASSERT(ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary)));
ary_verify(ary);
return ARY_SHARED_ROOT(ary);
@@ -1726,6 +1746,16 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
*
* Returns elements from +self+; does not modify +self+.
*
+ * In brief:
+ *
+ * a = [:foo, 'bar', 2]
+ * a[0] # => :foo
+ * a[-1] # => 2
+ * a[1, 2] # => ["bar", 2]
+ * a[0..1] # => [:foo, "bar"]
+ * a[0..-2] # => [:foo, "bar"]
+ * a[-2..2] # => ["bar", 2]
+ *
* When a single Integer argument +index+ is given, returns the element at offset +index+:
*
* a = [:foo, 'bar', 2]
@@ -1742,7 +1772,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
* If +index+ is out of range, returns +nil+.
*
* When two Integer arguments +start+ and +length+ are given,
- * returns a new \Array of size +length+ containing successive elements beginning at offset +start+:
+ * returns a new +Array+ of size +length+ containing successive elements beginning at offset +start+:
*
* a = [:foo, 'bar', 2]
* a[0, 2] # => [:foo, "bar"]
@@ -1757,7 +1787,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
* a[2, 2] # => [2]
*
* If <tt>start == self.size</tt> and <tt>length >= 0</tt>,
- * returns a new empty \Array.
+ * returns a new empty +Array+.
*
* If +length+ is negative, returns +nil+.
*
@@ -1769,7 +1799,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
* a[0..1] # => [:foo, "bar"]
* a[1..2] # => ["bar", 2]
*
- * Special case: If <tt>range.start == a.size</tt>, returns a new empty \Array.
+ * Special case: If <tt>range.start == a.size</tt>, returns a new empty +Array+.
*
* If <tt>range.end</tt> is negative, calculates the end index from the end:
*
@@ -1793,7 +1823,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
* a[4..-1] # => nil
*
* When a single Enumerator::ArithmeticSequence argument +aseq+ is given,
- * returns an \Array of elements corresponding to the indexes produced by
+ * returns an +Array+ of elements corresponding to the indexes produced by
* the sequence.
*
* a = ['--', 'data1', '--', 'data2', '--', 'data3']
@@ -2277,6 +2307,31 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
*
* Assigns elements in +self+; returns the given +object+.
*
+ * In brief:
+ *
+ * a_orig = [:foo, 'bar', 2]
+ * # With argument index.
+ * a = a_orig.dup
+ * a[0] = 'foo' # => "foo"
+ * a # => ["foo", "bar", 2]
+ * a = a_orig.dup
+ * a[7] = 'foo' # => "foo"
+ * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
+ * # With arguments start and length.
+ * a = a_orig.dup
+ * a[0, 2] = 'foo' # => "foo"
+ * a # => ["foo", 2]
+ * a = a_orig.dup
+ * a[6, 50] = 'foo' # => "foo"
+ * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
+ * # With argument range.
+ * a = a_orig.dup
+ * a[0..1] = 'foo' # => "foo"
+ * a # => ["foo", 2]
+ * a = a_orig.dup
+ * a[6..50] = 'foo' # => "foo"
+ * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
+ *
* When Integer argument +index+ is given, assigns +object+ to an element in +self+.
*
* If +index+ is non-negative, assigns +object+ the element at offset +index+:
@@ -2297,7 +2352,7 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
* a[-1] = 'two' # => "two"
* a # => [:foo, "bar", "two"]
*
- * When Integer arguments +start+ and +length+ are given and +object+ is not an \Array,
+ * When Integer arguments +start+ and +length+ are given and +object+ is not an +Array+,
* removes <tt>length - 1</tt> elements beginning at offset +start+,
* and assigns +object+ at offset +start+:
*
@@ -2332,7 +2387,7 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
* a[1, 5] = 'foo' # => "foo"
* a # => [:foo, "foo"]
*
- * When Range argument +range+ is given and +object+ is an \Array,
+ * When Range argument +range+ is given and +object+ is not an +Array+,
* removes <tt>length - 1</tt> elements beginning at offset +start+,
* and assigns +object+ at offset +start+:
*
@@ -2347,7 +2402,8 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
* a # => [:foo, "foo"]
*
* If the array length is less than <tt>range.begin</tt>,
- * assigns +object+ at offset <tt>range.begin</tt>, and ignores +length+:
+ * extends the array with +nil+, assigns +object+ at offset <tt>range.begin</tt>,
+ * and ignores +length+:
*
* a = [:foo, 'bar', 2]
* a[6..50] = 'foo' # => "foo"
@@ -2477,50 +2533,19 @@ ary_enum_length(VALUE ary, VALUE args, VALUE eobj)
return rb_ary_length(ary);
}
-/*
- * call-seq:
- * array.each {|element| ... } -> self
- * array.each -> Enumerator
- *
- * Iterates over array elements.
- *
- * When a block given, passes each successive array element to the block;
- * returns +self+:
- *
- * a = [:foo, 'bar', 2]
- * a.each {|element| puts "#{element.class} #{element}" }
- *
- * Output:
- *
- * Symbol foo
- * String bar
- * Integer 2
- *
- * Allows the array to be modified during iteration:
- *
- * a = [:foo, 'bar', 2]
- * a.each {|element| puts element; a.clear if element.to_s.start_with?('b') }
- *
- * Output:
- *
- * foo
- * bar
- *
- * When no block given, returns a new Enumerator:
- * a = [:foo, 'bar', 2]
- *
- * e = a.each
- * e # => #<Enumerator: [:foo, "bar", 2]:each>
- * a1 = e.each {|element| puts "#{element.class} #{element}" }
- *
- * Output:
- *
- * Symbol foo
- * String bar
- * Integer 2
- *
- * Related: #each_index, #reverse_each.
- */
+// Primitive to avoid a race condition in Array#each.
+// Return `true` and write `value` and `index` if the element exists.
+static VALUE
+ary_fetch_next(VALUE self, VALUE *index, VALUE *value)
+{
+ long i = NUM2LONG(*index);
+ if (i >= RARRAY_LEN(self)) {
+ return Qfalse;
+ }
+ *value = RARRAY_AREF(self, i);
+ *index = LONG2NUM(i + 1);
+ return Qtrue;
+}
VALUE
rb_ary_each(VALUE ary)
@@ -2925,12 +2950,12 @@ rb_ary_to_s(VALUE ary)
* call-seq:
* to_a -> self or new_array
*
- * When +self+ is an instance of \Array, returns +self+:
+ * When +self+ is an instance of +Array+, returns +self+:
*
* a = [:foo, 'bar', 2]
* a.to_a # => [:foo, "bar", 2]
*
- * Otherwise, returns a new \Array containing the elements of +self+:
+ * Otherwise, returns a new +Array+ containing the elements of +self+:
*
* class MyArray < Array; end
* a = MyArray.new(['foo', 'bar', 'two'])
@@ -2961,14 +2986,14 @@ rb_ary_to_a(VALUE ary)
* Returns a new Hash formed from +self+.
*
* When a block is given, calls the block with each array element;
- * the block must return a 2-element \Array whose two elements
+ * the block must return a 2-element +Array+ whose two elements
* form a key-value pair in the returned Hash:
*
* a = ['foo', :bar, 1, [2, 3], {baz: 4}]
* h = a.to_h {|item| [item, item] }
* h # => {"foo"=>"foo", :bar=>:bar, 1=>1, [2, 3]=>[2, 3], {:baz=>4}=>{:baz=>4}}
*
- * When no block is given, +self+ must be an \Array of 2-element sub-arrays,
+ * When no block is given, +self+ must be an +Array+ of 2-element sub-arrays,
* each sub-array is formed into a key-value pair in the new Hash:
*
* [].to_h # => {}
@@ -3062,7 +3087,7 @@ rb_ary_reverse_bang(VALUE ary)
* call-seq:
* array.reverse -> new_array
*
- * Returns a new \Array with the elements of +self+ in reverse order:
+ * Returns a new +Array+ with the elements of +self+ in reverse order:
*
* a = ['foo', 'bar', 'two']
* a1 = a.reverse
@@ -3186,10 +3211,10 @@ rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
* array.rotate -> new_array
* array.rotate(count) -> new_array
*
- * Returns a new \Array formed from +self+ with elements
+ * Returns a new +Array+ formed from +self+ with elements
* rotated from one end to the other.
*
- * When no argument given, returns a new \Array that is like +self+,
+ * When no argument given, returns a new +Array+ that is like +self+,
* except that the first element has been rotated to the last position:
*
* a = [:foo, 'bar', 2, 'bar']
@@ -3197,7 +3222,7 @@ rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
* a1 # => ["bar", 2, "bar", :foo]
*
* When given a non-negative Integer +count+,
- * returns a new \Array with +count+ elements rotated from the beginning to the end:
+ * returns a new +Array+ with +count+ elements rotated from the beginning to the end:
*
* a = [:foo, 'bar', 2]
* a1 = a.rotate(2)
@@ -3363,7 +3388,7 @@ VALUE
rb_ary_sort_bang(VALUE ary)
{
rb_ary_modify(ary);
- assert(!ARY_SHARED_P(ary));
+ RUBY_ASSERT(!ARY_SHARED_P(ary));
if (RARRAY_LEN(ary) > 1) {
VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */
struct ary_sort_data data;
@@ -3381,6 +3406,9 @@ rb_ary_sort_bang(VALUE ary)
rb_ary_unshare(ary);
FL_SET_EMBED(ary);
}
+ if (ARY_EMBED_LEN(tmp) > ARY_CAPA(ary)) {
+ ary_resize_capa(ary, ARY_EMBED_LEN(tmp));
+ }
ary_memcpy(ary, 0, ARY_EMBED_LEN(tmp), ARY_EMBED_PTR(tmp));
ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
}
@@ -3390,7 +3418,7 @@ rb_ary_sort_bang(VALUE ary)
ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
}
else {
- assert(!ARY_SHARED_P(tmp));
+ RUBY_ASSERT(!ARY_SHARED_P(tmp));
if (ARY_EMBED_P(ary)) {
FL_UNSET_EMBED(ary);
}
@@ -3423,7 +3451,7 @@ rb_ary_sort_bang(VALUE ary)
* array.sort -> new_array
* array.sort {|a, b| ... } -> new_array
*
- * Returns a new \Array whose elements are those from +self+, sorted.
+ * Returns a new +Array+ whose elements are those from +self+, sorted.
*
* With no block, compares elements using operator <tt><=></tt>
* (see Comparable):
@@ -3599,7 +3627,7 @@ rb_ary_sort_by_bang(VALUE ary)
* array.map -> new_enumerator
*
* Calls the block, if given, with each element of +self+;
- * returns a new \Array whose elements are the return values from the block:
+ * returns a new +Array+ whose elements are the return values from the block:
*
* a = [:foo, 'bar', 2]
* a1 = a.map {|element| element.class }
@@ -3717,7 +3745,7 @@ append_values_at_single(VALUE result, VALUE ary, long olen, VALUE idx)
* call-seq:
* array.values_at(*indexes) -> new_array
*
- * Returns a new \Array whose elements are the elements
+ * Returns a new +Array+ whose elements are the elements
* of +self+ at the given Integer or Range +indexes+.
*
* For each positive +index+, returns the element at offset +index+:
@@ -3737,7 +3765,7 @@ append_values_at_single(VALUE result, VALUE ary, long olen, VALUE idx)
* a = [:foo, 'bar', 2]
* a.values_at(0, 3, 1, 3) # => [:foo, nil, "bar", nil]
*
- * Returns a new empty \Array if no arguments given.
+ * Returns a new empty +Array+ if no arguments given.
*
* For each negative +index+, counts backward from the end of the array:
*
@@ -3775,7 +3803,7 @@ rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
* array.select -> new_enumerator
*
* Calls the block, if given, with each element of +self+;
- * returns a new \Array containing those elements of +self+
+ * returns a new +Array+ containing those elements of +self+
* for which the block returns a truthy value:
*
* a = [:foo, 'bar', 2, :bam]
@@ -4120,7 +4148,7 @@ ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len)
*
* When the only arguments are Integers +start+ and +length+,
* removes +length+ elements from +self+ beginning at offset +start+;
- * returns the deleted objects in a new \Array:
+ * returns the deleted objects in a new +Array+:
*
* a = [:foo, 'bar', 2]
* a.slice!(0, 2) # => [:foo, "bar"]
@@ -4134,7 +4162,7 @@ ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len)
* a # => [:foo]
*
* If <tt>start == a.size</tt> and +length+ is non-negative,
- * returns a new empty \Array.
+ * returns a new empty +Array+.
*
* If +length+ is negative, returns +nil+.
*
@@ -4145,7 +4173,7 @@ ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len)
* a.slice!(1..2) # => ["bar", 2]
* a # => [:foo]
*
- * If <tt>range.start == a.size</tt>, returns a new empty \Array.
+ * If <tt>range.start == a.size</tt>, returns a new empty +Array+.
*
* If <tt>range.start</tt> is larger than the array size, returns +nil+.
*
@@ -4274,7 +4302,7 @@ rb_ary_reject_bang(VALUE ary)
* array.reject {|element| ... } -> new_array
* array.reject -> new_enumerator
*
- * Returns a new \Array whose elements are all those from +self+
+ * Returns a new +Array+ whose elements are all those from +self+
* for which the block returns +false+ or +nil+:
*
* a = [:foo, 'bar', 2, 'bat']
@@ -4358,7 +4386,7 @@ take_items(VALUE obj, long n)
* array.zip(*other_arrays) -> new_array
* array.zip(*other_arrays) {|other_array| ... } -> nil
*
- * When no block given, returns a new \Array +new_array+ of size <tt>self.size</tt>
+ * When no block given, returns a new +Array+ +new_array+ of size <tt>self.size</tt>
* whose elements are Arrays.
*
* Each nested array <tt>new_array[n]</tt> is of size <tt>other_arrays.size+1</tt>,
@@ -4393,6 +4421,13 @@ take_items(VALUE obj, long n)
* d = a.zip(b, c)
* d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
*
+ * If an argument is not an array, it extracts the values by calling #each:
+ *
+ * a = [:a0, :a1, :a2, :a2]
+ * b = 1..4
+ * c = a.zip(b)
+ * c # => [[:a0, 1], [:a1, 2], [:a2, 3], [:a2, 4]]
+ *
* When a block is given, calls the block with each of the sub-arrays (formed as above); returns +nil+:
*
* a = [:a0, :a1, :a2, :a3]
@@ -4471,7 +4506,7 @@ rb_ary_zip(int argc, VALUE *argv, VALUE ary)
* call-seq:
* array.transpose -> new_array
*
- * Transposes the rows and columns in an \Array of Arrays;
+ * Transposes the rows and columns in an +Array+ of Arrays;
* the nested Arrays must all be the same size:
*
* a = [[:a0, :a1], [:b0, :b1], [:c0, :c1]]
@@ -4529,7 +4564,7 @@ rb_ary_replace(VALUE copy, VALUE orig)
/* orig has enough space to embed the contents of orig. */
if (RARRAY_LEN(orig) <= ary_embed_capa(copy)) {
- assert(ARY_EMBED_P(copy));
+ RUBY_ASSERT(ARY_EMBED_P(copy));
ary_memcpy(copy, 0, RARRAY_LEN(orig), RARRAY_CONST_PTR(orig));
ARY_SET_EMBED_LEN(copy, RARRAY_LEN(orig));
}
@@ -4537,7 +4572,7 @@ rb_ary_replace(VALUE copy, VALUE orig)
* contents of orig. */
else if (ARY_EMBED_P(orig)) {
long len = ARY_EMBED_LEN(orig);
- VALUE *ptr = ary_heap_alloc(len);
+ VALUE *ptr = ary_heap_alloc_buffer(len);
FL_UNSET_EMBED(copy);
ARY_SET_PTR(copy, ptr);
@@ -4857,7 +4892,7 @@ rb_ary_fill(int argc, VALUE *argv, VALUE ary)
* call-seq:
* array + other_array -> new_array
*
- * Returns a new \Array containing all elements of +array+
+ * Returns a new +Array+ containing all elements of +array+
* followed by all elements of +other_array+:
*
* a = [0, 1] + [2, 3]
@@ -4899,7 +4934,7 @@ ary_append(VALUE x, VALUE y)
* call-seq:
* array.concat(*other_arrays) -> self
*
- * Adds to +array+ all elements from each \Array in +other_arrays+; returns +self+:
+ * Adds to +array+ all elements from each +Array+ in +other_arrays+; returns +self+:
*
* a = [0, 1]
* a.concat([2, 3], [4, 5]) # => [0, 1, 2, 3, 4, 5]
@@ -4938,7 +4973,7 @@ rb_ary_concat(VALUE x, VALUE y)
* array * string_separator -> new_string
*
* When non-negative argument Integer +n+ is given,
- * returns a new \Array built by concatenating the +n+ copies of +self+:
+ * returns a new +Array+ built by concatenating the +n+ copies of +self+:
*
* a = ['x', 'y']
* a * 3 # => ["x", "y", "x", "y", "x", "y"]
@@ -4998,7 +5033,7 @@ rb_ary_times(VALUE ary, VALUE times)
* call-seq:
* array.assoc(obj) -> found_array or nil
*
- * Returns the first element in +self+ that is an \Array
+ * Returns the first element in +self+ that is an +Array+
* whose first element <tt>==</tt> +obj+:
*
* a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
@@ -5028,7 +5063,7 @@ rb_ary_assoc(VALUE ary, VALUE key)
* call-seq:
* array.rassoc(obj) -> found_array or nil
*
- * Returns the first element in +self+ that is an \Array
+ * Returns the first element in +self+ that is an +Array+
* whose second element <tt>==</tt> +obj+:
*
* a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
@@ -5046,7 +5081,7 @@ rb_ary_rassoc(VALUE ary, VALUE value)
VALUE v;
for (i = 0; i < RARRAY_LEN(ary); ++i) {
- v = RARRAY_AREF(ary, i);
+ v = rb_check_array_type(RARRAY_AREF(ary, i));
if (RB_TYPE_P(v, T_ARRAY) &&
RARRAY_LEN(v) > 1 &&
rb_equal(RARRAY_AREF(v, 1), value))
@@ -5137,10 +5172,10 @@ recursive_eql(VALUE ary1, VALUE ary2, int recur)
/*
* call-seq:
- * array.eql? other_array -> true or false
+ * array.eql?(other_array) -> true or false
*
* Returns +true+ if +self+ and +other_array+ are the same size,
- * and if, for each index +i+ in +self+, <tt>self[i].eql? other_array[i]</tt>:
+ * and if, for each index +i+ in +self+, <tt>self[i].eql?(other_array[i])</tt>:
*
* a0 = [:foo, 'bar', 2]
* a1 = [:foo, 'bar', 2]
@@ -5185,7 +5220,7 @@ rb_ary_hash_values(long len, const VALUE *elements)
*
* Returns the integer hash value for +self+.
*
- * Two arrays with the same content will have the same hash code (and will compare using eql?):
+ * Two arrays with the same content will have the same hash code (and will compare using #eql?):
*
* [0, 1, 2].hash == [0, 1, 2].hash # => true
* [0, 1, 2].hash == [0, 1, 3].hash # => false
@@ -5359,8 +5394,8 @@ ary_make_hash_by(VALUE ary)
* call-seq:
* array - other_array -> new_array
*
- * Returns a new \Array containing only those elements from +array+
- * that are not found in \Array +other_array+;
+ * Returns a new +Array+ containing only those elements from +array+
+ * that are not found in +Array+ +other_array+;
* items are compared using <tt>eql?</tt>;
* the order from +array+ is preserved:
*
@@ -5404,7 +5439,7 @@ rb_ary_diff(VALUE ary1, VALUE ary2)
* call-seq:
* array.difference(*other_arrays) -> new_array
*
- * Returns a new \Array containing only those elements from +self+
+ * Returns a new +Array+ containing only those elements from +self+
* that are not found in any of the Arrays +other_arrays+;
* items are compared using <tt>eql?</tt>; order from +self+ is preserved:
*
@@ -5458,7 +5493,7 @@ rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary)
* call-seq:
* array & other_array -> new_array
*
- * Returns a new \Array containing each element found in both +array+ and \Array +other_array+;
+ * Returns a new +Array+ containing each element found in both +array+ and +Array+ +other_array+;
* duplicates are omitted; items are compared using <tt>eql?</tt>
* (items must also implement +hash+ correctly):
*
@@ -5511,7 +5546,7 @@ rb_ary_and(VALUE ary1, VALUE ary2)
* call-seq:
* array.intersection(*other_arrays) -> new_array
*
- * Returns a new \Array containing each element found both in +self+
+ * Returns a new +Array+ containing each element found both in +self+
* and in all of the given Arrays +other_arrays+;
* duplicates are omitted; items are compared using <tt>eql?</tt>
* (items must also implement +hash+ correctly):
@@ -5576,7 +5611,7 @@ rb_ary_union_hash(VALUE hash, VALUE ary2)
* call-seq:
* array | other_array -> new_array
*
- * Returns the union of +array+ and \Array +other_array+;
+ * Returns the union of +array+ and +Array+ +other_array+;
* duplicates are removed; order is preserved;
* items are compared using <tt>eql?</tt>:
*
@@ -5610,7 +5645,7 @@ rb_ary_or(VALUE ary1, VALUE ary2)
* call-seq:
* array.union(*other_arrays) -> new_array
*
- * Returns a new \Array that is the union of +self+ and all given Arrays +other_arrays+;
+ * Returns a new +Array+ that is the union of +self+ and all given Arrays +other_arrays+;
* duplicates are removed; order is preserved; items are compared using <tt>eql?</tt>:
*
* [0, 1, 2, 3].union([4, 5], [6, 7]) # => [0, 1, 2, 3, 4, 5, 6, 7]
@@ -5663,7 +5698,7 @@ rb_ary_union_multi(int argc, VALUE *argv, VALUE ary)
* a.intersect?(b) #=> true
* a.intersect?(c) #=> false
*
- * Array elements are compared using <tt>eql?</tt>
+ * +Array+ elements are compared using <tt>eql?</tt>
* (items must also implement +hash+ correctly).
*/
@@ -5806,7 +5841,7 @@ ary_max_opt_string(VALUE ary, long i, VALUE vmax)
* Returns one of the following:
*
* - The maximum-valued element from +self+.
- * - A new \Array of maximum-valued elements selected from +self+.
+ * - A new +Array+ of maximum-valued elements selected from +self+.
*
* When no block is given, each element in +self+ must respond to method <tt><=></tt>
* with an Integer.
@@ -5816,7 +5851,7 @@ ary_max_opt_string(VALUE ary, long i, VALUE vmax)
*
* [0, 1, 2].max # => 2
*
- * With an argument Integer +n+ and no block, returns a new \Array with at most +n+ elements,
+ * With an argument Integer +n+ and no block, returns a new +Array+ with at most +n+ elements,
* in descending order per method <tt><=></tt>:
*
* [0, 1, 2, 3].max(3) # => [3, 2, 1]
@@ -5829,7 +5864,7 @@ ary_max_opt_string(VALUE ary, long i, VALUE vmax)
*
* ['0', '00', '000'].max {|a, b| a.size <=> b.size } # => "000"
*
- * With an argument +n+ and a block, returns a new \Array with at most +n+ elements,
+ * With an argument +n+ and a block, returns a new +Array+ with at most +n+ elements,
* in descending order per the block:
*
* ['0', '00', '000'].max(2) {|a, b| a.size <=> b.size } # => ["000", "00"]
@@ -5974,7 +6009,7 @@ ary_min_opt_string(VALUE ary, long i, VALUE vmin)
* Returns one of the following:
*
* - The minimum-valued element from +self+.
- * - A new \Array of minimum-valued elements selected from +self+.
+ * - A new +Array+ of minimum-valued elements selected from +self+.
*
* When no block is given, each element in +self+ must respond to method <tt><=></tt>
* with an Integer.
@@ -5984,7 +6019,7 @@ ary_min_opt_string(VALUE ary, long i, VALUE vmin)
*
* [0, 1, 2].min # => 0
*
- * With Integer argument +n+ and no block, returns a new \Array with at most +n+ elements,
+ * With Integer argument +n+ and no block, returns a new +Array+ with at most +n+ elements,
* in ascending order per method <tt><=></tt>:
*
* [0, 1, 2, 3].min(3) # => [0, 1, 2]
@@ -5997,7 +6032,7 @@ ary_min_opt_string(VALUE ary, long i, VALUE vmin)
*
* ['0', '00', '000'].min { |a, b| a.size <=> b.size } # => "0"
*
- * With an argument +n+ and a block, returns a new \Array with at most +n+ elements,
+ * With an argument +n+ and a block, returns a new +Array+ with at most +n+ elements,
* in ascending order per the block:
*
* ['0', '00', '000'].min(2) {|a, b| a.size <=> b.size } # => ["0", "00"]
@@ -6048,19 +6083,19 @@ rb_ary_min(int argc, VALUE *argv, VALUE ary)
* array.minmax -> [min_val, max_val]
* array.minmax {|a, b| ... } -> [min_val, max_val]
*
- * Returns a new 2-element \Array containing the minimum and maximum values
+ * Returns a new 2-element +Array+ containing the minimum and maximum values
* from +self+, either per method <tt><=></tt> or per a given block:.
*
* When no block is given, each element in +self+ must respond to method <tt><=></tt>
* with an Integer;
- * returns a new 2-element \Array containing the minimum and maximum values
+ * returns a new 2-element +Array+ containing the minimum and maximum values
* from +self+, per method <tt><=></tt>:
*
* [0, 1, 2].minmax # => [0, 2]
*
* When a block is given, the block must return an Integer;
* the block is called <tt>self.size-1</tt> times to compare elements;
- * returns a new 2-element \Array containing the minimum and maximum values
+ * returns a new 2-element +Array+ containing the minimum and maximum values
* from +self+, per the block:
*
* ['0', '00', '000'].minmax {|a, b| a.size <=> b.size } # => ["0", "000"]
@@ -6146,7 +6181,7 @@ rb_ary_uniq_bang(VALUE ary)
* array.uniq -> new_array
* array.uniq {|element| ... } -> new_array
*
- * Returns a new \Array containing those elements from +self+ that are not duplicates,
+ * Returns a new +Array+ containing those elements from +self+ that are not duplicates,
* the first occurrence always being retained.
*
* With no block given, identifies and omits duplicates using method <tt>eql?</tt>
@@ -6221,7 +6256,7 @@ rb_ary_compact_bang(VALUE ary)
* call-seq:
* array.compact -> new_array
*
- * Returns a new \Array containing all non-+nil+ elements from +self+:
+ * Returns a new +Array+ containing all non-+nil+ elements from +self+:
*
* a = [nil, 0, nil, 1, nil, 2, nil]
* a.compact # => [0, 1, 2]
@@ -6295,16 +6330,9 @@ rb_ary_count(int argc, VALUE *argv, VALUE ary)
static VALUE
flatten(VALUE ary, int level)
{
- static const rb_data_type_t flatten_memo_data_type = {
- .wrap_struct_name = "array_flatten_memo_data_type",
- .function = { NULL, (RUBY_DATA_FUNC)st_free_table },
- NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
- };
-
long i;
- VALUE stack, result, tmp = 0, elt, vmemo;
- st_table *memo = 0;
- st_data_t id;
+ VALUE stack, result, tmp = 0, elt;
+ VALUE memo = Qfalse;
for (i = 0; i < RARRAY_LEN(ary); i++) {
elt = RARRAY_AREF(ary, i);
@@ -6326,10 +6354,9 @@ flatten(VALUE ary, int level)
rb_ary_push(stack, LONG2NUM(i + 1));
if (level < 0) {
- memo = st_init_numtable();
- vmemo = TypedData_Wrap_Struct(0, &flatten_memo_data_type, memo);
- st_insert(memo, (st_data_t)ary, (st_data_t)Qtrue);
- st_insert(memo, (st_data_t)tmp, (st_data_t)Qtrue);
+ memo = rb_obj_hide(rb_ident_hash_new());
+ rb_hash_aset(memo, ary, Qtrue);
+ rb_hash_aset(memo, tmp, Qtrue);
}
ary = tmp;
@@ -6344,9 +6371,8 @@ flatten(VALUE ary, int level)
}
tmp = rb_check_array_type(elt);
if (RBASIC(result)->klass) {
- if (memo) {
- RB_GC_GUARD(vmemo);
- st_clear(memo);
+ if (RTEST(memo)) {
+ rb_hash_clear(memo);
}
rb_raise(rb_eRuntimeError, "flatten reentered");
}
@@ -6355,12 +6381,11 @@ flatten(VALUE ary, int level)
}
else {
if (memo) {
- id = (st_data_t)tmp;
- if (st_is_member(memo, id)) {
- st_clear(memo);
+ if (rb_hash_aref(memo, tmp) == Qtrue) {
+ rb_hash_clear(memo);
rb_raise(rb_eArgError, "tried to flatten recursive array");
}
- st_insert(memo, id, (st_data_t)Qtrue);
+ rb_hash_aset(memo, tmp, Qtrue);
}
rb_ary_push(stack, ary);
rb_ary_push(stack, LONG2NUM(i));
@@ -6372,8 +6397,7 @@ flatten(VALUE ary, int level)
break;
}
if (memo) {
- id = (st_data_t)ary;
- st_delete(memo, &id, 0);
+ rb_hash_delete(memo, ary);
}
tmp = rb_ary_pop(stack);
i = NUM2LONG(tmp);
@@ -6381,7 +6405,7 @@ flatten(VALUE ary, int level)
}
if (memo) {
- st_clear(memo);
+ rb_hash_clear(memo);
}
RBASIC_SET_CLASS(result, rb_cArray);
@@ -6393,7 +6417,7 @@ flatten(VALUE ary, int level)
* array.flatten! -> self or nil
* array.flatten!(level) -> self or nil
*
- * Replaces each nested \Array in +self+ with the elements from that \Array;
+ * Replaces each nested +Array+ in +self+ with the elements from that +Array+;
* returns +self+ if any changes, +nil+ otherwise.
*
* With non-negative Integer argument +level+, flattens recursively through +level+ levels:
@@ -6446,9 +6470,9 @@ rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
* array.flatten -> new_array
* array.flatten(level) -> new_array
*
- * Returns a new \Array that is a recursive flattening of +self+:
+ * Returns a new +Array+ that is a recursive flattening of +self+:
* - Each non-Array element is unchanged.
- * - Each \Array is replaced by its individual elements.
+ * - Each +Array+ is replaced by its individual elements.
*
* With non-negative Integer argument +level+, flattens recursively through +level+ levels:
*
@@ -6525,6 +6549,14 @@ rb_ary_shuffle(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
return ary;
}
+static const rb_data_type_t ary_sample_memo_type = {
+ .wrap_struct_name = "ary_sample_memo",
+ .function = {
+ .dfree = (RUBY_DATA_FUNC)st_free_table,
+ },
+ .flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
+};
+
static VALUE
ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE to_array)
{
@@ -6606,11 +6638,9 @@ ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE
}
else if (n <= memo_threshold / 2) {
long max_idx = 0;
-#undef RUBY_UNTYPED_DATA_WARNING
-#define RUBY_UNTYPED_DATA_WARNING 0
- VALUE vmemo = Data_Wrap_Struct(0, 0, st_free_table, 0);
+ VALUE vmemo = TypedData_Wrap_Struct(0, &ary_sample_memo_type, 0);
st_table *memo = st_init_numtable_with_size(n);
- DATA_PTR(vmemo) = memo;
+ RTYPEDDATA_DATA(vmemo) = memo;
result = rb_ary_new_capa(n);
RARRAY_PTR_USE(result, ptr_result, {
for (i=0; i<n; i++) {
@@ -6633,8 +6663,9 @@ ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE
}
});
});
- DATA_PTR(vmemo) = 0;
+ RTYPEDDATA_DATA(vmemo) = 0;
st_free_table(memo);
+ RB_GC_GUARD(vmemo);
}
else {
result = rb_ary_dup(ary);
@@ -6891,7 +6922,7 @@ rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
* [2, 0, 1]
* [2, 1, 0]
*
- * When +n+ is zero, calls the block once with a new empty \Array:
+ * When +n+ is zero, calls the block once with a new empty +Array+:
*
* a = [0, 1, 2]
* a.permutation(0) {|permutation| p permutation }
@@ -7029,7 +7060,7 @@ rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
*
* [0, 1, 2]
*
- * When +n+ is zero, calls the block once with a new empty \Array:
+ * When +n+ is zero, calls the block once with a new empty +Array+:
*
* a = [0, 1, 2]
* a1 = a.combination(0) {|combination| p combination }
@@ -7140,7 +7171,7 @@ rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
* array.repeated_permutation(n) -> new_enumerator
*
* Calls the block with each repeated permutation of length +n+ of the elements of +self+;
- * each permutation is an \Array;
+ * each permutation is an +Array+;
* returns +self+. The order of the permutations is indeterminate.
*
* When a block and a positive Integer argument +n+ are given, calls the block with each
@@ -7174,7 +7205,7 @@ rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
* [2, 1]
* [2, 2]
*
- * If +n+ is zero, calls the block once with an empty \Array.
+ * If +n+ is zero, calls the block once with an empty +Array+.
*
* If +n+ is negative, does not call the block:
*
@@ -7272,7 +7303,7 @@ rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
* array.repeated_combination(n) -> new_enumerator
*
* Calls the block with each repeated combination of length +n+ of the elements of +self+;
- * each combination is an \Array;
+ * each combination is an +Array+;
* returns +self+. The order of the combinations is indeterminate.
*
* When a block and a positive Integer argument +n+ are given, calls the block with each
@@ -7303,7 +7334,7 @@ rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
* [1, 2]
* [2, 2]
*
- * If +n+ is zero, calls the block once with an empty \Array.
+ * If +n+ is zero, calls the block once with an empty +Array+.
*
* If +n+ is negative, does not call the block:
*
@@ -7376,7 +7407,7 @@ rb_ary_repeated_combination(VALUE ary, VALUE num)
* including both +self+ and +other_arrays+.
* - The order of the returned combinations is indeterminate.
*
- * When no block is given, returns the combinations as an \Array of Arrays:
+ * When no block is given, returns the combinations as an +Array+ of Arrays:
*
* a = [0, 1, 2]
* a1 = [3, 4]
@@ -7388,14 +7419,14 @@ rb_ary_repeated_combination(VALUE ary, VALUE num)
* p.size # => 12 # a.size * a1.size * a2.size
* p # => [[0, 3, 5], [0, 3, 6], [0, 4, 5], [0, 4, 6], [1, 3, 5], [1, 3, 6], [1, 4, 5], [1, 4, 6], [2, 3, 5], [2, 3, 6], [2, 4, 5], [2, 4, 6]]
*
- * If any argument is an empty \Array, returns an empty \Array.
+ * If any argument is an empty +Array+, returns an empty +Array+.
*
- * If no argument is given, returns an \Array of 1-element Arrays,
+ * If no argument is given, returns an +Array+ of 1-element Arrays,
* each containing an element of +self+:
*
* a.product # => [[0], [1], [2]]
*
- * When a block is given, yields each combination as an \Array; returns +self+:
+ * When a block is given, yields each combination as an +Array+; returns +self+:
*
* a.product(a1) {|combination| p combination }
*
@@ -7408,11 +7439,11 @@ rb_ary_repeated_combination(VALUE ary, VALUE num)
* [2, 3]
* [2, 4]
*
- * If any argument is an empty \Array, does not call the block:
+ * If any argument is an empty +Array+, does not call the block:
*
* a.product(a1, a2, []) {|combination| fail 'Cannot happen' }
*
- * If no argument is given, yields each element of +self+ as a 1-element \Array:
+ * If no argument is given, yields each element of +self+ as a 1-element +Array+:
*
* a.product {|combination| p combination }
*
@@ -7516,7 +7547,7 @@ done:
* call-seq:
* array.take(n) -> new_array
*
- * Returns a new \Array containing the first +n+ element of +self+,
+ * Returns a new +Array+ containing the first +n+ element of +self+,
* where +n+ is a non-negative Integer;
* does not modify +self+.
*
@@ -7545,12 +7576,12 @@ rb_ary_take(VALUE obj, VALUE n)
* array.take_while {|element| ... } -> new_array
* array.take_while -> new_enumerator
*
- * Returns a new \Array containing zero or more leading elements of +self+;
+ * Returns a new +Array+ containing zero or more leading elements of +self+;
* does not modify +self+.
*
* With a block given, calls the block with each successive element of +self+;
* stops if the block returns +false+ or +nil+;
- * returns a new \Array containing those elements for which the block returned a truthy value:
+ * returns a new +Array+ containing those elements for which the block returned a truthy value:
*
* a = [0, 1, 2, 3, 4, 5]
* a.take_while {|element| element < 3 } # => [0, 1, 2]
@@ -7579,7 +7610,7 @@ rb_ary_take_while(VALUE ary)
* call-seq:
* array.drop(n) -> new_array
*
- * Returns a new \Array containing all but the first +n+ element of +self+,
+ * Returns a new +Array+ containing all but the first +n+ element of +self+,
* where +n+ is a non-negative Integer;
* does not modify +self+.
*
@@ -7611,12 +7642,12 @@ rb_ary_drop(VALUE ary, VALUE n)
* array.drop_while {|element| ... } -> new_array
* array.drop_while -> new_enumerator
- * Returns a new \Array containing zero or more trailing elements of +self+;
+ * Returns a new +Array+ containing zero or more trailing elements of +self+;
* does not modify +self+.
*
* With a block given, calls the block with each successive element of +self+;
* stops if the block returns +false+ or +nil+;
- * returns a new \Array _omitting_ those elements for which the block returned a truthy value:
+ * returns a new +Array+ _omitting_ those elements for which the block returned a truthy value:
*
* a = [0, 1, 2, 3, 4, 5]
* a.drop_while {|element| element < 3 } # => [3, 4, 5]
@@ -7978,7 +8009,7 @@ finish_exact_sum(long n, VALUE r, VALUE v, int z)
* Notes:
*
* - Array#join and Array#flatten may be faster than Array#sum
- * for an \Array of Strings or an \Array of Arrays.
+ * for an +Array+ of Strings or an +Array+ of Arrays.
* - Array#sum method may not respect method redefinition of "+" methods such as Integer#+.
*
*/
@@ -8100,6 +8131,7 @@ rb_ary_sum(int argc, VALUE *argv, VALUE ary)
return v;
}
+/* :nodoc: */
static VALUE
rb_ary_deconstruct(VALUE ary)
{
@@ -8107,13 +8139,13 @@ rb_ary_deconstruct(VALUE ary)
}
/*
- * An \Array is an ordered, integer-indexed collection of objects, called _elements_.
+ * An +Array+ is an ordered, integer-indexed collection of objects, called _elements_.
* Any object (even another array) may be an array element,
* and an array can contain objects of different types.
*
- * == \Array Indexes
+ * == +Array+ Indexes
*
- * \Array indexing starts at 0, as in C or Java.
+ * +Array+ indexing starts at 0, as in C or Java.
*
* A positive index is an offset from the first element:
*
@@ -8140,14 +8172,14 @@ rb_ary_deconstruct(VALUE ary)
* - Index -4 is out of range.
*
* Although the effective index into an array is always an integer,
- * some methods (both within and outside of class \Array)
+ * some methods (both within and outside of class +Array+)
* accept one or more non-integer arguments that are
* {integer-convertible objects}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
*
*
* == Creating Arrays
*
- * You can create an \Array object explicitly with:
+ * You can create an +Array+ object explicitly with:
*
* - An {array literal}[rdoc-ref:literals.rdoc@Array+Literals]:
*
@@ -8228,7 +8260,7 @@ rb_ary_deconstruct(VALUE ary)
* == Example Usage
*
* In addition to the methods it mixes in through the Enumerable module, the
- * \Array class has proprietary methods for accessing, searching and otherwise
+ * +Array+ class has proprietary methods for accessing, searching and otherwise
* manipulating arrays.
*
* Some of the more common ones are illustrated below.
@@ -8276,7 +8308,7 @@ rb_ary_deconstruct(VALUE ary)
*
* arr.drop(3) #=> [4, 5, 6]
*
- * == Obtaining Information about an \Array
+ * == Obtaining Information about an +Array+
*
* Arrays keep track of their own length at all times. To query an array
* about the number of elements it contains, use #length, #count or #size.
@@ -8314,7 +8346,7 @@ rb_ary_deconstruct(VALUE ary)
* arr.insert(3, 'orange', 'pear', 'grapefruit')
* #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
*
- * == Removing Items from an \Array
+ * == Removing Items from an +Array+
*
* The method #pop removes the last element in an array and returns it:
*
@@ -8356,9 +8388,9 @@ rb_ary_deconstruct(VALUE ary)
*
* == Iterating over Arrays
*
- * Like all classes that include the Enumerable module, \Array has an each
+ * Like all classes that include the Enumerable module, +Array+ has an each
* method, which defines what elements should be iterated over and how. In
- * case of Array's #each, all elements in the \Array instance are yielded to
+ * case of Array's #each, all elements in the +Array+ instance are yielded to
* the supplied block in sequence.
*
* Note that this operation leaves the array unchanged.
@@ -8385,7 +8417,7 @@ rb_ary_deconstruct(VALUE ary)
* arr #=> [1, 4, 9, 16, 25]
*
*
- * == Selecting Items from an \Array
+ * == Selecting Items from an +Array+
*
* Elements can be selected from an array according to criteria defined in a
* block. The selection can happen in a destructive or a non-destructive
@@ -8418,13 +8450,13 @@ rb_ary_deconstruct(VALUE ary)
*
* == What's Here
*
- * First, what's elsewhere. \Class \Array:
+ * First, what's elsewhere. \Class +Array+:
*
* - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
* - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
* which provides dozens of additional methods.
*
- * Here, class \Array provides methods that are useful for:
+ * Here, class +Array+ provides methods that are useful for:
*
* - {Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array]
* - {Querying}[rdoc-ref:Array@Methods+for+Querying]
@@ -8437,7 +8469,7 @@ rb_ary_deconstruct(VALUE ary)
* - {Converting}[rdoc-ref:Array@Methods+for+Converting]
* - {And more....}[rdoc-ref:Array@Other+Methods]
*
- * === Methods for Creating an \Array
+ * === Methods for Creating an +Array+
*
* - ::[]: Returns a new array populated with given objects.
* - ::new: Returns a new array.
@@ -8640,7 +8672,6 @@ Init_Array(void)
rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
rb_define_alias(rb_cArray, "prepend", "unshift");
rb_define_method(rb_cArray, "insert", rb_ary_insert, -1);
- rb_define_method(rb_cArray, "each", rb_ary_each, 0);
rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0);
rb_define_method(rb_cArray, "length", rb_ary_length, 0);
diff --git a/array.rb b/array.rb
index d17f374235..f63ff00056 100644
--- a/array.rb
+++ b/array.rb
@@ -1,5 +1,62 @@
class Array
# call-seq:
+ # array.each {|element| ... } -> self
+ # array.each -> Enumerator
+ #
+ # Iterates over array elements.
+ #
+ # When a block given, passes each successive array element to the block;
+ # returns +self+:
+ #
+ # a = [:foo, 'bar', 2]
+ # a.each {|element| puts "#{element.class} #{element}" }
+ #
+ # Output:
+ #
+ # Symbol foo
+ # String bar
+ # Integer 2
+ #
+ # Allows the array to be modified during iteration:
+ #
+ # a = [:foo, 'bar', 2]
+ # a.each {|element| puts element; a.clear if element.to_s.start_with?('b') }
+ #
+ # Output:
+ #
+ # foo
+ # bar
+ #
+ # When no block given, returns a new Enumerator:
+ # a = [:foo, 'bar', 2]
+ #
+ # e = a.each
+ # e # => #<Enumerator: [:foo, "bar", 2]:each>
+ # a1 = e.each {|element| puts "#{element.class} #{element}" }
+ #
+ # Output:
+ #
+ # Symbol foo
+ # String bar
+ # Integer 2
+ #
+ # Related: #each_index, #reverse_each.
+ def each
+ Primitive.attr! :inline_block
+ Primitive.attr! :use_block
+
+ unless defined?(yield)
+ return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
+ end
+ _i = 0
+ value = nil
+ while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) })
+ yield value
+ end
+ self
+ end
+
+ # call-seq:
# array.shuffle!(random: Random) -> array
#
# Shuffles the elements of +self+ in place.
@@ -39,7 +96,7 @@ class Array
# a.sample # => 8
# If +self+ is empty, returns +nil+.
#
- # When argument +n+ is given, returns a new \Array containing +n+ random
+ # When argument +n+ is given, returns a new +Array+ containing +n+ random
# elements from +self+:
# a.sample(3) # => [8, 9, 2]
# a.sample(6) # => [9, 6, 10, 3, 1, 4]
@@ -51,7 +108,7 @@ class Array
# a.sample(a.size * 2) # => [1, 1, 3, 2, 1, 2]
# The argument +n+ must be a non-negative numeric value.
# The order of the result array is unrelated to the order of +self+.
- # Returns a new empty \Array if +self+ is empty.
+ # Returns a new empty +Array+ if +self+ is empty.
#
# The optional +random+ argument will be used as the random number generator:
# a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
@@ -82,7 +139,7 @@ class Array
# If +self+ is empty, returns +nil+.
#
# When non-negative Integer argument +n+ is given,
- # returns the first +n+ elements in a new \Array:
+ # returns the first +n+ elements in a new +Array+:
#
# a = [:foo, 'bar', 2]
# a.first(2) # => [:foo, "bar"]
@@ -92,7 +149,7 @@ class Array
# a = [:foo, 'bar', 2]
# a.first(50) # => [:foo, "bar", 2]
#
- # If <tt>n == 0</tt> returns an new empty \Array:
+ # If <tt>n == 0</tt> returns an new empty +Array+:
#
# a = [:foo, 'bar', 2]
# a.first(0) # []
@@ -126,7 +183,7 @@ class Array
# If +self+ is empty, returns +nil+.
#
# When non-negative Integer argument +n+ is given,
- # returns the last +n+ elements in a new \Array:
+ # returns the last +n+ elements in a new +Array+:
#
# a = [:foo, 'bar', 2]
# a.last(2) # => ["bar", 2]
@@ -136,7 +193,7 @@ class Array
# a = [:foo, 'bar', 2]
# a.last(50) # => [:foo, "bar", 2]
#
- # If <tt>n == 0</tt>, returns an new empty \Array:
+ # If <tt>n == 0</tt>, returns an new empty +Array+:
#
# a = [:foo, 'bar', 2]
# a.last(0) # []
diff --git a/ast.c b/ast.c
index 50a54a9f4b..12b3996f94 100644
--- a/ast.c
+++ b/ast.c
@@ -16,7 +16,7 @@ static VALUE rb_mAST;
static VALUE rb_cNode;
struct ASTNodeData {
- rb_ast_t *ast;
+ VALUE ast_value;
const NODE *node;
};
@@ -24,14 +24,16 @@ static void
node_gc_mark(void *ptr)
{
struct ASTNodeData *data = (struct ASTNodeData *)ptr;
- rb_gc_mark((VALUE)data->ast);
+ rb_gc_mark(data->ast_value);
}
static size_t
node_memsize(const void *ptr)
{
struct ASTNodeData *data = (struct ASTNodeData *)ptr;
- return rb_ast_memsize(data->ast);
+ rb_ast_t *ast = rb_ruby_ast_data_get(data->ast_value);
+
+ return sizeof(struct ASTNodeData) + rb_ast_memsize(ast);
}
static const rb_data_type_t rb_node_type = {
@@ -44,22 +46,22 @@ static const rb_data_type_t rb_node_type = {
static VALUE rb_ast_node_alloc(VALUE klass);
static void
-setup_node(VALUE obj, rb_ast_t *ast, const NODE *node)
+setup_node(VALUE obj, VALUE ast_value, const NODE *node)
{
struct ASTNodeData *data;
TypedData_Get_Struct(obj, struct ASTNodeData, &rb_node_type, data);
- data->ast = ast;
+ data->ast_value = ast_value;
data->node = node;
}
static VALUE
-ast_new_internal(rb_ast_t *ast, const NODE *node)
+ast_new_internal(VALUE ast_value, const NODE *node)
{
VALUE obj;
obj = rb_ast_node_alloc(rb_cNode);
- setup_node(obj, ast, node);
+ setup_node(obj, ast_value, node);
return obj;
}
@@ -74,14 +76,16 @@ ast_parse_new(void)
}
static VALUE
-ast_parse_done(rb_ast_t *ast)
+ast_parse_done(VALUE ast_value)
{
+ rb_ast_t *ast = rb_ruby_ast_data_get(ast_value);
+
if (!ast->body.root) {
rb_ast_dispose(ast);
rb_exc_raise(GET_EC()->errinfo);
}
- return ast_new_internal(ast, (NODE *)ast->body.root);
+ return ast_new_internal(ast_value, (NODE *)ast->body.root);
}
static VALUE
@@ -93,15 +97,15 @@ ast_s_parse(rb_execution_context_t *ec, VALUE module, VALUE str, VALUE keep_scri
static VALUE
rb_ast_parse_str(VALUE str, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
{
- rb_ast_t *ast = 0;
+ VALUE ast_value;
StringValue(str);
VALUE vparser = ast_parse_new();
- if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser, Qtrue);
+ if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser);
if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser);
if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser);
- ast = rb_parser_compile_string_path(vparser, Qnil, str, 1);
- return ast_parse_done(ast);
+ ast_value = rb_parser_compile_string_path(vparser, Qnil, str, 1);
+ return ast_parse_done(ast_value);
}
static VALUE
@@ -114,48 +118,35 @@ static VALUE
rb_ast_parse_file(VALUE path, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
{
VALUE f;
- rb_ast_t *ast = 0;
+ VALUE ast_value = Qnil;
rb_encoding *enc = rb_utf8_encoding();
f = rb_file_open_str(path, "r");
rb_funcall(f, rb_intern("set_encoding"), 2, rb_enc_from_encoding(enc), rb_str_new_cstr("-"));
VALUE vparser = ast_parse_new();
- if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser, Qtrue);
+ if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser);
if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser);
if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser);
- ast = rb_parser_compile_file_path(vparser, Qnil, f, 1);
+ ast_value = rb_parser_compile_file_path(vparser, Qnil, f, 1);
rb_io_close(f);
- return ast_parse_done(ast);
-}
-
-static VALUE
-lex_array(VALUE array, int index)
-{
- VALUE str = rb_ary_entry(array, index);
- if (!NIL_P(str)) {
- StringValue(str);
- if (!rb_enc_asciicompat(rb_enc_get(str))) {
- rb_raise(rb_eArgError, "invalid source encoding");
- }
- }
- return str;
+ return ast_parse_done(ast_value);
}
static VALUE
rb_ast_parse_array(VALUE array, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
{
- rb_ast_t *ast = 0;
+ VALUE ast_value = Qnil;
array = rb_check_array_type(array);
VALUE vparser = ast_parse_new();
- if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser, Qtrue);
+ if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser);
if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser);
if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser);
- ast = rb_parser_compile_generic(vparser, lex_array, Qnil, array, 1);
- return ast_parse_done(ast);
+ ast_value = rb_parser_compile_array(vparser, Qnil, array, 1);
+ return ast_parse_done(ast_value);
}
-static VALUE node_children(rb_ast_t*, const NODE*);
+static VALUE node_children(VALUE, const NODE*);
static VALUE
node_find(VALUE self, const int node_id)
@@ -167,7 +158,7 @@ node_find(VALUE self, const int node_id)
if (nd_node_id(data->node) == node_id) return self;
- ary = node_children(data->ast, data->node);
+ ary = node_children(data->ast_value, data->node);
for (i = 0; i < RARRAY_LEN(ary); i++) {
VALUE child = RARRAY_AREF(ary, i);
@@ -183,29 +174,6 @@ node_find(VALUE self, const int node_id)
extern VALUE rb_e_script;
-VALUE
-rb_script_lines_for(VALUE path, bool add)
-{
- VALUE hash, lines;
- ID script_lines;
- CONST_ID(script_lines, "SCRIPT_LINES__");
- if (!rb_const_defined_at(rb_cObject, script_lines)) return Qnil;
- hash = rb_const_get_at(rb_cObject, script_lines);
- if (!RB_TYPE_P(hash, T_HASH)) return Qnil;
- if (add) {
- rb_hash_aset(hash, path, lines = rb_ary_new());
- }
- else if (!RB_TYPE_P((lines = rb_hash_lookup(hash, path)), T_ARRAY)) {
- return Qnil;
- }
- return lines;
-}
-static VALUE
-script_lines(VALUE path)
-{
- return rb_script_lines_for(path, false);
-}
-
static VALUE
node_id_for_backtrace_location(rb_execution_context_t *ec, VALUE module, VALUE location)
{
@@ -253,6 +221,11 @@ ast_s_of(rb_execution_context_t *ec, VALUE module, VALUE body, VALUE keep_script
if (!iseq) {
return Qnil;
}
+
+ if (ISEQ_BODY(iseq)->prism) {
+ rb_raise(rb_eRuntimeError, "cannot get AST for ISEQ compiled by prism");
+ }
+
lines = ISEQ_BODY(iseq)->variable.script_lines;
VALUE path = rb_iseq_path(iseq);
@@ -262,7 +235,7 @@ ast_s_of(rb_execution_context_t *ec, VALUE module, VALUE body, VALUE keep_script
rb_raise(rb_eArgError, "cannot get AST for method defined in eval");
}
- if (!NIL_P(lines) || !NIL_P(lines = script_lines(path))) {
+ if (!NIL_P(lines)) {
node = rb_ast_parse_array(lines, keep_script_lines, error_tolerant, keep_tokens);
}
else if (e_option) {
@@ -308,10 +281,10 @@ ast_node_node_id(rb_execution_context_t *ec, VALUE self)
return INT2FIX(nd_node_id(data->node));
}
-#define NEW_CHILD(ast, node) node ? ast_new_internal(ast, node) : Qnil
+#define NEW_CHILD(ast_value, node) (node ? ast_new_internal(ast_value, node) : Qnil)
static VALUE
-rb_ary_new_from_node_args(rb_ast_t *ast, long n, ...)
+rb_ary_new_from_node_args(VALUE ast_value, long n, ...)
{
va_list ar;
VALUE ary;
@@ -323,39 +296,39 @@ rb_ary_new_from_node_args(rb_ast_t *ast, long n, ...)
for (i=0; i<n; i++) {
NODE *node;
node = va_arg(ar, NODE *);
- rb_ary_push(ary, NEW_CHILD(ast, node));
+ rb_ary_push(ary, NEW_CHILD(ast_value, node));
}
va_end(ar);
return ary;
}
static VALUE
-dump_block(rb_ast_t *ast, const struct RNode_BLOCK *node)
+dump_block(VALUE ast_value, const struct RNode_BLOCK *node)
{
VALUE ary = rb_ary_new();
do {
- rb_ary_push(ary, NEW_CHILD(ast, node->nd_head));
+ rb_ary_push(ary, NEW_CHILD(ast_value, node->nd_head));
} while (node->nd_next &&
nd_type_p(node->nd_next, NODE_BLOCK) &&
(node = RNODE_BLOCK(node->nd_next), 1));
if (node->nd_next) {
- rb_ary_push(ary, NEW_CHILD(ast, node->nd_next));
+ rb_ary_push(ary, NEW_CHILD(ast_value, node->nd_next));
}
return ary;
}
static VALUE
-dump_array(rb_ast_t *ast, const struct RNode_LIST *node)
+dump_array(VALUE ast_value, const struct RNode_LIST *node)
{
VALUE ary = rb_ary_new();
- rb_ary_push(ary, NEW_CHILD(ast, node->nd_head));
+ rb_ary_push(ary, NEW_CHILD(ast_value, node->nd_head));
while (node->nd_next && nd_type_p(node->nd_next, NODE_LIST)) {
node = RNODE_LIST(node->nd_next);
- rb_ary_push(ary, NEW_CHILD(ast, node->nd_head));
+ rb_ary_push(ary, NEW_CHILD(ast_value, node->nd_head));
}
- rb_ary_push(ary, NEW_CHILD(ast, node->nd_next));
+ rb_ary_push(ary, NEW_CHILD(ast_value, node->nd_next));
return ary;
}
@@ -377,155 +350,155 @@ no_name_rest(void)
}
static VALUE
-rest_arg(rb_ast_t *ast, const NODE *rest_arg)
+rest_arg(VALUE ast_value, const NODE *rest_arg)
{
- return NODE_NAMED_REST_P(rest_arg) ? NEW_CHILD(ast, rest_arg) : no_name_rest();
+ return NODE_NAMED_REST_P(rest_arg) ? NEW_CHILD(ast_value, rest_arg) : no_name_rest();
}
static VALUE
-node_children(rb_ast_t *ast, const NODE *node)
+node_children(VALUE ast_value, const NODE *node)
{
char name[sizeof("$") + DECIMAL_SIZE_OF(long)];
enum node_type type = nd_type(node);
switch (type) {
case NODE_BLOCK:
- return dump_block(ast, RNODE_BLOCK(node));
+ return dump_block(ast_value, RNODE_BLOCK(node));
case NODE_IF:
- return rb_ary_new_from_node_args(ast, 3, RNODE_IF(node)->nd_cond, RNODE_IF(node)->nd_body, RNODE_IF(node)->nd_else);
+ return rb_ary_new_from_node_args(ast_value, 3, RNODE_IF(node)->nd_cond, RNODE_IF(node)->nd_body, RNODE_IF(node)->nd_else);
case NODE_UNLESS:
- return rb_ary_new_from_node_args(ast, 3, RNODE_UNLESS(node)->nd_cond, RNODE_UNLESS(node)->nd_body, RNODE_UNLESS(node)->nd_else);
+ return rb_ary_new_from_node_args(ast_value, 3, RNODE_UNLESS(node)->nd_cond, RNODE_UNLESS(node)->nd_body, RNODE_UNLESS(node)->nd_else);
case NODE_CASE:
- return rb_ary_new_from_node_args(ast, 2, RNODE_CASE(node)->nd_head, RNODE_CASE(node)->nd_body);
+ return rb_ary_new_from_node_args(ast_value, 2, RNODE_CASE(node)->nd_head, RNODE_CASE(node)->nd_body);
case NODE_CASE2:
- return rb_ary_new_from_node_args(ast, 2, RNODE_CASE2(node)->nd_head, RNODE_CASE2(node)->nd_body);
+ return rb_ary_new_from_node_args(ast_value, 2, RNODE_CASE2(node)->nd_head, RNODE_CASE2(node)->nd_body);
case NODE_CASE3:
- return rb_ary_new_from_node_args(ast, 2, RNODE_CASE3(node)->nd_head, RNODE_CASE3(node)->nd_body);
+ return rb_ary_new_from_node_args(ast_value, 2, RNODE_CASE3(node)->nd_head, RNODE_CASE3(node)->nd_body);
case NODE_WHEN:
- return rb_ary_new_from_node_args(ast, 3, RNODE_WHEN(node)->nd_head, RNODE_WHEN(node)->nd_body, RNODE_WHEN(node)->nd_next);
+ return rb_ary_new_from_node_args(ast_value, 3, RNODE_WHEN(node)->nd_head, RNODE_WHEN(node)->nd_body, RNODE_WHEN(node)->nd_next);
case NODE_IN:
- return rb_ary_new_from_node_args(ast, 3, RNODE_IN(node)->nd_head, RNODE_IN(node)->nd_body, RNODE_IN(node)->nd_next);
+ return rb_ary_new_from_node_args(ast_value, 3, RNODE_IN(node)->nd_head, RNODE_IN(node)->nd_body, RNODE_IN(node)->nd_next);
case NODE_WHILE:
case NODE_UNTIL:
- return rb_ary_push(rb_ary_new_from_node_args(ast, 2, RNODE_WHILE(node)->nd_cond, RNODE_WHILE(node)->nd_body),
+ return rb_ary_push(rb_ary_new_from_node_args(ast_value, 2, RNODE_WHILE(node)->nd_cond, RNODE_WHILE(node)->nd_body),
RBOOL(RNODE_WHILE(node)->nd_state));
case NODE_ITER:
case NODE_FOR:
- return rb_ary_new_from_node_args(ast, 2, RNODE_ITER(node)->nd_iter, RNODE_ITER(node)->nd_body);
+ return rb_ary_new_from_node_args(ast_value, 2, RNODE_ITER(node)->nd_iter, RNODE_ITER(node)->nd_body);
case NODE_FOR_MASGN:
- return rb_ary_new_from_node_args(ast, 1, RNODE_FOR_MASGN(node)->nd_var);
+ return rb_ary_new_from_node_args(ast_value, 1, RNODE_FOR_MASGN(node)->nd_var);
case NODE_BREAK:
- return rb_ary_new_from_node_args(ast, 1, RNODE_BREAK(node)->nd_stts);
+ return rb_ary_new_from_node_args(ast_value, 1, RNODE_BREAK(node)->nd_stts);
case NODE_NEXT:
- return rb_ary_new_from_node_args(ast, 1, RNODE_NEXT(node)->nd_stts);
+ return rb_ary_new_from_node_args(ast_value, 1, RNODE_NEXT(node)->nd_stts);
case NODE_RETURN:
- return rb_ary_new_from_node_args(ast, 1, RNODE_RETURN(node)->nd_stts);
+ return rb_ary_new_from_node_args(ast_value, 1, RNODE_RETURN(node)->nd_stts);
case NODE_REDO:
- return rb_ary_new_from_node_args(ast, 0);
+ return rb_ary_new_from_node_args(ast_value, 0);
case NODE_RETRY:
- return rb_ary_new_from_node_args(ast, 0);
+ return rb_ary_new_from_node_args(ast_value, 0);
case NODE_BEGIN:
- return rb_ary_new_from_node_args(ast, 1, RNODE_BEGIN(node)->nd_body);
+ return rb_ary_new_from_node_args(ast_value, 1, RNODE_BEGIN(node)->nd_body);
case NODE_RESCUE:
- return rb_ary_new_from_node_args(ast, 3, RNODE_RESCUE(node)->nd_head, RNODE_RESCUE(node)->nd_resq, RNODE_RESCUE(node)->nd_else);
+ return rb_ary_new_from_node_args(ast_value, 3, RNODE_RESCUE(node)->nd_head, RNODE_RESCUE(node)->nd_resq, RNODE_RESCUE(node)->nd_else);
case NODE_RESBODY:
- return rb_ary_new_from_node_args(ast, 3, RNODE_RESBODY(node)->nd_args, RNODE_RESBODY(node)->nd_body, RNODE_RESBODY(node)->nd_head);
+ return rb_ary_new_from_node_args(ast_value, 3, RNODE_RESBODY(node)->nd_args, RNODE_RESBODY(node)->nd_body, RNODE_RESBODY(node)->nd_next);
case NODE_ENSURE:
- return rb_ary_new_from_node_args(ast, 2, RNODE_ENSURE(node)->nd_head, RNODE_ENSURE(node)->nd_ensr);
+ return rb_ary_new_from_node_args(ast_value, 2, RNODE_ENSURE(node)->nd_head, RNODE_ENSURE(node)->nd_ensr);
case NODE_AND:
case NODE_OR:
{
VALUE ary = rb_ary_new();
while (1) {
- rb_ary_push(ary, NEW_CHILD(ast, RNODE_AND(node)->nd_1st));
+ rb_ary_push(ary, NEW_CHILD(ast_value, RNODE_AND(node)->nd_1st));
if (!RNODE_AND(node)->nd_2nd || !nd_type_p(RNODE_AND(node)->nd_2nd, type))
break;
node = RNODE_AND(node)->nd_2nd;
}
- rb_ary_push(ary, NEW_CHILD(ast, RNODE_AND(node)->nd_2nd));
+ rb_ary_push(ary, NEW_CHILD(ast_value, RNODE_AND(node)->nd_2nd));
return ary;
}
case NODE_MASGN:
if (NODE_NAMED_REST_P(RNODE_MASGN(node)->nd_args)) {
- return rb_ary_new_from_node_args(ast, 3, RNODE_MASGN(node)->nd_value, RNODE_MASGN(node)->nd_head, RNODE_MASGN(node)->nd_args);
+ return rb_ary_new_from_node_args(ast_value, 3, RNODE_MASGN(node)->nd_value, RNODE_MASGN(node)->nd_head, RNODE_MASGN(node)->nd_args);
}
else {
- return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_MASGN(node)->nd_value),
- NEW_CHILD(ast, RNODE_MASGN(node)->nd_head),
+ return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_MASGN(node)->nd_value),
+ NEW_CHILD(ast_value, RNODE_MASGN(node)->nd_head),
no_name_rest());
}
case NODE_LASGN:
if (NODE_REQUIRED_KEYWORD_P(RNODE_LASGN(node)->nd_value)) {
return rb_ary_new_from_args(2, var_name(RNODE_LASGN(node)->nd_vid), ID2SYM(rb_intern("NODE_SPECIAL_REQUIRED_KEYWORD")));
}
- return rb_ary_new_from_args(2, var_name(RNODE_LASGN(node)->nd_vid), NEW_CHILD(ast, RNODE_LASGN(node)->nd_value));
+ return rb_ary_new_from_args(2, var_name(RNODE_LASGN(node)->nd_vid), NEW_CHILD(ast_value, RNODE_LASGN(node)->nd_value));
case NODE_DASGN:
if (NODE_REQUIRED_KEYWORD_P(RNODE_DASGN(node)->nd_value)) {
return rb_ary_new_from_args(2, var_name(RNODE_DASGN(node)->nd_vid), ID2SYM(rb_intern("NODE_SPECIAL_REQUIRED_KEYWORD")));
}
- return rb_ary_new_from_args(2, var_name(RNODE_DASGN(node)->nd_vid), NEW_CHILD(ast, RNODE_DASGN(node)->nd_value));
+ return rb_ary_new_from_args(2, var_name(RNODE_DASGN(node)->nd_vid), NEW_CHILD(ast_value, RNODE_DASGN(node)->nd_value));
case NODE_IASGN:
- return rb_ary_new_from_args(2, var_name(RNODE_IASGN(node)->nd_vid), NEW_CHILD(ast, RNODE_IASGN(node)->nd_value));
+ return rb_ary_new_from_args(2, var_name(RNODE_IASGN(node)->nd_vid), NEW_CHILD(ast_value, RNODE_IASGN(node)->nd_value));
case NODE_CVASGN:
- return rb_ary_new_from_args(2, var_name(RNODE_CVASGN(node)->nd_vid), NEW_CHILD(ast, RNODE_CVASGN(node)->nd_value));
+ return rb_ary_new_from_args(2, var_name(RNODE_CVASGN(node)->nd_vid), NEW_CHILD(ast_value, RNODE_CVASGN(node)->nd_value));
case NODE_GASGN:
- return rb_ary_new_from_args(2, var_name(RNODE_GASGN(node)->nd_vid), NEW_CHILD(ast, RNODE_GASGN(node)->nd_value));
+ return rb_ary_new_from_args(2, var_name(RNODE_GASGN(node)->nd_vid), NEW_CHILD(ast_value, RNODE_GASGN(node)->nd_value));
case NODE_CDECL:
if (RNODE_CDECL(node)->nd_vid) {
- return rb_ary_new_from_args(2, ID2SYM(RNODE_CDECL(node)->nd_vid), NEW_CHILD(ast, RNODE_CDECL(node)->nd_value));
+ return rb_ary_new_from_args(2, ID2SYM(RNODE_CDECL(node)->nd_vid), NEW_CHILD(ast_value, RNODE_CDECL(node)->nd_value));
}
- return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_CDECL(node)->nd_else), ID2SYM(RNODE_COLON2(RNODE_CDECL(node)->nd_else)->nd_mid), NEW_CHILD(ast, RNODE_CDECL(node)->nd_value));
+ return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_CDECL(node)->nd_else), ID2SYM(RNODE_COLON2(RNODE_CDECL(node)->nd_else)->nd_mid), NEW_CHILD(ast_value, RNODE_CDECL(node)->nd_value));
case NODE_OP_ASGN1:
- return rb_ary_new_from_args(4, NEW_CHILD(ast, RNODE_OP_ASGN1(node)->nd_recv),
+ return rb_ary_new_from_args(4, NEW_CHILD(ast_value, RNODE_OP_ASGN1(node)->nd_recv),
ID2SYM(RNODE_OP_ASGN1(node)->nd_mid),
- NEW_CHILD(ast, RNODE_OP_ASGN1(node)->nd_index),
- NEW_CHILD(ast, RNODE_OP_ASGN1(node)->nd_rvalue));
+ NEW_CHILD(ast_value, RNODE_OP_ASGN1(node)->nd_index),
+ NEW_CHILD(ast_value, RNODE_OP_ASGN1(node)->nd_rvalue));
case NODE_OP_ASGN2:
- return rb_ary_new_from_args(5, NEW_CHILD(ast, RNODE_OP_ASGN2(node)->nd_recv),
+ return rb_ary_new_from_args(5, NEW_CHILD(ast_value, RNODE_OP_ASGN2(node)->nd_recv),
RBOOL(RNODE_OP_ASGN2(node)->nd_aid),
ID2SYM(RNODE_OP_ASGN2(node)->nd_vid),
ID2SYM(RNODE_OP_ASGN2(node)->nd_mid),
- NEW_CHILD(ast, RNODE_OP_ASGN2(node)->nd_value));
+ NEW_CHILD(ast_value, RNODE_OP_ASGN2(node)->nd_value));
case NODE_OP_ASGN_AND:
- return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_OP_ASGN_AND(node)->nd_head), ID2SYM(idANDOP),
- NEW_CHILD(ast, RNODE_OP_ASGN_AND(node)->nd_value));
+ return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_OP_ASGN_AND(node)->nd_head), ID2SYM(idANDOP),
+ NEW_CHILD(ast_value, RNODE_OP_ASGN_AND(node)->nd_value));
case NODE_OP_ASGN_OR:
- return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_OP_ASGN_OR(node)->nd_head), ID2SYM(idOROP),
- NEW_CHILD(ast, RNODE_OP_ASGN_OR(node)->nd_value));
+ return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_OP_ASGN_OR(node)->nd_head), ID2SYM(idOROP),
+ NEW_CHILD(ast_value, RNODE_OP_ASGN_OR(node)->nd_value));
case NODE_OP_CDECL:
- return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_OP_CDECL(node)->nd_head),
+ return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_OP_CDECL(node)->nd_head),
ID2SYM(RNODE_OP_CDECL(node)->nd_aid),
- NEW_CHILD(ast, RNODE_OP_CDECL(node)->nd_value));
+ NEW_CHILD(ast_value, RNODE_OP_CDECL(node)->nd_value));
case NODE_CALL:
- return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_CALL(node)->nd_recv),
+ return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_CALL(node)->nd_recv),
ID2SYM(RNODE_CALL(node)->nd_mid),
- NEW_CHILD(ast, RNODE_CALL(node)->nd_args));
+ NEW_CHILD(ast_value, RNODE_CALL(node)->nd_args));
case NODE_OPCALL:
- return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_OPCALL(node)->nd_recv),
+ return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_OPCALL(node)->nd_recv),
ID2SYM(RNODE_OPCALL(node)->nd_mid),
- NEW_CHILD(ast, RNODE_OPCALL(node)->nd_args));
+ NEW_CHILD(ast_value, RNODE_OPCALL(node)->nd_args));
case NODE_QCALL:
- return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_QCALL(node)->nd_recv),
+ return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_QCALL(node)->nd_recv),
ID2SYM(RNODE_QCALL(node)->nd_mid),
- NEW_CHILD(ast, RNODE_QCALL(node)->nd_args));
+ NEW_CHILD(ast_value, RNODE_QCALL(node)->nd_args));
case NODE_FCALL:
return rb_ary_new_from_args(2, ID2SYM(RNODE_FCALL(node)->nd_mid),
- NEW_CHILD(ast, RNODE_FCALL(node)->nd_args));
+ NEW_CHILD(ast_value, RNODE_FCALL(node)->nd_args));
case NODE_VCALL:
return rb_ary_new_from_args(1, ID2SYM(RNODE_VCALL(node)->nd_mid));
case NODE_SUPER:
- return rb_ary_new_from_node_args(ast, 1, RNODE_SUPER(node)->nd_args);
+ return rb_ary_new_from_node_args(ast_value, 1, RNODE_SUPER(node)->nd_args);
case NODE_ZSUPER:
- return rb_ary_new_from_node_args(ast, 0);
+ return rb_ary_new_from_node_args(ast_value, 0);
case NODE_LIST:
- return dump_array(ast, RNODE_LIST(node));
+ return dump_array(ast_value, RNODE_LIST(node));
case NODE_ZLIST:
- return rb_ary_new_from_node_args(ast, 0);
+ return rb_ary_new_from_node_args(ast_value, 0);
case NODE_HASH:
- return rb_ary_new_from_node_args(ast, 1, RNODE_HASH(node)->nd_head);
+ return rb_ary_new_from_node_args(ast_value, 1, RNODE_HASH(node)->nd_head);
case NODE_YIELD:
- return rb_ary_new_from_node_args(ast, 1, RNODE_YIELD(node)->nd_head);
+ return rb_ary_new_from_node_args(ast_value, 1, RNODE_YIELD(node)->nd_head);
case NODE_LVAR:
return rb_ary_new_from_args(1, var_name(RNODE_LVAR(node)->nd_vid));
case NODE_DVAR:
@@ -546,20 +519,30 @@ node_children(rb_ast_t *ast, const NODE *node)
name[1] = (char)RNODE_BACK_REF(node)->nd_nth;
name[2] = '\0';
return rb_ary_new_from_args(1, ID2SYM(rb_intern(name)));
+ case NODE_MATCH:
+ return rb_ary_new_from_args(1, rb_node_regx_string_val(node));
case NODE_MATCH2:
if (RNODE_MATCH2(node)->nd_args) {
- return rb_ary_new_from_node_args(ast, 3, RNODE_MATCH2(node)->nd_recv, RNODE_MATCH2(node)->nd_value, RNODE_MATCH2(node)->nd_args);
+ return rb_ary_new_from_node_args(ast_value, 3, RNODE_MATCH2(node)->nd_recv, RNODE_MATCH2(node)->nd_value, RNODE_MATCH2(node)->nd_args);
}
- return rb_ary_new_from_node_args(ast, 2, RNODE_MATCH2(node)->nd_recv, RNODE_MATCH2(node)->nd_value);
+ return rb_ary_new_from_node_args(ast_value, 2, RNODE_MATCH2(node)->nd_recv, RNODE_MATCH2(node)->nd_value);
case NODE_MATCH3:
- return rb_ary_new_from_node_args(ast, 2, RNODE_MATCH3(node)->nd_recv, RNODE_MATCH3(node)->nd_value);
- case NODE_MATCH:
- case NODE_LIT:
+ return rb_ary_new_from_node_args(ast_value, 2, RNODE_MATCH3(node)->nd_recv, RNODE_MATCH3(node)->nd_value);
case NODE_STR:
case NODE_XSTR:
- return rb_ary_new_from_args(1, RNODE_LIT(node)->nd_lit);
+ return rb_ary_new_from_args(1, rb_node_str_string_val(node));
+ case NODE_INTEGER:
+ return rb_ary_new_from_args(1, rb_node_integer_literal_val(node));
+ case NODE_FLOAT:
+ return rb_ary_new_from_args(1, rb_node_float_literal_val(node));
+ case NODE_RATIONAL:
+ return rb_ary_new_from_args(1, rb_node_rational_literal_val(node));
+ case NODE_IMAGINARY:
+ return rb_ary_new_from_args(1, rb_node_imaginary_literal_val(node));
+ case NODE_REGX:
+ return rb_ary_new_from_args(1, rb_node_regx_string_val(node));
case NODE_ONCE:
- return rb_ary_new_from_node_args(ast, 1, RNODE_ONCE(node)->nd_body);
+ return rb_ary_new_from_node_args(ast_value, 1, RNODE_ONCE(node)->nd_body);
case NODE_DSTR:
case NODE_DXSTR:
case NODE_DREGX:
@@ -568,89 +551,91 @@ node_children(rb_ast_t *ast, const NODE *node)
struct RNode_LIST *n = RNODE_DSTR(node)->nd_next;
VALUE head = Qnil, next = Qnil;
if (n) {
- head = NEW_CHILD(ast, n->nd_head);
- next = NEW_CHILD(ast, n->nd_next);
+ head = NEW_CHILD(ast_value, n->nd_head);
+ next = NEW_CHILD(ast_value, n->nd_next);
}
- return rb_ary_new_from_args(3, RNODE_DSTR(node)->nd_lit, head, next);
+ return rb_ary_new_from_args(3, rb_node_dstr_string_val(node), head, next);
}
+ case NODE_SYM:
+ return rb_ary_new_from_args(1, rb_node_sym_string_val(node));
case NODE_EVSTR:
- return rb_ary_new_from_node_args(ast, 1, RNODE_EVSTR(node)->nd_body);
+ return rb_ary_new_from_node_args(ast_value, 1, RNODE_EVSTR(node)->nd_body);
case NODE_ARGSCAT:
- return rb_ary_new_from_node_args(ast, 2, RNODE_ARGSCAT(node)->nd_head, RNODE_ARGSCAT(node)->nd_body);
+ return rb_ary_new_from_node_args(ast_value, 2, RNODE_ARGSCAT(node)->nd_head, RNODE_ARGSCAT(node)->nd_body);
case NODE_ARGSPUSH:
- return rb_ary_new_from_node_args(ast, 2, RNODE_ARGSPUSH(node)->nd_head, RNODE_ARGSPUSH(node)->nd_body);
+ return rb_ary_new_from_node_args(ast_value, 2, RNODE_ARGSPUSH(node)->nd_head, RNODE_ARGSPUSH(node)->nd_body);
case NODE_SPLAT:
- return rb_ary_new_from_node_args(ast, 1, RNODE_SPLAT(node)->nd_head);
+ return rb_ary_new_from_node_args(ast_value, 1, RNODE_SPLAT(node)->nd_head);
case NODE_BLOCK_PASS:
- return rb_ary_new_from_node_args(ast, 2, RNODE_BLOCK_PASS(node)->nd_head, RNODE_BLOCK_PASS(node)->nd_body);
+ return rb_ary_new_from_node_args(ast_value, 2, RNODE_BLOCK_PASS(node)->nd_head, RNODE_BLOCK_PASS(node)->nd_body);
case NODE_DEFN:
- return rb_ary_new_from_args(2, ID2SYM(RNODE_DEFN(node)->nd_mid), NEW_CHILD(ast, RNODE_DEFN(node)->nd_defn));
+ return rb_ary_new_from_args(2, ID2SYM(RNODE_DEFN(node)->nd_mid), NEW_CHILD(ast_value, RNODE_DEFN(node)->nd_defn));
case NODE_DEFS:
- return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_DEFS(node)->nd_recv), ID2SYM(RNODE_DEFS(node)->nd_mid), NEW_CHILD(ast, RNODE_DEFS(node)->nd_defn));
+ return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_DEFS(node)->nd_recv), ID2SYM(RNODE_DEFS(node)->nd_mid), NEW_CHILD(ast_value, RNODE_DEFS(node)->nd_defn));
case NODE_ALIAS:
- return rb_ary_new_from_node_args(ast, 2, RNODE_ALIAS(node)->nd_1st, RNODE_ALIAS(node)->nd_2nd);
+ return rb_ary_new_from_node_args(ast_value, 2, RNODE_ALIAS(node)->nd_1st, RNODE_ALIAS(node)->nd_2nd);
case NODE_VALIAS:
return rb_ary_new_from_args(2, ID2SYM(RNODE_VALIAS(node)->nd_alias), ID2SYM(RNODE_VALIAS(node)->nd_orig));
case NODE_UNDEF:
- return rb_ary_new_from_node_args(ast, 1, RNODE_UNDEF(node)->nd_undef);
+ return rb_ary_new_from_node_args(ast_value, 1, RNODE_UNDEF(node)->nd_undef);
case NODE_CLASS:
- return rb_ary_new_from_node_args(ast, 3, RNODE_CLASS(node)->nd_cpath, RNODE_CLASS(node)->nd_super, RNODE_CLASS(node)->nd_body);
+ return rb_ary_new_from_node_args(ast_value, 3, RNODE_CLASS(node)->nd_cpath, RNODE_CLASS(node)->nd_super, RNODE_CLASS(node)->nd_body);
case NODE_MODULE:
- return rb_ary_new_from_node_args(ast, 2, RNODE_MODULE(node)->nd_cpath, RNODE_MODULE(node)->nd_body);
+ return rb_ary_new_from_node_args(ast_value, 2, RNODE_MODULE(node)->nd_cpath, RNODE_MODULE(node)->nd_body);
case NODE_SCLASS:
- return rb_ary_new_from_node_args(ast, 2, RNODE_SCLASS(node)->nd_recv, RNODE_SCLASS(node)->nd_body);
+ return rb_ary_new_from_node_args(ast_value, 2, RNODE_SCLASS(node)->nd_recv, RNODE_SCLASS(node)->nd_body);
case NODE_COLON2:
- return rb_ary_new_from_args(2, NEW_CHILD(ast, RNODE_COLON2(node)->nd_head), ID2SYM(RNODE_COLON2(node)->nd_mid));
+ return rb_ary_new_from_args(2, NEW_CHILD(ast_value, RNODE_COLON2(node)->nd_head), ID2SYM(RNODE_COLON2(node)->nd_mid));
case NODE_COLON3:
return rb_ary_new_from_args(1, ID2SYM(RNODE_COLON3(node)->nd_mid));
case NODE_DOT2:
case NODE_DOT3:
case NODE_FLIP2:
case NODE_FLIP3:
- return rb_ary_new_from_node_args(ast, 2, RNODE_DOT2(node)->nd_beg, RNODE_DOT2(node)->nd_end);
+ return rb_ary_new_from_node_args(ast_value, 2, RNODE_DOT2(node)->nd_beg, RNODE_DOT2(node)->nd_end);
case NODE_SELF:
- return rb_ary_new_from_node_args(ast, 0);
+ return rb_ary_new_from_node_args(ast_value, 0);
case NODE_NIL:
- return rb_ary_new_from_node_args(ast, 0);
+ return rb_ary_new_from_node_args(ast_value, 0);
case NODE_TRUE:
- return rb_ary_new_from_node_args(ast, 0);
+ return rb_ary_new_from_node_args(ast_value, 0);
case NODE_FALSE:
- return rb_ary_new_from_node_args(ast, 0);
+ return rb_ary_new_from_node_args(ast_value, 0);
case NODE_ERRINFO:
- return rb_ary_new_from_node_args(ast, 0);
+ return rb_ary_new_from_node_args(ast_value, 0);
case NODE_DEFINED:
- return rb_ary_new_from_node_args(ast, 1, RNODE_DEFINED(node)->nd_head);
+ return rb_ary_new_from_node_args(ast_value, 1, RNODE_DEFINED(node)->nd_head);
case NODE_POSTEXE:
- return rb_ary_new_from_node_args(ast, 1, RNODE_POSTEXE(node)->nd_body);
+ return rb_ary_new_from_node_args(ast_value, 1, RNODE_POSTEXE(node)->nd_body);
case NODE_ATTRASGN:
- return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_ATTRASGN(node)->nd_recv), ID2SYM(RNODE_ATTRASGN(node)->nd_mid), NEW_CHILD(ast, RNODE_ATTRASGN(node)->nd_args));
+ return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_ATTRASGN(node)->nd_recv), ID2SYM(RNODE_ATTRASGN(node)->nd_mid), NEW_CHILD(ast_value, RNODE_ATTRASGN(node)->nd_args));
case NODE_LAMBDA:
- return rb_ary_new_from_node_args(ast, 1, RNODE_LAMBDA(node)->nd_body);
+ return rb_ary_new_from_node_args(ast_value, 1, RNODE_LAMBDA(node)->nd_body);
case NODE_OPT_ARG:
- return rb_ary_new_from_node_args(ast, 2, RNODE_OPT_ARG(node)->nd_body, RNODE_OPT_ARG(node)->nd_next);
+ return rb_ary_new_from_node_args(ast_value, 2, RNODE_OPT_ARG(node)->nd_body, RNODE_OPT_ARG(node)->nd_next);
case NODE_KW_ARG:
- return rb_ary_new_from_node_args(ast, 2, RNODE_KW_ARG(node)->nd_body, RNODE_KW_ARG(node)->nd_next);
+ return rb_ary_new_from_node_args(ast_value, 2, RNODE_KW_ARG(node)->nd_body, RNODE_KW_ARG(node)->nd_next);
case NODE_POSTARG:
if (NODE_NAMED_REST_P(RNODE_POSTARG(node)->nd_1st)) {
- return rb_ary_new_from_node_args(ast, 2, RNODE_POSTARG(node)->nd_1st, RNODE_POSTARG(node)->nd_2nd);
+ return rb_ary_new_from_node_args(ast_value, 2, RNODE_POSTARG(node)->nd_1st, RNODE_POSTARG(node)->nd_2nd);
}
return rb_ary_new_from_args(2, no_name_rest(),
- NEW_CHILD(ast, RNODE_POSTARG(node)->nd_2nd));
+ NEW_CHILD(ast_value, RNODE_POSTARG(node)->nd_2nd));
case NODE_ARGS:
{
struct rb_args_info *ainfo = &RNODE_ARGS(node)->nd_ainfo;
return rb_ary_new_from_args(10,
INT2NUM(ainfo->pre_args_num),
- NEW_CHILD(ast, ainfo->pre_init),
- NEW_CHILD(ast, (NODE *)ainfo->opt_args),
+ NEW_CHILD(ast_value, ainfo->pre_init),
+ NEW_CHILD(ast_value, (NODE *)ainfo->opt_args),
var_name(ainfo->first_post_arg),
INT2NUM(ainfo->post_args_num),
- NEW_CHILD(ast, ainfo->post_init),
+ NEW_CHILD(ast_value, ainfo->post_init),
(ainfo->rest_arg == NODE_SPECIAL_EXCESSIVE_COMMA
? ID2SYM(rb_intern("NODE_SPECIAL_EXCESSIVE_COMMA"))
: var_name(ainfo->rest_arg)),
- (ainfo->no_kwarg ? Qfalse : NEW_CHILD(ast, (NODE *)ainfo->kw_args)),
- (ainfo->no_kwarg ? Qfalse : NEW_CHILD(ast, ainfo->kw_rest_arg)),
+ (ainfo->no_kwarg ? Qfalse : NEW_CHILD(ast_value, (NODE *)ainfo->kw_args)),
+ (ainfo->no_kwarg ? Qfalse : NEW_CHILD(ast_value, ainfo->kw_rest_arg)),
var_name(ainfo->block_arg));
}
case NODE_SCOPE:
@@ -661,42 +646,46 @@ node_children(rb_ast_t *ast, const NODE *node)
for (i = 0; i < size; i++) {
rb_ary_push(locals, var_name(tbl->ids[i]));
}
- return rb_ary_new_from_args(3, locals, NEW_CHILD(ast, (NODE *)RNODE_SCOPE(node)->nd_args), NEW_CHILD(ast, RNODE_SCOPE(node)->nd_body));
+ return rb_ary_new_from_args(3, locals, NEW_CHILD(ast_value, (NODE *)RNODE_SCOPE(node)->nd_args), NEW_CHILD(ast_value, RNODE_SCOPE(node)->nd_body));
}
case NODE_ARYPTN:
{
- VALUE rest = rest_arg(ast, RNODE_ARYPTN(node)->rest_arg);
+ VALUE rest = rest_arg(ast_value, RNODE_ARYPTN(node)->rest_arg);
return rb_ary_new_from_args(4,
- NEW_CHILD(ast, RNODE_ARYPTN(node)->nd_pconst),
- NEW_CHILD(ast, RNODE_ARYPTN(node)->pre_args),
+ NEW_CHILD(ast_value, RNODE_ARYPTN(node)->nd_pconst),
+ NEW_CHILD(ast_value, RNODE_ARYPTN(node)->pre_args),
rest,
- NEW_CHILD(ast, RNODE_ARYPTN(node)->post_args));
+ NEW_CHILD(ast_value, RNODE_ARYPTN(node)->post_args));
}
case NODE_FNDPTN:
{
- VALUE pre_rest = rest_arg(ast, RNODE_FNDPTN(node)->pre_rest_arg);
- VALUE post_rest = rest_arg(ast, RNODE_FNDPTN(node)->post_rest_arg);
+ VALUE pre_rest = rest_arg(ast_value, RNODE_FNDPTN(node)->pre_rest_arg);
+ VALUE post_rest = rest_arg(ast_value, RNODE_FNDPTN(node)->post_rest_arg);
return rb_ary_new_from_args(4,
- NEW_CHILD(ast, RNODE_FNDPTN(node)->nd_pconst),
+ NEW_CHILD(ast_value, RNODE_FNDPTN(node)->nd_pconst),
pre_rest,
- NEW_CHILD(ast, RNODE_FNDPTN(node)->args),
+ NEW_CHILD(ast_value, RNODE_FNDPTN(node)->args),
post_rest);
}
case NODE_HSHPTN:
{
VALUE kwrest = RNODE_HSHPTN(node)->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD ? ID2SYM(rb_intern("NODE_SPECIAL_NO_REST_KEYWORD")) :
- NEW_CHILD(ast, RNODE_HSHPTN(node)->nd_pkwrestarg);
+ NEW_CHILD(ast_value, RNODE_HSHPTN(node)->nd_pkwrestarg);
return rb_ary_new_from_args(3,
- NEW_CHILD(ast, RNODE_HSHPTN(node)->nd_pconst),
- NEW_CHILD(ast, RNODE_HSHPTN(node)->nd_pkwargs),
+ NEW_CHILD(ast_value, RNODE_HSHPTN(node)->nd_pconst),
+ NEW_CHILD(ast_value, RNODE_HSHPTN(node)->nd_pkwargs),
kwrest);
}
+ case NODE_LINE:
+ return rb_ary_new_from_args(1, rb_node_line_lineno_val(node));
+ case NODE_FILE:
+ return rb_ary_new_from_args(1, rb_node_file_path_val(node));
+ case NODE_ENCODING:
+ return rb_ary_new_from_args(1, rb_node_encoding_val(node));
case NODE_ERROR:
- return rb_ary_new_from_node_args(ast, 0);
+ return rb_ary_new_from_node_args(ast_value, 0);
case NODE_ARGS_AUX:
- case NODE_RIPPER:
- case NODE_RIPPER_VALUES:
case NODE_LAST:
break;
}
@@ -710,7 +699,7 @@ ast_node_children(rb_execution_context_t *ec, VALUE self)
struct ASTNodeData *data;
TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
- return node_children(data->ast, data->node);
+ return node_children(data->ast_value, data->node);
}
static VALUE
@@ -752,10 +741,37 @@ ast_node_last_column(rb_execution_context_t *ec, VALUE self)
static VALUE
ast_node_all_tokens(rb_execution_context_t *ec, VALUE self)
{
+ long i;
struct ASTNodeData *data;
+ rb_ast_t *ast;
+ rb_parser_ary_t *parser_tokens;
+ rb_parser_ast_token_t *parser_token;
+ VALUE str, loc, token, all_tokens;
+
TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
+ ast = rb_ruby_ast_data_get(data->ast_value);
+
+ parser_tokens = ast->node_buffer->tokens;
+ if (parser_tokens == NULL) {
+ return Qnil;
+ }
+
+ all_tokens = rb_ary_new2(parser_tokens->len);
+ for (i = 0; i < parser_tokens->len; i++) {
+ parser_token = parser_tokens->data[i];
+ str = rb_str_new(parser_token->str->ptr, parser_token->str->len);
+ loc = rb_ary_new_from_args(4,
+ INT2FIX(parser_token->loc.beg_pos.lineno),
+ INT2FIX(parser_token->loc.beg_pos.column),
+ INT2FIX(parser_token->loc.end_pos.lineno),
+ INT2FIX(parser_token->loc.end_pos.column)
+ );
+ token = rb_ary_new_from_args(4, INT2FIX(parser_token->id), ID2SYM(rb_intern(parser_token->type_name)), str, loc);
+ rb_ary_push(all_tokens, token);
+ }
+ rb_obj_freeze(all_tokens);
- return rb_ast_tokens(data->ast);
+ return all_tokens;
}
static VALUE
@@ -782,10 +798,11 @@ static VALUE
ast_node_script_lines(rb_execution_context_t *ec, VALUE self)
{
struct ASTNodeData *data;
+ rb_ast_t *ast;
TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
- VALUE ret = data->ast->body.script_lines;
- if (!RB_TYPE_P(ret, T_ARRAY)) return Qnil;
- return ret;
+ ast = rb_ruby_ast_data_get(data->ast_value);
+ rb_parser_ary_t *ret = ast->body.script_lines;
+ return rb_parser_build_script_lines_from(ret);
}
#include "ast.rbinc"
diff --git a/basictest/test.rb b/basictest/test.rb
index 95875b52a6..711e4f4ab3 100755
--- a/basictest/test.rb
+++ b/basictest/test.rb
@@ -879,7 +879,7 @@ $x.sort!{|a,b| b-a} # reverse sort
test_ok($x == [7,5,3,2,1])
# split test
-$x = "The Book of Mormon"
+$x = +"The Book of Mormon"
test_ok($x.split(//).reverse!.join == $x.reverse)
test_ok($x.reverse == $x.reverse!)
test_ok("1 byte string".split(//).reverse.join(":") == "g:n:i:r:t:s: :e:t:y:b: :1")
@@ -1643,7 +1643,7 @@ test_ok(/^(?:ab+)+/ =~ "ababb" && $& == "ababb")
test_ok(/(\s+\d+){2}/ =~ " 1 2" && $& == " 1 2")
test_ok(/(?:\s+\d+){2}/ =~ " 1 2" && $& == " 1 2")
-$x = <<END;
+$x = +<<END;
ABCD
ABCD
END
@@ -1682,12 +1682,12 @@ test_ok(?a == ?a)
test_ok(?\C-a == "\1")
test_ok(?\M-a == "\341")
test_ok(?\M-\C-a == "\201")
-test_ok("a".upcase![0] == ?A)
-test_ok("A".downcase![0] == ?a)
-test_ok("abc".tr!("a-z", "A-Z") == "ABC")
-test_ok("aabbcccc".tr_s!("a-z", "A-Z") == "ABC")
-test_ok("abcc".squeeze!("a-z") == "abc")
-test_ok("abcd".delete!("bc") == "ad")
+test_ok("a".dup.upcase![0] == ?A)
+test_ok("A".dup.downcase![0] == ?a)
+test_ok("abc".dup.tr!("a-z", "A-Z") == "ABC")
+test_ok("aabbcccc".dup.tr_s!("a-z", "A-Z") == "ABC")
+test_ok("abcc".dup.squeeze!("a-z") == "abc")
+test_ok("abcd".dup.delete!("bc") == "ad")
$x = "abcdef"
$y = [ ?a, ?b, ?c, ?d, ?e, ?f ]
@@ -1700,7 +1700,7 @@ $x.each_byte {|i|
}
test_ok(!$bad)
-s = "a string"
+s = +"a string"
s[0..s.size]="another string"
test_ok(s == "another string")
diff --git a/benchmark/array_large_literal.yml b/benchmark/array_large_literal.yml
new file mode 100644
index 0000000000..423d68391f
--- /dev/null
+++ b/benchmark/array_large_literal.yml
@@ -0,0 +1,19 @@
+prelude: |
+ def def_array(size)
+ Object.class_eval(<<-END)
+ def array_#{size}
+ x = 1
+ [#{(['x'] * size).join(',')}]
+ end
+ END
+ end
+ def_array(100)
+ def_array(1000)
+ def_array(10000)
+ def_array(100000)
+benchmark:
+ array_100: array_100
+ array_1000: array_1000
+ array_10000: array_10000
+ array_100000: array_100000
+
diff --git a/benchmark/hash_aref_str_lit.yml b/benchmark/hash_aref_str_lit.yml
new file mode 100644
index 0000000000..ed8142bcf1
--- /dev/null
+++ b/benchmark/hash_aref_str_lit.yml
@@ -0,0 +1,20 @@
+prelude: |
+ # frozen_string_literal: true
+ hash = 10.times.to_h do |i|
+ [i, i]
+ end
+ dyn_sym = "dynamic_symbol".to_sym
+ binary = RubyVM::InstructionSequence.compile("# frozen_string_literal: true\n'iseq_load'").to_binary
+ iseq_literal_string = RubyVM::InstructionSequence.load_from_binary(binary).eval
+
+ hash[:some_symbol] = 1
+ hash[dyn_sym] = 2
+ hash["small"] = 3
+ hash["frozen_string_literal"] = 4
+ hash[iseq_literal_string] = 5
+benchmark:
+ symbol: hash[:some_symbol]
+ dyn_symbol: hash[dyn_sym]
+ small_lit: hash["small"]
+ frozen_lit: hash["frozen_string_literal"]
+ iseq_lit: hash[iseq_literal_string]
diff --git a/benchmark/hash_key.yml b/benchmark/hash_key.yml
new file mode 100644
index 0000000000..cab4cf9ca4
--- /dev/null
+++ b/benchmark/hash_key.yml
@@ -0,0 +1,5 @@
+prelude: |
+ obj = Object.new
+ hash = { obj => true }
+benchmark: hash.key?(obj)
+loop_count: 30000000
diff --git a/benchmark/loop_each.yml b/benchmark/loop_each.yml
new file mode 100644
index 0000000000..1c757185a8
--- /dev/null
+++ b/benchmark/loop_each.yml
@@ -0,0 +1,4 @@
+prelude: |
+ arr = [nil] * 30_000_000
+benchmark:
+ loop_each: arr.each{|e|}
diff --git a/benchmark/loop_times_megamorphic.yml b/benchmark/loop_times_megamorphic.yml
new file mode 100644
index 0000000000..f9343ba897
--- /dev/null
+++ b/benchmark/loop_times_megamorphic.yml
@@ -0,0 +1,7 @@
+prelude: |
+ eval(<<~EOS)
+ def loop_times_megamorphic
+ #{"1.times {|i|};" * 1000}
+ end
+ EOS
+benchmark: loop_times_megamorphic
diff --git a/benchmark/object_allocate.yml b/benchmark/object_allocate.yml
index 93ff463e41..bdbd4536db 100644
--- a/benchmark/object_allocate.yml
+++ b/benchmark/object_allocate.yml
@@ -11,6 +11,26 @@ prelude: |
class OneTwentyEight
128.times { include(Module.new) }
end
+ class OnePositional
+ def initialize a; end
+ end
+ class TwoPositional
+ def initialize a, b; end
+ end
+ class ThreePositional
+ def initialize a, b, c; end
+ end
+ class FourPositional
+ def initialize a, b, c, d; end
+ end
+ class KWArg
+ def initialize a:, b:, c:, d:
+ end
+ end
+ class Mixed
+ def initialize a, b, c:, d:
+ end
+ end
# Disable GC to see raw throughput:
GC.disable
benchmark:
@@ -18,4 +38,11 @@ benchmark:
allocate_32_deep: ThirtyTwo.new
allocate_64_deep: SixtyFour.new
allocate_128_deep: OneTwentyEight.new
+ allocate_1_positional_params: OnePositional.new(1)
+ allocate_2_positional_params: TwoPositional.new(1, 2)
+ allocate_3_positional_params: ThreePositional.new(1, 2, 3)
+ allocate_4_positional_params: FourPositional.new(1, 2, 3, 4)
+ allocate_kwarg_params: "KWArg.new(a: 1, b: 2, c: 3, d: 4)"
+ allocate_mixed_params: "Mixed.new(1, 2, c: 3, d: 4)"
+ allocate_no_params: "Object.new"
loop_count: 100000
diff --git a/benchmark/realpath.yml b/benchmark/realpath.yml
index 90a029d5b9..6b6a4836b0 100644
--- a/benchmark/realpath.yml
+++ b/benchmark/realpath.yml
@@ -12,6 +12,9 @@ prelude: |
relative_dir = 'b/c'
absolute_dir = File.join(pwd, relative_dir)
file_dir = 'c'
+teardown: |
+ require 'fileutils'
+ FileUtils.rm_rf('b')
benchmark:
relative_nil: "f.realpath(relative, nil)"
absolute_nil: "f.realpath(absolute, nil)"
diff --git a/benchmark/string_dup.yml b/benchmark/string_dup.yml
new file mode 100644
index 0000000000..90793f9f2a
--- /dev/null
+++ b/benchmark/string_dup.yml
@@ -0,0 +1,7 @@
+prelude: |
+ # frozen_string_literal: true
+benchmark:
+ uplus: |
+ +"A"
+ dup: |
+ "A".dup
diff --git a/benchmark/struct_accessor.yml b/benchmark/struct_accessor.yml
new file mode 100644
index 0000000000..61176cfdd4
--- /dev/null
+++ b/benchmark/struct_accessor.yml
@@ -0,0 +1,25 @@
+prelude: |
+ C = Struct.new(:x) do
+ class_eval <<-END
+ def r
+ #{'x;'*256}
+ end
+ def w
+ #{'self.x = nil;'*256}
+ end
+ def rm
+ m = method(:x)
+ #{'m.call;'*256}
+ end
+ def wm
+ m = method(:x=)
+ #{'m.call(nil);'*256}
+ end
+ END
+ end
+ obj = C.new(nil)
+benchmark:
+ member_reader: "obj.r"
+ member_writer: "obj.w"
+ member_reader_method: "obj.rm"
+ member_writer_method: "obj.wm"
diff --git a/benchmark/vm_call_kw_and_kw_splat.yml b/benchmark/vm_call_kw_and_kw_splat.yml
new file mode 100644
index 0000000000..aa6e549e0c
--- /dev/null
+++ b/benchmark/vm_call_kw_and_kw_splat.yml
@@ -0,0 +1,25 @@
+prelude: |
+ h1, h10, h100, h1000 = [1, 10, 100, 1000].map do |n|
+ h = {kw: 1}
+ n.times{|i| h[i.to_s.to_sym] = i}
+ h
+ end
+ eh = {}
+ def kw(kw: nil, **kws) end
+benchmark:
+ 1: |
+ kw(**h1)
+ 1_mutable: |
+ kw(**eh, **h1)
+ 10: |
+ kw(**h10)
+ 10_mutable: |
+ kw(**eh, **h10)
+ 100: |
+ kw(**h100)
+ 100_mutable: |
+ kw(**eh, **h100)
+ 1000: |
+ kw(**h1000)
+ 1000_mutable: |
+ kw(**eh, **h1000)
diff --git a/benchmark/vm_method_splat_calls.yml b/benchmark/vm_method_splat_calls.yml
new file mode 100644
index 0000000000..f2f366e99c
--- /dev/null
+++ b/benchmark/vm_method_splat_calls.yml
@@ -0,0 +1,13 @@
+prelude: |
+ def f(x=0, y: 0) end
+ a = [1]
+ ea = []
+ kw = {y: 1}
+ b = lambda{}
+benchmark:
+ arg_splat: "f(1, *ea)"
+ arg_splat_block: "f(1, *ea, &b)"
+ splat_kw_splat: "f(*a, **kw)"
+ splat_kw_splat_block: "f(*a, **kw, &b)"
+ splat_kw: "f(*a, y: 1)"
+ splat_kw_block: "f(*a, y: 1, &b)"
diff --git a/benchmark/vm_method_splat_calls2.yml b/benchmark/vm_method_splat_calls2.yml
new file mode 100644
index 0000000000..d33dcd7e8b
--- /dev/null
+++ b/benchmark/vm_method_splat_calls2.yml
@@ -0,0 +1,27 @@
+prelude: |
+ def named_arg_splat(*a) end
+ def named_arg_kw_splat(*a, **kw) end
+ def anon_arg_splat(*) end
+ def anon_kw_splat(**) end
+ def anon_arg_kw_splat(*, **) end
+ def anon_fw_to_named(*, **) named_arg_kw_splat(*, **) end
+ def fw_to_named(...) named_arg_kw_splat(...) end
+ def fw_to_anon_to_named(...) anon_fw_to_named(...) end
+ def fw_no_kw(...) named_arg_splat(...) end
+ a = [1]
+ kw = {y: 1}
+benchmark:
+ named_multi_arg_splat: "named_arg_splat(*a, *a)"
+ named_post_splat: "named_arg_splat(*a, a)"
+ anon_arg_splat: "anon_arg_splat(*a)"
+ anon_arg_kw_splat: "anon_arg_kw_splat(*a, **kw)"
+ anon_multi_arg_splat: "anon_arg_splat(*a, *a)"
+ anon_post_splat: "anon_arg_splat(*a, a)"
+ anon_kw_splat: "anon_kw_splat(**kw)"
+ anon_fw_to_named_splat: "anon_fw_to_named(*a, **kw)"
+ anon_fw_to_named_no_splat: "anon_fw_to_named(1, y: 1)"
+ fw_to_named_splat: "fw_to_named(*a, **kw)"
+ fw_to_named_no_splat: "fw_to_named(1, y: 1)"
+ fw_to_anon_to_named_splat: "fw_to_anon_to_named(*a, **kw)"
+ fw_to_anon_to_named_no_splat: "fw_to_anon_to_named(1, y: 1)"
+ fw_no_kw: "fw_no_kw(1, 2)"
diff --git a/benchmark/vm_super_splat_calls.yml b/benchmark/vm_super_splat_calls.yml
new file mode 100644
index 0000000000..795e44e4da
--- /dev/null
+++ b/benchmark/vm_super_splat_calls.yml
@@ -0,0 +1,25 @@
+prelude: |
+ @a = [1].freeze
+ @ea = [].freeze
+ @kw = {y: 1}.freeze
+ @b = lambda{}
+ extend(Module.new{def arg_splat(x=0, y: 0) end})
+ extend(Module.new{def arg_splat_block(x=0, y: 0) end})
+ extend(Module.new{def splat_kw_splat(x=0, y: 0) end})
+ extend(Module.new{def splat_kw_splat_block(x=0, y: 0) end})
+ extend(Module.new{def splat_kw(x=0, y: 0) end})
+ extend(Module.new{def splat_kw_block(x=0, y: 0) end})
+
+ extend(Module.new{def arg_splat; super(1, *@ea) end})
+ extend(Module.new{def arg_splat_block; super(1, *@ea, &@b) end})
+ extend(Module.new{def splat_kw_splat; super(*@a, **@kw) end})
+ extend(Module.new{def splat_kw_splat_block; super(*@a, **@kw, &@b) end})
+ extend(Module.new{def splat_kw; super(*@a, y: 1) end})
+ extend(Module.new{def splat_kw_block; super(*@a, y: 1, &@b) end})
+benchmark:
+ arg_splat: "arg_splat"
+ arg_splat_block: "arg_splat_block"
+ splat_kw_splat: "splat_kw_splat"
+ splat_kw_splat_block: "splat_kw_splat_block"
+ splat_kw: "splat_kw"
+ splat_kw_block: "splat_kw_block"
diff --git a/benchmark/vm_zsuper_splat_calls.yml b/benchmark/vm_zsuper_splat_calls.yml
new file mode 100644
index 0000000000..82dc22349d
--- /dev/null
+++ b/benchmark/vm_zsuper_splat_calls.yml
@@ -0,0 +1,28 @@
+prelude: |
+ a = [1].freeze
+ ea = [].freeze
+ kw = {y: 1}.freeze
+ b = lambda{}
+ extend(Module.new{def arg_splat(x=0, y: 0) end})
+ extend(Module.new{def arg_splat_block(x=0, y: 0) end})
+ extend(Module.new{def arg_splat_post(x=0, y: 0) end})
+ extend(Module.new{def splat_kw_splat(x=0, y: 0) end})
+ extend(Module.new{def splat_kw_splat_block(x=0, y: 0) end})
+ extend(Module.new{def splat_kw(x=0, y: 0) end})
+ extend(Module.new{def splat_kw_block(x=0, y: 0) end})
+
+ extend(Module.new{def arg_splat(x, *a) super end})
+ extend(Module.new{def arg_splat_block(x, *a, &b) super end})
+ extend(Module.new{def arg_splat_post(*a, x) super end})
+ extend(Module.new{def splat_kw_splat(*a, **kw) super end})
+ extend(Module.new{def splat_kw_splat_block(*a, **kw, &b) super end})
+ extend(Module.new{def splat_kw(*a, y: 1) super end})
+ extend(Module.new{def splat_kw_block(*a, y: 1, &b) super end})
+benchmark:
+ arg_splat: "arg_splat(1, *ea)"
+ arg_splat_block: "arg_splat_block(1, *ea, &b)"
+ arg_splat_post: "arg_splat_post(1, *ea, &b)"
+ splat_kw_splat: "splat_kw_splat(*a, **kw)"
+ splat_kw_splat_block: "splat_kw_splat_block(*a, **kw, &b)"
+ splat_kw: "splat_kw(*a, y: 1)"
+ splat_kw_block: "splat_kw_block(*a, y: 1, &b)"
diff --git a/bignum.c b/bignum.c
index e9bf37d206..e04843f478 100644
--- a/bignum.c
+++ b/bignum.c
@@ -30,9 +30,6 @@
# define USE_GMP 0
#endif
#endif
-#if USE_GMP
-# include <gmp.h>
-#endif
#include "id.h"
#include "internal.h"
@@ -48,6 +45,15 @@
#include "ruby/util.h"
#include "ruby_assert.h"
+#if USE_GMP
+RBIMPL_WARNING_PUSH()
+# ifdef _MSC_VER
+RBIMPL_WARNING_IGNORED(4146) /* for mpn_neg() */
+# endif
+# include <gmp.h>
+RBIMPL_WARNING_POP()
+#endif
+
static const bool debug_integer_pack = (
#ifdef DEBUG_INTEGER_PACK
DEBUG_INTEGER_PACK+0
@@ -349,7 +355,7 @@ maxpow_in_bdigit_dbl(int base, int *exp_ret)
BDIGIT_DBL maxpow;
int exponent;
- assert(2 <= base && base <= 36);
+ RUBY_ASSERT(2 <= base && base <= 36);
{
#if SIZEOF_BDIGIT_DBL == 2
@@ -381,7 +387,7 @@ maxpow_in_bdigit_dbl(int base, int *exp_ret)
static inline BDIGIT_DBL
bary2bdigitdbl(const BDIGIT *ds, size_t n)
{
- assert(n <= 2);
+ RUBY_ASSERT(n <= 2);
if (n == 2)
return ds[0] | BIGUP(ds[1]);
@@ -393,7 +399,7 @@ bary2bdigitdbl(const BDIGIT *ds, size_t n)
static inline void
bdigitdbl2bary(BDIGIT *ds, size_t n, BDIGIT_DBL num)
{
- assert(n == 2);
+ RUBY_ASSERT(n == 2);
ds[0] = BIGLO(num);
ds[1] = (BDIGIT)BIGDN(num);
@@ -424,7 +430,7 @@ bary_small_lshift(BDIGIT *zds, const BDIGIT *xds, size_t n, int shift)
{
size_t i;
BDIGIT_DBL num = 0;
- assert(0 <= shift && shift < BITSPERDIG);
+ RUBY_ASSERT(0 <= shift && shift < BITSPERDIG);
for (i=0; i<n; i++) {
num = num | (BDIGIT_DBL)*xds++ << shift;
@@ -440,7 +446,7 @@ bary_small_rshift(BDIGIT *zds, const BDIGIT *xds, size_t n, int shift, BDIGIT hi
size_t i;
BDIGIT_DBL num = 0;
- assert(0 <= shift && shift < BITSPERDIG);
+ RUBY_ASSERT(0 <= shift && shift < BITSPERDIG);
num = BIGUP(higher_bdigit);
for (i = 0; i < n; i++) {
@@ -1060,8 +1066,8 @@ integer_unpack_num_bdigits(size_t numwords, size_t wordsize, size_t nails, int *
if (debug_integer_pack) {
int nlp_bits1;
size_t num_bdigits1 = integer_unpack_num_bdigits_generic(numwords, wordsize, nails, &nlp_bits1);
- assert(num_bdigits == num_bdigits1);
- assert(*nlp_bits_ret == nlp_bits1);
+ RUBY_ASSERT(num_bdigits == num_bdigits1);
+ RUBY_ASSERT(*nlp_bits_ret == nlp_bits1);
(void)num_bdigits1;
}
}
@@ -1271,7 +1277,7 @@ bary_unpack_internal(BDIGIT *bdigits, size_t num_bdigits, const void *words, siz
}
if (dd)
*dp++ = (BDIGIT)dd;
- assert(dp <= de);
+ RUBY_ASSERT(dp <= de);
while (dp < de)
*dp++ = 0;
#undef PUSH_BITS
@@ -1330,7 +1336,7 @@ bary_unpack(BDIGIT *bdigits, size_t num_bdigits, const void *words, size_t numwo
num_bdigits0 = integer_unpack_num_bdigits(numwords, wordsize, nails, &nlp_bits);
- assert(num_bdigits0 <= num_bdigits);
+ RUBY_ASSERT(num_bdigits0 <= num_bdigits);
sign = bary_unpack_internal(bdigits, num_bdigits0, words, numwords, wordsize, nails, flags, nlp_bits);
@@ -1349,8 +1355,8 @@ bary_subb(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yd
size_t i;
size_t sn;
- assert(xn <= zn);
- assert(yn <= zn);
+ RUBY_ASSERT(xn <= zn);
+ RUBY_ASSERT(yn <= zn);
sn = xn < yn ? xn : yn;
@@ -1411,8 +1417,8 @@ bary_addc(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yd
BDIGIT_DBL num;
size_t i;
- assert(xn <= zn);
- assert(yn <= zn);
+ RUBY_ASSERT(xn <= zn);
+ RUBY_ASSERT(yn <= zn);
if (xn > yn) {
const BDIGIT *tds;
@@ -1476,7 +1482,7 @@ bary_mul_single(BDIGIT *zds, size_t zn, BDIGIT x, BDIGIT y)
{
BDIGIT_DBL n;
- assert(2 <= zn);
+ RUBY_ASSERT(2 <= zn);
n = (BDIGIT_DBL)x * y;
bdigitdbl2bary(zds, 2, n);
@@ -1490,7 +1496,7 @@ bary_muladd_1xN(BDIGIT *zds, size_t zn, BDIGIT x, const BDIGIT *yds, size_t yn)
BDIGIT_DBL dd;
size_t j;
- assert(zn > yn);
+ RUBY_ASSERT(zn > yn);
if (x == 0)
return 0;
@@ -1525,7 +1531,7 @@ bigdivrem_mulsub(BDIGIT *zds, size_t zn, BDIGIT x, const BDIGIT *yds, size_t yn)
BDIGIT_DBL t2;
BDIGIT_DBL_SIGNED num;
- assert(zn == yn + 1);
+ RUBY_ASSERT(zn == yn + 1);
num = 0;
t2 = 0;
@@ -1550,7 +1556,7 @@ bary_mulsub_1xN(BDIGIT *zds, size_t zn, BDIGIT x, const BDIGIT *yds, size_t yn)
{
BDIGIT_DBL_SIGNED num;
- assert(zn == yn + 1);
+ RUBY_ASSERT(zn == yn + 1);
num = bigdivrem_mulsub(zds, zn, x, yds, yn);
zds[yn] = BIGLO(num);
@@ -1564,7 +1570,7 @@ bary_mul_normal(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIG
{
size_t i;
- assert(xn + yn <= zn);
+ RUBY_ASSERT(xn + yn <= zn);
BDIGITS_ZERO(zds, zn);
for (i = 0; i < xn; i++) {
@@ -1595,7 +1601,7 @@ bary_sq_fast(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn)
BDIGIT vl;
int vh;
- assert(xn * 2 <= zn);
+ RUBY_ASSERT(xn * 2 <= zn);
BDIGITS_ZERO(zds, zn);
@@ -1667,9 +1673,9 @@ bary_mul_balance_with_mulfunc(BDIGIT *const zds, const size_t zn,
VALUE work = 0;
size_t n;
- assert(xn + yn <= zn);
- assert(xn <= yn);
- assert(!KARATSUBA_BALANCED(xn, yn) || !TOOM3_BALANCED(xn, yn));
+ RUBY_ASSERT(xn + yn <= zn);
+ RUBY_ASSERT(xn <= yn);
+ RUBY_ASSERT(!KARATSUBA_BALANCED(xn, yn) || !TOOM3_BALANCED(xn, yn));
BDIGITS_ZERO(zds, xn);
@@ -1751,9 +1757,9 @@ bary_mul_karatsuba(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const B
const BDIGIT *xds0, *xds1, *yds0, *yds1;
BDIGIT *zds0, *zds1, *zds2, *zds3;
- assert(xn + yn <= zn);
- assert(xn <= yn);
- assert(yn < 2 * xn);
+ RUBY_ASSERT(xn + yn <= zn);
+ RUBY_ASSERT(xn <= yn);
+ RUBY_ASSERT(yn < 2 * xn);
sq = xds == yds && xn == yn;
@@ -1768,7 +1774,7 @@ bary_mul_karatsuba(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const B
n = yn / 2;
- assert(n < xn);
+ RUBY_ASSERT(n < xn);
if (wn < n) {
/* This function itself needs only n BDIGITs for work area.
@@ -1889,7 +1895,7 @@ bary_mul_karatsuba(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const B
for (x = 0, i = xn-1; 0 <= i; i--) { x <<= SIZEOF_BDIGIT*CHAR_BIT; x |= xds[i]; }
for (y = 0, i = yn-1; 0 <= i; i--) { y <<= SIZEOF_BDIGIT*CHAR_BIT; y |= yds[i]; }
for (z = 0, i = zn-1; 0 <= i; i--) { z <<= SIZEOF_BDIGIT*CHAR_BIT; z |= zds[i]; }
- assert(z == x * y);
+ RUBY_ASSERT(z == x * y);
}
*/
@@ -1957,11 +1963,11 @@ bary_mul_toom3(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGI
int sq = xds == yds && xn == yn;
- assert(xn <= yn); /* assume y >= x */
- assert(xn + yn <= zn);
+ RUBY_ASSERT(xn <= yn); /* assume y >= x */
+ RUBY_ASSERT(xn + yn <= zn);
n = (yn + 2) / 3;
- assert(2*n < xn);
+ RUBY_ASSERT(2*n < xn);
wnc = 0;
@@ -2148,19 +2154,19 @@ bary_mul_toom3(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGI
/* z(1) : t1 <- u1 * v1 */
bary_mul_toom3_start(t1ds, t1n, u1ds, u1n, v1ds, v1n, wds, wn);
t1p = u1p == v1p;
- assert(t1ds[t1n-1] == 0);
+ RUBY_ASSERT(t1ds[t1n-1] == 0);
t1n--;
/* z(-1) : t2 <- u2 * v2 */
bary_mul_toom3_start(t2ds, t2n, u2ds, u2n, v2ds, v2n, wds, wn);
t2p = u2p == v2p;
- assert(t2ds[t2n-1] == 0);
+ RUBY_ASSERT(t2ds[t2n-1] == 0);
t2n--;
/* z(-2) : t3 <- u3 * v3 */
bary_mul_toom3_start(t3ds, t3n, u3ds, u3n, v3ds, v3n, wds, wn);
t3p = u3p == v3p;
- assert(t3ds[t3n-1] == 0);
+ RUBY_ASSERT(t3ds[t3n-1] == 0);
t3n--;
/* z(inf) : t4 <- x2 * y2 */
@@ -2336,7 +2342,7 @@ bary_mul_gmp(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT
mpz_t x, y, z;
size_t count;
- assert(xn + yn <= zn);
+ RUBY_ASSERT(xn + yn <= zn);
mpz_init(x);
mpz_init(y);
@@ -2371,7 +2377,7 @@ rb_big_mul_gmp(VALUE x, VALUE y)
static void
bary_short_mul(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
{
- assert(xn + yn <= zn);
+ RUBY_ASSERT(xn + yn <= zn);
if (xn == 1 && yn == 1) {
bary_mul_single(zds, zn, xds[0], yds[0]);
@@ -2407,7 +2413,7 @@ bary_mul_precheck(BDIGIT **zdsp, size_t *znp, const BDIGIT **xdsp, size_t *xnp,
const BDIGIT *yds = *ydsp;
size_t yn = *ynp;
- assert(xn + yn <= zn);
+ RUBY_ASSERT(xn + yn <= zn);
nlsz = 0;
@@ -2456,7 +2462,7 @@ bary_mul_precheck(BDIGIT **zdsp, size_t *znp, const BDIGIT **xdsp, size_t *xnp,
tds = xds; xds = yds; yds = tds;
tn = xn; xn = yn; yn = tn;
}
- assert(xn <= yn);
+ RUBY_ASSERT(xn <= yn);
if (xn <= 1) {
if (xn == 0) {
@@ -2639,8 +2645,8 @@ rb_big_stop(void *ptr)
static BDIGIT
bigdivrem_single1(BDIGIT *qds, const BDIGIT *xds, size_t xn, BDIGIT x_higher_bdigit, BDIGIT y)
{
- assert(0 < xn);
- assert(x_higher_bdigit < y);
+ RUBY_ASSERT(0 < xn);
+ RUBY_ASSERT(x_higher_bdigit < y);
if (POW2_P(y)) {
BDIGIT r;
r = xds[0] & (y-1);
@@ -2672,9 +2678,9 @@ bigdivrem_restoring(BDIGIT *zds, size_t zn, BDIGIT *yds, size_t yn)
struct big_div_struct bds;
size_t ynzero;
- assert(yn < zn);
- assert(BDIGIT_MSB(yds[yn-1]));
- assert(zds[zn-1] < yds[yn-1]);
+ RUBY_ASSERT(yn < zn);
+ RUBY_ASSERT(BDIGIT_MSB(yds[yn-1]));
+ RUBY_ASSERT(zds[zn-1] < yds[yn-1]);
for (ynzero = 0; !yds[ynzero]; ynzero++);
@@ -2713,9 +2719,9 @@ bary_divmod_normal(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT
size_t zn;
VALUE tmpyz = 0;
- assert(yn < xn || (xn == yn && yds[yn - 1] <= xds[xn - 1]));
- assert(qds ? (xn - yn + 1) <= qn : 1);
- assert(rds ? yn <= rn : 1);
+ RUBY_ASSERT(yn < xn || (xn == yn && yds[yn - 1] <= xds[xn - 1]));
+ RUBY_ASSERT(qds ? (xn - yn + 1) <= qn : 1);
+ RUBY_ASSERT(rds ? yn <= rn : 1);
zn = xn + BIGDIVREM_EXTRA_WORDS;
@@ -2807,10 +2813,10 @@ bary_divmod_gmp(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xd
mpz_t x, y, q, r;
size_t count;
- assert(yn < xn || (xn == yn && yds[yn - 1] <= xds[xn - 1]));
- assert(qds ? (xn - yn + 1) <= qn : 1);
- assert(rds ? yn <= rn : 1);
- assert(qds || rds);
+ RUBY_ASSERT(yn < xn || (xn == yn && yds[yn - 1] <= xds[xn - 1]));
+ RUBY_ASSERT(qds ? (xn - yn + 1) <= qn : 1);
+ RUBY_ASSERT(rds ? yn <= rn : 1);
+ RUBY_ASSERT(qds || rds);
mpz_init(x);
mpz_init(y);
@@ -2896,8 +2902,8 @@ bary_divmod_branch(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT
static void
bary_divmod(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
{
- assert(xn <= qn);
- assert(yn <= rn);
+ RUBY_ASSERT(xn <= qn);
+ RUBY_ASSERT(yn <= rn);
BARY_TRUNC(yds, yn);
if (yn == 0)
@@ -3432,8 +3438,8 @@ rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret)
if (debug_integer_pack) {
size_t numwords0, nlz_bits0;
numwords0 = absint_numwords_generic(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits0);
- assert(numwords0 == numwords);
- assert(nlz_bits0 == nlz_bits);
+ RUBY_ASSERT(numwords0 == numwords);
+ RUBY_ASSERT(nlz_bits0 == nlz_bits);
(void)numwords0;
}
}
@@ -3848,7 +3854,7 @@ str2big_poweroftwo(
if (numbits) {
*dp++ = BIGLO(dd);
}
- assert((size_t)(dp - BDIGITS(z)) == num_bdigits);
+ RUBY_ASSERT((size_t)(dp - BDIGITS(z)) == num_bdigits);
return z;
}
@@ -3891,7 +3897,7 @@ str2big_normal(
}
break;
}
- assert(blen <= num_bdigits);
+ RUBY_ASSERT(blen <= num_bdigits);
}
return z;
@@ -3949,7 +3955,7 @@ str2big_karatsuba(
current_base = 1;
}
}
- assert(i == num_bdigits);
+ RUBY_ASSERT(i == num_bdigits);
for (unit = 2; unit < num_bdigits; unit *= 2) {
for (i = 0; i < num_bdigits; i += unit*2) {
if (2*unit <= num_bdigits - i) {
@@ -4094,8 +4100,8 @@ rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits,
len -= (n); \
} while (0)
#define ASSERT_LEN() do {\
- assert(len != 0); \
- if (len0 >= 0) assert(s + len0 == str + len); \
+ RUBY_ASSERT(len != 0); \
+ if (len0 >= 0) RUBY_ASSERT(s + len0 == str + len); \
} while (0)
if (!str) {
@@ -4640,8 +4646,8 @@ big_shift2(VALUE x, int lshift_p, VALUE y)
size_t shift_numdigits;
int shift_numbits;
- assert(POW2_P(CHAR_BIT));
- assert(POW2_P(BITSPERDIG));
+ RUBY_ASSERT(POW2_P(CHAR_BIT));
+ RUBY_ASSERT(POW2_P(BITSPERDIG));
if (BIGZEROP(x))
return INT2FIX(0);
@@ -4728,7 +4734,7 @@ power_cache_get_power(int base, int power_level, size_t *numdigits_ret)
rb_obj_hide(power);
base36_power_cache[base - 2][power_level] = power;
base36_numdigits_cache[base - 2][power_level] = numdigits;
- rb_gc_register_mark_object(power);
+ rb_vm_register_global_object(power);
}
if (numdigits_ret)
*numdigits_ret = base36_numdigits_cache[base - 2][power_level];
@@ -4764,7 +4770,7 @@ big2str_2bdigits(struct big2str_struct *b2s, BDIGIT *xds, size_t xn, size_t tail
int beginning = !b2s->ptr;
size_t len = 0;
- assert(xn <= 2);
+ RUBY_ASSERT(xn <= 2);
num = bary2bdigitdbl(xds, xn);
if (beginning) {
@@ -4892,7 +4898,7 @@ big2str_karatsuba(struct big2str_struct *b2s, BDIGIT *xds, size_t xn, size_t wn,
/* bigdivrem_restoring will modify y.
* So use temporary buffer. */
tds = xds + qn;
- assert(qn + bn <= xn + wn);
+ RUBY_ASSERT(qn + bn <= xn + wn);
bary_small_lshift(tds, bds, bn, shift);
xds[xn] = bary_small_lshift(xds, xds, xn, shift);
}
@@ -4910,7 +4916,7 @@ big2str_karatsuba(struct big2str_struct *b2s, BDIGIT *xds, size_t xn, size_t wn,
}
BARY_TRUNC(qds, qn);
- assert(qn <= bn);
+ RUBY_ASSERT(qn <= bn);
big2str_karatsuba(b2s, qds, qn, xn+wn - (rn+qn), lower_power_level, lower_numdigits+taillen);
BARY_TRUNC(rds, rn);
big2str_karatsuba(b2s, rds, rn, xn+wn - rn, lower_power_level, taillen);
@@ -4975,7 +4981,7 @@ big2str_generic(VALUE x, int base)
invalid_radix(base);
if (xn >= LONG_MAX/BITSPERDIG) {
- rb_raise(rb_eRangeError, "bignum too big to convert into `string'");
+ rb_raise(rb_eRangeError, "bignum too big to convert into 'string'");
}
power_level = 0;
@@ -4985,7 +4991,7 @@ big2str_generic(VALUE x, int base)
power_level++;
power = power_cache_get_power(base, power_level, NULL);
}
- assert(power_level != MAX_BASE36_POWER_TABLE_ENTRIES);
+ RUBY_ASSERT(power_level != MAX_BASE36_POWER_TABLE_ENTRIES);
if ((size_t)BIGNUM_LEN(power) <= xn) {
/*
@@ -5100,7 +5106,7 @@ rb_big2str1(VALUE x, int base)
invalid_radix(base);
if (xn >= LONG_MAX/BITSPERDIG) {
- rb_raise(rb_eRangeError, "bignum too big to convert into `string'");
+ rb_raise(rb_eRangeError, "bignum too big to convert into 'string'");
}
if (POW2_P(base)) {
@@ -5136,7 +5142,7 @@ big2ulong(VALUE x, const char *type)
if (len == 0)
return 0;
if (BIGSIZE(x) > sizeof(long)) {
- rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type);
+ rb_raise(rb_eRangeError, "bignum too big to convert into '%s'", type);
}
ds = BDIGITS(x);
#if SIZEOF_LONG <= SIZEOF_BDIGIT
@@ -5179,7 +5185,7 @@ rb_big2long(VALUE x)
if (num <= 1+(unsigned long)(-(LONG_MIN+1)))
return -(long)(num-1)-1;
}
- rb_raise(rb_eRangeError, "bignum too big to convert into `long'");
+ rb_raise(rb_eRangeError, "bignum too big to convert into 'long'");
}
#if HAVE_LONG_LONG
@@ -5197,7 +5203,7 @@ big2ull(VALUE x, const char *type)
if (len == 0)
return 0;
if (BIGSIZE(x) > SIZEOF_LONG_LONG)
- rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type);
+ rb_raise(rb_eRangeError, "bignum too big to convert into '%s'", type);
#if SIZEOF_LONG_LONG <= SIZEOF_BDIGIT
num = (unsigned LONG_LONG)ds[0];
#else
@@ -5238,7 +5244,7 @@ rb_big2ll(VALUE x)
if (num <= 1+(unsigned LONG_LONG)(-(LLONG_MIN+1)))
return -(LONG_LONG)(num-1)-1;
}
- rb_raise(rb_eRangeError, "bignum too big to convert into `long long'");
+ rb_raise(rb_eRangeError, "bignum too big to convert into 'long long'");
}
#endif /* HAVE_LONG_LONG */
@@ -5501,10 +5507,10 @@ big_op(VALUE x, VALUE y, enum big_op_t op)
n = FIX2INT(rel);
switch (op) {
- case big_op_gt: return RBOOL(n > 0);
- case big_op_ge: return RBOOL(n >= 0);
- case big_op_lt: return RBOOL(n < 0);
- case big_op_le: return RBOOL(n <= 0);
+ case big_op_gt: return RBOOL(n > 0);
+ case big_op_ge: return RBOOL(n >= 0);
+ case big_op_lt: return RBOOL(n < 0);
+ case big_op_le: return RBOOL(n <= 0);
}
return Qundef;
}
@@ -5660,7 +5666,7 @@ bigsub_int(VALUE x, long y0)
zds = BDIGITS(z);
#if SIZEOF_BDIGIT >= SIZEOF_LONG
- assert(xn == zn);
+ RUBY_ASSERT(xn == zn);
num = (BDIGIT_DBL_SIGNED)xds[0] - y;
if (xn == 1 && num < 0) {
BIGNUM_NEGATE(z);
@@ -5723,7 +5729,7 @@ bigsub_int(VALUE x, long y0)
goto finish;
finish:
- assert(num == 0 || num == -1);
+ RUBY_ASSERT(num == 0 || num == -1);
if (num < 0) {
get2comp(z);
BIGNUM_NEGATE(z);
@@ -6878,63 +6884,11 @@ BDIGIT rb_bdigit_dbl_isqrt(BDIGIT_DBL);
# define BDIGIT_DBL_TO_DOUBLE(n) (double)(n)
#endif
-static BDIGIT *
-estimate_initial_sqrt(VALUE *xp, const size_t xn, const BDIGIT *nds, size_t len)
-{
- enum {dbl_per_bdig = roomof(DBL_MANT_DIG,BITSPERDIG)};
- const int zbits = nlz(nds[len-1]);
- VALUE x = *xp = bignew_1(0, xn, 1); /* division may release the GVL */
- BDIGIT *xds = BDIGITS(x);
- BDIGIT_DBL d = bary2bdigitdbl(nds+len-dbl_per_bdig, dbl_per_bdig);
- BDIGIT lowbits = 1;
- int rshift = (int)((BITSPERDIG*2-zbits+(len&BITSPERDIG&1) - DBL_MANT_DIG + 1) & ~1);
- double f;
-
- if (rshift > 0) {
- lowbits = (BDIGIT)d & ~(~(BDIGIT)1U << rshift);
- d >>= rshift;
- }
- else if (rshift < 0) {
- d <<= -rshift;
- d |= nds[len-dbl_per_bdig-1] >> (BITSPERDIG+rshift);
- }
- f = sqrt(BDIGIT_DBL_TO_DOUBLE(d));
- d = (BDIGIT_DBL)ceil(f);
- if (BDIGIT_DBL_TO_DOUBLE(d) == f) {
- if (lowbits || (lowbits = !bary_zero_p(nds, len-dbl_per_bdig)))
- ++d;
- }
- else {
- lowbits = 1;
- }
- rshift /= 2;
- rshift += (2-(len&1))*BITSPERDIG/2;
- if (rshift >= 0) {
- if (nlz((BDIGIT)d) + rshift >= BITSPERDIG) {
- /* (d << rshift) does cause overflow.
- * example: Integer.sqrt(0xffff_ffff_ffff_ffff ** 2)
- */
- d = ~(BDIGIT_DBL)0;
- }
- else {
- d <<= rshift;
- }
- }
- BDIGITS_ZERO(xds, xn-2);
- bdigitdbl2bary(&xds[xn-2], 2, d);
-
- if (!lowbits) return NULL; /* special case, exact result */
- return xds;
-}
-
VALUE
rb_big_isqrt(VALUE n)
{
BDIGIT *nds = BDIGITS(n);
size_t len = BIGNUM_LEN(n);
- size_t xn = (len+1) / 2;
- VALUE x;
- BDIGIT *xds;
if (len <= 2) {
BDIGIT sq = rb_bdigit_dbl_isqrt(bary2bdigitdbl(nds, len));
@@ -6944,25 +6898,19 @@ rb_big_isqrt(VALUE n)
return ULONG2NUM(sq);
#endif
}
- else if ((xds = estimate_initial_sqrt(&x, xn, nds, len)) != 0) {
- size_t tn = xn + BIGDIVREM_EXTRA_WORDS;
- VALUE t = bignew_1(0, tn, 1);
- BDIGIT *tds = BDIGITS(t);
- tn = BIGNUM_LEN(t);
-
- /* t = n/x */
- while (bary_divmod_branch(tds, tn, NULL, 0, nds, len, xds, xn),
- bary_cmp(tds, tn, xds, xn) < 0) {
- int carry;
- BARY_TRUNC(tds, tn);
- /* x = (x+t)/2 */
- carry = bary_add(xds, xn, xds, xn, tds, tn);
- bary_small_rshift(xds, xds, xn, 1, carry);
- tn = BIGNUM_LEN(t);
+ else {
+ size_t shift = FIX2LONG(rb_big_bit_length(n)) / 4;
+ VALUE n2 = rb_int_rshift(n, SIZET2NUM(2 * shift));
+ VALUE x = FIXNUM_P(n2) ? LONG2FIX(rb_ulong_isqrt(FIX2ULONG(n2))) : rb_big_isqrt(n2);
+ /* x = (x+n/x)/2 */
+ x = rb_int_plus(rb_int_lshift(x, SIZET2NUM(shift - 1)), rb_int_idiv(rb_int_rshift(n, SIZET2NUM(shift + 1)), x));
+ VALUE xx = rb_int_mul(x, x);
+ while (rb_int_gt(xx, n)) {
+ xx = rb_int_minus(xx, rb_int_minus(rb_int_plus(x, x), INT2FIX(1)));
+ x = rb_int_minus(x, INT2FIX(1));
}
+ return x;
}
- RBASIC_SET_CLASS_RAW(x, rb_cInteger);
- return x;
}
#if USE_GMP
@@ -7001,7 +6949,7 @@ int_pow_tmp3(VALUE x, VALUE y, VALUE m, int nega_flg)
if (FIXNUM_P(y)) {
y = rb_int2big(FIX2LONG(y));
}
- assert(RB_BIGNUM_TYPE_P(m));
+ RUBY_ASSERT(RB_BIGNUM_TYPE_P(m));
xn = BIGNUM_LEN(x);
yn = BIGNUM_LEN(y);
mn = BIGNUM_LEN(m);
diff --git a/bootstraptest/runner.rb b/bootstraptest/runner.rb
index c8ba824407..3e54318ac9 100755
--- a/bootstraptest/runner.rb
+++ b/bootstraptest/runner.rb
@@ -6,7 +6,6 @@
# Never use optparse in this file.
# Never use test/unit in this file.
# Never use Ruby extensions in this file.
-# Maintain Ruby 1.8 compatibility for now
$start_time = Time.now
@@ -77,6 +76,8 @@ bt = Struct.new(:ruby,
:width,
:indent,
:platform,
+ :timeout,
+ :timeout_scale,
)
BT = Class.new(bt) do
def indent=(n)
@@ -144,6 +145,10 @@ BT = Class.new(bt) do
end
super wn
end
+
+ def apply_timeout_scale(timeout)
+ timeout&.*(timeout_scale)
+ end
end.new
BT_STATE = Struct.new(:count, :error).new
@@ -156,6 +161,12 @@ def main
BT.color = nil
BT.tty = nil
BT.quiet = false
+ BT.timeout = 180
+ BT.timeout_scale = (defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? ? 3 : 1) # for --jit-wait
+ if (ts = (ENV["RUBY_TEST_TIMEOUT_SCALE"] || ENV["RUBY_TEST_SUBPROCESS_TIMEOUT_SCALE"]).to_i) > 1
+ BT.timeout_scale *= ts
+ end
+
# BT.wn = 1
dir = nil
quiet = false
@@ -186,14 +197,18 @@ def main
warn "unknown --tty argument: #$3" if $3
BT.tty = !$1 || !$2
true
- when /\A(-q|--q(uiet))\z/
+ when /\A(-q|--q(uiet)?)\z/
quiet = true
BT.quiet = true
true
when /\A-j(\d+)?/
BT.wn = $1.to_i
true
- when /\A(-v|--v(erbose))\z/
+ when /\A--timeout=(\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?)(?::(\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?))?/
+ BT.timeout = $1.to_f
+ BT.timeout_scale = $2.to_f if defined?($2)
+ true
+ when /\A(-v|--v(erbose)?)\z/
BT.verbose = true
BT.quiet = false
true
@@ -205,6 +220,7 @@ Usage: #{File.basename($0, '.*')} --ruby=PATH [--sets=NAME,NAME,...]
default: /tmp/bootstraptestXXXXX.tmpwd
--color[=WHEN] Colorize the output. WHEN defaults to 'always'
or can be 'never' or 'auto'.
+ --timeout=TIMEOUT Default timeout in seconds.
-s, --stress stress test.
-v, --verbose Output test name before exec.
-q, --quiet Don\'t print header message.
@@ -222,7 +238,7 @@ End
end
tests ||= ARGV
tests = Dir.glob("#{File.dirname($0)}/test_*.rb").sort if tests.empty?
- pathes = tests.map {|path| File.expand_path(path) }
+ paths = tests.map {|path| File.expand_path(path) }
BT.progress = %w[- \\ | /]
BT.progress_bs = "\b" * BT.progress[0].size
@@ -266,7 +282,7 @@ End
end
in_temporary_working_directory(dir) do
- exec_test pathes
+ exec_test paths
end
end
@@ -278,8 +294,8 @@ def erase(e = true)
end
end
-def load_test pathes
- pathes.each do |path|
+def load_test paths
+ paths.each do |path|
load File.expand_path(path)
end
end
@@ -329,13 +345,13 @@ def concurrent_exec_test
end
end
-def exec_test(pathes)
+def exec_test(paths)
# setup
- load_test pathes
+ load_test paths
BT_STATE.count = 0
BT_STATE.error = 0
BT.columns = 0
- BT.width = pathes.map {|path| File.basename(path).size}.max + 2
+ BT.width = paths.map {|path| File.basename(path).size}.max + 2
# execute tests
if BT.wn > 1
@@ -428,7 +444,7 @@ class Assertion < Struct.new(:src, :path, :lineno, :proc)
def initialize(*args)
super
self.class.add self
- @category = self.path.match(/test_(.+)\.rb/)[1]
+ @category = self.path[/\Atest_(.+)\.rb\z/, 1]
end
def call
@@ -526,14 +542,16 @@ class Assertion < Struct.new(:src, :path, :lineno, :proc)
end
end
- def get_result_string(opt = '', **argh)
+ def get_result_string(opt = '', timeout: BT.timeout, **argh)
if BT.ruby
+ timeout = BT.apply_timeout_scale(timeout)
filename = make_srcfile(**argh)
begin
kw = self.err ? {err: self.err} : {}
out = IO.popen("#{BT.ruby} -W0 #{opt} #{filename}", **kw)
pid = out.pid
- out.read.tap{ Process.waitpid(pid); out.close }
+ th = Thread.new {out.read.tap {Process.waitpid(pid); out.close}}
+ th.value if th.join(timeout)
ensure
raise Interrupt if $? and $?.signaled? && $?.termsig == Signal.list["INT"]
@@ -551,9 +569,14 @@ class Assertion < Struct.new(:src, :path, :lineno, :proc)
def make_srcfile(frozen_string_literal: nil)
filename = "bootstraptest.#{self.path}_#{self.lineno}_#{self.id}.rb"
File.open(filename, 'w') {|f|
- f.puts "#frozen_string_literal:true" if frozen_string_literal
- f.puts "GC.stress = true" if $stress
- f.puts "print(begin; #{self.src}; end)"
+ f.puts "#frozen_string_literal:#{frozen_string_literal}" unless frozen_string_literal.nil?
+ if $stress
+ f.puts "GC.stress = true" if $stress
+ else
+ f.puts ""
+ end
+ f.puts "class BT_Skip < Exception; end; def skip(msg) = raise(BT_Skip, msg.to_s)"
+ f.puts "print(begin; #{self.src}; rescue BT_Skip; $!.message; end)"
}
filename
end
@@ -567,9 +590,9 @@ def add_assertion src, pr
Assertion.new(src, path, lineno, pr)
end
-def assert_equal(expected, testsrc, message = '', opt = '', **argh)
+def assert_equal(expected, testsrc, message = '', opt = '', **kwargs)
add_assertion testsrc, -> as do
- as.assert_check(message, opt, **argh) {|result|
+ as.assert_check(message, opt, **kwargs) {|result|
if expected == result
nil
else
@@ -580,9 +603,9 @@ def assert_equal(expected, testsrc, message = '', opt = '', **argh)
end
end
-def assert_match(expected_pattern, testsrc, message = '')
+def assert_match(expected_pattern, testsrc, message = '', **argh)
add_assertion testsrc, -> as do
- as.assert_check(message) {|result|
+ as.assert_check(message, **argh) {|result|
if expected_pattern =~ result
nil
else
@@ -614,8 +637,9 @@ def assert_valid_syntax(testsrc, message = '')
end
end
-def assert_normal_exit(testsrc, *rest, timeout: nil, **opt)
+def assert_normal_exit(testsrc, *rest, timeout: BT.timeout, **opt)
add_assertion testsrc, -> as do
+ timeout = BT.apply_timeout_scale(timeout)
message, ignore_signals = rest
message ||= ''
as.show_progress(message) {
@@ -669,9 +693,7 @@ end
def assert_finish(timeout_seconds, testsrc, message = '')
add_assertion testsrc, -> as do
- if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? # for --jit-wait
- timeout_seconds *= 3
- end
+ timeout_seconds = BT.apply_timeout_scale(timeout_seconds)
as.show_progress(message) {
faildesc = nil
@@ -784,4 +806,13 @@ def check_coredump
end
end
+def yjit_enabled?
+ ENV.key?('RUBY_YJIT_ENABLE') || ENV.fetch('RUN_OPTS', '').include?('yjit') || BT.ruby.include?('yjit')
+end
+
+def rjit_enabled?
+ # Don't check `RubyVM::RJIT.enabled?`. On btest-bruby, target Ruby != runner Ruby.
+ ENV.fetch('RUN_OPTS', '').include?('rjit')
+end
+
exit main
diff --git a/bootstraptest/test_eval.rb b/bootstraptest/test_eval.rb
index a9f389c673..d923a957bc 100644
--- a/bootstraptest/test_eval.rb
+++ b/bootstraptest/test_eval.rb
@@ -227,6 +227,16 @@ assert_equal %q{[10, main]}, %q{
}, '[ruby-dev:31372]'
end
+assert_normal_exit %{
+ $stderr = STDOUT
+ 5000.times do
+ begin
+ eval "0 rescue break"
+ rescue SyntaxError
+ end
+ end
+}
+
assert_normal_exit %q{
$stderr = STDOUT
class Foo
@@ -354,3 +364,34 @@ assert_normal_exit %q{
end
}, 'check escaping the internal value th->base_block'
+assert_equal "false", <<~RUBY, "literal strings are mutable", "--disable-frozen-string-literal"
+ eval("'test'").frozen?
+RUBY
+
+assert_equal "false", <<~RUBY, "literal strings are mutable", "--disable-frozen-string-literal", frozen_string_literal: true
+ eval("'test'").frozen?
+RUBY
+
+assert_equal "true", <<~RUBY, "literal strings are frozen", "--enable-frozen-string-literal"
+ eval("'test'").frozen?
+RUBY
+
+assert_equal "true", <<~RUBY, "literal strings are frozen", "--enable-frozen-string-literal", frozen_string_literal: false
+ eval("'test'").frozen?
+RUBY
+
+assert_equal "false", <<~RUBY, "__FILE__ is mutable", "--disable-frozen-string-literal"
+ eval("__FILE__").frozen?
+RUBY
+
+assert_equal "false", <<~RUBY, "__FILE__ is mutable", "--disable-frozen-string-literal", frozen_string_literal: true
+ eval("__FILE__").frozen?
+RUBY
+
+assert_equal "true", <<~RUBY, "__FILE__ is frozen", "--enable-frozen-string-literal"
+ eval("__FILE__").frozen?
+RUBY
+
+assert_equal "true", <<~RUBY, "__FILE__ is frozen", "--enable-frozen-string-literal", frozen_string_literal: false
+ eval("__FILE__").frozen?
+RUBY
diff --git a/bootstraptest/test_exception.rb b/bootstraptest/test_exception.rb
index 0fb6f552b8..decfdc08a3 100644
--- a/bootstraptest/test_exception.rb
+++ b/bootstraptest/test_exception.rb
@@ -370,7 +370,7 @@ assert_equal %q{}, %q{
}
##
-assert_match /undefined method `foo\'/, %q{#`
+assert_match /undefined method 'foo\'/, %q{#`
STDERR.reopen(STDOUT)
class C
def inspect
diff --git a/bootstraptest/test_finalizer.rb b/bootstraptest/test_finalizer.rb
index 22a16b1220..ccfa0b55d6 100644
--- a/bootstraptest/test_finalizer.rb
+++ b/bootstraptest/test_finalizer.rb
@@ -6,3 +6,11 @@ ObjectSpace.define_finalizer(b1,proc{b1.inspect})
ObjectSpace.define_finalizer(a2,proc{a1.inspect})
ObjectSpace.define_finalizer(a1,proc{})
}, '[ruby-dev:35778]'
+
+assert_equal 'true', %q{
+ obj = Object.new
+ id = obj.object_id
+
+ ObjectSpace.define_finalizer(obj, proc { |i| print(id == i) })
+ nil
+}
diff --git a/bootstraptest/test_flow.rb b/bootstraptest/test_flow.rb
index 35f19db588..15528a4213 100644
--- a/bootstraptest/test_flow.rb
+++ b/bootstraptest/test_flow.rb
@@ -363,7 +363,7 @@ assert_equal %q{[1, 2, 3, 5, 2, 3, 5, 7, 8]}, %q{$a = []; begin; ; $a << 1
; $a << 8
; rescue Exception; $a << 99; end; $a}
assert_equal %q{[1, 2, 6, 3, 5, 7, 8]}, %q{$a = []; begin; ; $a << 1
- o = "test"; $a << 2
+ o = "test".dup; $a << 2
def o.test(a); $a << 3
return a; $a << 4
ensure; $a << 5
diff --git a/bootstraptest/test_gc.rb b/bootstraptest/test_gc.rb
index 9f17e14814..17bc497822 100644
--- a/bootstraptest/test_gc.rb
+++ b/bootstraptest/test_gc.rb
@@ -14,7 +14,7 @@ ms = "a".."k"
o.send(meth)
end
end
-}, '[ruby-dev:39453]' unless ENV.fetch('RUN_OPTS', '').include?('rjit') # speed up RJIT CI
+}, '[ruby-dev:39453]' unless rjit_enabled? # speed up RJIT CI
assert_normal_exit %q{
a = []
diff --git a/bootstraptest/test_insns.rb b/bootstraptest/test_insns.rb
index d2e799f855..06828a7f7a 100644
--- a/bootstraptest/test_insns.rb
+++ b/bootstraptest/test_insns.rb
@@ -92,7 +92,7 @@ tests = [
[ 'intern', %q{ :"#{true}" }, ],
[ 'newarray', %q{ ["true"][0] }, ],
- [ 'newarraykwsplat', %q{ [**{x:'true'}][0][:x] }, ],
+ [ 'pushtoarraykwsplat', %q{ [**{x:'true'}][0][:x] }, ],
[ 'duparray', %q{ [ true ][0] }, ],
[ 'expandarray', %q{ y = [ true, false, nil ]; x, = y; x }, ],
[ 'expandarray', %q{ y = [ true, false, nil ]; x, *z = y; x }, ],
@@ -354,7 +354,7 @@ tests = [
[ 'opt_ge', %q{ +0.0.next_float >= 0.0 }, ],
[ 'opt_ge', %q{ ?z >= ?a }, ],
- [ 'opt_ltlt', %q{ '' << 'true' }, ],
+ [ 'opt_ltlt', %q{ +'' << 'true' }, ],
[ 'opt_ltlt', %q{ ([] << 'true').join }, ],
[ 'opt_ltlt', %q{ (1 << 31) == 2147483648 }, ],
@@ -363,7 +363,7 @@ tests = [
[ 'opt_aref', %q{ 'true'[0] == ?t }, ],
[ 'opt_aset', %q{ [][0] = true }, ],
[ 'opt_aset', %q{ {}[0] = true }, ],
- [ 'opt_aset', %q{ x = 'frue'; x[0] = 't'; x }, ],
+ [ 'opt_aset', %q{ x = +'frue'; x[0] = 't'; x }, ],
[ 'opt_aset', <<-'},', ], # {
# opt_aref / opt_aset mixup situation
class X; def x; {}; end; end
diff --git a/bootstraptest/test_jump.rb b/bootstraptest/test_jump.rb
index d07c47a56d..8751343b1f 100644
--- a/bootstraptest/test_jump.rb
+++ b/bootstraptest/test_jump.rb
@@ -292,7 +292,7 @@ assert_equal "true", %q{
end
end
end
- s = "foo"
+ s = +"foo"
s.return_eigenclass == class << s; self; end
}, '[ruby-core:21379]'
diff --git a/bootstraptest/test_literal.rb b/bootstraptest/test_literal.rb
index a0d4ee08c6..a30661a796 100644
--- a/bootstraptest/test_literal.rb
+++ b/bootstraptest/test_literal.rb
@@ -70,6 +70,7 @@ if /wasi/ !~ target_platform
assert_equal "foo\n", %q(`echo foo`)
assert_equal "foo\n", %q(s = "foo"; `echo #{s}`)
end
+assert_equal "ECHO FOO", %q(def `(s) s.upcase; end; `echo foo`)
# regexp
assert_equal '', '//.source'
diff --git a/bootstraptest/test_literal_suffix.rb b/bootstraptest/test_literal_suffix.rb
index c36fa7078f..7a4d67d0fa 100644
--- a/bootstraptest/test_literal_suffix.rb
+++ b/bootstraptest/test_literal_suffix.rb
@@ -46,9 +46,9 @@ assert_equal '1', '1rescue nil'
assert_equal '10000000000000000001/10000000000000000000',
'1.0000000000000000001r'
-assert_equal 'syntax error, unexpected local variable or method, expecting end-of-input',
- %q{begin eval('1ir', nil, '', 0); rescue SyntaxError => e; e.message[/\A:(?:\d+:)? (.*)/, 1] end}
-assert_equal 'syntax error, unexpected local variable or method, expecting end-of-input',
- %q{begin eval('1.2ir', nil, '', 0); rescue SyntaxError => e; e.message[/\A:(?:\d+:)? (.*)/, 1] end}
-assert_equal 'syntax error, unexpected local variable or method, expecting end-of-input',
- %q{begin eval('1e1r', nil, '', 0); rescue SyntaxError => e; e.message[/\A:(?:\d+:)? (.*)/, 1] end}
+assert_equal 'unexpected local variable or method, expecting end-of-input',
+ %q{begin eval('1ir', nil, '', 0); rescue SyntaxError => e; e.message[/(?:\^~*|\A:(?:\d+:)? syntax error,) (.*)/, 1]; end}
+assert_equal 'unexpected local variable or method, expecting end-of-input',
+ %q{begin eval('1.2ir', nil, '', 0); rescue SyntaxError => e; e.message[/(?:\^~*|\A:(?:\d+:)? syntax error,) (.*)/, 1]; end}
+assert_equal 'unexpected local variable or method, expecting end-of-input',
+ %q{begin eval('1e1r', nil, '', 0); rescue SyntaxError => e; e.message[/(?:\^~*|\A:(?:\d+:)? syntax error,) (.*)/, 1]; end}
diff --git a/bootstraptest/test_method.rb b/bootstraptest/test_method.rb
index 04c9eb2d11..d1d1f57d55 100644
--- a/bootstraptest/test_method.rb
+++ b/bootstraptest/test_method.rb
@@ -340,24 +340,6 @@ assert_equal '1', %q( class C; def m() 7 end; private :m end
assert_equal '1', %q( class C; def m() 1 end; private :m end
C.new.send(:m) )
-# with block
-assert_equal '[[:ok1, :foo], [:ok2, :foo, :bar]]',
-%q{
- class C
- def [](a)
- $ary << [yield, a]
- end
- def []=(a, b)
- $ary << [yield, a, b]
- end
- end
-
- $ary = []
- C.new[:foo, &lambda{:ok1}]
- C.new[:foo, &lambda{:ok2}] = :bar
- $ary
-}
-
# with
assert_equal '[:ok1, [:ok2, 11]]', %q{
class C
@@ -404,7 +386,6 @@ $result
# aset and splat
assert_equal '4', %q{class Foo;def []=(a,b,c,d);end;end;Foo.new[1,*a=[2,3]]=4}
-assert_equal '4', %q{class Foo;def []=(a,b,c,d);end;end;def m(&blk)Foo.new[1,*a=[2,3],&blk]=4;end;m{}}
# post test
assert_equal %q{[1, 2, :o1, :o2, [], 3, 4, NilClass, nil, nil]}, %q{
@@ -1107,10 +1088,6 @@ assert_equal 'ok', %q{
'ok'
end
}
-assert_equal 'ok', %q{
- [0][0, &proc{}] += 21
- 'ok'
-}, '[ruby-core:30534]'
# should not cache when splat
assert_equal 'ok', %q{
@@ -1190,3 +1167,12 @@ assert_equal 'DC', %q{
test2 o1, [], block
$result.join
}
+
+assert_equal 'ok', %q{
+ def foo
+ binding
+ ["ok"].first
+ end
+ foo
+ foo
+}, '[Bug #20178]'
diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb
index 7a71f6e071..0390d38f9c 100644
--- a/bootstraptest/test_ractor.rb
+++ b/bootstraptest/test_ractor.rb
@@ -601,7 +601,7 @@ assert_equal '{:ok=>3}', %q{
end
3.times.map{Ractor.receive}.tally
-}
+} unless yjit_enabled? # `[BUG] Bus Error at 0x000000010b7002d0` in jit_exec()
# unshareable object are copied
assert_equal 'false', %q{
@@ -628,7 +628,7 @@ assert_equal "allocator undefined for Thread", %q{
}
# send shareable and unshareable objects
-assert_equal "ok", %q{
+assert_equal "ok", <<~'RUBY', frozen_string_literal: false
echo_ractor = Ractor.new do
loop do
v = Ractor.receive
@@ -695,10 +695,10 @@ assert_equal "ok", %q{
else
results.inspect
end
-}
+RUBY
# frozen Objects are shareable
-assert_equal [false, true, false].inspect, %q{
+assert_equal [false, true, false].inspect, <<~'RUBY', frozen_string_literal: false
class C
def initialize freeze
@a = 1
@@ -721,11 +721,11 @@ assert_equal [false, true, false].inspect, %q{
results << check(C.new(true)) # false
results << check(C.new(true).freeze) # true
results << check(C.new(false).freeze) # false
-}
+RUBY
# move example2: String
# touching moved object causes an error
-assert_equal 'hello world', %q{
+assert_equal 'hello world', <<~'RUBY', frozen_string_literal: false
# move
r = Ractor.new do
obj = Ractor.receive
@@ -743,7 +743,7 @@ assert_equal 'hello world', %q{
else
raise 'unreachable'
end
-}
+RUBY
# move example2: Array
assert_equal '[0, 1]', %q{
@@ -946,7 +946,7 @@ assert_equal 'ArgumentError', %q{
}
# ivar in shareable-objects are not allowed to access from non-main Ractor
-assert_equal "can not get unshareable values from instance variables of classes/modules from non-main Ractors", %q{
+assert_equal "can not get unshareable values from instance variables of classes/modules from non-main Ractors", <<~'RUBY', frozen_string_literal: false
class C
@iv = 'str'
end
@@ -957,13 +957,12 @@ assert_equal "can not get unshareable values from instance variables of classes/
end
end
-
begin
r.take
rescue Ractor::RemoteError => e
e.cause.message
end
-}
+RUBY
# ivar in shareable-objects are not allowed to access from non-main Ractor
assert_equal 'can not access instance variables of shareable objects from non-main Ractors', %q{
@@ -1087,6 +1086,27 @@ assert_equal '333', %q{
a + b + c + d + e + f
}
+# moved objects have their shape properly set to original object's shape
+assert_equal '1234', %q{
+class Obj
+ attr_accessor :a, :b, :c, :d
+ def initialize
+ @a = 1
+ @b = 2
+ @c = 3
+ end
+end
+r = Ractor.new do
+ obj = receive
+ obj.d = 4
+ [obj.a, obj.b, obj.c, obj.d]
+end
+obj = Obj.new
+r.send(obj, move: true)
+values = r.take
+values.join
+}
+
# cvar in shareable-objects are not allowed to access from non-main Ractor
assert_equal 'can not access class variables from non-main Ractors', %q{
class C
@@ -1129,7 +1149,7 @@ assert_equal 'can not access class variables from non-main Ractors', %q{
}
# Getting non-shareable objects via constants by other Ractors is not allowed
-assert_equal 'can not access non-shareable objects in constant C::CONST by non-main Ractor.', %q{
+assert_equal 'can not access non-shareable objects in constant C::CONST by non-main Ractor.', <<~'RUBY', frozen_string_literal: false
class C
CONST = 'str'
end
@@ -1141,10 +1161,10 @@ assert_equal 'can not access non-shareable objects in constant C::CONST by non-m
rescue Ractor::RemoteError => e
e.cause.message
end
-}
+ RUBY
# Constant cache should care about non-sharable constants
-assert_equal "can not access non-shareable objects in constant Object::STR by non-main Ractor.", %q{
+assert_equal "can not access non-shareable objects in constant Object::STR by non-main Ractor.", <<~'RUBY', frozen_string_literal: false
STR = "hello"
def str; STR; end
s = str() # fill const cache
@@ -1153,10 +1173,10 @@ assert_equal "can not access non-shareable objects in constant Object::STR by no
rescue Ractor::RemoteError => e
e.cause.message
end
-}
+RUBY
# Setting non-shareable objects into constants by other Ractors is not allowed
-assert_equal 'can not set constants with non-shareable objects by non-main Ractors', %q{
+assert_equal 'can not set constants with non-shareable objects by non-main Ractors', <<~'RUBY', frozen_string_literal: false
class C
end
r = Ractor.new do
@@ -1167,7 +1187,7 @@ assert_equal 'can not set constants with non-shareable objects by non-main Racto
rescue Ractor::RemoteError => e
e.cause.message
end
-}
+RUBY
# define_method is not allowed
assert_equal "defined with an un-shareable Proc in a different Ractor", %q{
@@ -1220,7 +1240,7 @@ assert_equal '0', %q{
}
# ObjectSpace._id2ref can not handle unshareable objects with Ractors
-assert_equal 'ok', %q{
+assert_equal 'ok', <<~'RUBY', frozen_string_literal: false
s = 'hello'
Ractor.new s.object_id do |id ;s|
@@ -1230,10 +1250,10 @@ assert_equal 'ok', %q{
:ok
end
end.take
-}
+RUBY
# Ractor.make_shareable(obj)
-assert_equal 'true', %q{
+assert_equal 'true', <<~'RUBY', frozen_string_literal: false
class C
def initialize
@a = 'foo'
@@ -1304,7 +1324,7 @@ assert_equal 'true', %q{
}
Ractor.shareable?(a)
-}
+RUBY
# Ractor.make_shareable(obj) doesn't freeze shareable objects
assert_equal 'true', %q{
@@ -1401,14 +1421,14 @@ assert_equal '[false, false, true, true]', %q{
}
# TracePoint with normal Proc should be Ractor local
-assert_equal '[4, 8]', %q{
+assert_equal '[6, 10]', %q{
rs = []
TracePoint.new(:line){|tp| rs << tp.lineno if tp.path == __FILE__}.enable do
- Ractor.new{ # line 4
+ Ractor.new{ # line 5
a = 1
b = 2
}.take
- c = 3 # line 8
+ c = 3 # line 9
end
rs
}
@@ -1446,6 +1466,25 @@ assert_equal '[:ok, :ok]', %q{
end
}
+# Ractor.select is interruptible
+assert_normal_exit %q{
+ trap(:INT) do
+ exit
+ end
+
+ r = Ractor.new do
+ loop do
+ sleep 1
+ end
+ end
+
+ Thread.new do
+ sleep 0.5
+ Process.kill(:INT, Process.pid)
+ end
+ Ractor.select(r)
+}
+
# Ractor-local storage
assert_equal '[nil, "b", "a"]', %q{
ans = []
@@ -1482,7 +1521,7 @@ assert_equal "#{n}#{n}", %Q{
2.times.map{
Ractor.new do
#{n}.times do
- obj = ''
+ obj = +''
obj.instance_variable_set("@a", 1)
obj.instance_variable_set("@b", 1)
obj.instance_variable_set("@c", 1)
@@ -1532,7 +1571,7 @@ assert_equal "ok", %q{
1_000.times { idle_worker, tmp_reporter = Ractor.select(*workers) }
"ok"
-} unless ENV['RUN_OPTS'] =~ /rjit/ # flaky
+} unless yjit_enabled? || rjit_enabled? # flaky
assert_equal "ok", %q{
def foo(*); ->{ super }; end
@@ -1641,18 +1680,40 @@ assert_match /\Atest_ractor\.rb:1:\s+warning:\s+Ractor is experimental/, %q{
Warning[:experimental] = $VERBOSE = true
STDERR.reopen(STDOUT)
eval("Ractor.new{}.take", nil, "test_ractor.rb", 1)
+}, frozen_string_literal: false
+
+# check moved object
+assert_equal 'ok', %q{
+ r = Ractor.new do
+ Ractor.receive
+ GC.start
+ :ok
+ end
+
+ obj = begin
+ raise
+ rescue => e
+ e = Marshal.load(Marshal.dump(e))
+ end
+
+ r.send obj, move: true
+ r.take
}
## Ractor::Selector
# Selector#empty? returns true
assert_equal 'true', %q{
+ skip true unless defined? Ractor::Selector
+
s = Ractor::Selector.new
s.empty?
}
# Selector#empty? returns false if there is target ractors
assert_equal 'false', %q{
+ skip false unless defined? Ractor::Selector
+
s = Ractor::Selector.new
s.add Ractor.new{}
s.empty?
@@ -1660,6 +1721,8 @@ assert_equal 'false', %q{
# Selector#clear removes all ractors from the waiting list
assert_equal 'true', %q{
+ skip true unless defined? Ractor::Selector
+
s = Ractor::Selector.new
s.add Ractor.new{10}
s.add Ractor.new{20}
@@ -1669,6 +1732,8 @@ assert_equal 'true', %q{
# Selector#wait can wait multiple ractors
assert_equal '[10, 20, true]', %q{
+ skip [10, 20, true] unless defined? Ractor::Selector
+
s = Ractor::Selector.new
s.add Ractor.new{10}
s.add Ractor.new{20}
@@ -1678,10 +1743,12 @@ assert_equal '[10, 20, true]', %q{
r, v = s.wait
vs << v
[*vs.sort, s.empty?]
-}
+} if defined? Ractor::Selector
# Selector#wait can wait multiple ractors with receiving.
assert_equal '30', %q{
+ skip 30 unless defined? Ractor::Selector
+
RN = 30
rs = RN.times.map{
Ractor.new{ :v }
@@ -1698,11 +1765,12 @@ assert_equal '30', %q{
end
results.size
-}
+} if defined? Ractor::Selector
# Selector#wait can support dynamic addition
-yjit_enabled = ENV.key?('RUBY_YJIT_ENABLE') || ENV.fetch('RUN_OPTS', '').include?('yjit') || BT.ruby.include?('yjit')
assert_equal '600', %q{
+ skip 600 unless defined? Ractor::Selector
+
RN = 100
s = Ractor::Selector.new
rs = RN.times.map{
@@ -1728,10 +1796,12 @@ assert_equal '600', %q{
end
h.sum{|k, v| v}
-} unless yjit_enabled # http://ci.rvm.jp/results/trunk-yjit@ruby-sp2-docker/4466770
+} unless yjit_enabled? # http://ci.rvm.jp/results/trunk-yjit@ruby-sp2-docker/4466770
# Selector should be GCed (free'ed) without trouble
assert_equal 'ok', %q{
+ skip :ok unless defined? Ractor::Selector
+
RN = 30
rs = RN.times.map{
Ractor.new{ :v }
@@ -1741,3 +1811,14 @@ assert_equal 'ok', %q{
}
end # if !ENV['GITHUB_WORKFLOW']
+
+# Chilled strings are not shareable
+assert_equal 'false', %q{
+ Ractor.shareable?("chilled")
+}
+
+# Chilled strings can be made shareable
+assert_equal 'true', %q{
+ shareable = Ractor.make_shareable("chilled")
+ shareable == "chilled" && Ractor.shareable?(shareable)
+}
diff --git a/bootstraptest/test_rjit.rb b/bootstraptest/test_rjit.rb
index 464af7a6e6..e123f35160 100644
--- a/bootstraptest/test_rjit.rb
+++ b/bootstraptest/test_rjit.rb
@@ -42,3 +42,17 @@ assert_equal '1', %q{
entry
}
+
+# Updating local type in Context
+assert_normal_exit %q{
+ def foo(flag, object)
+ klass = if flag
+ object
+ end
+ klass ||= object
+ return klass.new
+ end
+
+ foo(false, Object)
+ foo(true, Object)
+}
diff --git a/bootstraptest/test_syntax.rb b/bootstraptest/test_syntax.rb
index 59fdae651f..8301b344c6 100644
--- a/bootstraptest/test_syntax.rb
+++ b/bootstraptest/test_syntax.rb
@@ -528,24 +528,24 @@ assert_equal %q{1}, %q{
i
}
def assert_syntax_error expected, code, message = ''
- assert_equal "#{expected}",
- "begin eval(%q{#{code}}, nil, '', 0)"'; rescue SyntaxError => e; e.message[/\A:(?:\d+:)? (.*)/, 1] end', message
+ assert_match /^#{Regexp.escape(expected)}/,
+ "begin eval(%q{#{code}}, nil, '', 0)"'; rescue SyntaxError => e; e.message[/(?:\^~*|\A:(?:\d+:)?(?! syntax errors? found)(?: syntax error,)?) (.*)/, 1] end', message
end
assert_syntax_error "unterminated string meets end of file", '().."', '[ruby-dev:29732]'
assert_equal %q{[]}, %q{$&;[]}, '[ruby-dev:31068]'
-assert_syntax_error "syntax error, unexpected *, expecting '}'", %q{{*0}}, '[ruby-dev:31072]'
-assert_syntax_error "`@0' is not allowed as an instance variable name", %q{@0..0}, '[ruby-dev:31095]'
-assert_syntax_error "`$00' is not allowed as a global variable name", %q{$00..0}, '[ruby-dev:31100]'
-assert_syntax_error "`$00' is not allowed as a global variable name", %q{0..$00=1}
+assert_syntax_error "unexpected *, expecting '}'", %q{{*0}}, '[ruby-dev:31072]'
+assert_syntax_error "'@0' is not allowed as an instance variable name", %q{@0..0}, '[ruby-dev:31095]'
+assert_syntax_error "'$00' is not allowed as a global variable name", %q{$00..0}, '[ruby-dev:31100]'
+assert_syntax_error "'$00' is not allowed as a global variable name", %q{0..$00=1}
assert_equal %q{0}, %q{[*0];0}, '[ruby-dev:31102]'
-assert_syntax_error "syntax error, unexpected ')'", %q{v0,(*,v1,) = 0}, '[ruby-dev:31104]'
+assert_syntax_error "unexpected ')'", %q{v0,(*,v1,) = 0}, '[ruby-dev:31104]'
assert_equal %q{1}, %q{
class << (ary=[]); def []; 0; end; def []=(x); super(0,x);end;end; ary[]+=1
}, '[ruby-dev:31110]'
assert_syntax_error "Can't set variable $1", %q{0..$1=1}, '[ruby-dev:31118]'
assert_valid_syntax %q{1.times{1+(1&&next)}}, '[ruby-dev:31119]'
assert_valid_syntax %q{x=-1;loop{x+=1&&redo if (x+=1).zero?}}, '[ruby-dev:31119]'
-assert_syntax_error %q{syntax error, unexpected end-of-input}, %q{!}, '[ruby-dev:31243]'
+assert_syntax_error %q{unexpected end-of-input}, %q{!}, '[ruby-dev:31243]'
assert_equal %q{[nil]}, %q{[()]}, '[ruby-dev:31252]'
assert_equal %q{true}, %q{!_=()}, '[ruby-dev:31263]'
assert_equal 'ok', %q{while true; redo; end if 1 == 2; :ok}, '[ruby-dev:31360]'
@@ -629,7 +629,7 @@ assert_equal '2', %q{
assert_match /invalid multibyte char/, %q{
$stderr = STDOUT
- eval("\"\xf0".force_encoding("utf-8"))
+ eval("\"\xf0".dup.force_encoding("utf-8"))
}, '[ruby-dev:32429]'
# method ! and !=
@@ -848,7 +848,7 @@ assert_normal_exit %q{
def x(a=1, b, *rest); nil end
end
end
-}, bug2415
+}, bug2415 unless rjit_enabled? # flaky
assert_normal_exit %q{
0.times do
@@ -880,7 +880,7 @@ assert_normal_exit %q{
end
end
end
-}, bug2415
+}, bug2415 unless rjit_enabled? # flaky
assert_normal_exit %q{
a {
@@ -904,3 +904,35 @@ assert_normal_exit %q{
Class
end
}, '[ruby-core:30293]'
+
+assert_equal "false", <<~RUBY, "literal strings are mutable", "--disable-frozen-string-literal"
+ 'test'.frozen?
+RUBY
+
+assert_equal "true", <<~RUBY, "literal strings are frozen", "--disable-frozen-string-literal", frozen_string_literal: true
+ 'test'.frozen?
+RUBY
+
+assert_equal "true", <<~RUBY, "literal strings are frozen", "--enable-frozen-string-literal"
+ 'test'.frozen?
+RUBY
+
+assert_equal "false", <<~RUBY, "literal strings are mutable", "--enable-frozen-string-literal", frozen_string_literal: false
+ 'test'.frozen?
+RUBY
+
+assert_equal "false", <<~RUBY, "__FILE__ is mutable", "--disable-frozen-string-literal"
+ __FILE__.frozen?
+RUBY
+
+assert_equal "true", <<~RUBY, "__FILE__ is frozen", "--disable-frozen-string-literal", frozen_string_literal: true
+ __FILE__.frozen?
+RUBY
+
+assert_equal "true", <<~RUBY, "__FILE__ is frozen", "--enable-frozen-string-literal"
+ __FILE__.frozen?
+RUBY
+
+assert_equal "false", <<~RUBY, "__FILE__ is mutable", "--enable-frozen-string-literal", frozen_string_literal: false
+ __FILE__.frozen?
+RUBY
diff --git a/bootstraptest/test_thread.rb b/bootstraptest/test_thread.rb
index 18b4fcd2e9..a4d46e2f10 100644
--- a/bootstraptest/test_thread.rb
+++ b/bootstraptest/test_thread.rb
@@ -293,7 +293,6 @@ assert_normal_exit %q{
exec "/"
}
-rjit_enabled = RUBY_DESCRIPTION.include?('+RJIT')
assert_normal_exit %q{
(0..10).map {
Thread.new {
@@ -304,7 +303,7 @@ assert_normal_exit %q{
}.each {|t|
t.join
}
-} unless rjit_enabled # flaky
+} unless rjit_enabled? # flaky
assert_equal 'ok', %q{
def m
@@ -498,7 +497,7 @@ assert_equal 'foo', %q{
[th1, th2].each {|t| t.join }
GC.start
f.call.source
-} unless rjit_enabled # flaky
+} unless rjit_enabled? # flaky
assert_normal_exit %q{
class C
def inspect
diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb
index a2a05c45d7..f3e935d99e 100644
--- a/bootstraptest/test_yjit.rb
+++ b/bootstraptest/test_yjit.rb
@@ -1,3 +1,148 @@
+# To run the tests in this file only, with YJIT enabled:
+# make btest BTESTS=bootstraptest/test_yjit.rb RUN_OPTS="--yjit-call-threshold=1"
+
+# regression test for popping before side exit
+assert_equal "ok", %q{
+ def foo(a, *) = a
+
+ def call(args, &)
+ foo(1) # spill at where the block arg will be
+ foo(*args, &)
+ end
+
+ call([1, 2])
+
+ begin
+ call([])
+ rescue ArgumentError
+ :ok
+ end
+}
+
+# regression test for send processing before side exit
+assert_equal "ok", %q{
+ def foo(a, *) = :foo
+
+ def call(args)
+ send(:foo, *args)
+ end
+
+ call([1, 2])
+
+ begin
+ call([])
+ rescue ArgumentError
+ :ok
+ end
+}
+
+# test discarding extra yield arguments
+assert_equal "2210150001501015", %q{
+ def splat_kw(ary) = yield *ary, a: 1
+
+ def splat(ary) = yield *ary
+
+ def kw = yield 1, 2, a: 0
+
+ def simple = yield 0, 1
+
+ def calls
+ [
+ splat([1, 1, 2]) { |x, y| x + y },
+ splat([1, 1, 2]) { |y, opt = raise| opt + y},
+ splat_kw([0, 1]) { |a:| a },
+ kw { |a:| a },
+ kw { |a| a },
+ simple { 5.itself },
+ simple { |a| a },
+ simple { |opt = raise| opt },
+ simple { |*rest| rest },
+ simple { |opt_kw: 5| opt_kw },
+ # autosplat ineractions
+ [0, 1, 2].yield_self { |a, b| [a, b] },
+ [0, 1, 2].yield_self { |a, opt = raise| [a, opt] },
+ [1].yield_self { |a, opt = 4| a + opt },
+ ]
+ end
+
+ calls.join
+}
+
+# test autosplat with empty splat
+assert_equal "ok", %q{
+ def m(pos, splat) = yield pos, *splat
+
+ m([:ok], []) {|v0,| v0 }
+}
+
+# regression test for send stack shifting
+assert_normal_exit %q{
+ def foo(a, b)
+ a.singleton_methods(b)
+ end
+
+ def call_foo
+ [1, 1, 1, 1, 1, 1, send(:foo, 1, 1)]
+ end
+
+ call_foo
+}
+
+# regression test for keyword splat with yield
+assert_equal 'nil', %q{
+ def splat_kw(kwargs) = yield(**kwargs)
+
+ splat_kw({}) { _1 }.inspect
+}
+
+# regression test for arity check with splat
+assert_equal '[:ae, :ae]', %q{
+ def req_one(a_, b_ = 1) = raise
+
+ def test(args)
+ req_one *args
+ rescue ArgumentError
+ :ae
+ end
+
+ [test(Array.new 5), test([])]
+} unless rjit_enabled? # Not yet working on RJIT
+
+# regression test for arity check with splat and send
+assert_equal '[:ae, :ae]', %q{
+ def two_reqs(a, b_, _ = 1) = a.gsub(a, a)
+
+ def test(name, args)
+ send(name, *args)
+ rescue ArgumentError
+ :ae
+ end
+
+ [test(:two_reqs, ["g", nil, nil, nil]), test(:two_reqs, ["g"])]
+}
+
+# regression test for GC marking stubs in invalidated code
+assert_normal_exit %q{
+ garbage = Array.new(10_000) { [] } # create garbage to cause iseq movement
+ eval(<<~RUBY)
+ def foo(n, garbage)
+ if n == 2
+ # 1.times.each to create a cfunc frame to preserve the JIT frame
+ # which will return to a stub housed in an invalidated block
+ return 1.times.each do
+ Object.define_method(:foo) {}
+ garbage.clear
+ GC.verify_compaction_references(toward: :empty, expand_heap: true)
+ end
+ end
+
+ foo(n + 1, garbage)
+ end
+ RUBY
+
+ foo(1, garbage)
+}
+
# regression test for callee block handler overlapping with arguments
assert_equal '3', %q{
def foo(_req, *args) = args.last
@@ -20,7 +165,7 @@ assert_equal 'ok', %q{
GC.compact
end
:ok
-} unless defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? # Not yet working on RJIT
+} unless rjit_enabled? # Not yet working on RJIT
# regression test for overly generous guard elision
assert_equal '[0, :sum, 0, :sum]', %q{
@@ -40,7 +185,7 @@ assert_equal '[0, :sum, 0, :sum]', %q{
end
def cstring(iter)
- string = ""
+ string = "".dup
string.sum(iter.times { def string.sum(_) = :sum })
end
@@ -148,7 +293,7 @@ assert_equal '[:ok]', %q{
# Used to crash due to GC run in rb_ensure_iv_list_size()
# not marking the newly allocated [:ok].
RegressionTest.new.extender.itself
-} unless RUBY_DESCRIPTION.include?('+RJIT') # Skip on RJIT since this uncovers a crash
+} unless rjit_enabled? # Skip on RJIT since this uncovers a crash
assert_equal 'true', %q{
# regression test for tracking type of locals for too long
@@ -198,7 +343,7 @@ assert_normal_exit %q{
}
assert_normal_exit %q{
- # Test to ensure send on overriden c functions
+ # Test to ensure send on overridden c functions
# doesn't corrupt the stack
class Bar
def bar(x)
@@ -278,6 +423,33 @@ assert_equal '["instance-variable", 5]', %q{
Foo.new.foo
}
+# getinstancevariable with shape too complex
+assert_normal_exit %q{
+ class Foo
+ def initialize
+ @a = 1
+ end
+
+ def getter
+ @foobar
+ end
+ end
+
+ # Initialize ivars in changing order, making the Foo
+ # class have shape too complex
+ 100.times do |x|
+ foo = Foo.new
+ foo.instance_variable_set(:"@a#{x}", 1)
+ foo.instance_variable_set(:"@foobar", 777)
+
+ # The getter method eventually sees shape too complex
+ r = foo.getter
+ if r != 777
+ raise "error"
+ end
+ end
+}
+
assert_equal '0', %q{
# This is a regression test for incomplete invalidation from
# opt_setinlinecache. This test might be brittle, so
@@ -1078,7 +1250,7 @@ assert_equal "good", %q{
# Test polymorphic getinstancevariable. T_OBJECT -> T_STRING
assert_equal 'ok', %q{
@hello = @h1 = @h2 = @h3 = @h4 = 'ok'
- str = ""
+ str = +""
str.instance_variable_set(:@hello, 'ok')
public def get
@@ -1223,7 +1395,7 @@ assert_equal '[42, :default]', %q{
}
# Test default value block for Hash with opt_aref_with
-assert_equal "false", %q{
+assert_equal "false", <<~RUBY, frozen_string_literal: false
def index_with_string(h)
h["foo"]
end
@@ -1232,7 +1404,7 @@ assert_equal "false", %q{
index_with_string(h)
index_with_string(h)
-}
+RUBY
# A regression test for making sure cfp->sp is proper when
# hitting stubs. See :stub-sp-flush:
@@ -1732,7 +1904,7 @@ assert_equal 'foo', %q{
}
# Test that String unary plus returns the same object ID for an unfrozen string.
-assert_equal 'true', %q{
+assert_equal 'true', <<~RUBY, frozen_string_literal: false
def jittable_method
str = "bar"
@@ -1742,7 +1914,7 @@ assert_equal 'true', %q{
uplus_str.object_id == old_obj_id
end
jittable_method
-}
+RUBY
# Test that String unary plus returns a different unfrozen string when given a frozen string
assert_equal 'false', %q{
@@ -1872,7 +2044,68 @@ assert_equal '[97, :nil, 97, :nil, :raised]', %q{
getbyte("a", 0)
[getbyte("a", 0), getbyte("a", 1), getbyte("a", -1), getbyte("a", -2), getbyte("a", "a")]
-} unless defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? # Not yet working on RJIT
+} unless rjit_enabled? # Not yet working on RJIT
+
+# Basic test for String#setbyte
+assert_equal 'AoZ', %q{
+ s = +"foo"
+ s.setbyte(0, 65)
+ s.setbyte(-1, 90)
+ s
+}
+
+# String#setbyte IndexError
+assert_equal 'String#setbyte', %q{
+ def ccall = "".setbyte(1, 0)
+ begin
+ ccall
+ rescue => e
+ e.backtrace.first.split("'").last
+ end
+}
+
+# String#setbyte TypeError
+assert_equal 'String#setbyte', %q{
+ def ccall = "".setbyte(nil, 0)
+ begin
+ ccall
+ rescue => e
+ e.backtrace.first.split("'").last
+ end
+}
+
+# String#setbyte FrozenError
+assert_equal 'String#setbyte', %q{
+ def ccall = "a".freeze.setbyte(0, 0)
+ begin
+ ccall
+ rescue => e
+ e.backtrace.first.split("'").last
+ end
+}
+
+# non-leaf String#setbyte
+assert_equal 'String#setbyte', %q{
+ def to_int
+ @caller = caller
+ 0
+ end
+
+ def ccall = "a".dup.setbyte(self, 98)
+ ccall
+
+ @caller.first.split("'").last
+}
+
+# non-leaf String#byteslice
+assert_equal 'TypeError', %q{
+ def ccall = "".byteslice(nil, nil)
+ begin
+ ccall
+ rescue => e
+ e.class
+ end
+}
# Test << operator on string subclass
assert_equal 'abab', %q{
@@ -2084,6 +2317,19 @@ assert_equal '123', %q{
foo(Foo)
}
+# Test EP == BP invalidation with moving ISEQs
+assert_equal 'ok', %q{
+ def entry
+ ok = proc { :ok } # set #entry as an EP-escaping ISEQ
+ [nil].reverse_each do # avoid exiting the JIT frame on the constant
+ GC.compact # move #entry ISEQ
+ end
+ ok # should be read off of escaped EP
+ end
+
+ entry.call
+}
+
# invokesuper edge case
assert_equal '[:A, [:A, :B]]', %q{
class B
@@ -2272,6 +2518,18 @@ assert_equal '[0, 2]', %q{
B.new.foo
}
+# invokesuper zsuper in a bmethod
+assert_equal 'ok', %q{
+ class Foo
+ define_method(:itself) { super }
+ end
+ begin
+ Foo.new.itself
+ rescue RuntimeError
+ :ok
+ end
+}
+
# Call to fixnum
assert_equal '[true, false]', %q{
def is_odd(obj)
@@ -2312,6 +2570,16 @@ assert_equal '[true, false, true, false]', %q{
[is_odd(123), is_odd(456), is_odd(bignum), is_odd(bignum+1)]
}
+# Flonum and Flonum
+assert_equal '[2.0, 0.0, 1.0, 4.0]', %q{
+ [1.0 + 1.0, 1.0 - 1.0, 1.0 * 1.0, 8.0 / 2.0]
+}
+
+# Flonum and Fixnum
+assert_equal '[2.0, 0.0, 1.0, 4.0]', %q{
+ [1.0 + 1, 1.0 - 1, 1.0 * 1, 8.0 / 2]
+}
+
# Call to static and dynamic symbol
assert_equal 'bar', %q{
def to_string(obj)
@@ -2352,6 +2620,30 @@ assert_equal '[1, 2, 3, 4, 5]', %q{
splatarray
}
+# splatkw
+assert_equal '[1, 2]', %q{
+ def foo(a:) = [a, yield]
+
+ def entry(&block)
+ a = { a: 1 }
+ foo(**a, &block)
+ end
+
+ entry { 2 }
+}
+assert_equal '[1, 2]', %q{
+ def foo(a:) = [a, yield]
+
+ def entry(obj, &block)
+ foo(**obj, &block)
+ end
+
+ entry({ a: 3 }) { 2 }
+ obj = Object.new
+ def obj.to_hash = { a: 1 }
+ entry(obj) { 2 }
+}
+
assert_equal '[1, 1, 2, 1, 2, 3]', %q{
def expandarray
arr = [1, 2, 3]
@@ -2406,6 +2698,23 @@ assert_equal '[:not_array, nil, nil]', %q{
expandarray_not_array(obj)
}
+assert_equal '[1, 2]', %q{
+ class NilClass
+ private
+ def to_ary
+ [1, 2]
+ end
+ end
+
+ def expandarray_redefined_nilclass
+ a, b = nil
+ [a, b]
+ end
+
+ expandarray_redefined_nilclass
+ expandarray_redefined_nilclass
+} unless rjit_enabled?
+
assert_equal '[1, 2, nil]', %q{
def expandarray_rhs_too_small
a, b, c = [1, 2]
@@ -2516,7 +2825,7 @@ assert_equal '[[:c_return, :String, :string_alias, "events_to_str"]]', %q{
events.compiled(events)
events
-} unless defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? # RJIT calls extra Ruby methods
+} unless rjit_enabled? # RJIT calls extra Ruby methods
# test enabling a TracePoint that targets a particular line in a C method call
assert_equal '[true]', %q{
@@ -2598,7 +2907,7 @@ assert_equal '[[:c_call, :itself]]', %q{
tp.enable { shouldnt_compile }
events
-} unless defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? # RJIT calls extra Ruby methods
+} unless rjit_enabled? # RJIT calls extra Ruby methods
# test enabling c_return tracing before compiling
assert_equal '[[:c_return, :itself, main]]', %q{
@@ -2613,7 +2922,7 @@ assert_equal '[[:c_return, :itself, main]]', %q{
tp.enable { shouldnt_compile }
events
-} unless defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? # RJIT calls extra Ruby methods
+} unless rjit_enabled? # RJIT calls extra Ruby methods
# test c_call invalidation
assert_equal '[[:c_call, :itself]]', %q{
@@ -3871,7 +4180,7 @@ assert_equal '2', %q{
assert_equal 'Hello World', %q{
def bar
args = ["Hello "]
- greeting = "World"
+ greeting = +"World"
greeting.insert(0, *args)
greeting
end
@@ -4107,7 +4416,7 @@ assert_equal '[true, true, true, true, true]', %q{
calling_my_func
}
-# Regresssion test: rest and optional and splat
+# Regression test: rest and optional and splat
assert_equal 'true', %q{
def my_func(base=nil, *args)
[base, args]
@@ -4135,9 +4444,9 @@ assert_equal 'true', %q{
rescue ArgumentError
true
end
-} unless defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? # Not yet working on RJIT
+} unless rjit_enabled? # Not yet working on RJIT
-# Regresssion test: register allocator on expandarray
+# Regression test: register allocator on expandarray
assert_equal '[]', %q{
func = proc { [] }
proc do
@@ -4217,3 +4526,533 @@ assert_equal 'true', %q{
def entry = yield
entry { true }
}
+assert_equal 'sym', %q{
+ def entry = :sym.to_sym
+ entry
+}
+
+assert_normal_exit %q{
+ ivars = 1024.times.map { |i| "@iv_#{i} = #{i}\n" }.join
+ Foo = Class.new
+ Foo.class_eval "def initialize() #{ivars} end"
+ Foo.new
+}
+
+assert_equal '0', %q{
+ def spill
+ 1.to_i # not inlined
+ end
+
+ def inline(_stack1, _stack2, _stack3, _stack4, _stack5)
+ 0 # inlined
+ end
+
+ def entry
+ # RegTemps is 00111110 prior to the #inline call.
+ # Its return value goes to stack_idx=0, which conflicts with stack_idx=5.
+ inline(spill, 2, 3, 4, 5)
+ end
+
+ entry
+}
+
+# Integer succ and overflow
+assert_equal '[2, 4611686018427387904]', %q{
+ [1.succ, 4611686018427387903.succ]
+}
+
+# Integer right shift
+assert_equal '[0, 1, -4]', %q{
+ [0 >> 1, 2 >> 1, -7 >> 1]
+}
+
+# Integer XOR
+assert_equal '[0, 0, 4]', %q{
+ [0 ^ 0, 1 ^ 1, 7 ^ 3]
+}
+
+assert_equal '[nil, "yield"]', %q{
+ def defined_yield = defined?(yield)
+ [defined_yield, defined_yield {}]
+}
+
+# splat with ruby2_keywords into rest parameter
+assert_equal '[[{:a=>1}], {}]', %q{
+ ruby2_keywords def foo(*args) = args
+
+ def bar(*args, **kw) = [args, kw]
+
+ def pass_bar(*args) = bar(*args)
+
+ def body
+ args = foo(a: 1)
+ pass_bar(*args)
+ end
+
+ body
+}
+
+# concatarray
+assert_equal '[1, 2]', %q{
+ def foo(a, b) = [a, b]
+ arr = [2]
+ foo(*[1], *arr)
+}
+
+# pushtoarray
+assert_equal '[1, 2]', %q{
+ def foo(a, b) = [a, b]
+ arr = [1]
+ foo(*arr, 2)
+}
+
+# pop before fallback
+assert_normal_exit %q{
+ class Foo
+ attr_reader :foo
+
+ def try = foo(0, &nil)
+ end
+
+ Foo.new.try
+}
+
+# a kwrest case
+assert_equal '[1, 2, {:complete=>false}]', %q{
+ def rest(foo: 1, bar: 2, **kwrest)
+ [foo, bar, kwrest]
+ end
+
+ def callsite = rest(complete: false)
+
+ callsite
+}
+
+# splat+kw_splat+opt+rest
+assert_equal '[1, []]', %q{
+ def opt_rest(a = 0, *rest) = [a, rest]
+
+ def call_site(args) = opt_rest(*args, **nil)
+
+ call_site([1])
+}
+
+# splat and nil kw_splat
+assert_equal 'ok', %q{
+ def identity(x) = x
+
+ def splat_nil_kw_splat(args) = identity(*args, **nil)
+
+ splat_nil_kw_splat([:ok])
+}
+
+# empty splat and kwsplat into leaf builtins
+assert_equal '[1, 1, 1]', %q{
+ empty = []
+ [1.abs(*empty), 1.abs(**nil), 1.bit_length(*empty, **nil)]
+}
+
+# splat into C methods with -1 arity
+assert_equal '[[1, 2, 3], [0, 2, 3], [1, 2, 3], [2, 2, 3], [], [], [{}]]', %q{
+ class Foo < Array
+ def push(args) = super(1, *args)
+ end
+
+ def test_cfunc_vargs_splat(sub_instance, array_class, empty_kw_hash)
+ splat = [2, 3]
+ kw_splat = [empty_kw_hash]
+ [
+ sub_instance.push(splat),
+ array_class[0, *splat, **nil],
+ array_class[1, *splat, &nil],
+ array_class[2, *splat, **nil, &nil],
+ array_class.send(:[], *kw_splat),
+ # kw_splat disables keywords hash handling
+ array_class[*kw_splat],
+ array_class[*kw_splat, **nil],
+ ]
+ end
+
+ test_cfunc_vargs_splat(Foo.new, Array, Hash.ruby2_keywords_hash({}))
+}
+
+# Class#new (arity=-1), splat, and ruby2_keywords
+assert_equal '[0, {1=>1}]', %q{
+ class KwInit
+ attr_reader :init_args
+ def initialize(x = 0, **kw)
+ @init_args = [x, kw]
+ end
+ end
+
+ def test(klass, args)
+ klass.new(*args).init_args
+ end
+
+ test(KwInit, [Hash.ruby2_keywords_hash({1 => 1})])
+}
+
+# Chilled string setivar trigger warning
+assert_equal 'literal string will be frozen in the future', %q{
+ Warning[:deprecated] = true
+ $VERBOSE = true
+ $warning = "no-warning"
+ module ::Warning
+ def self.warn(message)
+ $warning = message.split("warning: ").last.strip
+ end
+ end
+
+ class String
+ def setivar!
+ @ivar = 42
+ end
+ end
+
+ def setivar!(str)
+ str.setivar!
+ end
+
+ 10.times { setivar!("mutable".dup) }
+ 10.times do
+ setivar!("frozen".freeze)
+ rescue FrozenError
+ end
+
+ setivar!("chilled") # Emit warning
+ $warning
+}
+
+# arity=-2 cfuncs
+assert_equal '["", "1/2", [0, [:ok, 1]]]', %q{
+ def test_cases(file, chain)
+ new_chain = chain.allocate # to call initialize directly
+ new_chain.send(:initialize, [0], ok: 1)
+
+ [
+ file.join,
+ file.join("1", "2"),
+ new_chain.to_a,
+ ]
+ end
+
+ test_cases(File, Enumerator::Chain)
+}
+
+# singleton class should invalidate Type::CString assumption
+assert_equal 'foo', %q{
+ def define_singleton(str, define)
+ if define
+ # Wrap a C method frame to avoid exiting JIT code on defineclass
+ [nil].reverse_each do
+ class << str
+ def +(_)
+ "foo"
+ end
+ end
+ end
+ end
+ "bar"
+ end
+
+ def entry(define)
+ str = ""
+ # When `define` is false, #+ compiles to rb_str_plus() without a class guard.
+ # When the code is reused with `define` is true, the class of `str` is changed
+ # to a singleton class, so the block should be invalidated.
+ str + define_singleton(str, define)
+ end
+
+ entry(false)
+ entry(true)
+}
+
+assert_equal '[:ok, :ok, :ok]', %q{
+ def identity(x) = x
+ def foo(x, _) = x
+ def bar(_, _, _, _, x) = x
+
+ def tests
+ [
+ identity(:ok),
+ foo(:ok, 2),
+ bar(1, 2, 3, 4, :ok),
+ ]
+ end
+
+ tests
+}
+
+# regression test for invalidating an empty block
+assert_equal '0', %q{
+ def foo = (* = 1).pred
+
+ foo # compile it
+
+ class Integer
+ def to_ary = [] # invalidate
+ end
+
+ foo # try again
+} unless rjit_enabled? # doesn't work on RJIT
+
+# test integer left shift with constant rhs
+assert_equal [0x80000000000, 'a+', :ok].inspect, %q{
+ def shift(val) = val << 43
+
+ def tests
+ int = shift(1)
+ str = shift("a")
+
+ Integer.define_method(:<<) { |_| :ok }
+ redef = shift(1)
+
+ [int, str, redef]
+ end
+
+ tests
+}
+
+# test integer left shift fusion followed by opt_getconstant_path
+assert_equal '33', %q{
+ def test(a)
+ (a << 5) | (Object; a)
+ end
+
+ test(1)
+}
+
+# test String#stebyte with arguments that need conversion
+assert_equal "abc", %q{
+ str = +"a00"
+ def change_bytes(str, one, two)
+ str.setbyte(one, "b".ord)
+ str.setbyte(2, two)
+ end
+
+ to_int_1 = Object.new
+ to_int_99 = Object.new
+ def to_int_1.to_int = 1
+ def to_int_99.to_int = 99
+
+ change_bytes(str, to_int_1, to_int_99)
+ str
+}
+
+# test --yjit-verify-ctx for arrays with a singleton class
+assert_equal "ok", %q{
+ class Array
+ def foo
+ self.singleton_class.define_method(:first) { :ok }
+ first
+ end
+ end
+
+ def test = [].foo
+
+ test
+}
+
+assert_equal '["raised", "Module", "Object"]', %q{
+ def foo(obj)
+ obj.superclass.name
+ end
+
+ ret = []
+
+ begin
+ foo(Class.allocate)
+ rescue TypeError
+ ret << 'raised'
+ end
+
+ ret += [foo(Class), foo(Class.new)]
+}
+
+# test TrueClass#=== before and after redefining TrueClass#==
+assert_equal '[[true, false, false], [true, true, false], [true, :error, :error]]', %q{
+ def true_eqq(x)
+ true === x
+ rescue NoMethodError
+ :error
+ end
+
+ def test
+ [
+ # first one is always true because rb_equal does object comparison before calling #==
+ true_eqq(true),
+ # these will use TrueClass#==
+ true_eqq(false),
+ true_eqq(:truthy),
+ ]
+ end
+
+ results = [test]
+
+ class TrueClass
+ def ==(x)
+ !x
+ end
+ end
+
+ results << test
+
+ class TrueClass
+ undef_method :==
+ end
+
+ results << test
+} unless rjit_enabled? # Not yet working on RJIT
+
+# test FalseClass#=== before and after redefining FalseClass#==
+assert_equal '[[true, false, false], [true, false, true], [true, :error, :error]]', %q{
+ def case_equal(x, y)
+ x === y
+ rescue NoMethodError
+ :error
+ end
+
+ def test
+ [
+ # first one is always true because rb_equal does object comparison before calling #==
+ case_equal(false, false),
+ # these will use #==
+ case_equal(false, true),
+ case_equal(false, nil),
+ ]
+ end
+
+ results = [test]
+
+ class FalseClass
+ def ==(x)
+ !x
+ end
+ end
+
+ results << test
+
+ class FalseClass
+ undef_method :==
+ end
+
+ results << test
+} unless rjit_enabled? # Not yet working on RJIT
+
+# test NilClass#=== before and after redefining NilClass#==
+assert_equal '[[true, false, false], [true, false, true], [true, :error, :error]]', %q{
+ def case_equal(x, y)
+ x === y
+ rescue NoMethodError
+ :error
+ end
+
+ def test
+ [
+ # first one is always true because rb_equal does object comparison before calling #==
+ case_equal(nil, nil),
+ # these will use #==
+ case_equal(nil, true),
+ case_equal(nil, false),
+ ]
+ end
+
+ results = [test]
+
+ class NilClass
+ def ==(x)
+ !x
+ end
+ end
+
+ results << test
+
+ class NilClass
+ undef_method :==
+ end
+
+ results << test
+} unless rjit_enabled? # Not yet working on RJIT
+
+# test struct accessors fire c_call events
+assert_equal '[[:c_call, :x=], [:c_call, :x]]', %q{
+ c = Struct.new(:x)
+ obj = c.new
+
+ events = []
+ TracePoint.new(:c_call) do
+ events << [_1.event, _1.method_id]
+ end.enable do
+ obj.x = 100
+ obj.x
+ end
+
+ events
+}
+
+# regression test for splatting empty array
+assert_equal '1', %q{
+ def callee(foo) = foo
+
+ def test_body(args) = callee(1, *args)
+
+ test_body([])
+ array = Array.new(100)
+ array.clear
+ test_body(array)
+}
+
+# regression test for splatting empty array to cfunc
+assert_normal_exit %q{
+ def test_body(args) = Array(1, *args)
+
+ test_body([])
+ 0x100.times do
+ array = Array.new(100)
+ array.clear
+ test_body(array)
+ end
+}
+
+# compiling code shouldn't emit warnings as it may call into more Ruby code
+assert_equal 'ok', <<~'RUBY'
+ # [Bug #20522]
+ $VERBOSE = true
+ Warning[:performance] = true
+
+ module StrictWarnings
+ def warn(msg, **)
+ raise msg
+ end
+ end
+ Warning.singleton_class.prepend(StrictWarnings)
+
+ class A
+ def compiled_method(is_private)
+ @some_ivar = is_private
+ end
+ end
+
+ shape_max_variations = 8
+ if defined?(RubyVM::Shape::SHAPE_MAX_VARIATIONS) && RubyVM::Shape::SHAPE_MAX_VARIATIONS != shape_max_variations
+ raise "Expected SHAPE_MAX_VARIATIONS to be #{shape_max_variations}, got: #{RubyVM::Shape::SHAPE_MAX_VARIATIONS}"
+ end
+
+ 100.times do |i|
+ klass = Class.new(A)
+ (shape_max_variations - 1).times do |j|
+ obj = klass.new
+ obj.instance_variable_set("@base_#{i}", 42)
+ obj.instance_variable_set("@ivar_#{j}", 42)
+ end
+ obj = klass.new
+ obj.instance_variable_set("@base_#{i}", 42)
+ begin
+ obj.compiled_method(true)
+ rescue
+ # expected
+ end
+ end
+
+ :ok
+RUBY
diff --git a/builtin.c b/builtin.c
index b725d8b968..fbc11bf1b4 100644
--- a/builtin.c
+++ b/builtin.c
@@ -46,7 +46,6 @@ rb_load_with_builtin_functions(const char *feature_name, const struct rb_builtin
rb_vm_t *vm = GET_VM();
if (vm->builtin_function_table != NULL) rb_bug("vm->builtin_function_table should be NULL.");
vm->builtin_function_table = table;
- vm->builtin_inline_index = 0;
const rb_iseq_t *iseq = rb_iseq_ibf_load_bytes((const char *)bin, size);
ASSUME(iseq); // otherwise an exception should have raised
vm->builtin_function_table = NULL;
@@ -58,6 +57,12 @@ rb_load_with_builtin_functions(const char *feature_name, const struct rb_builtin
#endif
void
+rb_free_loaded_builtin_table(void)
+{
+ // do nothing
+}
+
+void
Init_builtin(void)
{
// nothing
diff --git a/builtin.h b/builtin.h
index 85fd1a009a..24aa7c2fdb 100644
--- a/builtin.h
+++ b/builtin.h
@@ -106,6 +106,8 @@ rb_vm_lvar(rb_execution_context_t *ec, int index)
#endif
}
+#define LOCAL_PTR(local) local ## __ptr
+
// dump/load
struct builtin_binary {
diff --git a/ccan/list/list.h b/ccan/list/list.h
index 30b2af04e9..bf692a6937 100644
--- a/ccan/list/list.h
+++ b/ccan/list/list.h
@@ -635,14 +635,16 @@ static inline void ccan_list_prepend_list_(struct ccan_list_head *to,
/* internal macros, do not use directly */
#define ccan_list_for_each_off_dir_(h, i, off, dir) \
- for (i = ccan_list_node_to_off_(ccan_list_debug(h, CCAN_LIST_LOC)->n.dir, \
+ for (i = 0, \
+ i = ccan_list_node_to_off_(ccan_list_debug(h, CCAN_LIST_LOC)->n.dir, \
(off)); \
ccan_list_node_from_off_((void *)i, (off)) != &(h)->n; \
i = ccan_list_node_to_off_(ccan_list_node_from_off_((void *)i, (off))->dir, \
(off)))
#define ccan_list_for_each_safe_off_dir_(h, i, nxt, off, dir) \
- for (i = ccan_list_node_to_off_(ccan_list_debug(h, CCAN_LIST_LOC)->n.dir, \
+ for (i = 0, \
+ i = ccan_list_node_to_off_(ccan_list_debug(h, CCAN_LIST_LOC)->n.dir, \
(off)), \
nxt = ccan_list_node_to_off_(ccan_list_node_from_off_(i, (off))->dir, \
(off)); \
diff --git a/class.c b/class.c
index f730009709..5cce99e334 100644
--- a/class.c
+++ b/class.c
@@ -29,12 +29,18 @@
#include "internal/variable.h"
#include "ruby/st.h"
#include "vm_core.h"
+#include "yjit.h"
/* Flags of T_CLASS
*
- * 2: RCLASS_SUPERCLASSES_INCLUDE_SELF
- * The RCLASS_SUPERCLASSES contains the class as the last element.
- * This means that this class owns the RCLASS_SUPERCLASSES list.
+ * 0: RCLASS_IS_ROOT
+ * The class has been added to the VM roots. Will always be marked and pinned.
+ * This is done for classes defined from C to allow storing them in global variables.
+ * 1: RUBY_FL_SINGLETON
+ * This class is a singleton class.
+ * 2: RCLASS_SUPERCLASSES_INCLUDE_SELF
+ * The RCLASS_SUPERCLASSES contains the class as the last element.
+ * This means that this class owns the RCLASS_SUPERCLASSES list.
* if !SHAPE_IN_BASIC_FLAGS
* 4-19: SHAPE_FLAG_MASK
* Shape ID for the class.
@@ -54,6 +60,9 @@
/* Flags of T_MODULE
*
+ * 0: RCLASS_IS_ROOT
+ * The class has been added to the VM roots. Will always be marked and pinned.
+ * This is done for classes defined from C to allow storing them in global variables.
* 1: RMODULE_ALLOCATED_BUT_NOT_INITIALIZED
* Module has not been initialized.
* 2: RCLASS_SUPERCLASSES_INCLUDE_SELF
@@ -217,14 +226,14 @@ rb_class_detach_module_subclasses(VALUE klass)
/**
* Allocates a struct RClass for a new class.
*
- * \param flags initial value for basic.flags of the returned class.
- * \param klass the class of the returned class.
- * \return an uninitialized Class object.
- * \pre \p klass must refer \c Class class or an ancestor of Class.
- * \pre \code (flags | T_CLASS) != 0 \endcode
- * \post the returned class can safely be \c #initialize 'd.
+ * @param flags initial value for basic.flags of the returned class.
+ * @param klass the class of the returned class.
+ * @return an uninitialized Class object.
+ * @pre `klass` must refer `Class` class or an ancestor of Class.
+ * @pre `(flags | T_CLASS) != 0`
+ * @post the returned class can safely be `#initialize` 'd.
*
- * \note this function is not Class#allocate.
+ * @note this function is not Class#allocate.
*/
static VALUE
class_alloc(VALUE flags, VALUE klass)
@@ -259,14 +268,14 @@ RCLASS_M_TBL_INIT(VALUE c)
RCLASS_M_TBL(c) = rb_id_table_create(0);
}
-/*!
+/**
* A utility function that wraps class_alloc.
*
* allocates a class and initializes safely.
- * \param super a class from which the new class derives.
- * \return a class object.
- * \pre \a super must be a class.
- * \post the metaclass of the new class is Class.
+ * @param super a class from which the new class derives.
+ * @return a class object.
+ * @pre `super` must be a class.
+ * @post the metaclass of the new class is Class.
*/
VALUE
rb_class_boot(VALUE super)
@@ -338,7 +347,7 @@ rb_check_inheritable(VALUE super)
rb_raise(rb_eTypeError, "superclass must be an instance of Class (given an instance of %"PRIsVALUE")",
rb_obj_class(super));
}
- if (RBASIC(super)->flags & FL_SINGLETON) {
+ if (RCLASS_SINGLETON_P(super)) {
rb_raise(rb_eTypeError, "can't make subclass of singleton class");
}
if (super == rb_cClass) {
@@ -424,7 +433,7 @@ class_init_copy_check(VALUE clone, VALUE orig)
if (RCLASS_SUPER(clone) != 0 || clone == rb_cBasicObject) {
rb_raise(rb_eTypeError, "already initialized class");
}
- if (FL_TEST(orig, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON_P(orig)) {
rb_raise(rb_eTypeError, "can't copy singleton class");
}
}
@@ -542,7 +551,7 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
RCLASS_EXT(clone)->cloned = true;
RCLASS_EXT(orig)->cloned = true;
- if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) {
+ if (!RCLASS_SINGLETON_P(CLASS_OF(clone))) {
RBASIC_SET_CLASS(clone, rb_singleton_class_clone(orig));
rb_singleton_class_attached(METACLASS_OF(clone), (VALUE)clone);
}
@@ -578,9 +587,12 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
rb_bug("non iclass between module/class and origin");
}
clone_p = class_alloc(RBASIC(p)->flags, METACLASS_OF(p));
+ /* We should set the m_tbl right after allocation before anything
+ * that can trigger GC to avoid clone_p from becoming old and
+ * needing to fire write barriers. */
+ RCLASS_SET_M_TBL(clone_p, RCLASS_M_TBL(p));
RCLASS_SET_SUPER(prev_clone_p, clone_p);
prev_clone_p = clone_p;
- RCLASS_M_TBL(clone_p) = RCLASS_M_TBL(p);
RCLASS_CONST_TBL(clone_p) = RCLASS_CONST_TBL(p);
RCLASS_SET_ALLOCATOR(clone_p, RCLASS_ALLOCATOR(p));
if (RB_TYPE_P(clone, T_CLASS)) {
@@ -645,7 +657,7 @@ rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach)
// attached to an object other than `obj`. In which case `obj` does not have
// a material singleton class attached yet and there is no singleton class
// to clone.
- if (!(FL_TEST(klass, FL_SINGLETON) && RCLASS_ATTACHED_OBJECT(klass) == obj)) {
+ if (!(RCLASS_SINGLETON_P(klass) && RCLASS_ATTACHED_OBJECT(klass) == obj)) {
// nothing to clone
return klass;
}
@@ -696,7 +708,7 @@ rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach)
void
rb_singleton_class_attached(VALUE klass, VALUE obj)
{
- if (FL_TEST(klass, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON_P(klass)) {
RCLASS_SET_ATTACHED_OBJECT(klass, obj);
}
}
@@ -721,7 +733,7 @@ rb_singleton_class_internal_p(VALUE sklass)
!rb_singleton_class_has_metaclass_p(sklass));
}
-/*!
+/**
* whether k has a metaclass
* @retval 1 if \a k has a metaclass
* @retval 0 otherwise
@@ -730,25 +742,25 @@ rb_singleton_class_internal_p(VALUE sklass)
(FL_TEST(METACLASS_OF(k), FL_SINGLETON) && \
rb_singleton_class_has_metaclass_p(k))
-/*!
- * ensures \a klass belongs to its own eigenclass.
- * @return the eigenclass of \a klass
- * @post \a klass belongs to the returned eigenclass.
- * i.e. the attached object of the eigenclass is \a klass.
+/**
+ * ensures `klass` belongs to its own eigenclass.
+ * @return the eigenclass of `klass`
+ * @post `klass` belongs to the returned eigenclass.
+ * i.e. the attached object of the eigenclass is `klass`.
* @note this macro creates a new eigenclass if necessary.
*/
#define ENSURE_EIGENCLASS(klass) \
(HAVE_METACLASS_P(klass) ? METACLASS_OF(klass) : make_metaclass(klass))
-/*!
- * Creates a metaclass of \a klass
- * \param klass a class
- * \return created metaclass for the class
- * \pre \a klass is a Class object
- * \pre \a klass has no singleton class.
- * \post the class of \a klass is the returned class.
- * \post the returned class is meta^(n+1)-class when \a klass is a meta^(n)-klass for n >= 0
+/**
+ * Creates a metaclass of `klass`
+ * @param klass a class
+ * @return created metaclass for the class
+ * @pre `klass` is a Class object
+ * @pre `klass` has no singleton class.
+ * @post the class of `klass` is the returned class.
+ * @post the returned class is meta^(n+1)-class when `klass` is a meta^(n)-klass for n >= 0
*/
static inline VALUE
make_metaclass(VALUE klass)
@@ -779,11 +791,11 @@ make_metaclass(VALUE klass)
return metaclass;
}
-/*!
- * Creates a singleton class for \a obj.
- * \pre \a obj must not a immediate nor a special const.
- * \pre \a obj must not a Class object.
- * \pre \a obj has no singleton class.
+/**
+ * Creates a singleton class for `obj`.
+ * @pre `obj` must not be an immediate nor a special const.
+ * @pre `obj` must not be a Class object.
+ * @pre `obj` has no singleton class.
*/
static inline VALUE
make_singleton_class(VALUE obj)
@@ -794,6 +806,7 @@ make_singleton_class(VALUE obj)
FL_SET(klass, FL_SINGLETON);
RBASIC_SET_CLASS(obj, klass);
rb_singleton_class_attached(klass, obj);
+ rb_yjit_invalidate_no_singleton_class(orig_class);
SET_METACLASS_OF(klass, METACLASS_OF(rb_class_real(orig_class)));
return klass;
@@ -807,7 +820,7 @@ boot_defclass(const char *name, VALUE super)
ID id = rb_intern(name);
rb_const_set((rb_cObject ? rb_cObject : obj), id, obj);
- rb_vm_add_root_module(obj);
+ rb_vm_register_global_object(obj);
return obj;
}
@@ -889,7 +902,7 @@ Init_class_hierarchy(void)
{
rb_cBasicObject = boot_defclass("BasicObject", 0);
rb_cObject = boot_defclass("Object", rb_cBasicObject);
- rb_gc_register_mark_object(rb_cObject);
+ rb_vm_register_global_object(rb_cObject);
/* resolve class name ASAP for order-independence */
rb_set_class_path_string(rb_cObject, rb_cObject, rb_fstring_lit("Object"));
@@ -914,15 +927,15 @@ Init_class_hierarchy(void)
}
-/*!
- * \internal
+/**
+ * @internal
* Creates a new *singleton class* for an object.
*
- * \pre \a obj has no singleton class.
- * \note DO NOT USE the function in an extension libraries. Use \ref rb_singleton_class.
- * \param obj An object.
- * \param unused ignored.
- * \return The singleton class of the object.
+ * @pre `obj` has no singleton class.
+ * @note DO NOT USE the function in an extension libraries. Use @ref rb_singleton_class.
+ * @param obj An object.
+ * @param unused ignored.
+ * @return The singleton class of the object.
*/
VALUE
rb_make_metaclass(VALUE obj, VALUE unused)
@@ -948,13 +961,13 @@ rb_define_class_id(ID id, VALUE super)
}
-/*!
+/**
* Calls Class#inherited.
- * \param super A class which will be called #inherited.
+ * @param super A class which will be called #inherited.
* NULL means Object class.
- * \param klass A Class object which derived from \a super
- * \return the value \c Class#inherited's returns
- * \pre Each of \a super and \a klass must be a \c Class object.
+ * @param klass A Class object which derived from `super`
+ * @return the value `Class#inherited` returns
+ * @pre Each of `super` and `klass` must be a `Class` object.
*/
VALUE
rb_class_inherited(VALUE super, VALUE klass)
@@ -983,14 +996,14 @@ rb_define_class(const char *name, VALUE super)
}
/* Class may have been defined in Ruby and not pin-rooted */
- rb_vm_add_root_module(klass);
+ rb_vm_register_global_object(klass);
return klass;
}
if (!super) {
- rb_raise(rb_eArgError, "no super class for `%s'", name);
+ rb_raise(rb_eArgError, "no super class for '%s'", name);
}
klass = rb_define_class_id(id, super);
- rb_vm_add_root_module(klass);
+ rb_vm_register_global_object(klass);
rb_const_set(rb_cObject, id, klass);
rb_class_inherited(super, klass);
@@ -1004,7 +1017,7 @@ rb_define_class_under(VALUE outer, const char *name, VALUE super)
}
VALUE
-rb_define_class_id_under(VALUE outer, ID id, VALUE super)
+rb_define_class_id_under_no_pin(VALUE outer, ID id, VALUE super)
{
VALUE klass;
@@ -1021,25 +1034,30 @@ rb_define_class_id_under(VALUE outer, ID id, VALUE super)
" (%"PRIsVALUE" is given but was %"PRIsVALUE")",
outer, rb_id2str(id), RCLASS_SUPER(klass), super);
}
- /* Class may have been defined in Ruby and not pin-rooted */
- rb_vm_add_root_module(klass);
return klass;
}
if (!super) {
- rb_raise(rb_eArgError, "no super class for `%"PRIsVALUE"::%"PRIsVALUE"'",
+ rb_raise(rb_eArgError, "no super class for '%"PRIsVALUE"::%"PRIsVALUE"'",
rb_class_path(outer), rb_id2str(id));
}
klass = rb_define_class_id(id, super);
rb_set_class_path_string(klass, outer, rb_id2str(id));
rb_const_set(outer, id, klass);
rb_class_inherited(super, klass);
- rb_vm_add_root_module(klass);
return klass;
}
VALUE
+rb_define_class_id_under(VALUE outer, ID id, VALUE super)
+{
+ VALUE klass = rb_define_class_id_under_no_pin(outer, id, super);
+ rb_vm_register_global_object(klass);
+ return klass;
+}
+
+VALUE
rb_module_s_alloc(VALUE klass)
{
VALUE mod = class_alloc(T_MODULE, klass);
@@ -1089,11 +1107,11 @@ rb_define_module(const char *name)
name, rb_obj_class(module));
}
/* Module may have been defined in Ruby and not pin-rooted */
- rb_vm_add_root_module(module);
+ rb_vm_register_global_object(module);
return module;
}
module = rb_module_new();
- rb_vm_add_root_module(module);
+ rb_vm_register_global_object(module);
rb_const_set(rb_cObject, id, module);
return module;
@@ -1118,13 +1136,13 @@ rb_define_module_id_under(VALUE outer, ID id)
outer, rb_id2str(id), rb_obj_class(module));
}
/* Module may have been defined in Ruby and not pin-rooted */
- rb_gc_register_mark_object(module);
+ rb_vm_register_global_object(module);
return module;
}
module = rb_module_new();
rb_const_set(outer, id, module);
rb_set_class_path_string(module, outer, rb_id2str(id));
- rb_gc_register_mark_object(module);
+ rb_vm_register_global_object(module);
return module;
}
@@ -1134,7 +1152,7 @@ rb_include_class_new(VALUE module, VALUE super)
{
VALUE klass = class_alloc(T_ICLASS, rb_cClass);
- RCLASS_M_TBL(klass) = RCLASS_M_TBL(module);
+ RCLASS_SET_M_TBL(klass, RCLASS_M_TBL(module));
RCLASS_SET_ORIGIN(klass, klass);
if (BUILTIN_TYPE(module) == T_ICLASS) {
@@ -1410,10 +1428,10 @@ ensure_origin(VALUE klass)
VALUE origin = RCLASS_ORIGIN(klass);
if (origin == klass) {
origin = class_alloc(T_ICLASS, klass);
+ RCLASS_SET_M_TBL(origin, RCLASS_M_TBL(klass));
RCLASS_SET_SUPER(origin, RCLASS_SUPER(klass));
RCLASS_SET_SUPER(klass, origin);
RCLASS_SET_ORIGIN(klass, origin);
- RCLASS_M_TBL(origin) = RCLASS_M_TBL(klass);
RCLASS_M_TBL_INIT(klass);
rb_id_table_foreach(RCLASS_M_TBL(origin), cache_clear_refined_method, (void *)klass);
rb_id_table_foreach(RCLASS_M_TBL(origin), move_refined_method, (void *)klass);
@@ -1597,7 +1615,7 @@ class_descendants_recursive(VALUE klass, VALUE v)
{
struct subclass_traverse_data *data = (struct subclass_traverse_data *) v;
- if (BUILTIN_TYPE(klass) == T_CLASS && !FL_TEST(klass, FL_SINGLETON)) {
+ if (BUILTIN_TYPE(klass) == T_CLASS && !RCLASS_SINGLETON_P(klass)) {
if (data->buffer && data->count < data->maxcount && !rb_objspace_garbage_object_p(klass)) {
// assumes that this does not cause GC as long as the length does not exceed the capacity
rb_ary_push(data->buffer, klass);
@@ -1702,8 +1720,8 @@ rb_class_subclasses(VALUE klass)
VALUE
rb_class_attached_object(VALUE klass)
{
- if (!FL_TEST(klass, FL_SINGLETON)) {
- rb_raise(rb_eTypeError, "`%"PRIsVALUE"' is not a singleton class", klass);
+ if (!RCLASS_SINGLETON_P(klass)) {
+ rb_raise(rb_eTypeError, "'%"PRIsVALUE"' is not a singleton class", klass);
}
return RCLASS_ATTACHED_OBJECT(klass);
@@ -1805,7 +1823,7 @@ static bool
particular_class_p(VALUE mod)
{
if (!mod) return false;
- if (FL_TEST(mod, FL_SINGLETON)) return true;
+ if (RCLASS_SINGLETON_P(mod)) return true;
if (BUILTIN_TYPE(mod) == T_ICLASS) return true;
return false;
}
@@ -2082,19 +2100,19 @@ rb_obj_singleton_methods(int argc, const VALUE *argv, VALUE obj)
int recur = TRUE;
if (rb_check_arity(argc, 0, 1)) recur = RTEST(argv[0]);
- if (RB_TYPE_P(obj, T_CLASS) && FL_TEST(obj, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON_P(obj)) {
rb_singleton_class(obj);
}
klass = CLASS_OF(obj);
origin = RCLASS_ORIGIN(klass);
me_arg.list = st_init_numtable();
me_arg.recur = recur;
- if (klass && FL_TEST(klass, FL_SINGLETON)) {
+ if (klass && RCLASS_SINGLETON_P(klass)) {
if ((mtbl = RCLASS_M_TBL(origin)) != 0) rb_id_table_foreach(mtbl, method_entry_i, &me_arg);
klass = RCLASS_SUPER(klass);
}
if (recur) {
- while (klass && (FL_TEST(klass, FL_SINGLETON) || RB_TYPE_P(klass, T_ICLASS))) {
+ while (klass && (RCLASS_SINGLETON_P(klass) || RB_TYPE_P(klass, T_ICLASS))) {
if (klass != origin && (mtbl = RCLASS_M_TBL(klass)) != 0) rb_id_table_foreach(mtbl, method_entry_i, &me_arg);
klass = RCLASS_SUPER(klass);
}
@@ -2198,13 +2216,13 @@ rb_special_singleton_class(VALUE obj)
return special_singleton_class_of(obj);
}
-/*!
- * \internal
- * Returns the singleton class of \a obj. Creates it if necessary.
+/**
+ * @internal
+ * Returns the singleton class of `obj`. Creates it if necessary.
*
- * \note DO NOT expose the returned singleton class to
+ * @note DO NOT expose the returned singleton class to
* outside of class.c.
- * Use \ref rb_singleton_class instead for
+ * Use @ref rb_singleton_class instead for
* consistency of the metaclass hierarchy.
*/
static VALUE
@@ -2228,13 +2246,16 @@ singleton_class_of(VALUE obj)
return klass;
case T_STRING:
- if (FL_TEST_RAW(obj, RSTRING_FSTR)) {
+ if (CHILLED_STRING_P(obj)) {
+ CHILLED_STRING_MUTATED(obj);
+ }
+ else if (FL_TEST_RAW(obj, RSTRING_FSTR)) {
rb_raise(rb_eTypeError, "can't define singleton");
}
}
klass = METACLASS_OF(obj);
- if (!(FL_TEST(klass, FL_SINGLETON) &&
+ if (!(RCLASS_SINGLETON_P(klass) &&
RCLASS_ATTACHED_OBJECT(klass) == obj)) {
klass = rb_make_metaclass(obj, klass);
}
@@ -2248,21 +2269,21 @@ void
rb_freeze_singleton_class(VALUE x)
{
/* should not propagate to meta-meta-class, and so on */
- if (!(RBASIC(x)->flags & FL_SINGLETON)) {
+ if (!RCLASS_SINGLETON_P(x)) {
VALUE klass = RBASIC_CLASS(x);
if (klass && // no class when hidden from ObjectSpace
FL_TEST(klass, (FL_SINGLETON|FL_FREEZE)) == FL_SINGLETON) {
- OBJ_FREEZE_RAW(klass);
+ OBJ_FREEZE(klass);
}
}
}
-/*!
- * Returns the singleton class of \a obj, or nil if obj is not a
+/**
+ * Returns the singleton class of `obj`, or nil if obj is not a
* singleton object.
*
- * \param obj an arbitrary object.
- * \return the singleton class or nil.
+ * @param obj an arbitrary object.
+ * @return the singleton class or nil.
*/
VALUE
rb_singleton_class_get(VALUE obj)
@@ -2273,7 +2294,7 @@ rb_singleton_class_get(VALUE obj)
return rb_special_singleton_class(obj);
}
klass = METACLASS_OF(obj);
- if (!FL_TEST(klass, FL_SINGLETON)) return Qnil;
+ if (!RCLASS_SINGLETON_P(klass)) return Qnil;
if (RCLASS_ATTACHED_OBJECT(klass) != obj) return Qnil;
return klass;
}
diff --git a/common.mk b/common.mk
index d7ed7d77f6..03d1a397a8 100644
--- a/common.mk
+++ b/common.mk
@@ -64,21 +64,21 @@ LIBRUBY_EXTS = ./.libruby-with-ext.time
REVISION_H = ./.revision.time
PLATFORM_D = $(TIMESTAMPDIR)/.$(PLATFORM_DIR).time
ENC_TRANS_D = $(TIMESTAMPDIR)/.enc-trans.time
-RDOC = $(XRUBY) "$(srcdir)/libexec/rdoc" --root "$(srcdir)" --encoding=UTF-8 --all
+RDOC = $(XRUBY) "$(tooldir)/rdoc-srcdir"
RDOCOUT = $(EXTOUT)/rdoc
HTMLOUT = $(EXTOUT)/html
CAPIOUT = doc/capi
INSTALL_DOC_OPTS = --rdoc-output="$(RDOCOUT)" --html-output="$(HTMLOUT)"
-RDOC_GEN_OPTS = --page-dir "$(srcdir)/doc" --no-force-update \
+RDOC_GEN_OPTS = --no-force-update \
--title "Documentation for Ruby $(RUBY_API_VERSION)" \
- --main README.md
+ $(empty)
INITOBJS = dmyext.$(OBJEXT) dmyenc.$(OBJEXT)
NORMALMAINOBJ = main.$(OBJEXT)
MAINOBJ = $(NORMALMAINOBJ)
DLDOBJS = $(INITOBJS)
EXTSOLIBS =
-MINIOBJS = $(ARCHMINIOBJS) miniinit.$(OBJEXT) dmyext.$(OBJEXT)
+MINIOBJS = $(ARCHMINIOBJS) miniinit.$(OBJEXT)
ENC_MK = enc.mk
MAKE_ENC = -f $(ENC_MK) V="$(V)" UNICODE_HDR_DIR="$(UNICODE_HDR_DIR)" \
RUBY="$(BOOTSTRAPRUBY)" MINIRUBY="$(BOOTSTRAPRUBY)" $(mflags)
@@ -88,13 +88,7 @@ PRISM_BUILD_DIR = prism
PRISM_FILES = prism/api_node.$(OBJEXT) \
prism/api_pack.$(OBJEXT) \
prism/diagnostic.$(OBJEXT) \
- prism/enc/pm_big5.$(OBJEXT) \
- prism/enc/pm_euc_jp.$(OBJEXT) \
- prism/enc/pm_gbk.$(OBJEXT) \
- prism/enc/pm_shift_jis.$(OBJEXT) \
- prism/enc/pm_tables.$(OBJEXT) \
- prism/enc/pm_unicode.$(OBJEXT) \
- prism/enc/pm_windows_31j.$(OBJEXT) \
+ prism/encoding.$(OBJEXT) \
prism/extension.$(OBJEXT) \
prism/node.$(OBJEXT) \
prism/options.$(OBJEXT) \
@@ -102,16 +96,16 @@ PRISM_FILES = prism/api_node.$(OBJEXT) \
prism/prettyprint.$(OBJEXT) \
prism/regexp.$(OBJEXT) \
prism/serialize.$(OBJEXT) \
+ prism/static_literals.$(OBJEXT) \
prism/token_type.$(OBJEXT) \
prism/util/pm_buffer.$(OBJEXT) \
prism/util/pm_char.$(OBJEXT) \
prism/util/pm_constant_pool.$(OBJEXT) \
+ prism/util/pm_integer.$(OBJEXT) \
prism/util/pm_list.$(OBJEXT) \
prism/util/pm_memchr.$(OBJEXT) \
prism/util/pm_newline_list.$(OBJEXT) \
- prism/util/pm_state_stack.$(OBJEXT) \
prism/util/pm_string.$(OBJEXT) \
- prism/util/pm_string_list.$(OBJEXT) \
prism/util/pm_strncasecmp.$(OBJEXT) \
prism/util/pm_strpbrk.$(OBJEXT) \
prism/prism.$(OBJEXT) \
@@ -138,6 +132,7 @@ COMMONOBJS = array.$(OBJEXT) \
gc.$(OBJEXT) \
hash.$(OBJEXT) \
inits.$(OBJEXT) \
+ imemo.$(OBJEXT) \
io.$(OBJEXT) \
io_buffer.$(OBJEXT) \
iseq.$(OBJEXT) \
@@ -199,9 +194,9 @@ COMMONOBJS = array.$(OBJEXT) \
$(BUILTIN_TRANSOBJS) \
$(MISSING)
-$(PRISM_FILES): $(PRISM_BUILD_DIR)/.time $(PRISM_BUILD_DIR)/enc/.time $(PRISM_BUILD_DIR)/util/.time
+$(PRISM_FILES): $(PRISM_BUILD_DIR)/.time $(PRISM_BUILD_DIR)/util/.time
-$(PRISM_BUILD_DIR)/.time $(PRISM_BUILD_DIR)/enc/.time $(PRISM_BUILD_DIR)/util/.time:
+$(PRISM_BUILD_DIR)/.time $(PRISM_BUILD_DIR)/util/.time:
$(Q) $(MAKEDIRS) $(@D)
@$(NULLCMD) > $@
@@ -220,6 +215,11 @@ srcs: $(srcdir)/lib/prism/dsl.rb
$(srcdir)/lib/prism/dsl.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/dsl.rb.erb
$(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/dsl.rb $(srcdir)/lib/prism/dsl.rb
+main: $(srcdir)/lib/prism/inspect_visitor.rb
+srcs: $(srcdir)/lib/prism/inspect_visitor.rb
+$(srcdir)/lib/prism/inspect_visitor.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/inspect_visitor.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/inspect_visitor.rb $(srcdir)/lib/prism/inspect_visitor.rb
+
main: $(srcdir)/lib/prism/mutation_compiler.rb
srcs: $(srcdir)/lib/prism/mutation_compiler.rb
$(srcdir)/lib/prism/mutation_compiler.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/mutation_compiler.rb.erb
@@ -230,6 +230,11 @@ srcs: $(srcdir)/lib/prism/node.rb
$(srcdir)/lib/prism/node.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/node.rb.erb
$(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/node.rb $(srcdir)/lib/prism/node.rb
+main: $(srcdir)/lib/prism/reflection.rb
+srcs: $(srcdir)/lib/prism/reflection.rb
+$(srcdir)/lib/prism/reflection.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/reflection.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/reflection.rb $(srcdir)/lib/prism/reflection.rb
+
main: $(srcdir)/lib/prism/serialize.rb
srcs: $(srcdir)/lib/prism/serialize.rb
$(srcdir)/lib/prism/serialize.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/serialize.rb.erb
@@ -248,6 +253,14 @@ srcs: prism/ast.h
prism/ast.h: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/include/prism/ast.h.erb
$(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb include/prism/ast.h $@
+srcs: prism/diagnostic.c
+prism/diagnostic.c: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/src/diagnostic.c.erb
+ $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb src/diagnostic.c $@
+
+srcs: prism/diagnostic.h
+prism/diagnostic.h: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/include/prism/diagnostic.h.erb
+ $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb include/prism/diagnostic.h $@
+
srcs: prism/node.c
prism/node.c: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/src/node.c.erb
$(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb src/node.c $@
@@ -270,7 +283,7 @@ EXPORTOBJS = $(DLNOBJ) \
$(COMMONOBJS)
OBJS = $(EXPORTOBJS) builtin.$(OBJEXT)
-ALLOBJS = $(NORMALMAINOBJ) $(MINIOBJS) $(COMMONOBJS) $(INITOBJS)
+ALLOBJS = $(OBJS) $(MINIOBJS) $(INITOBJS) $(MAINOBJ)
GOLFOBJS = goruby.$(OBJEXT)
@@ -332,7 +345,7 @@ YJIT_RUSTC_ARGS = --crate-name=yjit \
'--out-dir=$(CARGO_TARGET_DIR)/release/' \
$(top_srcdir)/yjit/src/lib.rs
-all: $(SHOWFLAGS) main docs
+all: $(SHOWFLAGS) main
main: $(SHOWFLAGS) exts $(ENCSTATIC:static=lib)encs
@$(NULLCMD)
@@ -402,7 +415,7 @@ configure-ext: $(EXTS_MK)
build-ext: $(EXTS_MK)
$(Q)$(MAKE) -f $(EXTS_MK) $(mflags) libdir="$(libdir)" LIBRUBY_EXTS=$(LIBRUBY_EXTS) \
EXTENCS="$(ENCOBJS)" BASERUBY="$(BASERUBY)" MINIRUBY="$(MINIRUBY)" \
- UPDATE_LIBRARIES=no $(EXTSTATIC)
+ $(EXTSTATIC)
$(Q)$(MAKE) $(EXTS_NOTE)
exts-note: $(EXTS_MK)
@@ -418,7 +431,7 @@ programs: $(PROGRAM) $(WPROGRAM) $(arch)-fake.rb
$(PREP): $(MKFILES)
-miniruby$(EXEEXT): config.status $(ALLOBJS) $(ARCHFILE)
+miniruby$(EXEEXT): config.status $(NORMALMAINOBJ) $(MINIOBJS) $(COMMONOBJS) $(ARCHFILE)
objs: $(ALLOBJS)
@@ -466,8 +479,6 @@ ruby.imp: $(COMMONOBJS)
$(Q){ \
$(NM) -Pgp $(COMMONOBJS) | \
awk 'BEGIN{print "#!"}; $$2~/^[A-TV-Z]$$/&&$$1!~/^$(SYMBOL_PREFIX)(Init_|InitVM_|ruby_static_id_|.*_threadptr_|rb_ec_)|^\./{print $$1}'; \
- ($(CHDIR) $(srcdir) && \
- exec sed -n '/^RJIT_FUNC_EXPORTED/!d;N;s/.*\n\(rb_[a-zA-Z_0-9]*\).*/$(SYMBOL_PREFIX)\1/p' cont.c gc.c thread*c vm*.c) \
} | \
sort -u -o $@
@@ -476,9 +487,9 @@ docs: srcs-doc $(DOCTARGETS)
pkgconfig-data: $(ruby_pc)
$(ruby_pc): $(srcdir)/template/ruby.pc.in config.status
-install-all: docs pre-install-all do-install-all post-install-all
+install-all: pre-install-all do-install-all post-install-all
pre-install-all:: all pre-install-local pre-install-ext pre-install-gem pre-install-doc
-do-install-all: pre-install-all
+do-install-all: pre-install-all $(DOT_WAIT) docs
$(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) --install=all $(INSTALL_DOC_OPTS)
post-install-all:: post-install-local post-install-ext post-install-gem post-install-doc
@$(NULLCMD)
@@ -668,16 +679,22 @@ post-install-dbg::
rdoc: PHONY main srcs-doc
@echo Generating RDoc documentation
- $(Q) $(RDOC) --ri --op "$(RDOCOUT)" $(RDOC_GEN_OPTS) $(RDOCFLAGS) "$(srcdir)"
+ $(Q) $(RDOC) --ri --op "$(RDOCOUT)" $(RDOC_GEN_OPTS) $(RDOCFLAGS) .
html: PHONY main srcs-doc
@echo Generating RDoc HTML files
- $(Q) $(RDOC) --op "$(HTMLOUT)" $(RDOC_GEN_OPTS) $(RDOCFLAGS) "$(srcdir)"
+ $(Q) $(RDOC) --op "$(HTMLOUT)" $(RDOC_GEN_OPTS) $(RDOCFLAGS) .
rdoc-coverage: PHONY main srcs-doc
@echo Generating RDoc coverage report
$(Q) $(RDOC) --quiet -C $(RDOCFLAGS) "$(srcdir)"
+undocumented: PHONY main srcs-doc
+ $(Q) $(RDOC) --quiet -C $(RDOCFLAGS) "$(srcdir)" | \
+ sed -n \
+ -e '/^ *# in file /{' -e 's///;N;s/\n/: /p' -e '}' \
+ -e 's/^ *\(.*[^ ]\) *# in file \(.*\)/\2: \1/p'
+
RDOCBENCHOUT=/tmp/rdocbench
GCBENCH_ITEM=null
@@ -707,12 +724,12 @@ clear-installed-list: PHONY
clean: clean-ext clean-enc clean-golf clean-docs clean-extout clean-local clean-platform clean-spec
clean-local:: clean-runnable
- $(Q)$(RM) $(OBJS) $(MINIOBJS) $(INITOBJS) $(MAINOBJ) $(LIBRUBY_A) $(LIBRUBY_SO) $(LIBRUBY) $(LIBRUBY_ALIASES)
+ $(Q)$(RM) $(ALLOBJS) $(LIBRUBY_A) $(LIBRUBY_SO) $(LIBRUBY) $(LIBRUBY_ALIASES)
$(Q)$(RM) $(PROGRAM) $(WPROGRAM) miniruby$(EXEEXT) dmyext.$(OBJEXT) dmyenc.$(OBJEXT) $(ARCHFILE) .*.time
$(Q)$(RM) y.tab.c y.output encdb.h transdb.h config.log rbconfig.rb $(ruby_pc) $(COROUTINE_H:/Context.h=/.time)
$(Q)$(RM) probes.h probes.$(OBJEXT) probes.stamp ruby-glommed.$(OBJEXT) ruby.imp ChangeLog $(STATIC_RUBY)$(EXEEXT)
$(Q)$(RM) GNUmakefile.old Makefile.old $(arch)-fake.rb bisect.sh $(ENC_TRANS_D) builtin_binary.inc
- $(Q)$(RM) $(PRISM_BUILD_DIR)/.time $(PRISM_BUILD_DIR)/*/.time
+ $(Q)$(RM) $(PRISM_BUILD_DIR)/.time $(PRISM_BUILD_DIR)/*/.time yjit_exit_locations.dump
-$(Q)$(RMALL) yjit/target
-$(Q) $(RMDIR) enc/jis enc/trans enc $(COROUTINE_H:/Context.h=) coroutine yjit \
$(PRISM_BUILD_DIR)/*/ $(PRISM_BUILD_DIR) tmp \
@@ -721,9 +738,11 @@ clean-local:: clean-runnable
bin/clean-runnable:: PHONY
$(Q)$(CHDIR) bin 2>$(NULL) && $(RM) $(PROGRAM) $(WPROGRAM) $(GORUBY)$(EXEEXT) bin/*.$(DLEXT) 2>$(NULL) || $(NULLCMD)
lib/clean-runnable:: PHONY
- $(Q)$(CHDIR) lib 2>$(NULL) && $(RM) $(LIBRUBY_A) $(LIBRUBY) $(LIBRUBY_ALIASES) $(RUBY_BASE_NAME)/$(RUBY_PROGRAM_VERSION) $(RUBY_BASE_NAME)/vendor_ruby 2>$(NULL) || $(NULLCMD)
+ $(Q)$(CHDIR) lib 2>$(NULL) && $(RM) $(LIBRUBY_A) $(LIBRUBY) $(LIBRUBY_ALIASES) $(RUBY_BASE_NAME)/$(ruby_version) $(RUBY_BASE_NAME)/vendor_ruby 2>$(NULL) || $(NULLCMD)
clean-runnable:: bin/clean-runnable lib/clean-runnable PHONY
$(Q)$(RMDIR) lib/$(RUBY_BASE_NAME) lib bin 2>$(NULL) || $(NULLCMD)
+ -$(Q)$(RM) $(EXTOUT)/$(arch)/rbconfig.rb $(EXTOUT)/common/$(arch)
+ -$(Q)$(RMALL) exe/
clean-ext:: PHONY
clean-golf: PHONY
$(Q)$(RM) $(GORUBY)$(EXEEXT) $(GOLFOBJS)
@@ -932,19 +951,26 @@ test: test-short
# Separate to skip updating encs and exts by `make -o test-precheck`
# for GNU make.
-test-precheck: encs exts PHONY $(DOT_WAIT)
+test-precheck: $(ENCSTATIC:static=lib)encs exts PHONY $(DOT_WAIT)
yes-test-all-precheck: programs $(DOT_WAIT) test-precheck
+PRECHECK_TEST_ALL = yes-test-all-precheck
+
# $ make test-all TESTOPTS="--help" displays more detail
# for example, make test-all TESTOPTS="-j2 -v -n test-name -- test-file-name"
test-all: $(TEST_RUNNABLE)-test-all
-yes-test-all: yes-test-all-precheck
+yes-test-all: $(PRECHECK_TEST_ALL)
$(ACTIONS_GROUP)
- $(gnumake_recursive)$(Q)$(exec) $(RUNRUBY) "$(TESTSDIR)/runner.rb" --ruby="$(RUNRUBY)" $(TEST_EXCLUDES) $(TESTOPTS) $(TESTS)
+ $(gnumake_recursive)$(Q)$(exec) $(RUNRUBY) -r$(tooldir)/lib/_tmpdir \
+ "$(TESTSDIR)/runner.rb" --ruby="$(RUNRUBY)" \
+ $(TEST_EXCLUDES) $(TESTOPTS) $(TESTS)
$(ACTIONS_ENDGROUP)
TESTS_BUILD = mkmf
no-test-all: PHONY
- $(gnumake_recursive)$(MINIRUBY) -I"$(srcdir)/lib" "$(TESTSDIR)/runner.rb" $(TESTOPTS) $(TESTS_BUILD)
+ $(ACTIONS_GROUP)
+ $(gnumake_recursive)$(MINIRUBY) -I"$(srcdir)/lib" -r$(tooldir)/lib/_tmpdir \
+ "$(TESTSDIR)/runner.rb" $(TESTOPTS) $(TESTS_BUILD)
+ $(ACTIONS_ENDGROUP)
test-almost: test-all
yes-test-almost: yes-test-all
@@ -986,7 +1012,7 @@ test-spec: $(TEST_RUNNABLE)-test-spec
yes-test-spec: yes-test-spec-precheck
$(ACTIONS_GROUP)
$(gnumake_recursive)$(Q) \
- $(RUNRUBY) -r./$(arch)-fake -r$(tooldir)/rubyspec_temp \
+ $(RUNRUBY) -r./$(arch)-fake -r$(tooldir)/lib/_tmpdir \
$(srcdir)/spec/mspec/bin/mspec run -B $(srcdir)/spec/default.mspec $(MSPECOPT) $(SPECOPTS)
$(ACTIONS_ENDGROUP)
no-test-spec:
@@ -1043,6 +1069,7 @@ $(PLATFORM_D):
$(Q) $(MAKEDIRS) $(PLATFORM_DIR) $(@D)
@$(NULLCMD) > $@
+exe/$(PROGRAM): $(TIMESTAMPDIR)/$(arch)/.time
exe/$(PROGRAM): ruby-runner.c ruby-runner.h exe/.time $(PREP) {$(VPATH)}config.h
$(Q) $(CC) $(CFLAGS) $(INCFLAGS) $(CPPFLAGS) -DRUBY_INSTALL_NAME=$(@F) $(COUTFLAG)ruby-runner.$(OBJEXT) -c $(CSRCFLAG)$(srcdir)/ruby-runner.c
$(Q) $(PURIFY) $(CC) $(CFLAGS) $(LDFLAGS) $(OUTFLAG)$@ ruby-runner.$(OBJEXT) $(LIBS)
@@ -1055,6 +1082,8 @@ exe/$(PROGRAM): ruby-runner.c ruby-runner.h exe/.time $(PREP) {$(VPATH)}config.h
-e ' File.symlink(prog, dest)' \
-e 'end' \
$(@F) $(@D) $(RUBY_INSTALL_NAME)$(EXEEXT)
+ $(Q) $(BOOTSTRAPRUBY) -r$(srcdir)/lib/fileutils \
+ -e 'FileUtils::Verbose.ln_sr(*ARGV, force: true)' rbconfig.rb $(EXTOUT)/$(arch)
exe/.time:
$(Q) $(MAKEDIRS) $(@D)
@@ -1359,7 +1388,7 @@ $(srcdir)/ext/rbconfig/sizeof/limits.c: $(srcdir)/ext/rbconfig/sizeof/depend \
$(exec) $(MAKE) -f - $(mflags) \
Q=$(Q) ECHO=$(ECHO) top_srcdir=../../.. srcdir=. VPATH=../../.. RUBY="$(BASERUBY)" $(@F)
-$(srcdir)/ext/socket/constdefs.c: $(srcdir)/ext/socket/depend
+$(srcdir)/ext/socket/constdefs.c: $(srcdir)/ext/socket/depend $(srcdir)/ext/socket/mkconstants.rb
$(Q) $(CHDIR) $(@D) && \
$(CAT_DEPEND) depend | \
$(exec) $(MAKE) -f - $(mflags) \
@@ -1527,7 +1556,9 @@ clone-bundled-gems-src: PHONY
gems/bundled_gems
outdate-bundled-gems: PHONY
- $(Q) $(BASERUBY) $(tooldir)/$@.rb --make="$(MAKE)" --mflags="$(MFLAGS)" "$(srcdir)"
+ $(Q) $(BASERUBY) $(tooldir)/$@.rb --make="$(MAKE)" --mflags="$(MFLAGS)" \
+ --ruby-platform=$(arch) --ruby-version=$(ruby_version) \
+ "$(srcdir)"
update-bundled_gems: PHONY
$(Q) $(RUNRUBY) -rrubygems \
@@ -1559,7 +1590,7 @@ yes-test-bundled-gems-prepare: yes-test-bundled-gems-precheck
$(ACTIONS_ENDGROUP)
PREPARE_BUNDLED_GEMS = test-bundled-gems-prepare
-test-bundled-gems: $(TEST_RUNNABLE)-test-bundled-gems
+test-bundled-gems: $(TEST_RUNNABLE)-test-bundled-gems $(DOT_WAIT) $(TEST_RUNNABLE)-test-bundled-gems-spec
yes-test-bundled-gems: test-bundled-gems-run
no-test-bundled-gems:
@@ -1567,33 +1598,22 @@ no-test-bundled-gems:
# TEST_BUNDLED_GEMS_ALLOW_FAILURES =
BUNDLED_GEMS =
-test-bundled-gems-run: $(PREPARE_BUNDLED_GEMS)
+test-bundled-gems-run: $(TEST_RUNNABLE)-test-bundled-gems-run
+yes-test-bundled-gems-run: $(PREPARE_BUNDLED_GEMS)
$(gnumake_recursive)$(Q) $(XRUBY) $(tooldir)/test-bundled-gems.rb $(BUNDLED_GEMS)
+no-test-bundled-gems-run: $(PREPARE_BUNDLED_GEMS)
-test-syntax-suggest-precheck: $(TEST_RUNNABLE)-test-syntax-suggest-precheck
-no-test-syntax-suggest-precheck:
-yes-test-syntax-suggest-precheck: main
-
-test-syntax-suggest-prepare: $(TEST_RUNNABLE)-test-syntax-suggest-prepare
-no-test-syntax-suggest-prepare: no-test-syntax-suggest-precheck
-yes-test-syntax-suggest-prepare: yes-test-syntax-suggest-precheck
+test-bundled-gems-spec: $(TEST_RUNNABLE)-test-bundled-gems-spec
+yes-test-bundled-gems-spec: yes-test-spec-precheck $(PREPARE_BUNDLED_GEMS)
$(ACTIONS_GROUP)
- $(XRUBY) -C "$(srcdir)" bin/gem install --no-document \
- --install-dir .bundle --conservative "rspec:~> 3"
+ $(gnumake_recursive)$(Q) \
+ $(RUNRUBY) -r./$(arch)-fake -r$(tooldir)/lib/_tmpdir \
+ $(srcdir)/spec/mspec/bin/mspec run -B $(srcdir)/spec/bundled_gems.mspec $(MSPECOPT) $(SPECOPTS)
$(ACTIONS_ENDGROUP)
+no-test-bundled-gems-spec:
-RSPECOPTS =
-SYNTAX_SUGGEST_SPECS =
-PREPARE_SYNTAX_SUGGEST = $(TEST_RUNNABLE)-test-syntax-suggest-prepare
-test-syntax-suggest: $(TEST_RUNNABLE)-test-syntax-suggest
-yes-test-syntax-suggest: $(PREPARE_SYNTAX_SUGGEST)
- $(ACTIONS_GROUP)
- $(XRUBY) -C $(srcdir) -Ispec/syntax_suggest:spec/lib .bundle/bin/rspec \
- --require rspec/expectations \
- --require spec_helper --require formatter_overrides --require spec_coverage \
- $(RSPECOPTS) spec/syntax_suggest/$(SYNTAX_SUGGEST_SPECS)
- $(ACTIONS_ENDGROUP)
-no-test-syntax-suggest:
+
+test-syntax-suggest:
check: $(DOT_WAIT) $(PREPARE_SYNTAX_SUGGEST) test-syntax-suggest
@@ -1866,6 +1886,22 @@ ChangeLog:
-e 'VCS.detect(ARGV[0]).export_changelog(path: ARGV[1])' \
"$(srcdir)" $@
+# CAUTION: If using GNU make 3 which does not support `.WAIT`, this
+# recipe with multiple jobs makes build and `git reset` run
+# simultaneously, and will cause inconsistent results. Run with `-j1`
+# or update GNU make.
+nightly: yesterday $(DOT_WAIT) install
+ $(NULLCMD)
+
+# Rewind to the last commit "yesterday". "Yesterday" means here the
+# period where `RUBY_RELEASE_DATE` is the day before the date to be
+# generated now. In short, the yesterday in JST-9 time zone.
+yesterday: rewindable
+
+rewindable:
+ $(GIT) -C $(srcdir) status --porcelain
+ $(GIT) -C $(srcdir) diff --quiet
+
HELP_EXTRA_TASKS = ""
help: PHONY
@@ -1992,6 +2028,7 @@ array.$(OBJEXT): $(top_srcdir)/internal/numeric.h
array.$(OBJEXT): $(top_srcdir)/internal/object.h
array.$(OBJEXT): $(top_srcdir)/internal/proc.h
array.$(OBJEXT): $(top_srcdir)/internal/rational.h
+array.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
array.$(OBJEXT): $(top_srcdir)/internal/serial.h
array.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
array.$(OBJEXT): $(top_srcdir)/internal/variable.h
@@ -2162,6 +2199,7 @@ array.$(OBJEXT): {$(VPATH)}internal/special_consts.h
array.$(OBJEXT): {$(VPATH)}internal/static_assert.h
array.$(OBJEXT): {$(VPATH)}internal/stdalign.h
array.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+array.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
array.$(OBJEXT): {$(VPATH)}internal/symbol.h
array.$(OBJEXT): {$(VPATH)}internal/value.h
array.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -2194,17 +2232,44 @@ ast.$(OBJEXT): $(hdrdir)/ruby.h
ast.$(OBJEXT): $(hdrdir)/ruby/ruby.h
ast.$(OBJEXT): $(top_srcdir)/internal/array.h
ast.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+ast.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+ast.$(OBJEXT): $(top_srcdir)/internal/bits.h
ast.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+ast.$(OBJEXT): $(top_srcdir)/internal/complex.h
+ast.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
ast.$(OBJEXT): $(top_srcdir)/internal/gc.h
ast.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+ast.$(OBJEXT): $(top_srcdir)/internal/numeric.h
ast.$(OBJEXT): $(top_srcdir)/internal/parse.h
+ast.$(OBJEXT): $(top_srcdir)/internal/rational.h
ast.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
+ast.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
ast.$(OBJEXT): $(top_srcdir)/internal/serial.h
ast.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
ast.$(OBJEXT): $(top_srcdir)/internal/symbol.h
ast.$(OBJEXT): $(top_srcdir)/internal/variable.h
ast.$(OBJEXT): $(top_srcdir)/internal/vm.h
ast.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+ast.$(OBJEXT): $(top_srcdir)/prism/defines.h
+ast.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+ast.$(OBJEXT): $(top_srcdir)/prism/node.h
+ast.$(OBJEXT): $(top_srcdir)/prism/options.h
+ast.$(OBJEXT): $(top_srcdir)/prism/pack.h
+ast.$(OBJEXT): $(top_srcdir)/prism/parser.h
+ast.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+ast.$(OBJEXT): $(top_srcdir)/prism/prism.h
+ast.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+ast.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
ast.$(OBJEXT): {$(VPATH)}assert.h
ast.$(OBJEXT): {$(VPATH)}ast.c
ast.$(OBJEXT): {$(VPATH)}ast.rbinc
@@ -2369,6 +2434,7 @@ ast.$(OBJEXT): {$(VPATH)}internal/special_consts.h
ast.$(OBJEXT): {$(VPATH)}internal/static_assert.h
ast.$(OBJEXT): {$(VPATH)}internal/stdalign.h
ast.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+ast.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
ast.$(OBJEXT): {$(VPATH)}internal/symbol.h
ast.$(OBJEXT): {$(VPATH)}internal/value.h
ast.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -2381,6 +2447,10 @@ ast.$(OBJEXT): {$(VPATH)}missing.h
ast.$(OBJEXT): {$(VPATH)}node.h
ast.$(OBJEXT): {$(VPATH)}onigmo.h
ast.$(OBJEXT): {$(VPATH)}oniguruma.h
+ast.$(OBJEXT): {$(VPATH)}prism/ast.h
+ast.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
+ast.$(OBJEXT): {$(VPATH)}prism/version.h
+ast.$(OBJEXT): {$(VPATH)}prism_compile.h
ast.$(OBJEXT): {$(VPATH)}ruby_assert.h
ast.$(OBJEXT): {$(VPATH)}ruby_atomic.h
ast.$(OBJEXT): {$(VPATH)}rubyparser.h
@@ -2577,6 +2647,7 @@ bignum.$(OBJEXT): {$(VPATH)}internal/special_consts.h
bignum.$(OBJEXT): {$(VPATH)}internal/static_assert.h
bignum.$(OBJEXT): {$(VPATH)}internal/stdalign.h
bignum.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+bignum.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
bignum.$(OBJEXT): {$(VPATH)}internal/symbol.h
bignum.$(OBJEXT): {$(VPATH)}internal/value.h
bignum.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -2610,11 +2681,32 @@ builtin.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
builtin.$(OBJEXT): $(top_srcdir)/internal/compilers.h
builtin.$(OBJEXT): $(top_srcdir)/internal/gc.h
builtin.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+builtin.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
builtin.$(OBJEXT): $(top_srcdir)/internal/serial.h
builtin.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
builtin.$(OBJEXT): $(top_srcdir)/internal/variable.h
builtin.$(OBJEXT): $(top_srcdir)/internal/vm.h
builtin.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/defines.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/node.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/options.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/pack.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/parser.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/prism.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
builtin.$(OBJEXT): {$(VPATH)}assert.h
builtin.$(OBJEXT): {$(VPATH)}atomic.h
builtin.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -2779,6 +2871,7 @@ builtin.$(OBJEXT): {$(VPATH)}internal/special_consts.h
builtin.$(OBJEXT): {$(VPATH)}internal/static_assert.h
builtin.$(OBJEXT): {$(VPATH)}internal/stdalign.h
builtin.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+builtin.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
builtin.$(OBJEXT): {$(VPATH)}internal/symbol.h
builtin.$(OBJEXT): {$(VPATH)}internal/value.h
builtin.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -2791,6 +2884,10 @@ builtin.$(OBJEXT): {$(VPATH)}missing.h
builtin.$(OBJEXT): {$(VPATH)}node.h
builtin.$(OBJEXT): {$(VPATH)}onigmo.h
builtin.$(OBJEXT): {$(VPATH)}oniguruma.h
+builtin.$(OBJEXT): {$(VPATH)}prism/ast.h
+builtin.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
+builtin.$(OBJEXT): {$(VPATH)}prism/version.h
+builtin.$(OBJEXT): {$(VPATH)}prism_compile.h
builtin.$(OBJEXT): {$(VPATH)}ruby_assert.h
builtin.$(OBJEXT): {$(VPATH)}ruby_atomic.h
builtin.$(OBJEXT): {$(VPATH)}rubyparser.h
@@ -2815,6 +2912,7 @@ class.$(OBJEXT): $(top_srcdir)/internal/gc.h
class.$(OBJEXT): $(top_srcdir)/internal/hash.h
class.$(OBJEXT): $(top_srcdir)/internal/imemo.h
class.$(OBJEXT): $(top_srcdir)/internal/object.h
+class.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
class.$(OBJEXT): $(top_srcdir)/internal/serial.h
class.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
class.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -2984,6 +3082,7 @@ class.$(OBJEXT): {$(VPATH)}internal/special_consts.h
class.$(OBJEXT): {$(VPATH)}internal/static_assert.h
class.$(OBJEXT): {$(VPATH)}internal/stdalign.h
class.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+class.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
class.$(OBJEXT): {$(VPATH)}internal/symbol.h
class.$(OBJEXT): {$(VPATH)}internal/value.h
class.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -3004,8 +3103,12 @@ class.$(OBJEXT): {$(VPATH)}subst.h
class.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
class.$(OBJEXT): {$(VPATH)}thread_native.h
class.$(OBJEXT): {$(VPATH)}vm_core.h
+class.$(OBJEXT): {$(VPATH)}vm_debug.h
class.$(OBJEXT): {$(VPATH)}vm_opts.h
+class.$(OBJEXT): {$(VPATH)}vm_sync.h
+class.$(OBJEXT): {$(VPATH)}yjit.h
compar.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+compar.$(OBJEXT): $(hdrdir)/ruby/version.h
compar.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
compar.$(OBJEXT): $(top_srcdir)/internal/compar.h
compar.$(OBJEXT): $(top_srcdir)/internal/compilers.h
@@ -3173,6 +3276,7 @@ compar.$(OBJEXT): {$(VPATH)}internal/special_consts.h
compar.$(OBJEXT): {$(VPATH)}internal/static_assert.h
compar.$(OBJEXT): {$(VPATH)}internal/stdalign.h
compar.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+compar.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
compar.$(OBJEXT): {$(VPATH)}internal/symbol.h
compar.$(OBJEXT): {$(VPATH)}internal/value.h
compar.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -3189,6 +3293,7 @@ compile.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
compile.$(OBJEXT): $(CCAN_DIR)/list/list.h
compile.$(OBJEXT): $(CCAN_DIR)/str/str.h
compile.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+compile.$(OBJEXT): $(hdrdir)/ruby/version.h
compile.$(OBJEXT): $(top_srcdir)/internal/array.h
compile.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
compile.$(OBJEXT): $(top_srcdir)/internal/bignum.h
@@ -3203,10 +3308,14 @@ compile.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
compile.$(OBJEXT): $(top_srcdir)/internal/gc.h
compile.$(OBJEXT): $(top_srcdir)/internal/hash.h
compile.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+compile.$(OBJEXT): $(top_srcdir)/internal/io.h
compile.$(OBJEXT): $(top_srcdir)/internal/numeric.h
compile.$(OBJEXT): $(top_srcdir)/internal/object.h
+compile.$(OBJEXT): $(top_srcdir)/internal/parse.h
compile.$(OBJEXT): $(top_srcdir)/internal/rational.h
compile.$(OBJEXT): $(top_srcdir)/internal/re.h
+compile.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
+compile.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
compile.$(OBJEXT): $(top_srcdir)/internal/serial.h
compile.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
compile.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -3216,8 +3325,7 @@ compile.$(OBJEXT): $(top_srcdir)/internal/variable.h
compile.$(OBJEXT): $(top_srcdir)/internal/vm.h
compile.$(OBJEXT): $(top_srcdir)/internal/warnings.h
compile.$(OBJEXT): $(top_srcdir)/prism/defines.h
-compile.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
-compile.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
+compile.$(OBJEXT): $(top_srcdir)/prism/encoding.h
compile.$(OBJEXT): $(top_srcdir)/prism/node.h
compile.$(OBJEXT): $(top_srcdir)/prism/options.h
compile.$(OBJEXT): $(top_srcdir)/prism/pack.h
@@ -3225,15 +3333,15 @@ compile.$(OBJEXT): $(top_srcdir)/prism/parser.h
compile.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
compile.$(OBJEXT): $(top_srcdir)/prism/prism.h
compile.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+compile.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h
compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
compile.$(OBJEXT): $(top_srcdir)/prism_compile.c
@@ -3406,12 +3514,14 @@ compile.$(OBJEXT): {$(VPATH)}internal/special_consts.h
compile.$(OBJEXT): {$(VPATH)}internal/static_assert.h
compile.$(OBJEXT): {$(VPATH)}internal/stdalign.h
compile.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+compile.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
compile.$(OBJEXT): {$(VPATH)}internal/symbol.h
compile.$(OBJEXT): {$(VPATH)}internal/value.h
compile.$(OBJEXT): {$(VPATH)}internal/value_type.h
compile.$(OBJEXT): {$(VPATH)}internal/variable.h
compile.$(OBJEXT): {$(VPATH)}internal/warning_push.h
compile.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+compile.$(OBJEXT): {$(VPATH)}io.h
compile.$(OBJEXT): {$(VPATH)}iseq.h
compile.$(OBJEXT): {$(VPATH)}method.h
compile.$(OBJEXT): {$(VPATH)}missing.h
@@ -3420,10 +3530,12 @@ compile.$(OBJEXT): {$(VPATH)}onigmo.h
compile.$(OBJEXT): {$(VPATH)}oniguruma.h
compile.$(OBJEXT): {$(VPATH)}optinsn.inc
compile.$(OBJEXT): {$(VPATH)}prism/ast.h
+compile.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
compile.$(OBJEXT): {$(VPATH)}prism/prism.h
compile.$(OBJEXT): {$(VPATH)}prism/version.h
compile.$(OBJEXT): {$(VPATH)}prism_compile.c
compile.$(OBJEXT): {$(VPATH)}prism_compile.h
+compile.$(OBJEXT): {$(VPATH)}ractor.h
compile.$(OBJEXT): {$(VPATH)}re.h
compile.$(OBJEXT): {$(VPATH)}regex.h
compile.$(OBJEXT): {$(VPATH)}ruby_assert.h
@@ -3439,6 +3551,7 @@ compile.$(OBJEXT): {$(VPATH)}vm_callinfo.h
compile.$(OBJEXT): {$(VPATH)}vm_core.h
compile.$(OBJEXT): {$(VPATH)}vm_debug.h
compile.$(OBJEXT): {$(VPATH)}vm_opts.h
+compile.$(OBJEXT): {$(VPATH)}vm_sync.h
compile.$(OBJEXT): {$(VPATH)}yjit.h
complex.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
complex.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
@@ -3459,8 +3572,10 @@ complex.$(OBJEXT): $(top_srcdir)/internal/math.h
complex.$(OBJEXT): $(top_srcdir)/internal/numeric.h
complex.$(OBJEXT): $(top_srcdir)/internal/object.h
complex.$(OBJEXT): $(top_srcdir)/internal/rational.h
+complex.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
complex.$(OBJEXT): $(top_srcdir)/internal/serial.h
complex.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+complex.$(OBJEXT): $(top_srcdir)/internal/string.h
complex.$(OBJEXT): $(top_srcdir)/internal/variable.h
complex.$(OBJEXT): $(top_srcdir)/internal/vm.h
complex.$(OBJEXT): $(top_srcdir)/internal/warnings.h
@@ -3478,6 +3593,7 @@ complex.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
complex.$(OBJEXT): {$(VPATH)}complex.c
complex.$(OBJEXT): {$(VPATH)}config.h
complex.$(OBJEXT): {$(VPATH)}constant.h
+complex.$(OBJEXT): {$(VPATH)}debug_counter.h
complex.$(OBJEXT): {$(VPATH)}defines.h
complex.$(OBJEXT): {$(VPATH)}encoding.h
complex.$(OBJEXT): {$(VPATH)}id.h
@@ -3626,6 +3742,7 @@ complex.$(OBJEXT): {$(VPATH)}internal/special_consts.h
complex.$(OBJEXT): {$(VPATH)}internal/static_assert.h
complex.$(OBJEXT): {$(VPATH)}internal/stdalign.h
complex.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+complex.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
complex.$(OBJEXT): {$(VPATH)}internal/symbol.h
complex.$(OBJEXT): {$(VPATH)}internal/value.h
complex.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -3646,13 +3763,16 @@ complex.$(OBJEXT): {$(VPATH)}subst.h
complex.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
complex.$(OBJEXT): {$(VPATH)}thread_native.h
complex.$(OBJEXT): {$(VPATH)}vm_core.h
+complex.$(OBJEXT): {$(VPATH)}vm_debug.h
complex.$(OBJEXT): {$(VPATH)}vm_opts.h
+complex.$(OBJEXT): {$(VPATH)}vm_sync.h
cont.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
cont.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
cont.$(OBJEXT): $(CCAN_DIR)/list/list.h
cont.$(OBJEXT): $(CCAN_DIR)/str/str.h
cont.$(OBJEXT): $(hdrdir)/ruby.h
cont.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+cont.$(OBJEXT): $(hdrdir)/ruby/version.h
cont.$(OBJEXT): $(top_srcdir)/internal/array.h
cont.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
cont.$(OBJEXT): $(top_srcdir)/internal/compilers.h
@@ -3669,6 +3789,26 @@ cont.$(OBJEXT): $(top_srcdir)/internal/thread.h
cont.$(OBJEXT): $(top_srcdir)/internal/variable.h
cont.$(OBJEXT): $(top_srcdir)/internal/vm.h
cont.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+cont.$(OBJEXT): $(top_srcdir)/prism/defines.h
+cont.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+cont.$(OBJEXT): $(top_srcdir)/prism/node.h
+cont.$(OBJEXT): $(top_srcdir)/prism/options.h
+cont.$(OBJEXT): $(top_srcdir)/prism/pack.h
+cont.$(OBJEXT): $(top_srcdir)/prism/parser.h
+cont.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+cont.$(OBJEXT): $(top_srcdir)/prism/prism.h
+cont.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+cont.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
cont.$(OBJEXT): {$(VPATH)}$(COROUTINE_H)
cont.$(OBJEXT): {$(VPATH)}assert.h
cont.$(OBJEXT): {$(VPATH)}atomic.h
@@ -3835,6 +3975,7 @@ cont.$(OBJEXT): {$(VPATH)}internal/special_consts.h
cont.$(OBJEXT): {$(VPATH)}internal/static_assert.h
cont.$(OBJEXT): {$(VPATH)}internal/stdalign.h
cont.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+cont.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
cont.$(OBJEXT): {$(VPATH)}internal/symbol.h
cont.$(OBJEXT): {$(VPATH)}internal/value.h
cont.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -3847,6 +3988,10 @@ cont.$(OBJEXT): {$(VPATH)}missing.h
cont.$(OBJEXT): {$(VPATH)}node.h
cont.$(OBJEXT): {$(VPATH)}onigmo.h
cont.$(OBJEXT): {$(VPATH)}oniguruma.h
+cont.$(OBJEXT): {$(VPATH)}prism/ast.h
+cont.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
+cont.$(OBJEXT): {$(VPATH)}prism/version.h
+cont.$(OBJEXT): {$(VPATH)}prism_compile.h
cont.$(OBJEXT): {$(VPATH)}ractor.h
cont.$(OBJEXT): {$(VPATH)}ractor_core.h
cont.$(OBJEXT): {$(VPATH)}rjit.h
@@ -3874,6 +4019,7 @@ debug.$(OBJEXT): $(top_srcdir)/internal/class.h
debug.$(OBJEXT): $(top_srcdir)/internal/compilers.h
debug.$(OBJEXT): $(top_srcdir)/internal/gc.h
debug.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+debug.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
debug.$(OBJEXT): $(top_srcdir)/internal/serial.h
debug.$(OBJEXT): $(top_srcdir)/internal/signal.h
debug.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
@@ -4045,6 +4191,7 @@ debug.$(OBJEXT): {$(VPATH)}internal/special_consts.h
debug.$(OBJEXT): {$(VPATH)}internal/static_assert.h
debug.$(OBJEXT): {$(VPATH)}internal/stdalign.h
debug.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+debug.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
debug.$(OBJEXT): {$(VPATH)}internal/symbol.h
debug.$(OBJEXT): {$(VPATH)}internal/value.h
debug.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -4073,6 +4220,7 @@ debug.$(OBJEXT): {$(VPATH)}vm_callinfo.h
debug.$(OBJEXT): {$(VPATH)}vm_core.h
debug.$(OBJEXT): {$(VPATH)}vm_debug.h
debug.$(OBJEXT): {$(VPATH)}vm_opts.h
+debug.$(OBJEXT): {$(VPATH)}vm_sync.h
debug_counter.$(OBJEXT): $(hdrdir)/ruby/ruby.h
debug_counter.$(OBJEXT): {$(VPATH)}assert.h
debug_counter.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -4222,6 +4370,7 @@ debug_counter.$(OBJEXT): {$(VPATH)}internal/special_consts.h
debug_counter.$(OBJEXT): {$(VPATH)}internal/static_assert.h
debug_counter.$(OBJEXT): {$(VPATH)}internal/stdalign.h
debug_counter.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
debug_counter.$(OBJEXT): {$(VPATH)}internal/symbol.h
debug_counter.$(OBJEXT): {$(VPATH)}internal/value.h
debug_counter.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -4237,6 +4386,7 @@ dir.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
dir.$(OBJEXT): $(CCAN_DIR)/list/list.h
dir.$(OBJEXT): $(CCAN_DIR)/str/str.h
dir.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+dir.$(OBJEXT): $(hdrdir)/ruby/version.h
dir.$(OBJEXT): $(top_srcdir)/internal/array.h
dir.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
dir.$(OBJEXT): $(top_srcdir)/internal/class.h
@@ -4249,6 +4399,7 @@ dir.$(OBJEXT): $(top_srcdir)/internal/gc.h
dir.$(OBJEXT): $(top_srcdir)/internal/imemo.h
dir.$(OBJEXT): $(top_srcdir)/internal/io.h
dir.$(OBJEXT): $(top_srcdir)/internal/object.h
+dir.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
dir.$(OBJEXT): $(top_srcdir)/internal/serial.h
dir.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
dir.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -4420,6 +4571,7 @@ dir.$(OBJEXT): {$(VPATH)}internal/special_consts.h
dir.$(OBJEXT): {$(VPATH)}internal/static_assert.h
dir.$(OBJEXT): {$(VPATH)}internal/stdalign.h
dir.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+dir.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
dir.$(OBJEXT): {$(VPATH)}internal/symbol.h
dir.$(OBJEXT): {$(VPATH)}internal/value.h
dir.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -4596,6 +4748,7 @@ dln.$(OBJEXT): {$(VPATH)}internal/special_consts.h
dln.$(OBJEXT): {$(VPATH)}internal/static_assert.h
dln.$(OBJEXT): {$(VPATH)}internal/stdalign.h
dln.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+dln.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
dln.$(OBJEXT): {$(VPATH)}internal/symbol.h
dln.$(OBJEXT): {$(VPATH)}internal/value.h
dln.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -4753,6 +4906,7 @@ dln_find.$(OBJEXT): {$(VPATH)}internal/special_consts.h
dln_find.$(OBJEXT): {$(VPATH)}internal/static_assert.h
dln_find.$(OBJEXT): {$(VPATH)}internal/stdalign.h
dln_find.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
dln_find.$(OBJEXT): {$(VPATH)}internal/symbol.h
dln_find.$(OBJEXT): {$(VPATH)}internal/value.h
dln_find.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -4909,6 +5063,7 @@ dmydln.$(OBJEXT): {$(VPATH)}internal/special_consts.h
dmydln.$(OBJEXT): {$(VPATH)}internal/static_assert.h
dmydln.$(OBJEXT): {$(VPATH)}internal/stdalign.h
dmydln.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
dmydln.$(OBJEXT): {$(VPATH)}internal/symbol.h
dmydln.$(OBJEXT): {$(VPATH)}internal/value.h
dmydln.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -5738,14 +5893,22 @@ enc/utf_8.$(OBJEXT): {$(VPATH)}oniguruma.h
enc/utf_8.$(OBJEXT): {$(VPATH)}regenc.h
enc/utf_8.$(OBJEXT): {$(VPATH)}st.h
enc/utf_8.$(OBJEXT): {$(VPATH)}subst.h
+encoding.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+encoding.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+encoding.$(OBJEXT): $(CCAN_DIR)/list/list.h
+encoding.$(OBJEXT): $(CCAN_DIR)/str/str.h
encoding.$(OBJEXT): $(hdrdir)/ruby.h
encoding.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+encoding.$(OBJEXT): $(hdrdir)/ruby/version.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/array.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
encoding.$(OBJEXT): $(top_srcdir)/internal/class.h
encoding.$(OBJEXT): $(top_srcdir)/internal/compilers.h
encoding.$(OBJEXT): $(top_srcdir)/internal/enc.h
encoding.$(OBJEXT): $(top_srcdir)/internal/encoding.h
encoding.$(OBJEXT): $(top_srcdir)/internal/error.h
encoding.$(OBJEXT): $(top_srcdir)/internal/gc.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/imemo.h
encoding.$(OBJEXT): $(top_srcdir)/internal/inits.h
encoding.$(OBJEXT): $(top_srcdir)/internal/load.h
encoding.$(OBJEXT): $(top_srcdir)/internal/object.h
@@ -5756,6 +5919,7 @@ encoding.$(OBJEXT): $(top_srcdir)/internal/variable.h
encoding.$(OBJEXT): $(top_srcdir)/internal/vm.h
encoding.$(OBJEXT): $(top_srcdir)/internal/warnings.h
encoding.$(OBJEXT): {$(VPATH)}assert.h
+encoding.$(OBJEXT): {$(VPATH)}atomic.h
encoding.$(OBJEXT): {$(VPATH)}backward/2/assume.h
encoding.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
encoding.$(OBJEXT): {$(VPATH)}backward/2/bool.h
@@ -5772,6 +5936,7 @@ encoding.$(OBJEXT): {$(VPATH)}defines.h
encoding.$(OBJEXT): {$(VPATH)}encindex.h
encoding.$(OBJEXT): {$(VPATH)}encoding.c
encoding.$(OBJEXT): {$(VPATH)}encoding.h
+encoding.$(OBJEXT): {$(VPATH)}id.h
encoding.$(OBJEXT): {$(VPATH)}id_table.h
encoding.$(OBJEXT): {$(VPATH)}intern.h
encoding.$(OBJEXT): {$(VPATH)}internal.h
@@ -5917,22 +6082,31 @@ encoding.$(OBJEXT): {$(VPATH)}internal/special_consts.h
encoding.$(OBJEXT): {$(VPATH)}internal/static_assert.h
encoding.$(OBJEXT): {$(VPATH)}internal/stdalign.h
encoding.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+encoding.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
encoding.$(OBJEXT): {$(VPATH)}internal/symbol.h
encoding.$(OBJEXT): {$(VPATH)}internal/value.h
encoding.$(OBJEXT): {$(VPATH)}internal/value_type.h
encoding.$(OBJEXT): {$(VPATH)}internal/variable.h
encoding.$(OBJEXT): {$(VPATH)}internal/warning_push.h
encoding.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+encoding.$(OBJEXT): {$(VPATH)}method.h
encoding.$(OBJEXT): {$(VPATH)}missing.h
+encoding.$(OBJEXT): {$(VPATH)}node.h
encoding.$(OBJEXT): {$(VPATH)}onigmo.h
encoding.$(OBJEXT): {$(VPATH)}oniguruma.h
encoding.$(OBJEXT): {$(VPATH)}regenc.h
encoding.$(OBJEXT): {$(VPATH)}ruby_assert.h
+encoding.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+encoding.$(OBJEXT): {$(VPATH)}rubyparser.h
encoding.$(OBJEXT): {$(VPATH)}shape.h
encoding.$(OBJEXT): {$(VPATH)}st.h
encoding.$(OBJEXT): {$(VPATH)}subst.h
+encoding.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+encoding.$(OBJEXT): {$(VPATH)}thread_native.h
encoding.$(OBJEXT): {$(VPATH)}util.h
+encoding.$(OBJEXT): {$(VPATH)}vm_core.h
encoding.$(OBJEXT): {$(VPATH)}vm_debug.h
+encoding.$(OBJEXT): {$(VPATH)}vm_opts.h
encoding.$(OBJEXT): {$(VPATH)}vm_sync.h
enum.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enum.$(OBJEXT): $(top_srcdir)/internal/array.h
@@ -6118,6 +6292,7 @@ enum.$(OBJEXT): {$(VPATH)}internal/special_consts.h
enum.$(OBJEXT): {$(VPATH)}internal/static_assert.h
enum.$(OBJEXT): {$(VPATH)}internal/stdalign.h
enum.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+enum.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
enum.$(OBJEXT): {$(VPATH)}internal/symbol.h
enum.$(OBJEXT): {$(VPATH)}internal/value.h
enum.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -6138,6 +6313,7 @@ enumerator.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
enumerator.$(OBJEXT): $(CCAN_DIR)/list/list.h
enumerator.$(OBJEXT): $(CCAN_DIR)/str/str.h
enumerator.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+enumerator.$(OBJEXT): $(hdrdir)/ruby/version.h
enumerator.$(OBJEXT): $(top_srcdir)/internal/array.h
enumerator.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
enumerator.$(OBJEXT): $(top_srcdir)/internal/bignum.h
@@ -6153,6 +6329,7 @@ enumerator.$(OBJEXT): $(top_srcdir)/internal/imemo.h
enumerator.$(OBJEXT): $(top_srcdir)/internal/numeric.h
enumerator.$(OBJEXT): $(top_srcdir)/internal/range.h
enumerator.$(OBJEXT): $(top_srcdir)/internal/rational.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
enumerator.$(OBJEXT): $(top_srcdir)/internal/serial.h
enumerator.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
enumerator.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -6173,6 +6350,7 @@ enumerator.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
enumerator.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
enumerator.$(OBJEXT): {$(VPATH)}config.h
enumerator.$(OBJEXT): {$(VPATH)}constant.h
+enumerator.$(OBJEXT): {$(VPATH)}debug_counter.h
enumerator.$(OBJEXT): {$(VPATH)}defines.h
enumerator.$(OBJEXT): {$(VPATH)}encoding.h
enumerator.$(OBJEXT): {$(VPATH)}enumerator.c
@@ -6322,6 +6500,7 @@ enumerator.$(OBJEXT): {$(VPATH)}internal/special_consts.h
enumerator.$(OBJEXT): {$(VPATH)}internal/static_assert.h
enumerator.$(OBJEXT): {$(VPATH)}internal/stdalign.h
enumerator.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
enumerator.$(OBJEXT): {$(VPATH)}internal/symbol.h
enumerator.$(OBJEXT): {$(VPATH)}internal/value.h
enumerator.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -6342,12 +6521,15 @@ enumerator.$(OBJEXT): {$(VPATH)}subst.h
enumerator.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
enumerator.$(OBJEXT): {$(VPATH)}thread_native.h
enumerator.$(OBJEXT): {$(VPATH)}vm_core.h
+enumerator.$(OBJEXT): {$(VPATH)}vm_debug.h
enumerator.$(OBJEXT): {$(VPATH)}vm_opts.h
+enumerator.$(OBJEXT): {$(VPATH)}vm_sync.h
error.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
error.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
error.$(OBJEXT): $(CCAN_DIR)/list/list.h
error.$(OBJEXT): $(CCAN_DIR)/str/str.h
error.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+error.$(OBJEXT): $(hdrdir)/ruby/version.h
error.$(OBJEXT): $(top_srcdir)/internal/array.h
error.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
error.$(OBJEXT): $(top_srcdir)/internal/class.h
@@ -6361,6 +6543,7 @@ error.$(OBJEXT): $(top_srcdir)/internal/io.h
error.$(OBJEXT): $(top_srcdir)/internal/load.h
error.$(OBJEXT): $(top_srcdir)/internal/object.h
error.$(OBJEXT): $(top_srcdir)/internal/process.h
+error.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
error.$(OBJEXT): $(top_srcdir)/internal/serial.h
error.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
error.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -6383,6 +6566,7 @@ error.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
error.$(OBJEXT): {$(VPATH)}builtin.h
error.$(OBJEXT): {$(VPATH)}config.h
error.$(OBJEXT): {$(VPATH)}constant.h
+error.$(OBJEXT): {$(VPATH)}debug_counter.h
error.$(OBJEXT): {$(VPATH)}defines.h
error.$(OBJEXT): {$(VPATH)}encoding.h
error.$(OBJEXT): {$(VPATH)}error.c
@@ -6532,6 +6716,7 @@ error.$(OBJEXT): {$(VPATH)}internal/special_consts.h
error.$(OBJEXT): {$(VPATH)}internal/static_assert.h
error.$(OBJEXT): {$(VPATH)}internal/stdalign.h
error.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+error.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
error.$(OBJEXT): {$(VPATH)}internal/symbol.h
error.$(OBJEXT): {$(VPATH)}internal/value.h
error.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -6555,14 +6740,18 @@ error.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
error.$(OBJEXT): {$(VPATH)}thread_native.h
error.$(OBJEXT): {$(VPATH)}util.h
error.$(OBJEXT): {$(VPATH)}vm_core.h
+error.$(OBJEXT): {$(VPATH)}vm_debug.h
error.$(OBJEXT): {$(VPATH)}vm_opts.h
+error.$(OBJEXT): {$(VPATH)}vm_sync.h
error.$(OBJEXT): {$(VPATH)}warning.rbinc
+error.$(OBJEXT): {$(VPATH)}yjit.h
eval.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
eval.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
eval.$(OBJEXT): $(CCAN_DIR)/list/list.h
eval.$(OBJEXT): $(CCAN_DIR)/str/str.h
eval.$(OBJEXT): $(hdrdir)/ruby.h
eval.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+eval.$(OBJEXT): $(hdrdir)/ruby/version.h
eval.$(OBJEXT): $(top_srcdir)/internal/array.h
eval.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
eval.$(OBJEXT): $(top_srcdir)/internal/class.h
@@ -6576,6 +6765,7 @@ eval.$(OBJEXT): $(top_srcdir)/internal/imemo.h
eval.$(OBJEXT): $(top_srcdir)/internal/inits.h
eval.$(OBJEXT): $(top_srcdir)/internal/io.h
eval.$(OBJEXT): $(top_srcdir)/internal/object.h
+eval.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
eval.$(OBJEXT): $(top_srcdir)/internal/serial.h
eval.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
eval.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -6583,6 +6773,26 @@ eval.$(OBJEXT): $(top_srcdir)/internal/thread.h
eval.$(OBJEXT): $(top_srcdir)/internal/variable.h
eval.$(OBJEXT): $(top_srcdir)/internal/vm.h
eval.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+eval.$(OBJEXT): $(top_srcdir)/prism/defines.h
+eval.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+eval.$(OBJEXT): $(top_srcdir)/prism/node.h
+eval.$(OBJEXT): $(top_srcdir)/prism/options.h
+eval.$(OBJEXT): $(top_srcdir)/prism/pack.h
+eval.$(OBJEXT): $(top_srcdir)/prism/parser.h
+eval.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+eval.$(OBJEXT): $(top_srcdir)/prism/prism.h
+eval.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+eval.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
eval.$(OBJEXT): {$(VPATH)}assert.h
eval.$(OBJEXT): {$(VPATH)}atomic.h
eval.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -6750,6 +6960,7 @@ eval.$(OBJEXT): {$(VPATH)}internal/special_consts.h
eval.$(OBJEXT): {$(VPATH)}internal/static_assert.h
eval.$(OBJEXT): {$(VPATH)}internal/stdalign.h
eval.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+eval.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
eval.$(OBJEXT): {$(VPATH)}internal/symbol.h
eval.$(OBJEXT): {$(VPATH)}internal/value.h
eval.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -6763,6 +6974,10 @@ eval.$(OBJEXT): {$(VPATH)}missing.h
eval.$(OBJEXT): {$(VPATH)}node.h
eval.$(OBJEXT): {$(VPATH)}onigmo.h
eval.$(OBJEXT): {$(VPATH)}oniguruma.h
+eval.$(OBJEXT): {$(VPATH)}prism/ast.h
+eval.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
+eval.$(OBJEXT): {$(VPATH)}prism/version.h
+eval.$(OBJEXT): {$(VPATH)}prism_compile.h
eval.$(OBJEXT): {$(VPATH)}probes.dmyh
eval.$(OBJEXT): {$(VPATH)}probes.h
eval.$(OBJEXT): {$(VPATH)}probes_helper.h
@@ -6781,6 +6996,7 @@ eval.$(OBJEXT): {$(VPATH)}vm.h
eval.$(OBJEXT): {$(VPATH)}vm_core.h
eval.$(OBJEXT): {$(VPATH)}vm_debug.h
eval.$(OBJEXT): {$(VPATH)}vm_opts.h
+eval.$(OBJEXT): {$(VPATH)}vm_sync.h
explicit_bzero.$(OBJEXT): {$(VPATH)}config.h
explicit_bzero.$(OBJEXT): {$(VPATH)}explicit_bzero.c
explicit_bzero.$(OBJEXT): {$(VPATH)}internal/attr/format.h
@@ -6801,6 +7017,7 @@ file.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
file.$(OBJEXT): $(CCAN_DIR)/list/list.h
file.$(OBJEXT): $(CCAN_DIR)/str/str.h
file.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+file.$(OBJEXT): $(hdrdir)/ruby/version.h
file.$(OBJEXT): $(top_srcdir)/internal/array.h
file.$(OBJEXT): $(top_srcdir)/internal/class.h
file.$(OBJEXT): $(top_srcdir)/internal/compilers.h
@@ -6983,6 +7200,7 @@ file.$(OBJEXT): {$(VPATH)}internal/special_consts.h
file.$(OBJEXT): {$(VPATH)}internal/static_assert.h
file.$(OBJEXT): {$(VPATH)}internal/stdalign.h
file.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+file.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
file.$(OBJEXT): {$(VPATH)}internal/symbol.h
file.$(OBJEXT): {$(VPATH)}internal/value.h
file.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -7005,6 +7223,7 @@ gc.$(OBJEXT): $(CCAN_DIR)/list/list.h
gc.$(OBJEXT): $(CCAN_DIR)/str/str.h
gc.$(OBJEXT): $(hdrdir)/ruby.h
gc.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+gc.$(OBJEXT): $(hdrdir)/ruby/version.h
gc.$(OBJEXT): $(top_srcdir)/internal/array.h
gc.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
gc.$(OBJEXT): $(top_srcdir)/internal/bignum.h
@@ -7035,6 +7254,26 @@ gc.$(OBJEXT): $(top_srcdir)/internal/thread.h
gc.$(OBJEXT): $(top_srcdir)/internal/variable.h
gc.$(OBJEXT): $(top_srcdir)/internal/vm.h
gc.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+gc.$(OBJEXT): $(top_srcdir)/prism/defines.h
+gc.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+gc.$(OBJEXT): $(top_srcdir)/prism/node.h
+gc.$(OBJEXT): $(top_srcdir)/prism/options.h
+gc.$(OBJEXT): $(top_srcdir)/prism/pack.h
+gc.$(OBJEXT): $(top_srcdir)/prism/parser.h
+gc.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+gc.$(OBJEXT): $(top_srcdir)/prism/prism.h
+gc.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+gc.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
gc.$(OBJEXT): {$(VPATH)}assert.h
gc.$(OBJEXT): {$(VPATH)}atomic.h
gc.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -7204,6 +7443,7 @@ gc.$(OBJEXT): {$(VPATH)}internal/special_consts.h
gc.$(OBJEXT): {$(VPATH)}internal/static_assert.h
gc.$(OBJEXT): {$(VPATH)}internal/stdalign.h
gc.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+gc.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
gc.$(OBJEXT): {$(VPATH)}internal/symbol.h
gc.$(OBJEXT): {$(VPATH)}internal/value.h
gc.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -7217,6 +7457,10 @@ gc.$(OBJEXT): {$(VPATH)}missing.h
gc.$(OBJEXT): {$(VPATH)}node.h
gc.$(OBJEXT): {$(VPATH)}onigmo.h
gc.$(OBJEXT): {$(VPATH)}oniguruma.h
+gc.$(OBJEXT): {$(VPATH)}prism/ast.h
+gc.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
+gc.$(OBJEXT): {$(VPATH)}prism/version.h
+gc.$(OBJEXT): {$(VPATH)}prism_compile.h
gc.$(OBJEXT): {$(VPATH)}probes.dmyh
gc.$(OBJEXT): {$(VPATH)}probes.h
gc.$(OBJEXT): {$(VPATH)}ractor.h
@@ -7250,15 +7494,43 @@ goruby.$(OBJEXT): $(hdrdir)/ruby.h
goruby.$(OBJEXT): $(hdrdir)/ruby/ruby.h
goruby.$(OBJEXT): $(top_srcdir)/internal/array.h
goruby.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/bits.h
goruby.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/complex.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
goruby.$(OBJEXT): $(top_srcdir)/internal/gc.h
goruby.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/parse.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/rational.h
goruby.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
goruby.$(OBJEXT): $(top_srcdir)/internal/serial.h
goruby.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
goruby.$(OBJEXT): $(top_srcdir)/internal/variable.h
goruby.$(OBJEXT): $(top_srcdir)/internal/vm.h
goruby.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/defines.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/node.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/options.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/pack.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/parser.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/prism.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
goruby.$(OBJEXT): {$(VPATH)}assert.h
goruby.$(OBJEXT): {$(VPATH)}atomic.h
goruby.$(OBJEXT): {$(VPATH)}backward.h
@@ -7423,6 +7695,7 @@ goruby.$(OBJEXT): {$(VPATH)}internal/special_consts.h
goruby.$(OBJEXT): {$(VPATH)}internal/static_assert.h
goruby.$(OBJEXT): {$(VPATH)}internal/stdalign.h
goruby.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+goruby.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
goruby.$(OBJEXT): {$(VPATH)}internal/symbol.h
goruby.$(OBJEXT): {$(VPATH)}internal/value.h
goruby.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -7436,6 +7709,10 @@ goruby.$(OBJEXT): {$(VPATH)}missing.h
goruby.$(OBJEXT): {$(VPATH)}node.h
goruby.$(OBJEXT): {$(VPATH)}onigmo.h
goruby.$(OBJEXT): {$(VPATH)}oniguruma.h
+goruby.$(OBJEXT): {$(VPATH)}prism/ast.h
+goruby.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
+goruby.$(OBJEXT): {$(VPATH)}prism/version.h
+goruby.$(OBJEXT): {$(VPATH)}prism_compile.h
goruby.$(OBJEXT): {$(VPATH)}ruby_assert.h
goruby.$(OBJEXT): {$(VPATH)}ruby_atomic.h
goruby.$(OBJEXT): {$(VPATH)}rubyparser.h
@@ -7452,6 +7729,7 @@ hash.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
hash.$(OBJEXT): $(CCAN_DIR)/list/list.h
hash.$(OBJEXT): $(CCAN_DIR)/str/str.h
hash.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+hash.$(OBJEXT): $(hdrdir)/ruby/version.h
hash.$(OBJEXT): $(top_srcdir)/internal/array.h
hash.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
hash.$(OBJEXT): $(top_srcdir)/internal/bignum.h
@@ -7465,7 +7743,9 @@ hash.$(OBJEXT): $(top_srcdir)/internal/hash.h
hash.$(OBJEXT): $(top_srcdir)/internal/imemo.h
hash.$(OBJEXT): $(top_srcdir)/internal/object.h
hash.$(OBJEXT): $(top_srcdir)/internal/proc.h
+hash.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
hash.$(OBJEXT): $(top_srcdir)/internal/serial.h
+hash.$(OBJEXT): $(top_srcdir)/internal/st.h
hash.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
hash.$(OBJEXT): $(top_srcdir)/internal/string.h
hash.$(OBJEXT): $(top_srcdir)/internal/symbol.h
@@ -7474,6 +7754,26 @@ hash.$(OBJEXT): $(top_srcdir)/internal/time.h
hash.$(OBJEXT): $(top_srcdir)/internal/variable.h
hash.$(OBJEXT): $(top_srcdir)/internal/vm.h
hash.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+hash.$(OBJEXT): $(top_srcdir)/prism/defines.h
+hash.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+hash.$(OBJEXT): $(top_srcdir)/prism/node.h
+hash.$(OBJEXT): $(top_srcdir)/prism/options.h
+hash.$(OBJEXT): $(top_srcdir)/prism/pack.h
+hash.$(OBJEXT): $(top_srcdir)/prism/parser.h
+hash.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+hash.$(OBJEXT): $(top_srcdir)/prism/prism.h
+hash.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+hash.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
hash.$(OBJEXT): {$(VPATH)}assert.h
hash.$(OBJEXT): {$(VPATH)}atomic.h
hash.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -7634,9 +7934,11 @@ hash.$(OBJEXT): {$(VPATH)}internal/module.h
hash.$(OBJEXT): {$(VPATH)}internal/newobj.h
hash.$(OBJEXT): {$(VPATH)}internal/scan_args.h
hash.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+hash.$(OBJEXT): {$(VPATH)}internal/st.h
hash.$(OBJEXT): {$(VPATH)}internal/static_assert.h
hash.$(OBJEXT): {$(VPATH)}internal/stdalign.h
hash.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+hash.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
hash.$(OBJEXT): {$(VPATH)}internal/symbol.h
hash.$(OBJEXT): {$(VPATH)}internal/value.h
hash.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -7649,6 +7951,10 @@ hash.$(OBJEXT): {$(VPATH)}missing.h
hash.$(OBJEXT): {$(VPATH)}node.h
hash.$(OBJEXT): {$(VPATH)}onigmo.h
hash.$(OBJEXT): {$(VPATH)}oniguruma.h
+hash.$(OBJEXT): {$(VPATH)}prism/ast.h
+hash.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
+hash.$(OBJEXT): {$(VPATH)}prism/version.h
+hash.$(OBJEXT): {$(VPATH)}prism_compile.h
hash.$(OBJEXT): {$(VPATH)}probes.dmyh
hash.$(OBJEXT): {$(VPATH)}probes.h
hash.$(OBJEXT): {$(VPATH)}ractor.h
@@ -7666,6 +7972,211 @@ hash.$(OBJEXT): {$(VPATH)}vm_core.h
hash.$(OBJEXT): {$(VPATH)}vm_debug.h
hash.$(OBJEXT): {$(VPATH)}vm_opts.h
hash.$(OBJEXT): {$(VPATH)}vm_sync.h
+imemo.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+imemo.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+imemo.$(OBJEXT): $(CCAN_DIR)/list/list.h
+imemo.$(OBJEXT): $(CCAN_DIR)/str/str.h
+imemo.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/array.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/class.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/gc.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/serial.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/variable.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/vm.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+imemo.$(OBJEXT): {$(VPATH)}assert.h
+imemo.$(OBJEXT): {$(VPATH)}atomic.h
+imemo.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+imemo.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+imemo.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+imemo.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+imemo.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+imemo.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+imemo.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+imemo.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+imemo.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+imemo.$(OBJEXT): {$(VPATH)}config.h
+imemo.$(OBJEXT): {$(VPATH)}constant.h
+imemo.$(OBJEXT): {$(VPATH)}debug_counter.h
+imemo.$(OBJEXT): {$(VPATH)}defines.h
+imemo.$(OBJEXT): {$(VPATH)}encoding.h
+imemo.$(OBJEXT): {$(VPATH)}id.h
+imemo.$(OBJEXT): {$(VPATH)}id_table.h
+imemo.$(OBJEXT): {$(VPATH)}imemo.c
+imemo.$(OBJEXT): {$(VPATH)}intern.h
+imemo.$(OBJEXT): {$(VPATH)}internal.h
+imemo.$(OBJEXT): {$(VPATH)}internal/abi.h
+imemo.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+imemo.$(OBJEXT): {$(VPATH)}internal/assume.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+imemo.$(OBJEXT): {$(VPATH)}internal/cast.h
+imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+imemo.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+imemo.$(OBJEXT): {$(VPATH)}internal/config.h
+imemo.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+imemo.$(OBJEXT): {$(VPATH)}internal/core.h
+imemo.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+imemo.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+imemo.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+imemo.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+imemo.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+imemo.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+imemo.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+imemo.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+imemo.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+imemo.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+imemo.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+imemo.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+imemo.$(OBJEXT): {$(VPATH)}internal/ctype.h
+imemo.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+imemo.$(OBJEXT): {$(VPATH)}internal/dosish.h
+imemo.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+imemo.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+imemo.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+imemo.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+imemo.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+imemo.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+imemo.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+imemo.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+imemo.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
+imemo.$(OBJEXT): {$(VPATH)}internal/error.h
+imemo.$(OBJEXT): {$(VPATH)}internal/eval.h
+imemo.$(OBJEXT): {$(VPATH)}internal/event.h
+imemo.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+imemo.$(OBJEXT): {$(VPATH)}internal/gc.h
+imemo.$(OBJEXT): {$(VPATH)}internal/glob.h
+imemo.$(OBJEXT): {$(VPATH)}internal/globals.h
+imemo.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+imemo.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+imemo.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+imemo.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+imemo.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+imemo.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+imemo.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+imemo.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+imemo.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+imemo.$(OBJEXT): {$(VPATH)}internal/iterator.h
+imemo.$(OBJEXT): {$(VPATH)}internal/memory.h
+imemo.$(OBJEXT): {$(VPATH)}internal/method.h
+imemo.$(OBJEXT): {$(VPATH)}internal/module.h
+imemo.$(OBJEXT): {$(VPATH)}internal/newobj.h
+imemo.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+imemo.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+imemo.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+imemo.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+imemo.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+imemo.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
+imemo.$(OBJEXT): {$(VPATH)}internal/symbol.h
+imemo.$(OBJEXT): {$(VPATH)}internal/value.h
+imemo.$(OBJEXT): {$(VPATH)}internal/value_type.h
+imemo.$(OBJEXT): {$(VPATH)}internal/variable.h
+imemo.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+imemo.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+imemo.$(OBJEXT): {$(VPATH)}method.h
+imemo.$(OBJEXT): {$(VPATH)}missing.h
+imemo.$(OBJEXT): {$(VPATH)}node.h
+imemo.$(OBJEXT): {$(VPATH)}onigmo.h
+imemo.$(OBJEXT): {$(VPATH)}oniguruma.h
+imemo.$(OBJEXT): {$(VPATH)}ruby_assert.h
+imemo.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+imemo.$(OBJEXT): {$(VPATH)}rubyparser.h
+imemo.$(OBJEXT): {$(VPATH)}shape.h
+imemo.$(OBJEXT): {$(VPATH)}st.h
+imemo.$(OBJEXT): {$(VPATH)}subst.h
+imemo.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+imemo.$(OBJEXT): {$(VPATH)}thread_native.h
+imemo.$(OBJEXT): {$(VPATH)}vm_callinfo.h
+imemo.$(OBJEXT): {$(VPATH)}vm_core.h
+imemo.$(OBJEXT): {$(VPATH)}vm_debug.h
+imemo.$(OBJEXT): {$(VPATH)}vm_opts.h
+imemo.$(OBJEXT): {$(VPATH)}vm_sync.h
inits.$(OBJEXT): $(hdrdir)/ruby.h
inits.$(OBJEXT): $(hdrdir)/ruby/ruby.h
inits.$(OBJEXT): $(top_srcdir)/internal/compilers.h
@@ -7819,6 +8330,7 @@ inits.$(OBJEXT): {$(VPATH)}internal/special_consts.h
inits.$(OBJEXT): {$(VPATH)}internal/static_assert.h
inits.$(OBJEXT): {$(VPATH)}internal/stdalign.h
inits.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+inits.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
inits.$(OBJEXT): {$(VPATH)}internal/symbol.h
inits.$(OBJEXT): {$(VPATH)}internal/value.h
inits.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -7834,6 +8346,7 @@ io.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
io.$(OBJEXT): $(CCAN_DIR)/list/list.h
io.$(OBJEXT): $(CCAN_DIR)/str/str.h
io.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+io.$(OBJEXT): $(hdrdir)/ruby/version.h
io.$(OBJEXT): $(top_srcdir)/internal/array.h
io.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
io.$(OBJEXT): $(top_srcdir)/internal/bignum.h
@@ -7850,6 +8363,7 @@ io.$(OBJEXT): $(top_srcdir)/internal/io.h
io.$(OBJEXT): $(top_srcdir)/internal/numeric.h
io.$(OBJEXT): $(top_srcdir)/internal/object.h
io.$(OBJEXT): $(top_srcdir)/internal/process.h
+io.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
io.$(OBJEXT): $(top_srcdir)/internal/serial.h
io.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
io.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -7872,6 +8386,7 @@ io.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
io.$(OBJEXT): {$(VPATH)}builtin.h
io.$(OBJEXT): {$(VPATH)}config.h
io.$(OBJEXT): {$(VPATH)}constant.h
+io.$(OBJEXT): {$(VPATH)}debug_counter.h
io.$(OBJEXT): {$(VPATH)}defines.h
io.$(OBJEXT): {$(VPATH)}dln.h
io.$(OBJEXT): {$(VPATH)}encindex.h
@@ -8023,6 +8538,7 @@ io.$(OBJEXT): {$(VPATH)}internal/special_consts.h
io.$(OBJEXT): {$(VPATH)}internal/static_assert.h
io.$(OBJEXT): {$(VPATH)}internal/stdalign.h
io.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+io.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
io.$(OBJEXT): {$(VPATH)}internal/symbol.h
io.$(OBJEXT): {$(VPATH)}internal/value.h
io.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -8050,12 +8566,15 @@ io.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
io.$(OBJEXT): {$(VPATH)}thread_native.h
io.$(OBJEXT): {$(VPATH)}util.h
io.$(OBJEXT): {$(VPATH)}vm_core.h
+io.$(OBJEXT): {$(VPATH)}vm_debug.h
io.$(OBJEXT): {$(VPATH)}vm_opts.h
+io.$(OBJEXT): {$(VPATH)}vm_sync.h
io_buffer.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
io_buffer.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
io_buffer.$(OBJEXT): $(CCAN_DIR)/list/list.h
io_buffer.$(OBJEXT): $(CCAN_DIR)/str/str.h
io_buffer.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+io_buffer.$(OBJEXT): $(hdrdir)/ruby/version.h
io_buffer.$(OBJEXT): $(top_srcdir)/internal/array.h
io_buffer.$(OBJEXT): $(top_srcdir)/internal/bignum.h
io_buffer.$(OBJEXT): $(top_srcdir)/internal/bits.h
@@ -8226,6 +8745,7 @@ io_buffer.$(OBJEXT): {$(VPATH)}internal/special_consts.h
io_buffer.$(OBJEXT): {$(VPATH)}internal/static_assert.h
io_buffer.$(OBJEXT): {$(VPATH)}internal/stdalign.h
io_buffer.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
io_buffer.$(OBJEXT): {$(VPATH)}internal/symbol.h
io_buffer.$(OBJEXT): {$(VPATH)}internal/value.h
io_buffer.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -8247,18 +8767,25 @@ iseq.$(OBJEXT): $(CCAN_DIR)/list/list.h
iseq.$(OBJEXT): $(CCAN_DIR)/str/str.h
iseq.$(OBJEXT): $(hdrdir)/ruby.h
iseq.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+iseq.$(OBJEXT): $(hdrdir)/ruby/version.h
iseq.$(OBJEXT): $(top_srcdir)/internal/array.h
iseq.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/bignum.h
iseq.$(OBJEXT): $(top_srcdir)/internal/bits.h
iseq.$(OBJEXT): $(top_srcdir)/internal/class.h
iseq.$(OBJEXT): $(top_srcdir)/internal/compile.h
iseq.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/complex.h
iseq.$(OBJEXT): $(top_srcdir)/internal/error.h
iseq.$(OBJEXT): $(top_srcdir)/internal/file.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
iseq.$(OBJEXT): $(top_srcdir)/internal/gc.h
iseq.$(OBJEXT): $(top_srcdir)/internal/hash.h
iseq.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/io.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/numeric.h
iseq.$(OBJEXT): $(top_srcdir)/internal/parse.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/rational.h
iseq.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
iseq.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
iseq.$(OBJEXT): $(top_srcdir)/internal/serial.h
@@ -8270,8 +8797,7 @@ iseq.$(OBJEXT): $(top_srcdir)/internal/variable.h
iseq.$(OBJEXT): $(top_srcdir)/internal/vm.h
iseq.$(OBJEXT): $(top_srcdir)/internal/warnings.h
iseq.$(OBJEXT): $(top_srcdir)/prism/defines.h
-iseq.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
-iseq.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/encoding.h
iseq.$(OBJEXT): $(top_srcdir)/prism/node.h
iseq.$(OBJEXT): $(top_srcdir)/prism/options.h
iseq.$(OBJEXT): $(top_srcdir)/prism/pack.h
@@ -8279,15 +8805,15 @@ iseq.$(OBJEXT): $(top_srcdir)/prism/parser.h
iseq.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
iseq.$(OBJEXT): $(top_srcdir)/prism/prism.h
iseq.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h
iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
iseq.$(OBJEXT): {$(VPATH)}assert.h
@@ -8457,12 +8983,14 @@ iseq.$(OBJEXT): {$(VPATH)}internal/special_consts.h
iseq.$(OBJEXT): {$(VPATH)}internal/static_assert.h
iseq.$(OBJEXT): {$(VPATH)}internal/stdalign.h
iseq.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+iseq.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
iseq.$(OBJEXT): {$(VPATH)}internal/symbol.h
iseq.$(OBJEXT): {$(VPATH)}internal/value.h
iseq.$(OBJEXT): {$(VPATH)}internal/value_type.h
iseq.$(OBJEXT): {$(VPATH)}internal/variable.h
iseq.$(OBJEXT): {$(VPATH)}internal/warning_push.h
iseq.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+iseq.$(OBJEXT): {$(VPATH)}io.h
iseq.$(OBJEXT): {$(VPATH)}iseq.c
iseq.$(OBJEXT): {$(VPATH)}iseq.h
iseq.$(OBJEXT): {$(VPATH)}method.h
@@ -8471,6 +8999,7 @@ iseq.$(OBJEXT): {$(VPATH)}node.h
iseq.$(OBJEXT): {$(VPATH)}onigmo.h
iseq.$(OBJEXT): {$(VPATH)}oniguruma.h
iseq.$(OBJEXT): {$(VPATH)}prism/ast.h
+iseq.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
iseq.$(OBJEXT): {$(VPATH)}prism/prism.h
iseq.$(OBJEXT): {$(VPATH)}prism/version.h
iseq.$(OBJEXT): {$(VPATH)}prism_compile.h
@@ -8487,25 +9016,35 @@ iseq.$(OBJEXT): {$(VPATH)}thread_native.h
iseq.$(OBJEXT): {$(VPATH)}util.h
iseq.$(OBJEXT): {$(VPATH)}vm_callinfo.h
iseq.$(OBJEXT): {$(VPATH)}vm_core.h
+iseq.$(OBJEXT): {$(VPATH)}vm_debug.h
iseq.$(OBJEXT): {$(VPATH)}vm_opts.h
+iseq.$(OBJEXT): {$(VPATH)}vm_sync.h
iseq.$(OBJEXT): {$(VPATH)}yjit.h
load.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
load.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
load.$(OBJEXT): $(CCAN_DIR)/list/list.h
load.$(OBJEXT): $(CCAN_DIR)/str/str.h
load.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+load.$(OBJEXT): $(hdrdir)/ruby/version.h
load.$(OBJEXT): $(top_srcdir)/internal/array.h
load.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+load.$(OBJEXT): $(top_srcdir)/internal/bignum.h
load.$(OBJEXT): $(top_srcdir)/internal/bits.h
load.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+load.$(OBJEXT): $(top_srcdir)/internal/complex.h
load.$(OBJEXT): $(top_srcdir)/internal/dir.h
load.$(OBJEXT): $(top_srcdir)/internal/error.h
load.$(OBJEXT): $(top_srcdir)/internal/file.h
+load.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
load.$(OBJEXT): $(top_srcdir)/internal/gc.h
+load.$(OBJEXT): $(top_srcdir)/internal/hash.h
load.$(OBJEXT): $(top_srcdir)/internal/imemo.h
load.$(OBJEXT): $(top_srcdir)/internal/load.h
+load.$(OBJEXT): $(top_srcdir)/internal/numeric.h
load.$(OBJEXT): $(top_srcdir)/internal/parse.h
+load.$(OBJEXT): $(top_srcdir)/internal/rational.h
load.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
+load.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
load.$(OBJEXT): $(top_srcdir)/internal/serial.h
load.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
load.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -8513,6 +9052,26 @@ load.$(OBJEXT): $(top_srcdir)/internal/thread.h
load.$(OBJEXT): $(top_srcdir)/internal/variable.h
load.$(OBJEXT): $(top_srcdir)/internal/vm.h
load.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+load.$(OBJEXT): $(top_srcdir)/prism/defines.h
+load.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+load.$(OBJEXT): $(top_srcdir)/prism/node.h
+load.$(OBJEXT): $(top_srcdir)/prism/options.h
+load.$(OBJEXT): $(top_srcdir)/prism/pack.h
+load.$(OBJEXT): $(top_srcdir)/prism/parser.h
+load.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+load.$(OBJEXT): $(top_srcdir)/prism/prism.h
+load.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+load.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+load.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+load.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+load.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+load.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+load.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+load.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+load.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+load.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+load.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+load.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
load.$(OBJEXT): {$(VPATH)}assert.h
load.$(OBJEXT): {$(VPATH)}atomic.h
load.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -8677,6 +9236,7 @@ load.$(OBJEXT): {$(VPATH)}internal/special_consts.h
load.$(OBJEXT): {$(VPATH)}internal/static_assert.h
load.$(OBJEXT): {$(VPATH)}internal/stdalign.h
load.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+load.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
load.$(OBJEXT): {$(VPATH)}internal/symbol.h
load.$(OBJEXT): {$(VPATH)}internal/value.h
load.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -8690,6 +9250,10 @@ load.$(OBJEXT): {$(VPATH)}missing.h
load.$(OBJEXT): {$(VPATH)}node.h
load.$(OBJEXT): {$(VPATH)}onigmo.h
load.$(OBJEXT): {$(VPATH)}oniguruma.h
+load.$(OBJEXT): {$(VPATH)}prism/ast.h
+load.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
+load.$(OBJEXT): {$(VPATH)}prism/version.h
+load.$(OBJEXT): {$(VPATH)}prism_compile.h
load.$(OBJEXT): {$(VPATH)}probes.dmyh
load.$(OBJEXT): {$(VPATH)}probes.h
load.$(OBJEXT): {$(VPATH)}ruby_assert.h
@@ -8851,6 +9415,7 @@ loadpath.$(OBJEXT): {$(VPATH)}internal/special_consts.h
loadpath.$(OBJEXT): {$(VPATH)}internal/static_assert.h
loadpath.$(OBJEXT): {$(VPATH)}internal/stdalign.h
loadpath.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
loadpath.$(OBJEXT): {$(VPATH)}internal/symbol.h
loadpath.$(OBJEXT): {$(VPATH)}internal/value.h
loadpath.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -9020,6 +9585,7 @@ localeinit.$(OBJEXT): {$(VPATH)}internal/special_consts.h
localeinit.$(OBJEXT): {$(VPATH)}internal/static_assert.h
localeinit.$(OBJEXT): {$(VPATH)}internal/stdalign.h
localeinit.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
localeinit.$(OBJEXT): {$(VPATH)}internal/symbol.h
localeinit.$(OBJEXT): {$(VPATH)}internal/value.h
localeinit.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -9034,11 +9600,15 @@ localeinit.$(OBJEXT): {$(VPATH)}st.h
localeinit.$(OBJEXT): {$(VPATH)}subst.h
main.$(OBJEXT): $(hdrdir)/ruby.h
main.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+main.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+main.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+main.$(OBJEXT): $(top_srcdir)/internal/warnings.h
main.$(OBJEXT): {$(VPATH)}assert.h
main.$(OBJEXT): {$(VPATH)}backward.h
main.$(OBJEXT): {$(VPATH)}backward/2/assume.h
main.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
main.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+main.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
main.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
main.$(OBJEXT): {$(VPATH)}backward/2/limits.h
main.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
@@ -9180,6 +9750,7 @@ main.$(OBJEXT): {$(VPATH)}internal/special_consts.h
main.$(OBJEXT): {$(VPATH)}internal/static_assert.h
main.$(OBJEXT): {$(VPATH)}internal/stdalign.h
main.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+main.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
main.$(OBJEXT): {$(VPATH)}internal/symbol.h
main.$(OBJEXT): {$(VPATH)}internal/value.h
main.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -9196,6 +9767,7 @@ marshal.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
marshal.$(OBJEXT): $(CCAN_DIR)/list/list.h
marshal.$(OBJEXT): $(CCAN_DIR)/str/str.h
marshal.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+marshal.$(OBJEXT): $(hdrdir)/ruby/version.h
marshal.$(OBJEXT): $(top_srcdir)/internal/array.h
marshal.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
marshal.$(OBJEXT): $(top_srcdir)/internal/bignum.h
@@ -9210,6 +9782,7 @@ marshal.$(OBJEXT): $(top_srcdir)/internal/hash.h
marshal.$(OBJEXT): $(top_srcdir)/internal/imemo.h
marshal.$(OBJEXT): $(top_srcdir)/internal/numeric.h
marshal.$(OBJEXT): $(top_srcdir)/internal/object.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
marshal.$(OBJEXT): $(top_srcdir)/internal/serial.h
marshal.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
marshal.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -9233,6 +9806,7 @@ marshal.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
marshal.$(OBJEXT): {$(VPATH)}builtin.h
marshal.$(OBJEXT): {$(VPATH)}config.h
marshal.$(OBJEXT): {$(VPATH)}constant.h
+marshal.$(OBJEXT): {$(VPATH)}debug_counter.h
marshal.$(OBJEXT): {$(VPATH)}defines.h
marshal.$(OBJEXT): {$(VPATH)}encindex.h
marshal.$(OBJEXT): {$(VPATH)}encoding.h
@@ -9382,6 +9956,7 @@ marshal.$(OBJEXT): {$(VPATH)}internal/special_consts.h
marshal.$(OBJEXT): {$(VPATH)}internal/static_assert.h
marshal.$(OBJEXT): {$(VPATH)}internal/stdalign.h
marshal.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+marshal.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
marshal.$(OBJEXT): {$(VPATH)}internal/symbol.h
marshal.$(OBJEXT): {$(VPATH)}internal/value.h
marshal.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -9406,7 +9981,9 @@ marshal.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
marshal.$(OBJEXT): {$(VPATH)}thread_native.h
marshal.$(OBJEXT): {$(VPATH)}util.h
marshal.$(OBJEXT): {$(VPATH)}vm_core.h
+marshal.$(OBJEXT): {$(VPATH)}vm_debug.h
marshal.$(OBJEXT): {$(VPATH)}vm_opts.h
+marshal.$(OBJEXT): {$(VPATH)}vm_sync.h
math.$(OBJEXT): $(hdrdir)/ruby/ruby.h
math.$(OBJEXT): $(top_srcdir)/internal/bignum.h
math.$(OBJEXT): $(top_srcdir)/internal/class.h
@@ -9569,6 +10146,7 @@ math.$(OBJEXT): {$(VPATH)}internal/special_consts.h
math.$(OBJEXT): {$(VPATH)}internal/static_assert.h
math.$(OBJEXT): {$(VPATH)}internal/stdalign.h
math.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+math.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
math.$(OBJEXT): {$(VPATH)}internal/symbol.h
math.$(OBJEXT): {$(VPATH)}internal/value.h
math.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -9591,6 +10169,7 @@ memory_view.$(OBJEXT): $(top_srcdir)/internal/compilers.h
memory_view.$(OBJEXT): $(top_srcdir)/internal/gc.h
memory_view.$(OBJEXT): $(top_srcdir)/internal/hash.h
memory_view.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+memory_view.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
memory_view.$(OBJEXT): $(top_srcdir)/internal/serial.h
memory_view.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
memory_view.$(OBJEXT): $(top_srcdir)/internal/variable.h
@@ -9758,6 +10337,7 @@ memory_view.$(OBJEXT): {$(VPATH)}internal/special_consts.h
memory_view.$(OBJEXT): {$(VPATH)}internal/static_assert.h
memory_view.$(OBJEXT): {$(VPATH)}internal/stdalign.h
memory_view.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
memory_view.$(OBJEXT): {$(VPATH)}internal/symbol.h
memory_view.$(OBJEXT): {$(VPATH)}internal/value.h
memory_view.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -9792,15 +10372,43 @@ miniinit.$(OBJEXT): $(hdrdir)/ruby/ruby.h
miniinit.$(OBJEXT): $(srcdir)/rjit_c.rb
miniinit.$(OBJEXT): $(top_srcdir)/internal/array.h
miniinit.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/bits.h
miniinit.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/complex.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
miniinit.$(OBJEXT): $(top_srcdir)/internal/gc.h
miniinit.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/parse.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/rational.h
miniinit.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
miniinit.$(OBJEXT): $(top_srcdir)/internal/serial.h
miniinit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
miniinit.$(OBJEXT): $(top_srcdir)/internal/variable.h
miniinit.$(OBJEXT): $(top_srcdir)/internal/vm.h
miniinit.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/defines.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/node.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/options.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/pack.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/parser.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/prism.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
miniinit.$(OBJEXT): {$(VPATH)}array.rb
miniinit.$(OBJEXT): {$(VPATH)}assert.h
miniinit.$(OBJEXT): {$(VPATH)}ast.rb
@@ -9968,6 +10576,7 @@ miniinit.$(OBJEXT): {$(VPATH)}internal/special_consts.h
miniinit.$(OBJEXT): {$(VPATH)}internal/static_assert.h
miniinit.$(OBJEXT): {$(VPATH)}internal/stdalign.h
miniinit.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
miniinit.$(OBJEXT): {$(VPATH)}internal/symbol.h
miniinit.$(OBJEXT): {$(VPATH)}internal/value.h
miniinit.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -9990,6 +10599,10 @@ miniinit.$(OBJEXT): {$(VPATH)}onigmo.h
miniinit.$(OBJEXT): {$(VPATH)}oniguruma.h
miniinit.$(OBJEXT): {$(VPATH)}pack.rb
miniinit.$(OBJEXT): {$(VPATH)}prelude.rb
+miniinit.$(OBJEXT): {$(VPATH)}prism/ast.h
+miniinit.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
+miniinit.$(OBJEXT): {$(VPATH)}prism/version.h
+miniinit.$(OBJEXT): {$(VPATH)}prism_compile.h
miniinit.$(OBJEXT): {$(VPATH)}ractor.rb
miniinit.$(OBJEXT): {$(VPATH)}rjit.rb
miniinit.$(OBJEXT): {$(VPATH)}rjit_c.rb
@@ -10020,6 +10633,7 @@ node.$(OBJEXT): $(top_srcdir)/internal/compilers.h
node.$(OBJEXT): $(top_srcdir)/internal/gc.h
node.$(OBJEXT): $(top_srcdir)/internal/hash.h
node.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+node.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
node.$(OBJEXT): $(top_srcdir)/internal/serial.h
node.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
node.$(OBJEXT): $(top_srcdir)/internal/variable.h
@@ -10186,6 +10800,7 @@ node.$(OBJEXT): {$(VPATH)}internal/special_consts.h
node.$(OBJEXT): {$(VPATH)}internal/static_assert.h
node.$(OBJEXT): {$(VPATH)}internal/stdalign.h
node.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+node.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
node.$(OBJEXT): {$(VPATH)}internal/symbol.h
node.$(OBJEXT): {$(VPATH)}internal/value.h
node.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -10216,10 +10831,20 @@ node_dump.$(OBJEXT): $(CCAN_DIR)/str/str.h
node_dump.$(OBJEXT): $(hdrdir)/ruby/ruby.h
node_dump.$(OBJEXT): $(top_srcdir)/internal/array.h
node_dump.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/bits.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/class.h
node_dump.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/complex.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
node_dump.$(OBJEXT): $(top_srcdir)/internal/gc.h
node_dump.$(OBJEXT): $(top_srcdir)/internal/hash.h
node_dump.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/parse.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/rational.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
node_dump.$(OBJEXT): $(top_srcdir)/internal/serial.h
node_dump.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
node_dump.$(OBJEXT): $(top_srcdir)/internal/variable.h
@@ -10238,6 +10863,7 @@ node_dump.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
node_dump.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
node_dump.$(OBJEXT): {$(VPATH)}config.h
node_dump.$(OBJEXT): {$(VPATH)}constant.h
+node_dump.$(OBJEXT): {$(VPATH)}debug_counter.h
node_dump.$(OBJEXT): {$(VPATH)}defines.h
node_dump.$(OBJEXT): {$(VPATH)}encoding.h
node_dump.$(OBJEXT): {$(VPATH)}id.h
@@ -10386,6 +11012,7 @@ node_dump.$(OBJEXT): {$(VPATH)}internal/special_consts.h
node_dump.$(OBJEXT): {$(VPATH)}internal/static_assert.h
node_dump.$(OBJEXT): {$(VPATH)}internal/stdalign.h
node_dump.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
node_dump.$(OBJEXT): {$(VPATH)}internal/symbol.h
node_dump.$(OBJEXT): {$(VPATH)}internal/value.h
node_dump.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -10407,7 +11034,9 @@ node_dump.$(OBJEXT): {$(VPATH)}subst.h
node_dump.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
node_dump.$(OBJEXT): {$(VPATH)}thread_native.h
node_dump.$(OBJEXT): {$(VPATH)}vm_core.h
+node_dump.$(OBJEXT): {$(VPATH)}vm_debug.h
node_dump.$(OBJEXT): {$(VPATH)}vm_opts.h
+node_dump.$(OBJEXT): {$(VPATH)}vm_sync.h
numeric.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
numeric.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
numeric.$(OBJEXT): $(CCAN_DIR)/list/list.h
@@ -10428,6 +11057,7 @@ numeric.$(OBJEXT): $(top_srcdir)/internal/imemo.h
numeric.$(OBJEXT): $(top_srcdir)/internal/numeric.h
numeric.$(OBJEXT): $(top_srcdir)/internal/object.h
numeric.$(OBJEXT): $(top_srcdir)/internal/rational.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
numeric.$(OBJEXT): $(top_srcdir)/internal/serial.h
numeric.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
numeric.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -10597,6 +11227,7 @@ numeric.$(OBJEXT): {$(VPATH)}internal/special_consts.h
numeric.$(OBJEXT): {$(VPATH)}internal/static_assert.h
numeric.$(OBJEXT): {$(VPATH)}internal/stdalign.h
numeric.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+numeric.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
numeric.$(OBJEXT): {$(VPATH)}internal/symbol.h
numeric.$(OBJEXT): {$(VPATH)}internal/value.h
numeric.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -10626,6 +11257,7 @@ object.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
object.$(OBJEXT): $(CCAN_DIR)/list/list.h
object.$(OBJEXT): $(CCAN_DIR)/str/str.h
object.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+object.$(OBJEXT): $(hdrdir)/ruby/version.h
object.$(OBJEXT): $(top_srcdir)/internal/array.h
object.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
object.$(OBJEXT): $(top_srcdir)/internal/bignum.h
@@ -10640,7 +11272,9 @@ object.$(OBJEXT): $(top_srcdir)/internal/imemo.h
object.$(OBJEXT): $(top_srcdir)/internal/inits.h
object.$(OBJEXT): $(top_srcdir)/internal/numeric.h
object.$(OBJEXT): $(top_srcdir)/internal/object.h
+object.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
object.$(OBJEXT): $(top_srcdir)/internal/serial.h
+object.$(OBJEXT): $(top_srcdir)/internal/st.h
object.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
object.$(OBJEXT): $(top_srcdir)/internal/string.h
object.$(OBJEXT): $(top_srcdir)/internal/struct.h
@@ -10662,6 +11296,7 @@ object.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
object.$(OBJEXT): {$(VPATH)}builtin.h
object.$(OBJEXT): {$(VPATH)}config.h
object.$(OBJEXT): {$(VPATH)}constant.h
+object.$(OBJEXT): {$(VPATH)}debug_counter.h
object.$(OBJEXT): {$(VPATH)}defines.h
object.$(OBJEXT): {$(VPATH)}encoding.h
object.$(OBJEXT): {$(VPATH)}id.h
@@ -10807,9 +11442,11 @@ object.$(OBJEXT): {$(VPATH)}internal/module.h
object.$(OBJEXT): {$(VPATH)}internal/newobj.h
object.$(OBJEXT): {$(VPATH)}internal/scan_args.h
object.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+object.$(OBJEXT): {$(VPATH)}internal/st.h
object.$(OBJEXT): {$(VPATH)}internal/static_assert.h
object.$(OBJEXT): {$(VPATH)}internal/stdalign.h
object.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+object.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
object.$(OBJEXT): {$(VPATH)}internal/symbol.h
object.$(OBJEXT): {$(VPATH)}internal/value.h
object.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -10837,7 +11474,10 @@ object.$(OBJEXT): {$(VPATH)}thread_native.h
object.$(OBJEXT): {$(VPATH)}util.h
object.$(OBJEXT): {$(VPATH)}variable.h
object.$(OBJEXT): {$(VPATH)}vm_core.h
+object.$(OBJEXT): {$(VPATH)}vm_debug.h
object.$(OBJEXT): {$(VPATH)}vm_opts.h
+object.$(OBJEXT): {$(VPATH)}vm_sync.h
+object.$(OBJEXT): {$(VPATH)}yjit.h
pack.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
pack.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
pack.$(OBJEXT): $(CCAN_DIR)/list/list.h
@@ -10849,6 +11489,7 @@ pack.$(OBJEXT): $(top_srcdir)/internal/bits.h
pack.$(OBJEXT): $(top_srcdir)/internal/compilers.h
pack.$(OBJEXT): $(top_srcdir)/internal/gc.h
pack.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+pack.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
pack.$(OBJEXT): $(top_srcdir)/internal/serial.h
pack.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
pack.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -11018,6 +11659,7 @@ pack.$(OBJEXT): {$(VPATH)}internal/special_consts.h
pack.$(OBJEXT): {$(VPATH)}internal/static_assert.h
pack.$(OBJEXT): {$(VPATH)}internal/stdalign.h
pack.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+pack.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
pack.$(OBJEXT): {$(VPATH)}internal/symbol.h
pack.$(OBJEXT): {$(VPATH)}internal/value.h
pack.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -11048,6 +11690,7 @@ parse.$(OBJEXT): $(CCAN_DIR)/list/list.h
parse.$(OBJEXT): $(CCAN_DIR)/str/str.h
parse.$(OBJEXT): $(hdrdir)/ruby.h
parse.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+parse.$(OBJEXT): $(hdrdir)/ruby/version.h
parse.$(OBJEXT): $(top_srcdir)/internal/array.h
parse.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
parse.$(OBJEXT): $(top_srcdir)/internal/bignum.h
@@ -11067,6 +11710,7 @@ parse.$(OBJEXT): $(top_srcdir)/internal/parse.h
parse.$(OBJEXT): $(top_srcdir)/internal/rational.h
parse.$(OBJEXT): $(top_srcdir)/internal/re.h
parse.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
+parse.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
parse.$(OBJEXT): $(top_srcdir)/internal/serial.h
parse.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
parse.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -11237,6 +11881,7 @@ parse.$(OBJEXT): {$(VPATH)}internal/special_consts.h
parse.$(OBJEXT): {$(VPATH)}internal/static_assert.h
parse.$(OBJEXT): {$(VPATH)}internal/stdalign.h
parse.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+parse.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
parse.$(OBJEXT): {$(VPATH)}internal/symbol.h
parse.$(OBJEXT): {$(VPATH)}internal/value.h
parse.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -11338,8 +11983,7 @@ parser_st.$(OBJEXT): {$(VPATH)}st.c
prism/api_node.$(OBJEXT): $(hdrdir)/ruby.h
prism/api_node.$(OBJEXT): $(hdrdir)/ruby/ruby.h
prism/api_node.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/api_node.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
-prism/api_node.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/encoding.h
prism/api_node.$(OBJEXT): $(top_srcdir)/prism/extension.h
prism/api_node.$(OBJEXT): $(top_srcdir)/prism/node.h
prism/api_node.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -11348,15 +11992,15 @@ prism/api_node.$(OBJEXT): $(top_srcdir)/prism/parser.h
prism/api_node.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
prism/api_node.$(OBJEXT): $(top_srcdir)/prism/prism.h
prism/api_node.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h
prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
prism/api_node.$(OBJEXT): {$(VPATH)}assert.h
@@ -11514,6 +12158,7 @@ prism/api_node.$(OBJEXT): {$(VPATH)}internal/special_consts.h
prism/api_node.$(OBJEXT): {$(VPATH)}internal/static_assert.h
prism/api_node.$(OBJEXT): {$(VPATH)}internal/stdalign.h
prism/api_node.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
prism/api_node.$(OBJEXT): {$(VPATH)}internal/symbol.h
prism/api_node.$(OBJEXT): {$(VPATH)}internal/value.h
prism/api_node.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -11525,6 +12170,7 @@ prism/api_node.$(OBJEXT): {$(VPATH)}onigmo.h
prism/api_node.$(OBJEXT): {$(VPATH)}oniguruma.h
prism/api_node.$(OBJEXT): {$(VPATH)}prism/api_node.c
prism/api_node.$(OBJEXT): {$(VPATH)}prism/ast.h
+prism/api_node.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
prism/api_node.$(OBJEXT): {$(VPATH)}prism/version.h
prism/api_node.$(OBJEXT): {$(VPATH)}st.h
prism/api_node.$(OBJEXT): {$(VPATH)}subst.h
@@ -11532,8 +12178,7 @@ prism/api_pack.$(OBJEXT): $(hdrdir)/ruby.h
prism/api_pack.$(OBJEXT): $(hdrdir)/ruby/ruby.h
prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/api_pack.c
prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/encoding.h
prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/extension.h
prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/node.h
prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -11542,15 +12187,15 @@ prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/parser.h
prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/prism.h
prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h
prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
prism/api_pack.$(OBJEXT): {$(VPATH)}assert.h
@@ -11708,6 +12353,7 @@ prism/api_pack.$(OBJEXT): {$(VPATH)}internal/special_consts.h
prism/api_pack.$(OBJEXT): {$(VPATH)}internal/static_assert.h
prism/api_pack.$(OBJEXT): {$(VPATH)}internal/stdalign.h
prism/api_pack.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
prism/api_pack.$(OBJEXT): {$(VPATH)}internal/symbol.h
prism/api_pack.$(OBJEXT): {$(VPATH)}internal/value.h
prism/api_pack.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -11718,127 +12364,29 @@ prism/api_pack.$(OBJEXT): {$(VPATH)}missing.h
prism/api_pack.$(OBJEXT): {$(VPATH)}onigmo.h
prism/api_pack.$(OBJEXT): {$(VPATH)}oniguruma.h
prism/api_pack.$(OBJEXT): {$(VPATH)}prism/ast.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
prism/api_pack.$(OBJEXT): {$(VPATH)}prism/version.h
prism/api_pack.$(OBJEXT): {$(VPATH)}st.h
prism/api_pack.$(OBJEXT): {$(VPATH)}subst.h
prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/diagnostic.c
-prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-prism/diagnostic.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_ascii.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_ascii.$(OBJEXT): $(top_srcdir)/prism/enc/pm_ascii.c
-prism/enc/pm_ascii.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_ascii.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_big5.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_big5.$(OBJEXT): $(top_srcdir)/prism/enc/pm_big5.c
-prism/enc/pm_big5.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_big5.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_euc_jp.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_euc_jp.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_euc_jp.$(OBJEXT): $(top_srcdir)/prism/enc/pm_euc_jp.c
-prism/enc/pm_euc_jp.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_gbk.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_gbk.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_gbk.$(OBJEXT): $(top_srcdir)/prism/enc/pm_gbk.c
-prism/enc/pm_gbk.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_iso_8859_1.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_iso_8859_1.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_iso_8859_1.$(OBJEXT): $(top_srcdir)/prism/enc/pm_iso_8859_1.c
-prism/enc/pm_iso_8859_1.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_iso_8859_10.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_iso_8859_10.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_iso_8859_10.$(OBJEXT): $(top_srcdir)/prism/enc/pm_iso_8859_10.c
-prism/enc/pm_iso_8859_10.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_iso_8859_11.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_iso_8859_11.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_iso_8859_11.$(OBJEXT): $(top_srcdir)/prism/enc/pm_iso_8859_11.c
-prism/enc/pm_iso_8859_11.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_iso_8859_13.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_iso_8859_13.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_iso_8859_13.$(OBJEXT): $(top_srcdir)/prism/enc/pm_iso_8859_13.c
-prism/enc/pm_iso_8859_13.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_iso_8859_14.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_iso_8859_14.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_iso_8859_14.$(OBJEXT): $(top_srcdir)/prism/enc/pm_iso_8859_14.c
-prism/enc/pm_iso_8859_14.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_iso_8859_15.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_iso_8859_15.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_iso_8859_15.$(OBJEXT): $(top_srcdir)/prism/enc/pm_iso_8859_15.c
-prism/enc/pm_iso_8859_15.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_iso_8859_16.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_iso_8859_16.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_iso_8859_16.$(OBJEXT): $(top_srcdir)/prism/enc/pm_iso_8859_16.c
-prism/enc/pm_iso_8859_16.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_iso_8859_2.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_iso_8859_2.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_iso_8859_2.$(OBJEXT): $(top_srcdir)/prism/enc/pm_iso_8859_2.c
-prism/enc/pm_iso_8859_2.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_iso_8859_3.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_iso_8859_3.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_iso_8859_3.$(OBJEXT): $(top_srcdir)/prism/enc/pm_iso_8859_3.c
-prism/enc/pm_iso_8859_3.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_iso_8859_4.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_iso_8859_4.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_iso_8859_4.$(OBJEXT): $(top_srcdir)/prism/enc/pm_iso_8859_4.c
-prism/enc/pm_iso_8859_4.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_iso_8859_5.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_iso_8859_5.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_iso_8859_5.$(OBJEXT): $(top_srcdir)/prism/enc/pm_iso_8859_5.c
-prism/enc/pm_iso_8859_5.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_iso_8859_6.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_iso_8859_6.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_iso_8859_6.$(OBJEXT): $(top_srcdir)/prism/enc/pm_iso_8859_6.c
-prism/enc/pm_iso_8859_6.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_iso_8859_7.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_iso_8859_7.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_iso_8859_7.$(OBJEXT): $(top_srcdir)/prism/enc/pm_iso_8859_7.c
-prism/enc/pm_iso_8859_7.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_iso_8859_8.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_iso_8859_8.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_iso_8859_8.$(OBJEXT): $(top_srcdir)/prism/enc/pm_iso_8859_8.c
-prism/enc/pm_iso_8859_8.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_iso_8859_9.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_iso_8859_9.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_iso_8859_9.$(OBJEXT): $(top_srcdir)/prism/enc/pm_iso_8859_9.c
-prism/enc/pm_iso_8859_9.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_koi8_r.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_koi8_r.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_koi8_r.$(OBJEXT): $(top_srcdir)/prism/enc/pm_koi8_r.c
-prism/enc/pm_koi8_r.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_shared.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_shared.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_shared.$(OBJEXT): $(top_srcdir)/prism/enc/pm_shared.c
-prism/enc/pm_shared.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_shift_jis.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_shift_jis.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_shift_jis.$(OBJEXT): $(top_srcdir)/prism/enc/pm_shift_jis.c
-prism/enc/pm_shift_jis.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_tables.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_tables.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_tables.$(OBJEXT): $(top_srcdir)/prism/enc/pm_tables.c
-prism/enc/pm_tables.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_unicode.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_unicode.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_unicode.$(OBJEXT): $(top_srcdir)/prism/enc/pm_unicode.c
-prism/enc/pm_unicode.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_windows_1251.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_windows_1251.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_windows_1251.$(OBJEXT): $(top_srcdir)/prism/enc/pm_windows_1251.c
-prism/enc/pm_windows_1251.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_windows_1252.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_windows_1252.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_windows_1252.$(OBJEXT): $(top_srcdir)/prism/enc/pm_windows_1252.c
-prism/enc/pm_windows_1252.$(OBJEXT): {$(VPATH)}config.h
-prism/enc/pm_windows_31j.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/enc/pm_windows_31j.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
-prism/enc/pm_windows_31j.$(OBJEXT): $(top_srcdir)/prism/enc/pm_windows_31j.c
-prism/enc/pm_windows_31j.$(OBJEXT): {$(VPATH)}config.h
+prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+prism/diagnostic.$(OBJEXT): {$(VPATH)}prism/ast.h
+prism/diagnostic.$(OBJEXT): {$(VPATH)}prism/diagnostic.c
+prism/diagnostic.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
+prism/encoding.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/encoding.$(OBJEXT): $(top_srcdir)/prism/encoding.c
+prism/encoding.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+prism/encoding.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
prism/extension.$(OBJEXT): $(hdrdir)/ruby.h
prism/extension.$(OBJEXT): $(hdrdir)/ruby/ruby.h
prism/extension.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/encoding.h
prism/extension.$(OBJEXT): $(top_srcdir)/prism/extension.c
prism/extension.$(OBJEXT): $(top_srcdir)/prism/extension.h
prism/extension.$(OBJEXT): $(top_srcdir)/prism/node.h
@@ -11848,15 +12396,15 @@ prism/extension.$(OBJEXT): $(top_srcdir)/prism/parser.h
prism/extension.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
prism/extension.$(OBJEXT): $(top_srcdir)/prism/prism.h
prism/extension.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h
prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
prism/extension.$(OBJEXT): {$(VPATH)}assert.h
@@ -12014,6 +12562,7 @@ prism/extension.$(OBJEXT): {$(VPATH)}internal/special_consts.h
prism/extension.$(OBJEXT): {$(VPATH)}internal/static_assert.h
prism/extension.$(OBJEXT): {$(VPATH)}internal/stdalign.h
prism/extension.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
prism/extension.$(OBJEXT): {$(VPATH)}internal/symbol.h
prism/extension.$(OBJEXT): {$(VPATH)}internal/value.h
prism/extension.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -12024,29 +12573,30 @@ prism/extension.$(OBJEXT): {$(VPATH)}missing.h
prism/extension.$(OBJEXT): {$(VPATH)}onigmo.h
prism/extension.$(OBJEXT): {$(VPATH)}oniguruma.h
prism/extension.$(OBJEXT): {$(VPATH)}prism/ast.h
+prism/extension.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
prism/extension.$(OBJEXT): {$(VPATH)}prism/version.h
prism/extension.$(OBJEXT): {$(VPATH)}st.h
prism/extension.$(OBJEXT): {$(VPATH)}subst.h
prism/node.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/node.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
-prism/node.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/encoding.h
prism/node.$(OBJEXT): $(top_srcdir)/prism/node.h
prism/node.$(OBJEXT): $(top_srcdir)/prism/options.h
prism/node.$(OBJEXT): $(top_srcdir)/prism/pack.h
prism/node.$(OBJEXT): $(top_srcdir)/prism/parser.h
prism/node.$(OBJEXT): $(top_srcdir)/prism/prism.h
prism/node.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h
prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-prism/node.$(OBJEXT): {$(VPATH)}config.h
prism/node.$(OBJEXT): {$(VPATH)}prism/ast.h
+prism/node.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
prism/node.$(OBJEXT): {$(VPATH)}prism/node.c
prism/options.$(OBJEXT): $(top_srcdir)/prism/defines.h
prism/options.$(OBJEXT): $(top_srcdir)/prism/options.c
@@ -12055,23 +12605,24 @@ prism/options.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
prism/pack.$(OBJEXT): $(top_srcdir)/prism/defines.h
prism/pack.$(OBJEXT): $(top_srcdir)/prism/pack.c
prism/pack.$(OBJEXT): $(top_srcdir)/prism/pack.h
-prism/pack.$(OBJEXT): {$(VPATH)}config.h
prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
+prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/options.h
prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/parser.h
prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h
prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/prettyprint.$(OBJEXT): {$(VPATH)}config.h
+prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
prism/prettyprint.$(OBJEXT): {$(VPATH)}prism/ast.h
prism/prettyprint.$(OBJEXT): {$(VPATH)}prism/prettyprint.c
prism/prism.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/encoding.h
prism/prism.$(OBJEXT): $(top_srcdir)/prism/node.h
prism/prism.$(OBJEXT): $(top_srcdir)/prism/options.h
prism/prism.$(OBJEXT): $(top_srcdir)/prism/pack.h
@@ -12080,38 +12631,40 @@ prism/prism.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
prism/prism.$(OBJEXT): $(top_srcdir)/prism/prism.c
prism/prism.$(OBJEXT): $(top_srcdir)/prism/prism.h
prism/prism.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h
prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
prism/prism.$(OBJEXT): $(top_srcdir)/prism/version.h
-prism/prism.$(OBJEXT): {$(VPATH)}config.h
prism/prism.$(OBJEXT): {$(VPATH)}prism/ast.h
+prism/prism.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
prism/prism.$(OBJEXT): {$(VPATH)}prism/version.h
prism/regexp.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/regexp.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
+prism/regexp.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+prism/regexp.$(OBJEXT): $(top_srcdir)/prism/options.h
prism/regexp.$(OBJEXT): $(top_srcdir)/prism/parser.h
prism/regexp.$(OBJEXT): $(top_srcdir)/prism/regexp.c
prism/regexp.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+prism/regexp.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h
prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-prism/regexp.$(OBJEXT): {$(VPATH)}config.h
+prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
prism/regexp.$(OBJEXT): {$(VPATH)}prism/ast.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/serialize.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
-prism/serialize.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/encoding.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/node.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/options.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/pack.h
@@ -12119,93 +12672,108 @@ prism/serialize.$(OBJEXT): $(top_srcdir)/prism/parser.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/prism.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-prism/serialize.$(OBJEXT): {$(VPATH)}config.h
prism/serialize.$(OBJEXT): {$(VPATH)}prism/ast.h
+prism/serialize.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
prism/serialize.$(OBJEXT): {$(VPATH)}prism/serialize.c
prism/serialize.$(OBJEXT): {$(VPATH)}prism/version.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/node.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/options.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/parser.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/static_literals.c
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+prism/static_literals.$(OBJEXT): {$(VPATH)}prism/ast.h
prism/token_type.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/token_type.$(OBJEXT): {$(VPATH)}config.h
prism/token_type.$(OBJEXT): {$(VPATH)}prism/ast.h
prism/token_type.$(OBJEXT): {$(VPATH)}prism/token_type.c
prism/util/pm_buffer.$(OBJEXT): $(top_srcdir)/prism/defines.h
prism/util/pm_buffer.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.c
prism/util/pm_buffer.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-prism/util/pm_buffer.$(OBJEXT): {$(VPATH)}config.h
+prism/util/pm_buffer.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+prism/util/pm_buffer.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
prism/util/pm_char.$(OBJEXT): $(top_srcdir)/prism/defines.h
prism/util/pm_char.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.c
prism/util/pm_char.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
prism/util/pm_char.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/util/pm_char.$(OBJEXT): {$(VPATH)}config.h
prism/util/pm_constant_pool.$(OBJEXT): $(top_srcdir)/prism/defines.h
prism/util/pm_constant_pool.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.c
prism/util/pm_constant_pool.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-prism/util/pm_constant_pool.$(OBJEXT): {$(VPATH)}config.h
+prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.c
+prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
prism/util/pm_list.$(OBJEXT): $(top_srcdir)/prism/defines.h
prism/util/pm_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.c
prism/util/pm_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-prism/util/pm_list.$(OBJEXT): {$(VPATH)}config.h
prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
+prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/encoding.h
prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/parser.h
prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.c
prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h
prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/util/pm_memchr.$(OBJEXT): {$(VPATH)}config.h
+prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
prism/util/pm_memchr.$(OBJEXT): {$(VPATH)}prism/ast.h
prism/util/pm_newline_list.$(OBJEXT): $(top_srcdir)/prism/defines.h
prism/util/pm_newline_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.c
prism/util/pm_newline_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/util/pm_newline_list.$(OBJEXT): {$(VPATH)}config.h
-prism/util/pm_state_stack.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/util/pm_state_stack.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.c
-prism/util/pm_state_stack.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h
-prism/util/pm_state_stack.$(OBJEXT): {$(VPATH)}config.h
prism/util/pm_string.$(OBJEXT): $(top_srcdir)/prism/defines.h
prism/util/pm_string.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.c
prism/util/pm_string.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/util/pm_string.$(OBJEXT): {$(VPATH)}config.h
-prism/util/pm_string_list.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/util/pm_string_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/util/pm_string_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.c
-prism/util/pm_string_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-prism/util/pm_string_list.$(OBJEXT): {$(VPATH)}config.h
prism/util/pm_strncasecmp.$(OBJEXT): $(top_srcdir)/prism/defines.h
prism/util/pm_strncasecmp.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.c
prism/util/pm_strncasecmp.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
+prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/options.h
prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/parser.h
+prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h
prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.c
prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-prism/util/pm_strpbrk.$(OBJEXT): {$(VPATH)}config.h
prism/util/pm_strpbrk.$(OBJEXT): {$(VPATH)}prism/ast.h
+prism/util/pm_strpbrk.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
prism_init.$(OBJEXT): $(hdrdir)/ruby.h
prism_init.$(OBJEXT): $(hdrdir)/ruby/ruby.h
prism_init.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/encoding.h
prism_init.$(OBJEXT): $(top_srcdir)/prism/extension.h
prism_init.$(OBJEXT): $(top_srcdir)/prism/node.h
prism_init.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -12214,15 +12782,15 @@ prism_init.$(OBJEXT): $(top_srcdir)/prism/parser.h
prism_init.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
prism_init.$(OBJEXT): $(top_srcdir)/prism/prism.h
prism_init.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h
prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
prism_init.$(OBJEXT): $(top_srcdir)/prism_init.c
@@ -12381,6 +12949,7 @@ prism_init.$(OBJEXT): {$(VPATH)}internal/special_consts.h
prism_init.$(OBJEXT): {$(VPATH)}internal/static_assert.h
prism_init.$(OBJEXT): {$(VPATH)}internal/stdalign.h
prism_init.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
prism_init.$(OBJEXT): {$(VPATH)}internal/symbol.h
prism_init.$(OBJEXT): {$(VPATH)}internal/value.h
prism_init.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -12391,6 +12960,7 @@ prism_init.$(OBJEXT): {$(VPATH)}missing.h
prism_init.$(OBJEXT): {$(VPATH)}onigmo.h
prism_init.$(OBJEXT): {$(VPATH)}oniguruma.h
prism_init.$(OBJEXT): {$(VPATH)}prism/ast.h
+prism_init.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
prism_init.$(OBJEXT): {$(VPATH)}prism/version.h
prism_init.$(OBJEXT): {$(VPATH)}prism_init.c
prism_init.$(OBJEXT): {$(VPATH)}st.h
@@ -12400,6 +12970,7 @@ proc.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
proc.$(OBJEXT): $(CCAN_DIR)/list/list.h
proc.$(OBJEXT): $(CCAN_DIR)/str/str.h
proc.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+proc.$(OBJEXT): $(hdrdir)/ruby/version.h
proc.$(OBJEXT): $(top_srcdir)/internal/array.h
proc.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
proc.$(OBJEXT): $(top_srcdir)/internal/class.h
@@ -12410,6 +12981,7 @@ proc.$(OBJEXT): $(top_srcdir)/internal/gc.h
proc.$(OBJEXT): $(top_srcdir)/internal/imemo.h
proc.$(OBJEXT): $(top_srcdir)/internal/object.h
proc.$(OBJEXT): $(top_srcdir)/internal/proc.h
+proc.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
proc.$(OBJEXT): $(top_srcdir)/internal/serial.h
proc.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
proc.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -12417,6 +12989,26 @@ proc.$(OBJEXT): $(top_srcdir)/internal/symbol.h
proc.$(OBJEXT): $(top_srcdir)/internal/variable.h
proc.$(OBJEXT): $(top_srcdir)/internal/vm.h
proc.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+proc.$(OBJEXT): $(top_srcdir)/prism/defines.h
+proc.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+proc.$(OBJEXT): $(top_srcdir)/prism/node.h
+proc.$(OBJEXT): $(top_srcdir)/prism/options.h
+proc.$(OBJEXT): $(top_srcdir)/prism/pack.h
+proc.$(OBJEXT): $(top_srcdir)/prism/parser.h
+proc.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+proc.$(OBJEXT): $(top_srcdir)/prism/prism.h
+proc.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+proc.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
proc.$(OBJEXT): {$(VPATH)}assert.h
proc.$(OBJEXT): {$(VPATH)}atomic.h
proc.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -12430,6 +13022,7 @@ proc.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
proc.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
proc.$(OBJEXT): {$(VPATH)}config.h
proc.$(OBJEXT): {$(VPATH)}constant.h
+proc.$(OBJEXT): {$(VPATH)}debug_counter.h
proc.$(OBJEXT): {$(VPATH)}defines.h
proc.$(OBJEXT): {$(VPATH)}encoding.h
proc.$(OBJEXT): {$(VPATH)}eval_intern.h
@@ -12579,6 +13172,7 @@ proc.$(OBJEXT): {$(VPATH)}internal/special_consts.h
proc.$(OBJEXT): {$(VPATH)}internal/static_assert.h
proc.$(OBJEXT): {$(VPATH)}internal/stdalign.h
proc.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+proc.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
proc.$(OBJEXT): {$(VPATH)}internal/symbol.h
proc.$(OBJEXT): {$(VPATH)}internal/value.h
proc.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -12591,6 +13185,10 @@ proc.$(OBJEXT): {$(VPATH)}missing.h
proc.$(OBJEXT): {$(VPATH)}node.h
proc.$(OBJEXT): {$(VPATH)}onigmo.h
proc.$(OBJEXT): {$(VPATH)}oniguruma.h
+proc.$(OBJEXT): {$(VPATH)}prism/ast.h
+proc.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
+proc.$(OBJEXT): {$(VPATH)}prism/version.h
+proc.$(OBJEXT): {$(VPATH)}prism_compile.h
proc.$(OBJEXT): {$(VPATH)}proc.c
proc.$(OBJEXT): {$(VPATH)}ruby_assert.h
proc.$(OBJEXT): {$(VPATH)}ruby_atomic.h
@@ -12601,7 +13199,9 @@ proc.$(OBJEXT): {$(VPATH)}subst.h
proc.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
proc.$(OBJEXT): {$(VPATH)}thread_native.h
proc.$(OBJEXT): {$(VPATH)}vm_core.h
+proc.$(OBJEXT): {$(VPATH)}vm_debug.h
proc.$(OBJEXT): {$(VPATH)}vm_opts.h
+proc.$(OBJEXT): {$(VPATH)}vm_sync.h
proc.$(OBJEXT): {$(VPATH)}yjit.h
process.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
process.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
@@ -12609,6 +13209,7 @@ process.$(OBJEXT): $(CCAN_DIR)/list/list.h
process.$(OBJEXT): $(CCAN_DIR)/str/str.h
process.$(OBJEXT): $(hdrdir)/ruby.h
process.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+process.$(OBJEXT): $(hdrdir)/ruby/version.h
process.$(OBJEXT): $(top_srcdir)/internal/array.h
process.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
process.$(OBJEXT): $(top_srcdir)/internal/bignum.h
@@ -12626,6 +13227,7 @@ process.$(OBJEXT): $(top_srcdir)/internal/io.h
process.$(OBJEXT): $(top_srcdir)/internal/numeric.h
process.$(OBJEXT): $(top_srcdir)/internal/object.h
process.$(OBJEXT): $(top_srcdir)/internal/process.h
+process.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
process.$(OBJEXT): $(top_srcdir)/internal/serial.h
process.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
process.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -12799,6 +13401,7 @@ process.$(OBJEXT): {$(VPATH)}internal/special_consts.h
process.$(OBJEXT): {$(VPATH)}internal/static_assert.h
process.$(OBJEXT): {$(VPATH)}internal/stdalign.h
process.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+process.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
process.$(OBJEXT): {$(VPATH)}internal/symbol.h
process.$(OBJEXT): {$(VPATH)}internal/value.h
process.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -12834,6 +13437,7 @@ ractor.$(OBJEXT): $(CCAN_DIR)/list/list.h
ractor.$(OBJEXT): $(CCAN_DIR)/str/str.h
ractor.$(OBJEXT): $(hdrdir)/ruby.h
ractor.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+ractor.$(OBJEXT): $(hdrdir)/ruby/version.h
ractor.$(OBJEXT): $(top_srcdir)/internal/array.h
ractor.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
ractor.$(OBJEXT): $(top_srcdir)/internal/bignum.h
@@ -12847,6 +13451,7 @@ ractor.$(OBJEXT): $(top_srcdir)/internal/hash.h
ractor.$(OBJEXT): $(top_srcdir)/internal/imemo.h
ractor.$(OBJEXT): $(top_srcdir)/internal/numeric.h
ractor.$(OBJEXT): $(top_srcdir)/internal/rational.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
ractor.$(OBJEXT): $(top_srcdir)/internal/serial.h
ractor.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
ractor.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -13019,6 +13624,7 @@ ractor.$(OBJEXT): {$(VPATH)}internal/special_consts.h
ractor.$(OBJEXT): {$(VPATH)}internal/static_assert.h
ractor.$(OBJEXT): {$(VPATH)}internal/stdalign.h
ractor.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+ractor.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
ractor.$(OBJEXT): {$(VPATH)}internal/symbol.h
ractor.$(OBJEXT): {$(VPATH)}internal/value.h
ractor.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -13232,6 +13838,7 @@ random.$(OBJEXT): {$(VPATH)}internal/special_consts.h
random.$(OBJEXT): {$(VPATH)}internal/static_assert.h
random.$(OBJEXT): {$(VPATH)}internal/stdalign.h
random.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+random.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
random.$(OBJEXT): {$(VPATH)}internal/symbol.h
random.$(OBJEXT): {$(VPATH)}internal/value.h
random.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -13260,6 +13867,7 @@ random.$(OBJEXT): {$(VPATH)}thread_native.h
random.$(OBJEXT): {$(VPATH)}vm_core.h
random.$(OBJEXT): {$(VPATH)}vm_opts.h
range.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+range.$(OBJEXT): $(hdrdir)/ruby/version.h
range.$(OBJEXT): $(top_srcdir)/internal/array.h
range.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
range.$(OBJEXT): $(top_srcdir)/internal/bignum.h
@@ -13437,6 +14045,7 @@ range.$(OBJEXT): {$(VPATH)}internal/special_consts.h
range.$(OBJEXT): {$(VPATH)}internal/static_assert.h
range.$(OBJEXT): {$(VPATH)}internal/stdalign.h
range.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+range.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
range.$(OBJEXT): {$(VPATH)}internal/symbol.h
range.$(OBJEXT): {$(VPATH)}internal/value.h
range.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -13468,6 +14077,7 @@ rational.$(OBJEXT): $(top_srcdir)/internal/imemo.h
rational.$(OBJEXT): $(top_srcdir)/internal/numeric.h
rational.$(OBJEXT): $(top_srcdir)/internal/object.h
rational.$(OBJEXT): $(top_srcdir)/internal/rational.h
+rational.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
rational.$(OBJEXT): $(top_srcdir)/internal/serial.h
rational.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
rational.$(OBJEXT): $(top_srcdir)/internal/variable.h
@@ -13634,6 +14244,7 @@ rational.$(OBJEXT): {$(VPATH)}internal/special_consts.h
rational.$(OBJEXT): {$(VPATH)}internal/static_assert.h
rational.$(OBJEXT): {$(VPATH)}internal/stdalign.h
rational.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+rational.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
rational.$(OBJEXT): {$(VPATH)}internal/symbol.h
rational.$(OBJEXT): {$(VPATH)}internal/value.h
rational.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -13674,6 +14285,7 @@ re.$(OBJEXT): $(top_srcdir)/internal/imemo.h
re.$(OBJEXT): $(top_srcdir)/internal/object.h
re.$(OBJEXT): $(top_srcdir)/internal/ractor.h
re.$(OBJEXT): $(top_srcdir)/internal/re.h
+re.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
re.$(OBJEXT): $(top_srcdir)/internal/serial.h
re.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
re.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -13845,6 +14457,7 @@ re.$(OBJEXT): {$(VPATH)}internal/special_consts.h
re.$(OBJEXT): {$(VPATH)}internal/static_assert.h
re.$(OBJEXT): {$(VPATH)}internal/stdalign.h
re.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+re.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
re.$(OBJEXT): {$(VPATH)}internal/symbol.h
re.$(OBJEXT): {$(VPATH)}internal/value.h
re.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -14019,6 +14632,7 @@ regcomp.$(OBJEXT): {$(VPATH)}internal/special_consts.h
regcomp.$(OBJEXT): {$(VPATH)}internal/static_assert.h
regcomp.$(OBJEXT): {$(VPATH)}internal/stdalign.h
regcomp.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
regcomp.$(OBJEXT): {$(VPATH)}internal/symbol.h
regcomp.$(OBJEXT): {$(VPATH)}internal/value.h
regcomp.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -14180,6 +14794,7 @@ regenc.$(OBJEXT): {$(VPATH)}internal/special_consts.h
regenc.$(OBJEXT): {$(VPATH)}internal/static_assert.h
regenc.$(OBJEXT): {$(VPATH)}internal/stdalign.h
regenc.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+regenc.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
regenc.$(OBJEXT): {$(VPATH)}internal/symbol.h
regenc.$(OBJEXT): {$(VPATH)}internal/value.h
regenc.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -14340,6 +14955,7 @@ regerror.$(OBJEXT): {$(VPATH)}internal/special_consts.h
regerror.$(OBJEXT): {$(VPATH)}internal/static_assert.h
regerror.$(OBJEXT): {$(VPATH)}internal/stdalign.h
regerror.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+regerror.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
regerror.$(OBJEXT): {$(VPATH)}internal/symbol.h
regerror.$(OBJEXT): {$(VPATH)}internal/value.h
regerror.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -14500,6 +15116,7 @@ regexec.$(OBJEXT): {$(VPATH)}internal/special_consts.h
regexec.$(OBJEXT): {$(VPATH)}internal/static_assert.h
regexec.$(OBJEXT): {$(VPATH)}internal/stdalign.h
regexec.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+regexec.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
regexec.$(OBJEXT): {$(VPATH)}internal/symbol.h
regexec.$(OBJEXT): {$(VPATH)}internal/value.h
regexec.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -14664,6 +15281,7 @@ regparse.$(OBJEXT): {$(VPATH)}internal/special_consts.h
regparse.$(OBJEXT): {$(VPATH)}internal/static_assert.h
regparse.$(OBJEXT): {$(VPATH)}internal/stdalign.h
regparse.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+regparse.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
regparse.$(OBJEXT): {$(VPATH)}internal/symbol.h
regparse.$(OBJEXT): {$(VPATH)}internal/value.h
regparse.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -14825,6 +15443,7 @@ regsyntax.$(OBJEXT): {$(VPATH)}internal/special_consts.h
regsyntax.$(OBJEXT): {$(VPATH)}internal/static_assert.h
regsyntax.$(OBJEXT): {$(VPATH)}internal/stdalign.h
regsyntax.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
regsyntax.$(OBJEXT): {$(VPATH)}internal/symbol.h
regsyntax.$(OBJEXT): {$(VPATH)}internal/value.h
regsyntax.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -14857,6 +15476,7 @@ rjit.$(OBJEXT): $(top_srcdir)/internal/gc.h
rjit.$(OBJEXT): $(top_srcdir)/internal/hash.h
rjit.$(OBJEXT): $(top_srcdir)/internal/imemo.h
rjit.$(OBJEXT): $(top_srcdir)/internal/process.h
+rjit.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
rjit.$(OBJEXT): $(top_srcdir)/internal/serial.h
rjit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
rjit.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -14864,6 +15484,26 @@ rjit.$(OBJEXT): $(top_srcdir)/internal/struct.h
rjit.$(OBJEXT): $(top_srcdir)/internal/variable.h
rjit.$(OBJEXT): $(top_srcdir)/internal/vm.h
rjit.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+rjit.$(OBJEXT): $(top_srcdir)/prism/defines.h
+rjit.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+rjit.$(OBJEXT): $(top_srcdir)/prism/node.h
+rjit.$(OBJEXT): $(top_srcdir)/prism/options.h
+rjit.$(OBJEXT): $(top_srcdir)/prism/pack.h
+rjit.$(OBJEXT): $(top_srcdir)/prism/parser.h
+rjit.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+rjit.$(OBJEXT): $(top_srcdir)/prism/prism.h
+rjit.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+rjit.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
rjit.$(OBJEXT): {$(VPATH)}assert.h
rjit.$(OBJEXT): {$(VPATH)}atomic.h
rjit.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -15032,6 +15672,7 @@ rjit.$(OBJEXT): {$(VPATH)}internal/special_consts.h
rjit.$(OBJEXT): {$(VPATH)}internal/static_assert.h
rjit.$(OBJEXT): {$(VPATH)}internal/stdalign.h
rjit.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+rjit.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
rjit.$(OBJEXT): {$(VPATH)}internal/symbol.h
rjit.$(OBJEXT): {$(VPATH)}internal/value.h
rjit.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -15044,6 +15685,10 @@ rjit.$(OBJEXT): {$(VPATH)}missing.h
rjit.$(OBJEXT): {$(VPATH)}node.h
rjit.$(OBJEXT): {$(VPATH)}onigmo.h
rjit.$(OBJEXT): {$(VPATH)}oniguruma.h
+rjit.$(OBJEXT): {$(VPATH)}prism/ast.h
+rjit.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
+rjit.$(OBJEXT): {$(VPATH)}prism/version.h
+rjit.$(OBJEXT): {$(VPATH)}prism_compile.h
rjit.$(OBJEXT): {$(VPATH)}ractor.h
rjit.$(OBJEXT): {$(VPATH)}ractor_core.h
rjit.$(OBJEXT): {$(VPATH)}rjit.c
@@ -15092,6 +15737,26 @@ rjit_c.$(OBJEXT): $(top_srcdir)/internal/struct.h
rjit_c.$(OBJEXT): $(top_srcdir)/internal/variable.h
rjit_c.$(OBJEXT): $(top_srcdir)/internal/vm.h
rjit_c.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+rjit_c.$(OBJEXT): $(top_srcdir)/prism/defines.h
+rjit_c.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+rjit_c.$(OBJEXT): $(top_srcdir)/prism/node.h
+rjit_c.$(OBJEXT): $(top_srcdir)/prism/options.h
+rjit_c.$(OBJEXT): $(top_srcdir)/prism/pack.h
+rjit_c.$(OBJEXT): $(top_srcdir)/prism/parser.h
+rjit_c.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+rjit_c.$(OBJEXT): $(top_srcdir)/prism/prism.h
+rjit_c.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+rjit_c.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
rjit_c.$(OBJEXT): {$(VPATH)}assert.h
rjit_c.$(OBJEXT): {$(VPATH)}atomic.h
rjit_c.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -15259,6 +15924,7 @@ rjit_c.$(OBJEXT): {$(VPATH)}internal/special_consts.h
rjit_c.$(OBJEXT): {$(VPATH)}internal/static_assert.h
rjit_c.$(OBJEXT): {$(VPATH)}internal/stdalign.h
rjit_c.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+rjit_c.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
rjit_c.$(OBJEXT): {$(VPATH)}internal/symbol.h
rjit_c.$(OBJEXT): {$(VPATH)}internal/value.h
rjit_c.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -15271,6 +15937,10 @@ rjit_c.$(OBJEXT): {$(VPATH)}missing.h
rjit_c.$(OBJEXT): {$(VPATH)}node.h
rjit_c.$(OBJEXT): {$(VPATH)}onigmo.h
rjit_c.$(OBJEXT): {$(VPATH)}oniguruma.h
+rjit_c.$(OBJEXT): {$(VPATH)}prism/ast.h
+rjit_c.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
+rjit_c.$(OBJEXT): {$(VPATH)}prism/version.h
+rjit_c.$(OBJEXT): {$(VPATH)}prism_compile.h
rjit_c.$(OBJEXT): {$(VPATH)}probes.dmyh
rjit_c.$(OBJEXT): {$(VPATH)}probes.h
rjit_c.$(OBJEXT): {$(VPATH)}probes_helper.h
@@ -15289,9 +15959,11 @@ rjit_c.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
rjit_c.$(OBJEXT): {$(VPATH)}thread_native.h
rjit_c.$(OBJEXT): {$(VPATH)}vm_callinfo.h
rjit_c.$(OBJEXT): {$(VPATH)}vm_core.h
+rjit_c.$(OBJEXT): {$(VPATH)}vm_debug.h
rjit_c.$(OBJEXT): {$(VPATH)}vm_exec.h
rjit_c.$(OBJEXT): {$(VPATH)}vm_insnhelper.h
rjit_c.$(OBJEXT): {$(VPATH)}vm_opts.h
+rjit_c.$(OBJEXT): {$(VPATH)}vm_sync.h
rjit_c.$(OBJEXT): {$(VPATH)}yjit.h
ruby-runner.$(OBJEXT): {$(VPATH)}config.h
ruby-runner.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
@@ -15314,12 +15986,16 @@ ruby.$(OBJEXT): $(hdrdir)/ruby/ruby.h
ruby.$(OBJEXT): $(hdrdir)/ruby/version.h
ruby.$(OBJEXT): $(top_srcdir)/internal/array.h
ruby.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/bits.h
ruby.$(OBJEXT): $(top_srcdir)/internal/class.h
ruby.$(OBJEXT): $(top_srcdir)/internal/cmdlineopt.h
ruby.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/complex.h
ruby.$(OBJEXT): $(top_srcdir)/internal/cont.h
ruby.$(OBJEXT): $(top_srcdir)/internal/error.h
ruby.$(OBJEXT): $(top_srcdir)/internal/file.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
ruby.$(OBJEXT): $(top_srcdir)/internal/gc.h
ruby.$(OBJEXT): $(top_srcdir)/internal/imemo.h
ruby.$(OBJEXT): $(top_srcdir)/internal/inits.h
@@ -15327,9 +16003,12 @@ ruby.$(OBJEXT): $(top_srcdir)/internal/io.h
ruby.$(OBJEXT): $(top_srcdir)/internal/load.h
ruby.$(OBJEXT): $(top_srcdir)/internal/loadpath.h
ruby.$(OBJEXT): $(top_srcdir)/internal/missing.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/numeric.h
ruby.$(OBJEXT): $(top_srcdir)/internal/object.h
ruby.$(OBJEXT): $(top_srcdir)/internal/parse.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/rational.h
ruby.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
ruby.$(OBJEXT): $(top_srcdir)/internal/serial.h
ruby.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
ruby.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -15338,8 +16017,7 @@ ruby.$(OBJEXT): $(top_srcdir)/internal/variable.h
ruby.$(OBJEXT): $(top_srcdir)/internal/vm.h
ruby.$(OBJEXT): $(top_srcdir)/internal/warnings.h
ruby.$(OBJEXT): $(top_srcdir)/prism/defines.h
-ruby.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
-ruby.$(OBJEXT): $(top_srcdir)/prism/enc/pm_encoding.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/encoding.h
ruby.$(OBJEXT): $(top_srcdir)/prism/node.h
ruby.$(OBJEXT): $(top_srcdir)/prism/options.h
ruby.$(OBJEXT): $(top_srcdir)/prism/pack.h
@@ -15347,15 +16025,15 @@ ruby.$(OBJEXT): $(top_srcdir)/prism/parser.h
ruby.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
ruby.$(OBJEXT): $(top_srcdir)/prism/prism.h
ruby.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h
ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
ruby.$(OBJEXT): {$(VPATH)}assert.h
@@ -15522,6 +16200,7 @@ ruby.$(OBJEXT): {$(VPATH)}internal/special_consts.h
ruby.$(OBJEXT): {$(VPATH)}internal/static_assert.h
ruby.$(OBJEXT): {$(VPATH)}internal/stdalign.h
ruby.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+ruby.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
ruby.$(OBJEXT): {$(VPATH)}internal/symbol.h
ruby.$(OBJEXT): {$(VPATH)}internal/value.h
ruby.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -15536,6 +16215,7 @@ ruby.$(OBJEXT): {$(VPATH)}node.h
ruby.$(OBJEXT): {$(VPATH)}onigmo.h
ruby.$(OBJEXT): {$(VPATH)}oniguruma.h
ruby.$(OBJEXT): {$(VPATH)}prism/ast.h
+ruby.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
ruby.$(OBJEXT): {$(VPATH)}prism/version.h
ruby.$(OBJEXT): {$(VPATH)}prism_compile.h
ruby.$(OBJEXT): {$(VPATH)}rjit.h
@@ -15553,7 +16233,197 @@ ruby.$(OBJEXT): {$(VPATH)}util.h
ruby.$(OBJEXT): {$(VPATH)}vm_core.h
ruby.$(OBJEXT): {$(VPATH)}vm_opts.h
ruby.$(OBJEXT): {$(VPATH)}yjit.h
+ruby_parser.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/array.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/bits.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/complex.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/error.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/parse.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/rational.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/re.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/serial.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/string.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/vm.h
+ruby_parser.$(OBJEXT): {$(VPATH)}assert.h
+ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+ruby_parser.$(OBJEXT): {$(VPATH)}config.h
+ruby_parser.$(OBJEXT): {$(VPATH)}defines.h
+ruby_parser.$(OBJEXT): {$(VPATH)}encoding.h
+ruby_parser.$(OBJEXT): {$(VPATH)}intern.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/abi.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/assume.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/cast.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/config.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/core.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/ctype.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/dosish.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/error.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/eval.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/event.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/gc.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/glob.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/globals.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/iterator.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/memory.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/method.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/module.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/newobj.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/symbol.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/value.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/value_type.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/variable.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+ruby_parser.$(OBJEXT): {$(VPATH)}missing.h
+ruby_parser.$(OBJEXT): {$(VPATH)}node.h
+ruby_parser.$(OBJEXT): {$(VPATH)}onigmo.h
+ruby_parser.$(OBJEXT): {$(VPATH)}oniguruma.h
+ruby_parser.$(OBJEXT): {$(VPATH)}ruby_assert.h
ruby_parser.$(OBJEXT): {$(VPATH)}ruby_parser.c
+ruby_parser.$(OBJEXT): {$(VPATH)}rubyparser.h
+ruby_parser.$(OBJEXT): {$(VPATH)}st.h
+ruby_parser.$(OBJEXT): {$(VPATH)}subst.h
scheduler.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
scheduler.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
scheduler.$(OBJEXT): $(CCAN_DIR)/list/list.h
@@ -15564,6 +16434,7 @@ scheduler.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
scheduler.$(OBJEXT): $(top_srcdir)/internal/compilers.h
scheduler.$(OBJEXT): $(top_srcdir)/internal/gc.h
scheduler.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+scheduler.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
scheduler.$(OBJEXT): $(top_srcdir)/internal/serial.h
scheduler.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
scheduler.$(OBJEXT): $(top_srcdir)/internal/thread.h
@@ -15732,6 +16603,7 @@ scheduler.$(OBJEXT): {$(VPATH)}internal/special_consts.h
scheduler.$(OBJEXT): {$(VPATH)}internal/static_assert.h
scheduler.$(OBJEXT): {$(VPATH)}internal/stdalign.h
scheduler.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
scheduler.$(OBJEXT): {$(VPATH)}internal/symbol.h
scheduler.$(OBJEXT): {$(VPATH)}internal/value.h
scheduler.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -15903,6 +16775,7 @@ setproctitle.$(OBJEXT): {$(VPATH)}internal/special_consts.h
setproctitle.$(OBJEXT): {$(VPATH)}internal/static_assert.h
setproctitle.$(OBJEXT): {$(VPATH)}internal/stdalign.h
setproctitle.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
setproctitle.$(OBJEXT): {$(VPATH)}internal/symbol.h
setproctitle.$(OBJEXT): {$(VPATH)}internal/value.h
setproctitle.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -15919,6 +16792,7 @@ shape.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
shape.$(OBJEXT): $(CCAN_DIR)/list/list.h
shape.$(OBJEXT): $(CCAN_DIR)/str/str.h
shape.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+shape.$(OBJEXT): $(hdrdir)/ruby/version.h
shape.$(OBJEXT): $(top_srcdir)/internal/array.h
shape.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
shape.$(OBJEXT): $(top_srcdir)/internal/class.h
@@ -15926,6 +16800,8 @@ shape.$(OBJEXT): $(top_srcdir)/internal/compilers.h
shape.$(OBJEXT): $(top_srcdir)/internal/error.h
shape.$(OBJEXT): $(top_srcdir)/internal/gc.h
shape.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+shape.$(OBJEXT): $(top_srcdir)/internal/object.h
+shape.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
shape.$(OBJEXT): $(top_srcdir)/internal/serial.h
shape.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
shape.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -16095,6 +16971,7 @@ shape.$(OBJEXT): {$(VPATH)}internal/special_consts.h
shape.$(OBJEXT): {$(VPATH)}internal/static_assert.h
shape.$(OBJEXT): {$(VPATH)}internal/stdalign.h
shape.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+shape.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
shape.$(OBJEXT): {$(VPATH)}internal/symbol.h
shape.$(OBJEXT): {$(VPATH)}internal/value.h
shape.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -16126,6 +17003,7 @@ signal.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
signal.$(OBJEXT): $(CCAN_DIR)/list/list.h
signal.$(OBJEXT): $(CCAN_DIR)/str/str.h
signal.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+signal.$(OBJEXT): $(hdrdir)/ruby/version.h
signal.$(OBJEXT): $(top_srcdir)/internal/array.h
signal.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
signal.$(OBJEXT): $(top_srcdir)/internal/compilers.h
@@ -16305,6 +17183,7 @@ signal.$(OBJEXT): {$(VPATH)}internal/special_consts.h
signal.$(OBJEXT): {$(VPATH)}internal/static_assert.h
signal.$(OBJEXT): {$(VPATH)}internal/stdalign.h
signal.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+signal.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
signal.$(OBJEXT): {$(VPATH)}internal/symbol.h
signal.$(OBJEXT): {$(VPATH)}internal/value.h
signal.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -16331,6 +17210,7 @@ signal.$(OBJEXT): {$(VPATH)}vm_core.h
signal.$(OBJEXT): {$(VPATH)}vm_debug.h
signal.$(OBJEXT): {$(VPATH)}vm_opts.h
sprintf.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+sprintf.$(OBJEXT): $(hdrdir)/ruby/version.h
sprintf.$(OBJEXT): $(top_srcdir)/internal/bignum.h
sprintf.$(OBJEXT): $(top_srcdir)/internal/bits.h
sprintf.$(OBJEXT): $(top_srcdir)/internal/class.h
@@ -16510,6 +17390,7 @@ sprintf.$(OBJEXT): {$(VPATH)}internal/special_consts.h
sprintf.$(OBJEXT): {$(VPATH)}internal/static_assert.h
sprintf.$(OBJEXT): {$(VPATH)}internal/stdalign.h
sprintf.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
sprintf.$(OBJEXT): {$(VPATH)}internal/symbol.h
sprintf.$(OBJEXT): {$(VPATH)}internal/value.h
sprintf.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -16532,6 +17413,7 @@ st.$(OBJEXT): $(top_srcdir)/internal/bits.h
st.$(OBJEXT): $(top_srcdir)/internal/compilers.h
st.$(OBJEXT): $(top_srcdir)/internal/hash.h
st.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+st.$(OBJEXT): $(top_srcdir)/internal/st.h
st.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
st.$(OBJEXT): $(top_srcdir)/internal/warnings.h
st.$(OBJEXT): {$(VPATH)}assert.h
@@ -16678,9 +17560,11 @@ st.$(OBJEXT): {$(VPATH)}internal/module.h
st.$(OBJEXT): {$(VPATH)}internal/newobj.h
st.$(OBJEXT): {$(VPATH)}internal/scan_args.h
st.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+st.$(OBJEXT): {$(VPATH)}internal/st.h
st.$(OBJEXT): {$(VPATH)}internal/static_assert.h
st.$(OBJEXT): {$(VPATH)}internal/stdalign.h
st.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+st.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
st.$(OBJEXT): {$(VPATH)}internal/symbol.h
st.$(OBJEXT): {$(VPATH)}internal/value.h
st.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -16855,6 +17739,7 @@ strftime.$(OBJEXT): {$(VPATH)}internal/special_consts.h
strftime.$(OBJEXT): {$(VPATH)}internal/static_assert.h
strftime.$(OBJEXT): {$(VPATH)}internal/stdalign.h
strftime.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+strftime.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
strftime.$(OBJEXT): {$(VPATH)}internal/symbol.h
strftime.$(OBJEXT): {$(VPATH)}internal/value.h
strftime.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -16874,6 +17759,7 @@ string.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
string.$(OBJEXT): $(CCAN_DIR)/list/list.h
string.$(OBJEXT): $(CCAN_DIR)/str/str.h
string.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+string.$(OBJEXT): $(hdrdir)/ruby/version.h
string.$(OBJEXT): $(top_srcdir)/internal/array.h
string.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
string.$(OBJEXT): $(top_srcdir)/internal/bignum.h
@@ -17062,6 +17948,7 @@ string.$(OBJEXT): {$(VPATH)}internal/special_consts.h
string.$(OBJEXT): {$(VPATH)}internal/static_assert.h
string.$(OBJEXT): {$(VPATH)}internal/stdalign.h
string.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+string.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
string.$(OBJEXT): {$(VPATH)}internal/symbol.h
string.$(OBJEXT): {$(VPATH)}internal/value.h
string.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -17126,6 +18013,7 @@ struct.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
struct.$(OBJEXT): $(CCAN_DIR)/list/list.h
struct.$(OBJEXT): $(CCAN_DIR)/str/str.h
struct.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+struct.$(OBJEXT): $(hdrdir)/ruby/version.h
struct.$(OBJEXT): $(top_srcdir)/internal/array.h
struct.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
struct.$(OBJEXT): $(top_srcdir)/internal/class.h
@@ -17136,6 +18024,7 @@ struct.$(OBJEXT): $(top_srcdir)/internal/hash.h
struct.$(OBJEXT): $(top_srcdir)/internal/imemo.h
struct.$(OBJEXT): $(top_srcdir)/internal/object.h
struct.$(OBJEXT): $(top_srcdir)/internal/proc.h
+struct.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
struct.$(OBJEXT): $(top_srcdir)/internal/serial.h
struct.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
struct.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -17158,6 +18047,7 @@ struct.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
struct.$(OBJEXT): {$(VPATH)}builtin.h
struct.$(OBJEXT): {$(VPATH)}config.h
struct.$(OBJEXT): {$(VPATH)}constant.h
+struct.$(OBJEXT): {$(VPATH)}debug_counter.h
struct.$(OBJEXT): {$(VPATH)}defines.h
struct.$(OBJEXT): {$(VPATH)}encoding.h
struct.$(OBJEXT): {$(VPATH)}id.h
@@ -17306,6 +18196,7 @@ struct.$(OBJEXT): {$(VPATH)}internal/special_consts.h
struct.$(OBJEXT): {$(VPATH)}internal/static_assert.h
struct.$(OBJEXT): {$(VPATH)}internal/stdalign.h
struct.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+struct.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
struct.$(OBJEXT): {$(VPATH)}internal/symbol.h
struct.$(OBJEXT): {$(VPATH)}internal/value.h
struct.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -17327,12 +18218,15 @@ struct.$(OBJEXT): {$(VPATH)}subst.h
struct.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
struct.$(OBJEXT): {$(VPATH)}thread_native.h
struct.$(OBJEXT): {$(VPATH)}vm_core.h
+struct.$(OBJEXT): {$(VPATH)}vm_debug.h
struct.$(OBJEXT): {$(VPATH)}vm_opts.h
+struct.$(OBJEXT): {$(VPATH)}vm_sync.h
symbol.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
symbol.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
symbol.$(OBJEXT): $(CCAN_DIR)/list/list.h
symbol.$(OBJEXT): $(CCAN_DIR)/str/str.h
symbol.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+symbol.$(OBJEXT): $(hdrdir)/ruby/version.h
symbol.$(OBJEXT): $(top_srcdir)/internal/array.h
symbol.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
symbol.$(OBJEXT): $(top_srcdir)/internal/class.h
@@ -17342,6 +18236,7 @@ symbol.$(OBJEXT): $(top_srcdir)/internal/gc.h
symbol.$(OBJEXT): $(top_srcdir)/internal/hash.h
symbol.$(OBJEXT): $(top_srcdir)/internal/imemo.h
symbol.$(OBJEXT): $(top_srcdir)/internal/object.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
symbol.$(OBJEXT): $(top_srcdir)/internal/serial.h
symbol.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
symbol.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -17514,6 +18409,7 @@ symbol.$(OBJEXT): {$(VPATH)}internal/special_consts.h
symbol.$(OBJEXT): {$(VPATH)}internal/static_assert.h
symbol.$(OBJEXT): {$(VPATH)}internal/stdalign.h
symbol.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+symbol.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
symbol.$(OBJEXT): {$(VPATH)}internal/symbol.h
symbol.$(OBJEXT): {$(VPATH)}internal/value.h
symbol.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -17549,6 +18445,7 @@ thread.$(OBJEXT): $(CCAN_DIR)/list/list.h
thread.$(OBJEXT): $(CCAN_DIR)/str/str.h
thread.$(OBJEXT): $(hdrdir)/ruby.h
thread.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+thread.$(OBJEXT): $(hdrdir)/ruby/version.h
thread.$(OBJEXT): $(top_srcdir)/internal/array.h
thread.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
thread.$(OBJEXT): $(top_srcdir)/internal/bits.h
@@ -17562,6 +18459,7 @@ thread.$(OBJEXT): $(top_srcdir)/internal/imemo.h
thread.$(OBJEXT): $(top_srcdir)/internal/io.h
thread.$(OBJEXT): $(top_srcdir)/internal/object.h
thread.$(OBJEXT): $(top_srcdir)/internal/proc.h
+thread.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
thread.$(OBJEXT): $(top_srcdir)/internal/serial.h
thread.$(OBJEXT): $(top_srcdir)/internal/signal.h
thread.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
@@ -17571,6 +18469,26 @@ thread.$(OBJEXT): $(top_srcdir)/internal/time.h
thread.$(OBJEXT): $(top_srcdir)/internal/variable.h
thread.$(OBJEXT): $(top_srcdir)/internal/vm.h
thread.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+thread.$(OBJEXT): $(top_srcdir)/prism/defines.h
+thread.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+thread.$(OBJEXT): $(top_srcdir)/prism/node.h
+thread.$(OBJEXT): $(top_srcdir)/prism/options.h
+thread.$(OBJEXT): $(top_srcdir)/prism/pack.h
+thread.$(OBJEXT): $(top_srcdir)/prism/parser.h
+thread.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+thread.$(OBJEXT): $(top_srcdir)/prism/prism.h
+thread.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+thread.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
thread.$(OBJEXT): {$(VPATH)}$(COROUTINE_H)
thread.$(OBJEXT): {$(VPATH)}assert.h
thread.$(OBJEXT): {$(VPATH)}atomic.h
@@ -17739,6 +18657,7 @@ thread.$(OBJEXT): {$(VPATH)}internal/special_consts.h
thread.$(OBJEXT): {$(VPATH)}internal/static_assert.h
thread.$(OBJEXT): {$(VPATH)}internal/stdalign.h
thread.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+thread.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
thread.$(OBJEXT): {$(VPATH)}internal/symbol.h
thread.$(OBJEXT): {$(VPATH)}internal/value.h
thread.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -17752,6 +18671,10 @@ thread.$(OBJEXT): {$(VPATH)}missing.h
thread.$(OBJEXT): {$(VPATH)}node.h
thread.$(OBJEXT): {$(VPATH)}onigmo.h
thread.$(OBJEXT): {$(VPATH)}oniguruma.h
+thread.$(OBJEXT): {$(VPATH)}prism/ast.h
+thread.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
+thread.$(OBJEXT): {$(VPATH)}prism/version.h
+thread.$(OBJEXT): {$(VPATH)}prism_compile.h
thread.$(OBJEXT): {$(VPATH)}ractor.h
thread.$(OBJEXT): {$(VPATH)}ractor_core.h
thread.$(OBJEXT): {$(VPATH)}rjit.h
@@ -17791,6 +18714,7 @@ time.$(OBJEXT): $(top_srcdir)/internal/hash.h
time.$(OBJEXT): $(top_srcdir)/internal/imemo.h
time.$(OBJEXT): $(top_srcdir)/internal/numeric.h
time.$(OBJEXT): $(top_srcdir)/internal/rational.h
+time.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
time.$(OBJEXT): $(top_srcdir)/internal/serial.h
time.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
time.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -17960,6 +18884,7 @@ time.$(OBJEXT): {$(VPATH)}internal/special_consts.h
time.$(OBJEXT): {$(VPATH)}internal/static_assert.h
time.$(OBJEXT): {$(VPATH)}internal/stdalign.h
time.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+time.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
time.$(OBJEXT): {$(VPATH)}internal/symbol.h
time.$(OBJEXT): {$(VPATH)}internal/value.h
time.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -18157,6 +19082,7 @@ transcode.$(OBJEXT): {$(VPATH)}internal/special_consts.h
transcode.$(OBJEXT): {$(VPATH)}internal/static_assert.h
transcode.$(OBJEXT): {$(VPATH)}internal/stdalign.h
transcode.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+transcode.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
transcode.$(OBJEXT): {$(VPATH)}internal/symbol.h
transcode.$(OBJEXT): {$(VPATH)}internal/value.h
transcode.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -18172,8 +19098,11 @@ transcode.$(OBJEXT): {$(VPATH)}subst.h
transcode.$(OBJEXT): {$(VPATH)}transcode.c
transcode.$(OBJEXT): {$(VPATH)}transcode_data.h
util.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+util.$(OBJEXT): $(top_srcdir)/internal/array.h
util.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+util.$(OBJEXT): $(top_srcdir)/internal/imemo.h
util.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+util.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
util.$(OBJEXT): $(top_srcdir)/internal/util.h
util.$(OBJEXT): $(top_srcdir)/internal/warnings.h
util.$(OBJEXT): {$(VPATH)}assert.h
@@ -18325,6 +19254,7 @@ util.$(OBJEXT): {$(VPATH)}internal/special_consts.h
util.$(OBJEXT): {$(VPATH)}internal/static_assert.h
util.$(OBJEXT): {$(VPATH)}internal/stdalign.h
util.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+util.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
util.$(OBJEXT): {$(VPATH)}internal/symbol.h
util.$(OBJEXT): {$(VPATH)}internal/value.h
util.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -18342,6 +19272,7 @@ variable.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
variable.$(OBJEXT): $(CCAN_DIR)/list/list.h
variable.$(OBJEXT): $(CCAN_DIR)/str/str.h
variable.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+variable.$(OBJEXT): $(hdrdir)/ruby/version.h
variable.$(OBJEXT): $(top_srcdir)/internal/array.h
variable.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
variable.$(OBJEXT): $(top_srcdir)/internal/class.h
@@ -18353,6 +19284,7 @@ variable.$(OBJEXT): $(top_srcdir)/internal/hash.h
variable.$(OBJEXT): $(top_srcdir)/internal/imemo.h
variable.$(OBJEXT): $(top_srcdir)/internal/object.h
variable.$(OBJEXT): $(top_srcdir)/internal/re.h
+variable.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
variable.$(OBJEXT): $(top_srcdir)/internal/serial.h
variable.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
variable.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -18523,6 +19455,7 @@ variable.$(OBJEXT): {$(VPATH)}internal/special_consts.h
variable.$(OBJEXT): {$(VPATH)}internal/static_assert.h
variable.$(OBJEXT): {$(VPATH)}internal/stdalign.h
variable.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+variable.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
variable.$(OBJEXT): {$(VPATH)}internal/symbol.h
variable.$(OBJEXT): {$(VPATH)}internal/value.h
variable.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -18565,6 +19498,7 @@ version.$(OBJEXT): $(top_srcdir)/internal/cmdlineopt.h
version.$(OBJEXT): $(top_srcdir)/internal/compilers.h
version.$(OBJEXT): $(top_srcdir)/internal/gc.h
version.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+version.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
version.$(OBJEXT): $(top_srcdir)/internal/serial.h
version.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
version.$(OBJEXT): $(top_srcdir)/internal/variable.h
@@ -18733,6 +19667,7 @@ version.$(OBJEXT): {$(VPATH)}internal/special_consts.h
version.$(OBJEXT): {$(VPATH)}internal/static_assert.h
version.$(OBJEXT): {$(VPATH)}internal/stdalign.h
version.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+version.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
version.$(OBJEXT): {$(VPATH)}internal/symbol.h
version.$(OBJEXT): {$(VPATH)}internal/value.h
version.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -18764,6 +19699,7 @@ vm.$(OBJEXT): $(CCAN_DIR)/list/list.h
vm.$(OBJEXT): $(CCAN_DIR)/str/str.h
vm.$(OBJEXT): $(hdrdir)/ruby.h
vm.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+vm.$(OBJEXT): $(hdrdir)/ruby/version.h
vm.$(OBJEXT): $(top_srcdir)/internal/array.h
vm.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
vm.$(OBJEXT): $(top_srcdir)/internal/bignum.h
@@ -18772,7 +19708,9 @@ vm.$(OBJEXT): $(top_srcdir)/internal/class.h
vm.$(OBJEXT): $(top_srcdir)/internal/compar.h
vm.$(OBJEXT): $(top_srcdir)/internal/compile.h
vm.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+vm.$(OBJEXT): $(top_srcdir)/internal/complex.h
vm.$(OBJEXT): $(top_srcdir)/internal/cont.h
+vm.$(OBJEXT): $(top_srcdir)/internal/encoding.h
vm.$(OBJEXT): $(top_srcdir)/internal/error.h
vm.$(OBJEXT): $(top_srcdir)/internal/eval.h
vm.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
@@ -18780,11 +19718,13 @@ vm.$(OBJEXT): $(top_srcdir)/internal/gc.h
vm.$(OBJEXT): $(top_srcdir)/internal/hash.h
vm.$(OBJEXT): $(top_srcdir)/internal/imemo.h
vm.$(OBJEXT): $(top_srcdir)/internal/inits.h
+vm.$(OBJEXT): $(top_srcdir)/internal/missing.h
vm.$(OBJEXT): $(top_srcdir)/internal/numeric.h
vm.$(OBJEXT): $(top_srcdir)/internal/object.h
vm.$(OBJEXT): $(top_srcdir)/internal/parse.h
vm.$(OBJEXT): $(top_srcdir)/internal/proc.h
vm.$(OBJEXT): $(top_srcdir)/internal/random.h
+vm.$(OBJEXT): $(top_srcdir)/internal/rational.h
vm.$(OBJEXT): $(top_srcdir)/internal/re.h
vm.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
vm.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
@@ -18794,9 +19734,30 @@ vm.$(OBJEXT): $(top_srcdir)/internal/string.h
vm.$(OBJEXT): $(top_srcdir)/internal/struct.h
vm.$(OBJEXT): $(top_srcdir)/internal/symbol.h
vm.$(OBJEXT): $(top_srcdir)/internal/thread.h
+vm.$(OBJEXT): $(top_srcdir)/internal/transcode.h
vm.$(OBJEXT): $(top_srcdir)/internal/variable.h
vm.$(OBJEXT): $(top_srcdir)/internal/vm.h
vm.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+vm.$(OBJEXT): $(top_srcdir)/prism/defines.h
+vm.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+vm.$(OBJEXT): $(top_srcdir)/prism/node.h
+vm.$(OBJEXT): $(top_srcdir)/prism/options.h
+vm.$(OBJEXT): $(top_srcdir)/prism/pack.h
+vm.$(OBJEXT): $(top_srcdir)/prism/parser.h
+vm.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+vm.$(OBJEXT): $(top_srcdir)/prism/prism.h
+vm.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+vm.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
vm.$(OBJEXT): {$(VPATH)}assert.h
vm.$(OBJEXT): {$(VPATH)}atomic.h
vm.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -18965,6 +19926,7 @@ vm.$(OBJEXT): {$(VPATH)}internal/special_consts.h
vm.$(OBJEXT): {$(VPATH)}internal/static_assert.h
vm.$(OBJEXT): {$(VPATH)}internal/stdalign.h
vm.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+vm.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
vm.$(OBJEXT): {$(VPATH)}internal/symbol.h
vm.$(OBJEXT): {$(VPATH)}internal/value.h
vm.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -18977,6 +19939,10 @@ vm.$(OBJEXT): {$(VPATH)}missing.h
vm.$(OBJEXT): {$(VPATH)}node.h
vm.$(OBJEXT): {$(VPATH)}onigmo.h
vm.$(OBJEXT): {$(VPATH)}oniguruma.h
+vm.$(OBJEXT): {$(VPATH)}prism/ast.h
+vm.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
+vm.$(OBJEXT): {$(VPATH)}prism/version.h
+vm.$(OBJEXT): {$(VPATH)}prism_compile.h
vm.$(OBJEXT): {$(VPATH)}probes.dmyh
vm.$(OBJEXT): {$(VPATH)}probes.h
vm.$(OBJEXT): {$(VPATH)}probes_helper.h
@@ -19015,6 +19981,7 @@ vm_backtrace.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
vm_backtrace.$(OBJEXT): $(CCAN_DIR)/list/list.h
vm_backtrace.$(OBJEXT): $(CCAN_DIR)/str/str.h
vm_backtrace.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+vm_backtrace.$(OBJEXT): $(hdrdir)/ruby/version.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/array.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/class.h
@@ -19022,12 +19989,33 @@ vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/compilers.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/error.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/gc.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/serial.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/string.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/variable.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/vm.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/defines.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/node.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/options.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/pack.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/parser.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/prism.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
vm_backtrace.$(OBJEXT): {$(VPATH)}assert.h
vm_backtrace.$(OBJEXT): {$(VPATH)}atomic.h
vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -19042,6 +20030,7 @@ vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
vm_backtrace.$(OBJEXT): {$(VPATH)}config.h
vm_backtrace.$(OBJEXT): {$(VPATH)}constant.h
vm_backtrace.$(OBJEXT): {$(VPATH)}debug.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}debug_counter.h
vm_backtrace.$(OBJEXT): {$(VPATH)}defines.h
vm_backtrace.$(OBJEXT): {$(VPATH)}encoding.h
vm_backtrace.$(OBJEXT): {$(VPATH)}eval_intern.h
@@ -19191,6 +20180,7 @@ vm_backtrace.$(OBJEXT): {$(VPATH)}internal/special_consts.h
vm_backtrace.$(OBJEXT): {$(VPATH)}internal/static_assert.h
vm_backtrace.$(OBJEXT): {$(VPATH)}internal/stdalign.h
vm_backtrace.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
vm_backtrace.$(OBJEXT): {$(VPATH)}internal/symbol.h
vm_backtrace.$(OBJEXT): {$(VPATH)}internal/value.h
vm_backtrace.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -19203,6 +20193,10 @@ vm_backtrace.$(OBJEXT): {$(VPATH)}missing.h
vm_backtrace.$(OBJEXT): {$(VPATH)}node.h
vm_backtrace.$(OBJEXT): {$(VPATH)}onigmo.h
vm_backtrace.$(OBJEXT): {$(VPATH)}oniguruma.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}prism/ast.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}prism/version.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}prism_compile.h
vm_backtrace.$(OBJEXT): {$(VPATH)}ruby_assert.h
vm_backtrace.$(OBJEXT): {$(VPATH)}ruby_atomic.h
vm_backtrace.$(OBJEXT): {$(VPATH)}rubyparser.h
@@ -19213,7 +20207,9 @@ vm_backtrace.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
vm_backtrace.$(OBJEXT): {$(VPATH)}thread_native.h
vm_backtrace.$(OBJEXT): {$(VPATH)}vm_backtrace.c
vm_backtrace.$(OBJEXT): {$(VPATH)}vm_core.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}vm_debug.h
vm_backtrace.$(OBJEXT): {$(VPATH)}vm_opts.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}vm_sync.h
vm_dump.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
vm_dump.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
vm_dump.$(OBJEXT): $(CCAN_DIR)/list/list.h
@@ -19224,11 +20220,32 @@ vm_dump.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
vm_dump.$(OBJEXT): $(top_srcdir)/internal/compilers.h
vm_dump.$(OBJEXT): $(top_srcdir)/internal/gc.h
vm_dump.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+vm_dump.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
vm_dump.$(OBJEXT): $(top_srcdir)/internal/serial.h
vm_dump.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
vm_dump.$(OBJEXT): $(top_srcdir)/internal/variable.h
vm_dump.$(OBJEXT): $(top_srcdir)/internal/vm.h
vm_dump.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/defines.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/node.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/options.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/pack.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/parser.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/prism.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
vm_dump.$(OBJEXT): {$(VPATH)}addr2line.h
vm_dump.$(OBJEXT): {$(VPATH)}assert.h
vm_dump.$(OBJEXT): {$(VPATH)}atomic.h
@@ -19391,6 +20408,7 @@ vm_dump.$(OBJEXT): {$(VPATH)}internal/special_consts.h
vm_dump.$(OBJEXT): {$(VPATH)}internal/static_assert.h
vm_dump.$(OBJEXT): {$(VPATH)}internal/stdalign.h
vm_dump.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
vm_dump.$(OBJEXT): {$(VPATH)}internal/symbol.h
vm_dump.$(OBJEXT): {$(VPATH)}internal/value.h
vm_dump.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -19403,6 +20421,10 @@ vm_dump.$(OBJEXT): {$(VPATH)}missing.h
vm_dump.$(OBJEXT): {$(VPATH)}node.h
vm_dump.$(OBJEXT): {$(VPATH)}onigmo.h
vm_dump.$(OBJEXT): {$(VPATH)}oniguruma.h
+vm_dump.$(OBJEXT): {$(VPATH)}prism/ast.h
+vm_dump.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
+vm_dump.$(OBJEXT): {$(VPATH)}prism/version.h
+vm_dump.$(OBJEXT): {$(VPATH)}prism_compile.h
vm_dump.$(OBJEXT): {$(VPATH)}procstat_vm.c
vm_dump.$(OBJEXT): {$(VPATH)}ractor.h
vm_dump.$(OBJEXT): {$(VPATH)}ractor_core.h
@@ -19428,6 +20450,7 @@ vm_sync.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
vm_sync.$(OBJEXT): $(top_srcdir)/internal/compilers.h
vm_sync.$(OBJEXT): $(top_srcdir)/internal/gc.h
vm_sync.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+vm_sync.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
vm_sync.$(OBJEXT): $(top_srcdir)/internal/serial.h
vm_sync.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
vm_sync.$(OBJEXT): $(top_srcdir)/internal/thread.h
@@ -19596,6 +20619,7 @@ vm_sync.$(OBJEXT): {$(VPATH)}internal/special_consts.h
vm_sync.$(OBJEXT): {$(VPATH)}internal/static_assert.h
vm_sync.$(OBJEXT): {$(VPATH)}internal/stdalign.h
vm_sync.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
vm_sync.$(OBJEXT): {$(VPATH)}internal/symbol.h
vm_sync.$(OBJEXT): {$(VPATH)}internal/value.h
vm_sync.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -19630,17 +20654,40 @@ vm_trace.$(OBJEXT): $(hdrdir)/ruby.h
vm_trace.$(OBJEXT): $(hdrdir)/ruby/ruby.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/array.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/bits.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/class.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/compilers.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/gc.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/hash.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/serial.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/thread.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/variable.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/vm.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/defines.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/node.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/options.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/pack.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/parser.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/prism.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
vm_trace.$(OBJEXT): {$(VPATH)}assert.h
vm_trace.$(OBJEXT): {$(VPATH)}atomic.h
vm_trace.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -19806,6 +20853,7 @@ vm_trace.$(OBJEXT): {$(VPATH)}internal/special_consts.h
vm_trace.$(OBJEXT): {$(VPATH)}internal/static_assert.h
vm_trace.$(OBJEXT): {$(VPATH)}internal/stdalign.h
vm_trace.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
vm_trace.$(OBJEXT): {$(VPATH)}internal/symbol.h
vm_trace.$(OBJEXT): {$(VPATH)}internal/value.h
vm_trace.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -19818,6 +20866,10 @@ vm_trace.$(OBJEXT): {$(VPATH)}missing.h
vm_trace.$(OBJEXT): {$(VPATH)}node.h
vm_trace.$(OBJEXT): {$(VPATH)}onigmo.h
vm_trace.$(OBJEXT): {$(VPATH)}oniguruma.h
+vm_trace.$(OBJEXT): {$(VPATH)}prism/ast.h
+vm_trace.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
+vm_trace.$(OBJEXT): {$(VPATH)}prism/version.h
+vm_trace.$(OBJEXT): {$(VPATH)}prism_compile.h
vm_trace.$(OBJEXT): {$(VPATH)}ractor.h
vm_trace.$(OBJEXT): {$(VPATH)}rjit.h
vm_trace.$(OBJEXT): {$(VPATH)}ruby_assert.h
@@ -19830,7 +20882,9 @@ vm_trace.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
vm_trace.$(OBJEXT): {$(VPATH)}thread_native.h
vm_trace.$(OBJEXT): {$(VPATH)}trace_point.rbinc
vm_trace.$(OBJEXT): {$(VPATH)}vm_core.h
+vm_trace.$(OBJEXT): {$(VPATH)}vm_debug.h
vm_trace.$(OBJEXT): {$(VPATH)}vm_opts.h
+vm_trace.$(OBJEXT): {$(VPATH)}vm_sync.h
vm_trace.$(OBJEXT): {$(VPATH)}vm_trace.c
vm_trace.$(OBJEXT): {$(VPATH)}yjit.h
weakmap.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
@@ -20009,6 +21063,7 @@ weakmap.$(OBJEXT): {$(VPATH)}internal/special_consts.h
weakmap.$(OBJEXT): {$(VPATH)}internal/static_assert.h
weakmap.$(OBJEXT): {$(VPATH)}internal/stdalign.h
weakmap.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
weakmap.$(OBJEXT): {$(VPATH)}internal/symbol.h
weakmap.$(OBJEXT): {$(VPATH)}internal/value.h
weakmap.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -20055,6 +21110,26 @@ yjit.$(OBJEXT): $(top_srcdir)/internal/string.h
yjit.$(OBJEXT): $(top_srcdir)/internal/variable.h
yjit.$(OBJEXT): $(top_srcdir)/internal/vm.h
yjit.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/defines.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/node.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/options.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/pack.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/parser.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/prism.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
yjit.$(OBJEXT): {$(VPATH)}assert.h
yjit.$(OBJEXT): {$(VPATH)}atomic.h
yjit.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -20223,6 +21298,7 @@ yjit.$(OBJEXT): {$(VPATH)}internal/special_consts.h
yjit.$(OBJEXT): {$(VPATH)}internal/static_assert.h
yjit.$(OBJEXT): {$(VPATH)}internal/stdalign.h
yjit.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+yjit.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
yjit.$(OBJEXT): {$(VPATH)}internal/symbol.h
yjit.$(OBJEXT): {$(VPATH)}internal/value.h
yjit.$(OBJEXT): {$(VPATH)}internal/value_type.h
@@ -20235,6 +21311,10 @@ yjit.$(OBJEXT): {$(VPATH)}missing.h
yjit.$(OBJEXT): {$(VPATH)}node.h
yjit.$(OBJEXT): {$(VPATH)}onigmo.h
yjit.$(OBJEXT): {$(VPATH)}oniguruma.h
+yjit.$(OBJEXT): {$(VPATH)}prism/ast.h
+yjit.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
+yjit.$(OBJEXT): {$(VPATH)}prism/version.h
+yjit.$(OBJEXT): {$(VPATH)}prism_compile.h
yjit.$(OBJEXT): {$(VPATH)}probes.dmyh
yjit.$(OBJEXT): {$(VPATH)}probes.h
yjit.$(OBJEXT): {$(VPATH)}probes_helper.h
diff --git a/compar.c b/compar.c
index 2f62455a0e..081b4e2dea 100644
--- a/compar.c
+++ b/compar.c
@@ -263,25 +263,28 @@ cmp_clamp(int argc, VALUE *argv, VALUE x)
* <code>==</code>, <code>>=</code>, and <code>></code>) and the
* method <code>between?</code>.
*
- * class SizeMatters
+ * class StringSorter
* include Comparable
+ *
* attr :str
* def <=>(other)
* str.size <=> other.str.size
* end
+ *
* def initialize(str)
* @str = str
* end
+ *
* def inspect
* @str
* end
* end
*
- * s1 = SizeMatters.new("Z")
- * s2 = SizeMatters.new("YY")
- * s3 = SizeMatters.new("XXX")
- * s4 = SizeMatters.new("WWWW")
- * s5 = SizeMatters.new("VVVVV")
+ * s1 = StringSorter.new("Z")
+ * s2 = StringSorter.new("YY")
+ * s3 = StringSorter.new("XXX")
+ * s4 = StringSorter.new("WWWW")
+ * s5 = StringSorter.new("VVVVV")
*
* s1 < s2 #=> true
* s4.between?(s1, s3) #=> false
diff --git a/compile.c b/compile.c
index 6c92b15acd..a0bbcab54b 100644
--- a/compile.c
+++ b/compile.c
@@ -26,14 +26,17 @@
#include "internal/error.h"
#include "internal/gc.h"
#include "internal/hash.h"
+#include "internal/io.h"
#include "internal/numeric.h"
#include "internal/object.h"
#include "internal/rational.h"
#include "internal/re.h"
+#include "internal/ruby_parser.h"
#include "internal/symbol.h"
#include "internal/thread.h"
#include "internal/variable.h"
#include "iseq.h"
+#include "ruby/ractor.h"
#include "ruby/re.h"
#include "ruby/util.h"
#include "vm_core.h"
@@ -44,10 +47,6 @@
#include "builtin.h"
#include "insns.inc"
#include "insns_info.inc"
-#include "prism_compile.h"
-
-#undef RUBY_UNTYPED_DATA_WARNING
-#define RUBY_UNTYPED_DATA_WARNING 0
#define FIXNUM_INC(n, i) ((n)+(INT2FIX(i)&~FIXNUM_FLAG))
#define FIXNUM_OR(n, i) ((n)|INT2FIX(i))
@@ -221,30 +220,34 @@ const ID rb_iseq_shared_exc_local_tbl[] = {idERROR_INFO};
/* add an instruction */
#define ADD_INSN(seq, line_node, insn) \
- ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, (line_node), BIN(insn), 0))
+ ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, nd_line(line_node), nd_node_id(line_node), BIN(insn), 0))
+
+/* add an instruction with the given line number and node id */
+#define ADD_SYNTHETIC_INSN(seq, line_no, node_id, insn) \
+ ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, (line_no), (node_id), BIN(insn), 0))
/* insert an instruction before next */
-#define INSERT_BEFORE_INSN(next, line_node, insn) \
- ELEM_INSERT_PREV(&(next)->link, (LINK_ELEMENT *) new_insn_body(iseq, (line_node), BIN(insn), 0))
+#define INSERT_BEFORE_INSN(next, line_no, node_id, insn) \
+ ELEM_INSERT_PREV(&(next)->link, (LINK_ELEMENT *) new_insn_body(iseq, line_no, node_id, BIN(insn), 0))
/* insert an instruction after prev */
-#define INSERT_AFTER_INSN(prev, line_node, insn) \
- ELEM_INSERT_NEXT(&(prev)->link, (LINK_ELEMENT *) new_insn_body(iseq, (line_node), BIN(insn), 0))
+#define INSERT_AFTER_INSN(prev, line_no, node_id, insn) \
+ ELEM_INSERT_NEXT(&(prev)->link, (LINK_ELEMENT *) new_insn_body(iseq, line_no, node_id, BIN(insn), 0))
/* add an instruction with some operands (1, 2, 3, 5) */
#define ADD_INSN1(seq, line_node, insn, op1) \
ADD_ELEM((seq), (LINK_ELEMENT *) \
- new_insn_body(iseq, (line_node), BIN(insn), 1, (VALUE)(op1)))
+ new_insn_body(iseq, nd_line(line_node), nd_node_id(line_node), BIN(insn), 1, (VALUE)(op1)))
/* insert an instruction with some operands (1, 2, 3, 5) before next */
-#define INSERT_BEFORE_INSN1(next, line_node, insn, op1) \
+#define INSERT_BEFORE_INSN1(next, line_no, node_id, insn, op1) \
ELEM_INSERT_PREV(&(next)->link, (LINK_ELEMENT *) \
- new_insn_body(iseq, (line_node), BIN(insn), 1, (VALUE)(op1)))
+ new_insn_body(iseq, line_no, node_id, BIN(insn), 1, (VALUE)(op1)))
/* insert an instruction with some operands (1, 2, 3, 5) after prev */
-#define INSERT_AFTER_INSN1(prev, line_node, insn, op1) \
+#define INSERT_AFTER_INSN1(prev, line_no, node_id, insn, op1) \
ELEM_INSERT_NEXT(&(prev)->link, (LINK_ELEMENT *) \
- new_insn_body(iseq, (line_node), BIN(insn), 1, (VALUE)(op1)))
+ new_insn_body(iseq, line_no, node_id, BIN(insn), 1, (VALUE)(op1)))
#define LABEL_REF(label) ((label)->refcnt++)
@@ -253,11 +256,11 @@ const ID rb_iseq_shared_exc_local_tbl[] = {idERROR_INFO};
#define ADD_INSN2(seq, line_node, insn, op1, op2) \
ADD_ELEM((seq), (LINK_ELEMENT *) \
- new_insn_body(iseq, (line_node), BIN(insn), 2, (VALUE)(op1), (VALUE)(op2)))
+ new_insn_body(iseq, nd_line(line_node), nd_node_id(line_node), BIN(insn), 2, (VALUE)(op1), (VALUE)(op2)))
#define ADD_INSN3(seq, line_node, insn, op1, op2, op3) \
ADD_ELEM((seq), (LINK_ELEMENT *) \
- new_insn_body(iseq, (line_node), BIN(insn), 3, (VALUE)(op1), (VALUE)(op2), (VALUE)(op3)))
+ new_insn_body(iseq, nd_line(line_node), nd_node_id(line_node), BIN(insn), 3, (VALUE)(op1), (VALUE)(op2), (VALUE)(op3)))
/* Specific Insn factory */
#define ADD_SEND(seq, line_node, id, argc) \
@@ -279,7 +282,7 @@ const ID rb_iseq_shared_exc_local_tbl[] = {idERROR_INFO};
ADD_SEND_R((seq), (line_node), (id), (argc), (block), (VALUE)INT2FIX(VM_CALL_FCALL), NULL)
#define ADD_SEND_R(seq, line_node, id, argc, block, flag, keywords) \
- ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_send(iseq, (line_node), (id), (VALUE)(argc), (block), (VALUE)(flag), (keywords)))
+ ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_send(iseq, nd_line(line_node), nd_node_id(line_node), (id), (VALUE)(argc), (block), (VALUE)(flag), (keywords)))
#define ADD_TRACE(seq, event) \
ADD_ELEM((seq), (LINK_ELEMENT *)new_trace_body(iseq, (event), 0))
@@ -472,7 +475,7 @@ static void dump_disasm_list(const LINK_ELEMENT *elem);
static int insn_data_length(INSN *iobj);
static int calc_sp_depth(int depth, INSN *iobj);
-static INSN *new_insn_body(rb_iseq_t *iseq, const NODE *const line_node, enum ruby_vminsn_type insn_id, int argc, ...);
+static INSN *new_insn_body(rb_iseq_t *iseq, int line_no, int node_id, enum ruby_vminsn_type insn_id, int argc, ...);
static LABEL *new_label_body(rb_iseq_t *iseq, long line);
static ADJUST *new_adjust_body(rb_iseq_t *iseq, LABEL *label, int line);
static TRACE *new_trace_body(rb_iseq_t *iseq, rb_event_flag_t event, long data);
@@ -606,11 +609,13 @@ branch_coverage_valid_p(rb_iseq_t *iseq, int first_line)
return 1;
}
+#define PTR2NUM(x) (rb_int2inum((intptr_t)(void *)(x)))
+
static VALUE
-decl_branch_base(rb_iseq_t *iseq, const NODE *node, const char *type)
+decl_branch_base(rb_iseq_t *iseq, VALUE key, const rb_code_location_t *loc, const char *type)
{
- const int first_lineno = nd_first_lineno(node), first_column = nd_first_column(node);
- const int last_lineno = nd_last_lineno(node), last_column = nd_last_column(node);
+ const int first_lineno = loc->beg_pos.lineno, first_column = loc->beg_pos.column;
+ const int last_lineno = loc->end_pos.lineno, last_column = loc->end_pos.column;
if (!branch_coverage_valid_p(iseq, first_lineno)) return Qundef;
@@ -623,7 +628,6 @@ decl_branch_base(rb_iseq_t *iseq, const NODE *node, const char *type)
*/
VALUE structure = RARRAY_AREF(ISEQ_BRANCH_COVERAGE(iseq), 0);
- VALUE key = (VALUE)node | 1; // FIXNUM for hash key
VALUE branch_base = rb_hash_aref(structure, key);
VALUE branches;
@@ -656,10 +660,10 @@ generate_dummy_line_node(int lineno, int node_id)
}
static void
-add_trace_branch_coverage(rb_iseq_t *iseq, LINK_ANCHOR *const seq, const NODE *node, int branch_id, const char *type, VALUE branches)
+add_trace_branch_coverage(rb_iseq_t *iseq, LINK_ANCHOR *const seq, const rb_code_location_t *loc, int node_id, int branch_id, const char *type, VALUE branches)
{
- const int first_lineno = nd_first_lineno(node), first_column = nd_first_column(node);
- const int last_lineno = nd_last_lineno(node), last_column = nd_last_column(node);
+ const int first_lineno = loc->beg_pos.lineno, first_column = loc->beg_pos.column;
+ const int last_lineno = loc->end_pos.lineno, last_column = loc->end_pos.column;
if (!branch_coverage_valid_p(iseq, first_lineno)) return;
@@ -693,9 +697,7 @@ add_trace_branch_coverage(rb_iseq_t *iseq, LINK_ANCHOR *const seq, const NODE *n
}
ADD_TRACE_WITH_DATA(seq, RUBY_EVENT_COVERAGE_BRANCH, counter_idx);
-
- NODE dummy_line_node = generate_dummy_line_node(last_lineno, nd_node_id(node));
- ADD_INSN(seq, &dummy_line_node, nop);
+ ADD_SYNTHETIC_INSN(seq, last_lineno, node_id, nop);
}
#define ISEQ_LAST_LINE(iseq) (ISEQ_COMPILE_DATA(iseq)->last_line)
@@ -819,7 +821,6 @@ get_nd_vid(const NODE *node)
}
}
-
static NODE *
get_nd_value(const NODE *node)
{
@@ -833,6 +834,19 @@ get_nd_value(const NODE *node)
}
}
+static VALUE
+get_string_value(const NODE *node)
+{
+ switch (nd_type(node)) {
+ case NODE_STR:
+ return rb_node_str_string_val(node);
+ case NODE_FILE:
+ return rb_node_file_path_val(node);
+ default:
+ rb_bug("unexpected node: %s", ruby_node_name(nd_type(node)));
+ }
+}
+
VALUE
rb_iseq_compile_callback(rb_iseq_t *iseq, const struct rb_iseq_new_with_callback_callback_func * ifunc)
{
@@ -841,8 +855,7 @@ rb_iseq_compile_callback(rb_iseq_t *iseq, const struct rb_iseq_new_with_callback
(*ifunc->func)(iseq, ret, ifunc->data);
- NODE dummy_line_node = generate_dummy_line_node(ISEQ_COMPILE_DATA(iseq)->last_line, -1);
- ADD_INSN(ret, &dummy_line_node, leave);
+ ADD_SYNTHETIC_INSN(ret, ISEQ_COMPILE_DATA(iseq)->last_line, -1, leave);
CHECK(iseq_setup_insn(iseq, ret));
return iseq_setup(iseq, ret);
@@ -854,10 +867,6 @@ rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node)
DECL_ANCHOR(ret);
INIT_ANCHOR(ret);
- if (IMEMO_TYPE_P(node, imemo_ifunc)) {
- rb_raise(rb_eArgError, "unexpected imemo_ifunc");
- }
-
if (node == 0) {
NO_CHECK(COMPILE(ret, "nil", node));
iseq_set_local_table(iseq, 0);
@@ -878,8 +887,7 @@ rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node)
end->rescued = LABEL_RESCUE_END;
ADD_TRACE(ret, RUBY_EVENT_B_CALL);
- NODE dummy_line_node = generate_dummy_line_node(ISEQ_BODY(iseq)->location.first_lineno, -1);
- ADD_INSN (ret, &dummy_line_node, nop);
+ ADD_SYNTHETIC_INSN(ret, ISEQ_BODY(iseq)->location.first_lineno, -1, nop);
ADD_LABEL(ret, start);
CHECK(COMPILE(ret, "block body", RNODE_SCOPE(node)->nd_body));
ADD_LABEL(ret, end);
@@ -953,8 +961,7 @@ rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node)
ADD_INSN1(ret, &dummy_line_node, throw, INT2FIX(0) /* continue throw */ );
}
else {
- NODE dummy_line_node = generate_dummy_line_node(ISEQ_COMPILE_DATA(iseq)->last_line, -1);
- ADD_INSN(ret, &dummy_line_node, leave);
+ ADD_SYNTHETIC_INSN(ret, ISEQ_COMPILE_DATA(iseq)->last_line, -1, leave);
}
#if OPT_SUPPORT_JOKE
@@ -968,20 +975,6 @@ rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node)
return iseq_setup(iseq, ret);
}
-static VALUE rb_translate_prism(pm_parser_t *parser, rb_iseq_t *iseq, pm_scope_node_t *scope_node, LINK_ANCHOR *const ret);
-
-VALUE
-rb_iseq_compile_prism_node(rb_iseq_t * iseq, pm_scope_node_t *scope_node, pm_parser_t *parser)
-{
- DECL_ANCHOR(ret);
- INIT_ANCHOR(ret);
-
- CHECK(rb_translate_prism(parser, iseq, scope_node, ret));
-
- CHECK(iseq_setup_insn(iseq, ret));
- return iseq_setup(iseq, ret);
-}
-
static int
rb_iseq_translate_threaded_code(rb_iseq_t *iseq)
{
@@ -1001,6 +994,7 @@ rb_iseq_translate_threaded_code(rb_iseq_t *iseq)
#if USE_YJIT
rb_yjit_live_iseq_count++;
+ rb_yjit_iseq_alloc_count++;
#endif
return COMPILE_OK;
@@ -1375,7 +1369,7 @@ new_adjust_body(rb_iseq_t *iseq, LABEL *label, int line)
}
static void
-iseq_insn_each_markable_object(INSN *insn, void (*func)(VALUE *, VALUE), VALUE data)
+iseq_insn_each_markable_object(INSN *insn, void (*func)(VALUE, VALUE), VALUE data)
{
const char *types = insn_op_types(insn->insn_id);
for (int j = 0; types[j]; j++) {
@@ -1386,7 +1380,7 @@ iseq_insn_each_markable_object(INSN *insn, void (*func)(VALUE *, VALUE), VALUE d
case TS_VALUE:
case TS_IC: // constant path array
case TS_CALLDATA: // ci is stored.
- func(&OPERAND_AT(insn, j), data);
+ func(OPERAND_AT(insn, j), data);
break;
default:
break;
@@ -1395,14 +1389,13 @@ iseq_insn_each_markable_object(INSN *insn, void (*func)(VALUE *, VALUE), VALUE d
}
static void
-iseq_insn_each_object_write_barrier(VALUE *obj_ptr, VALUE iseq)
+iseq_insn_each_object_write_barrier(VALUE obj, VALUE iseq)
{
- RB_OBJ_WRITTEN(iseq, Qundef, *obj_ptr);
+ RB_OBJ_WRITTEN(iseq, Qundef, obj);
}
static INSN *
-new_insn_core(rb_iseq_t *iseq, const NODE *line_node,
- int insn_id, int argc, VALUE *argv)
+new_insn_core(rb_iseq_t *iseq, int line_no, int node_id, int insn_id, int argc, VALUE *argv)
{
INSN *iobj = compile_data_alloc_insn(iseq);
@@ -1411,8 +1404,8 @@ new_insn_core(rb_iseq_t *iseq, const NODE *line_node,
iobj->link.type = ISEQ_ELEMENT_INSN;
iobj->link.next = 0;
iobj->insn_id = insn_id;
- iobj->insn_info.line_no = nd_line(line_node);
- iobj->insn_info.node_id = nd_node_id(line_node);
+ iobj->insn_info.line_no = line_no;
+ iobj->insn_info.node_id = node_id;
iobj->insn_info.events = 0;
iobj->operands = argv;
iobj->operand_size = argc;
@@ -1424,7 +1417,7 @@ new_insn_core(rb_iseq_t *iseq, const NODE *line_node,
}
static INSN *
-new_insn_body(rb_iseq_t *iseq, const NODE *const line_node, enum ruby_vminsn_type insn_id, int argc, ...)
+new_insn_body(rb_iseq_t *iseq, int line_no, int node_id, enum ruby_vminsn_type insn_id, int argc, ...)
{
VALUE *operands = 0;
va_list argv;
@@ -1438,7 +1431,7 @@ new_insn_body(rb_iseq_t *iseq, const NODE *const line_node, enum ruby_vminsn_typ
}
va_end(argv);
}
- return new_insn_core(iseq, line_node, insn_id, argc, operands);
+ return new_insn_core(iseq, line_no, node_id, insn_id, argc, operands);
}
static const struct rb_callinfo *
@@ -1463,7 +1456,7 @@ new_callinfo(rb_iseq_t *iseq, ID mid, int argc, unsigned int flag, struct rb_cal
}
static INSN *
-new_insn_send(rb_iseq_t *iseq, const NODE *const line_node, ID id, VALUE argc, const rb_iseq_t *blockiseq, VALUE flag, struct rb_callinfo_kwarg *keywords)
+new_insn_send(rb_iseq_t *iseq, int line_no, int node_id, ID id, VALUE argc, const rb_iseq_t *blockiseq, VALUE flag, struct rb_callinfo_kwarg *keywords)
{
VALUE *operands = compile_data_calloc2(iseq, sizeof(VALUE), 2);
VALUE ci = (VALUE)new_callinfo(iseq, id, FIX2INT(argc), FIX2INT(flag), keywords, blockiseq != NULL);
@@ -1472,7 +1465,7 @@ new_insn_send(rb_iseq_t *iseq, const NODE *const line_node, ID id, VALUE argc, c
if (blockiseq) {
RB_OBJ_WRITTEN(iseq, Qundef, blockiseq);
}
- INSN *insn = new_insn_core(iseq, line_node, BIN(send), 2, operands);
+ INSN *insn = new_insn_core(iseq, line_no, node_id, BIN(send), 2, operands);
RB_OBJ_WRITTEN(iseq, Qundef, ci);
RB_GC_GUARD(ci);
return insn;
@@ -1483,20 +1476,16 @@ new_child_iseq(rb_iseq_t *iseq, const NODE *const node,
VALUE name, const rb_iseq_t *parent, enum rb_iseq_type type, int line_no)
{
rb_iseq_t *ret_iseq;
- rb_ast_body_t ast;
-
- ast.root = node;
- ast.frozen_string_literal = -1;
- ast.coverage_enabled = -1;
- ast.script_lines = ISEQ_BODY(iseq)->variable.script_lines;
+ VALUE ast_value = rb_ruby_ast_new(node);
debugs("[new_child_iseq]> ---------------------------------------\n");
int isolated_depth = ISEQ_COMPILE_DATA(iseq)->isolated_depth;
- ret_iseq = rb_iseq_new_with_opt(&ast, name,
+ ret_iseq = rb_iseq_new_with_opt(ast_value, name,
rb_iseq_path(iseq), rb_iseq_realpath(iseq),
line_no, parent,
isolated_depth ? isolated_depth + 1 : 0,
- type, ISEQ_COMPILE_DATA(iseq)->option);
+ type, ISEQ_COMPILE_DATA(iseq)->option,
+ ISEQ_BODY(iseq)->variable.script_lines);
debugs("[new_child_iseq]< ---------------------------------------\n");
return ret_iseq;
}
@@ -1591,14 +1580,15 @@ iseq_insert_nop_between_end_and_cont(rb_iseq_t *iseq)
for (e = end; e && (IS_LABEL(e) || IS_TRACE(e)); e = e->next) {
if (e == cont) {
- NODE dummy_line_node = generate_dummy_line_node(0, -1);
- INSN *nop = new_insn_core(iseq, &dummy_line_node, BIN(nop), 0, 0);
+ INSN *nop = new_insn_core(iseq, 0, -1, BIN(nop), 0, 0);
ELEM_INSERT_NEXT(end, &nop->link);
break;
}
}
}
}
+
+ RB_GC_GUARD(catch_table_ary);
}
static int
@@ -1795,7 +1785,7 @@ access_outer_variables(const rb_iseq_t *iseq, int level, ID id, bool write)
COMPILE_ERROR(iseq, ISEQ_LAST_LINE(iseq), "can not yield from isolated Proc");
}
else {
- COMPILE_ERROR(iseq, ISEQ_LAST_LINE(iseq), "can not access variable `%s' from isolated Proc", rb_id2name(id));
+ COMPILE_ERROR(iseq, ISEQ_LAST_LINE(iseq), "can not access variable '%s' from isolated Proc", rb_id2name(id));
}
}
@@ -1927,8 +1917,29 @@ iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *const optargs,
}
else {
switch (nd_type(val_node)) {
- case NODE_LIT:
- dv = RNODE_LIT(val_node)->nd_lit;
+ case NODE_SYM:
+ dv = rb_node_sym_string_val(val_node);
+ break;
+ case NODE_REGX:
+ dv = rb_node_regx_string_val(val_node);
+ break;
+ case NODE_LINE:
+ dv = rb_node_line_lineno_val(val_node);
+ break;
+ case NODE_INTEGER:
+ dv = rb_node_integer_literal_val(val_node);
+ break;
+ case NODE_FLOAT:
+ dv = rb_node_float_literal_val(val_node);
+ break;
+ case NODE_RATIONAL:
+ dv = rb_node_rational_literal_val(val_node);
+ break;
+ case NODE_IMAGINARY:
+ dv = rb_node_imaginary_literal_val(val_node);
+ break;
+ case NODE_ENCODING:
+ dv = rb_node_encoding_val(val_node);
break;
case NODE_NIL:
dv = Qnil;
@@ -1954,8 +1965,11 @@ iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *const optargs,
keyword->num = kw;
if (RNODE_DVAR(args->kw_rest_arg)->nd_vid != 0) {
+ ID kw_id = iseq->body->local_table[arg_size];
keyword->rest_start = arg_size++;
body->param.flags.has_kwrest = TRUE;
+
+ if (kw_id == idPow) body->param.flags.anon_kwrest = TRUE;
}
keyword->required_num = rkw;
keyword->table = &body->local_table[keyword->bits_start - keyword->num];
@@ -1977,6 +1991,22 @@ iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *const optargs,
return arg_size;
}
+static void
+iseq_set_use_block(rb_iseq_t *iseq)
+{
+ struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
+ if (!body->param.flags.use_block) {
+ body->param.flags.use_block = 1;
+
+ rb_vm_t *vm = GET_VM();
+
+ if (!vm->unused_block_warning_strict) {
+ st_data_t key = (st_data_t)rb_intern_str(body->location.label); // String -> ID
+ st_insert(vm->unused_block_warning_table, key, 1);
+ }
+ }
+}
+
static int
iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const NODE *const node_args)
{
@@ -2042,7 +2072,8 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const NODE *cons
if (rest_id) {
body->param.rest_start = arg_size++;
body->param.flags.has_rest = TRUE;
- assert(body->param.rest_start != -1);
+ if (rest_id == '*') body->param.flags.anon_rest = TRUE;
+ RUBY_ASSERT(body->param.rest_start != -1);
}
if (args->first_post_arg) {
@@ -2060,10 +2091,15 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const NODE *cons
arg_size = iseq_set_arguments_keywords(iseq, optargs, args, arg_size);
}
else if (args->kw_rest_arg) {
+ ID kw_id = iseq->body->local_table[arg_size];
struct rb_iseq_param_keyword *keyword = ZALLOC_N(struct rb_iseq_param_keyword, 1);
keyword->rest_start = arg_size++;
body->param.keyword = keyword;
body->param.flags.has_kwrest = TRUE;
+
+ static ID anon_kwrest = 0;
+ if (!anon_kwrest) anon_kwrest = rb_intern("**");
+ if (kw_id == anon_kwrest) body->param.flags.anon_kwrest = TRUE;
}
else if (args->no_kwarg) {
body->param.flags.accepts_no_kwarg = TRUE;
@@ -2072,6 +2108,7 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const NODE *cons
if (block_id) {
body->param.block_start = arg_size++;
body->param.flags.has_block = TRUE;
+ iseq_set_use_block(iseq);
}
iseq_calc_param_size(iseq);
@@ -2654,10 +2691,10 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
break;
}
- case TS_CALLDATA:
+ case TS_CALLDATA:
{
const struct rb_callinfo *source_ci = (const struct rb_callinfo *)operands[j];
- assert(ISEQ_COMPILE_DATA(iseq)->ci_index <= body->ci_size);
+ RUBY_ASSERT(ISEQ_COMPILE_DATA(iseq)->ci_index <= body->ci_size);
struct rb_call_data *cd = &body->call_data[ISEQ_COMPILE_DATA(iseq)->ci_index++];
cd->ci = source_ci;
cd->cc = vm_cc_empty();
@@ -2796,9 +2833,11 @@ iseq_set_exception_table(rb_iseq_t *iseq)
struct iseq_catch_table_entry *entry;
ISEQ_BODY(iseq)->catch_table = NULL;
- if (NIL_P(ISEQ_COMPILE_DATA(iseq)->catch_table_ary)) return COMPILE_OK;
- tlen = (int)RARRAY_LEN(ISEQ_COMPILE_DATA(iseq)->catch_table_ary);
- tptr = RARRAY_CONST_PTR(ISEQ_COMPILE_DATA(iseq)->catch_table_ary);
+
+ VALUE catch_table_ary = ISEQ_COMPILE_DATA(iseq)->catch_table_ary;
+ if (NIL_P(catch_table_ary)) return COMPILE_OK;
+ tlen = (int)RARRAY_LEN(catch_table_ary);
+ tptr = RARRAY_CONST_PTR(catch_table_ary);
if (tlen > 0) {
struct iseq_catch_table *table = xmalloc(iseq_catch_table_bytes(tlen));
@@ -2823,6 +2862,7 @@ iseq_set_exception_table(rb_iseq_t *iseq)
if (entry->type == CATCH_TYPE_RESCUE ||
entry->type == CATCH_TYPE_BREAK ||
entry->type == CATCH_TYPE_NEXT) {
+ RUBY_ASSERT(entry->sp > 0);
entry->sp--;
}
}
@@ -2834,6 +2874,8 @@ iseq_set_exception_table(rb_iseq_t *iseq)
RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->catch_table_ary, 0); /* free */
}
+ RB_GC_GUARD(catch_table_ary);
+
return COMPILE_OK;
}
@@ -3035,7 +3077,7 @@ iseq_pop_newarray(rb_iseq_t *iseq, INSN *iobj)
static int
is_frozen_putstring(INSN *insn, VALUE *op)
{
- if (IS_INSN_ID(insn, putstring)) {
+ if (IS_INSN_ID(insn, putstring) || IS_INSN_ID(insn, putchilledstring)) {
*op = OPERAND_AT(insn, 0);
return 1;
}
@@ -3077,6 +3119,7 @@ optimize_checktype(rb_iseq_t *iseq, INSN *iobj)
switch (INSN_OF(iobj)) {
case BIN(putstring):
+ case BIN(putchilledstring):
type = INT2FIX(T_STRING);
break;
case BIN(putnil):
@@ -3117,7 +3160,6 @@ optimize_checktype(rb_iseq_t *iseq, INSN *iobj)
}
line = ciobj->insn_info.line_no;
node_id = ciobj->insn_info.node_id;
- NODE dummy_line_node = generate_dummy_line_node(line, node_id);
if (!dest) {
if (niobj->link.next && IS_LABEL(niobj->link.next)) {
dest = (LABEL *)niobj->link.next; /* reuse label */
@@ -3127,9 +3169,9 @@ optimize_checktype(rb_iseq_t *iseq, INSN *iobj)
ELEM_INSERT_NEXT(&niobj->link, &dest->link);
}
}
- INSERT_AFTER_INSN1(iobj, &dummy_line_node, jump, dest);
+ INSERT_AFTER_INSN1(iobj, line, node_id, jump, dest);
LABEL_REF(dest);
- if (!dup) INSERT_AFTER_INSN(iobj, &dummy_line_node, pop);
+ if (!dup) INSERT_AFTER_INSN(iobj, line, node_id, pop);
return TRUE;
}
@@ -3155,6 +3197,34 @@ ci_argc_set(const rb_iseq_t *iseq, const struct rb_callinfo *ci, int argc)
return nci;
}
+static bool
+optimize_args_splat_no_copy(rb_iseq_t *iseq, INSN *insn, LINK_ELEMENT *niobj,
+ unsigned int set_flags, unsigned int unset_flags, unsigned int remove_flags)
+{
+ LINK_ELEMENT *iobj = (LINK_ELEMENT *)insn;
+ if ((set_flags & VM_CALL_ARGS_BLOCKARG) && (set_flags & VM_CALL_KW_SPLAT) &&
+ IS_NEXT_INSN_ID(niobj, splatkw)) {
+ niobj = niobj->next;
+ }
+ if (!IS_NEXT_INSN_ID(niobj, send) && !IS_NEXT_INSN_ID(niobj, invokesuper)) {
+ return false;
+ }
+ niobj = niobj->next;
+
+ const struct rb_callinfo *ci = (const struct rb_callinfo *)OPERAND_AT(niobj, 0);
+ unsigned int flags = vm_ci_flag(ci);
+ if ((flags & set_flags) == set_flags && !(flags & unset_flags)) {
+ RUBY_ASSERT(flags & VM_CALL_ARGS_SPLAT_MUT);
+ OPERAND_AT(iobj, 0) = Qfalse;
+ const struct rb_callinfo *nci = vm_ci_new(vm_ci_mid(ci),
+ flags & ~(VM_CALL_ARGS_SPLAT_MUT|remove_flags), vm_ci_argc(ci), vm_ci_kwarg(ci));
+ RB_OBJ_WRITTEN(iseq, ci, nci);
+ OPERAND_AT(niobj, 0) = (VALUE)nci;
+ return true;
+ }
+ return false;
+}
+
static int
iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcallopt)
{
@@ -3263,8 +3333,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
* pop
* jump L1
*/
- NODE dummy_line_node = generate_dummy_line_node(iobj->insn_info.line_no, iobj->insn_info.node_id);
- INSN *popiobj = new_insn_core(iseq, &dummy_line_node, BIN(pop), 0, 0);
+ INSN *popiobj = new_insn_core(iseq, iobj->insn_info.line_no, iobj->insn_info.node_id, BIN(pop), 0, 0);
ELEM_REPLACE(&piobj->link, &popiobj->link);
}
}
@@ -3309,15 +3378,15 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
/*
* ...
* duparray [...]
- * concatarray
+ * concatarray | concattoarray
* =>
* ...
* putobject [...]
- * concatarray
+ * concatarray | concattoarray
*/
if (IS_INSN_ID(iobj, duparray)) {
LINK_ELEMENT *next = iobj->link.next;
- if (IS_INSN(next) && IS_INSN_ID(next, concatarray)) {
+ if (IS_INSN(next) && (IS_INSN_ID(next, concatarray) || IS_INSN_ID(next, concattoarray))) {
iobj->insn_id = BIN(putobject);
}
}
@@ -3443,14 +3512,12 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
ELEM_REMOVE(iobj->link.prev);
}
else if (!iseq_pop_newarray(iseq, pobj)) {
- NODE dummy_line_node = generate_dummy_line_node(pobj->insn_info.line_no, pobj->insn_info.node_id);
- pobj = new_insn_core(iseq, &dummy_line_node, BIN(pop), 0, NULL);
+ pobj = new_insn_core(iseq, pobj->insn_info.line_no, pobj->insn_info.node_id, BIN(pop), 0, NULL);
ELEM_INSERT_PREV(&iobj->link, &pobj->link);
}
if (cond) {
if (prev_dup) {
- NODE dummy_line_node = generate_dummy_line_node(pobj->insn_info.line_no, pobj->insn_info.node_id);
- pobj = new_insn_core(iseq, &dummy_line_node, BIN(putnil), 0, NULL);
+ pobj = new_insn_core(iseq, pobj->insn_info.line_no, pobj->insn_info.node_id, BIN(putnil), 0, NULL);
ELEM_INSERT_NEXT(&iobj->link, &pobj->link);
}
iobj->insn_id = BIN(jump);
@@ -3480,6 +3547,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
enum ruby_vminsn_type previ = ((INSN *)prev)->insn_id;
if (previ == BIN(putobject) || previ == BIN(putnil) ||
previ == BIN(putself) || previ == BIN(putstring) ||
+ previ == BIN(putchilledstring) ||
previ == BIN(dup) ||
previ == BIN(getlocal) ||
previ == BIN(getblockparam) ||
@@ -3496,8 +3564,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
}
else if (previ == BIN(concatarray)) {
INSN *piobj = (INSN *)prev;
- NODE dummy_line_node = generate_dummy_line_node(piobj->insn_info.line_no, piobj->insn_info.node_id);
- INSERT_BEFORE_INSN1(piobj, &dummy_line_node, splatarray, Qfalse);
+ INSERT_BEFORE_INSN1(piobj, piobj->insn_info.line_no, piobj->insn_info.node_id, splatarray, Qfalse);
INSN_OF(piobj) = BIN(pop);
}
else if (previ == BIN(concatstrings)) {
@@ -3514,7 +3581,6 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
if (IS_INSN_ID(iobj, newarray) ||
IS_INSN_ID(iobj, duparray) ||
- IS_INSN_ID(iobj, expandarray) ||
IS_INSN_ID(iobj, concatarray) ||
IS_INSN_ID(iobj, splatarray) ||
0) {
@@ -3563,7 +3629,6 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
}
}
else {
- NODE dummy_line_node = generate_dummy_line_node(iobj->insn_info.line_no, iobj->insn_info.node_id);
long diff = FIX2LONG(op1) - FIX2LONG(op2);
INSN_OF(iobj) = BIN(opt_reverse);
OPERAND_AT(iobj, 0) = OPERAND_AT(next, 0);
@@ -3577,7 +3642,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
* opt_reverse Y
*/
for (; diff > 0; diff--) {
- INSERT_BEFORE_INSN(iobj, &dummy_line_node, pop);
+ INSERT_BEFORE_INSN(iobj, iobj->insn_info.line_no, iobj->insn_info.node_id, pop);
}
}
else { /* (op1 < op2) */
@@ -3589,7 +3654,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
* opt_reverse Y
*/
for (; diff < 0; diff++) {
- INSERT_BEFORE_INSN(iobj, &dummy_line_node, putnil);
+ INSERT_BEFORE_INSN(iobj, iobj->insn_info.line_no, iobj->insn_info.node_id, putnil);
}
}
}
@@ -3624,7 +3689,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
}
}
- if (IS_INSN_ID(iobj, putstring) ||
+ if (IS_INSN_ID(iobj, putstring) || IS_INSN_ID(iobj, putchilledstring) ||
(IS_INSN_ID(iobj, putobject) && RB_TYPE_P(OPERAND_AT(iobj, 0), T_STRING))) {
/*
* putstring ""
@@ -3813,7 +3878,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
iobj->insn_id = BIN(opt_invokebuiltin_delegate_leave);
const struct rb_builtin_function *bf = (const struct rb_builtin_function *)iobj->operands[0];
if (iobj == (INSN *)list && bf->argc == 0 && (iseq->body->builtin_attrs & BUILTIN_ATTR_LEAF)) {
- iseq->body->builtin_attrs |= BUILTIN_ATTR_SINGLE_NOARG_INLINE;
+ iseq->body->builtin_attrs |= BUILTIN_ATTR_SINGLE_NOARG_LEAF;
}
}
}
@@ -3832,6 +3897,135 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
}
}
+ if (IS_INSN_ID(iobj, splatarray) && OPERAND_AT(iobj, 0) == Qtrue) {
+ LINK_ELEMENT *niobj = &iobj->link;
+
+ /*
+ * Eliminate array allocation for f(1, *a)
+ *
+ * splatarray true
+ * send ARGS_SPLAT and not KW_SPLAT|ARGS_BLOCKARG
+ * =>
+ * splatarray false
+ * send
+ */
+ if (optimize_args_splat_no_copy(iseq, iobj, niobj,
+ VM_CALL_ARGS_SPLAT, VM_CALL_KW_SPLAT|VM_CALL_ARGS_BLOCKARG, 0)) goto optimized_splat;
+
+ if (IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable)) {
+ niobj = niobj->next;
+
+ /*
+ * Eliminate array allocation for f(1, *a, &lvar) and f(1, *a, &@iv)
+ *
+ * splatarray true
+ * getlocal / getinstancevariable
+ * send ARGS_SPLAT|ARGS_BLOCKARG and not KW_SPLAT
+ * =>
+ * splatarray false
+ * getlocal / getinstancevariable
+ * send
+ */
+ if (optimize_args_splat_no_copy(iseq, iobj, niobj,
+ VM_CALL_ARGS_SPLAT|VM_CALL_ARGS_BLOCKARG, VM_CALL_KW_SPLAT, 0)) goto optimized_splat;
+
+ /*
+ * Eliminate array allocation for f(*a, **lvar) and f(*a, **@iv)
+ *
+ * splatarray true
+ * getlocal / getinstancevariable
+ * send ARGS_SPLAT|KW_SPLAT and not ARGS_BLOCKARG
+ * =>
+ * splatarray false
+ * getlocal / getinstancevariable
+ * send
+ */
+ if (optimize_args_splat_no_copy(iseq, iobj, niobj,
+ VM_CALL_ARGS_SPLAT|VM_CALL_KW_SPLAT, VM_CALL_ARGS_BLOCKARG, 0)) goto optimized_splat;
+
+ if (IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable) ||
+ IS_NEXT_INSN_ID(niobj, getblockparamproxy)) {
+ niobj = niobj->next;
+
+ /*
+ * Eliminate array allocation for f(*a, **lvar, &{arg,lvar,@iv})
+ *
+ * splatarray true
+ * getlocal / getinstancevariable
+ * getlocal / getinstancevariable / getblockparamproxy
+ * send ARGS_SPLAT|KW_SPLAT|ARGS_BLOCKARG
+ * =>
+ * splatarray false
+ * getlocal / getinstancevariable
+ * getlocal / getinstancevariable / getblockparamproxy
+ * send
+ */
+ optimize_args_splat_no_copy(iseq, iobj, niobj,
+ VM_CALL_ARGS_SPLAT|VM_CALL_KW_SPLAT|VM_CALL_ARGS_BLOCKARG, 0, 0);
+ }
+ } else if (IS_NEXT_INSN_ID(niobj, getblockparamproxy)) {
+ /*
+ * Eliminate array allocation for f(1, *a, &arg)
+ *
+ * splatarray true
+ * getblockparamproxy
+ * send ARGS_SPLAT|ARGS_BLOCKARG and not KW_SPLAT
+ * =>
+ * splatarray false
+ * getblockparamproxy
+ * send
+ */
+ optimize_args_splat_no_copy(iseq, iobj, niobj,
+ VM_CALL_ARGS_SPLAT|VM_CALL_ARGS_BLOCKARG, VM_CALL_KW_SPLAT, 0);
+ } else if (IS_NEXT_INSN_ID(niobj, duphash)) {
+ niobj = niobj->next;
+
+ /*
+ * Eliminate array and hash allocation for f(*a, kw: 1)
+ *
+ * splatarray true
+ * duphash
+ * send ARGS_SPLAT|KW_SPLAT|KW_SPLAT_MUT and not ARGS_BLOCKARG
+ * =>
+ * splatarray false
+ * putobject
+ * send ARGS_SPLAT|KW_SPLAT
+ */
+ if (optimize_args_splat_no_copy(iseq, iobj, niobj,
+ VM_CALL_ARGS_SPLAT|VM_CALL_KW_SPLAT|VM_CALL_KW_SPLAT_MUT, VM_CALL_ARGS_BLOCKARG, VM_CALL_KW_SPLAT_MUT)) {
+
+ ((INSN*)niobj)->insn_id = BIN(putobject);
+ OPERAND_AT(niobj, 0) = rb_hash_freeze(rb_hash_resurrect(OPERAND_AT(niobj, 0)));
+
+ goto optimized_splat;
+ }
+
+ if (IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable) ||
+ IS_NEXT_INSN_ID(niobj, getblockparamproxy)) {
+ /*
+ * Eliminate array and hash allocation for f(*a, kw: 1, &{arg,lvar,@iv})
+ *
+ * splatarray true
+ * duphash
+ * getlocal / getinstancevariable / getblockparamproxy
+ * send ARGS_SPLAT|KW_SPLAT|KW_SPLAT_MUT|ARGS_BLOCKARG
+ * =>
+ * splatarray false
+ * putobject
+ * getlocal / getinstancevariable / getblockparamproxy
+ * send ARGS_SPLAT|KW_SPLAT|ARGS_BLOCKARG
+ */
+ if (optimize_args_splat_no_copy(iseq, iobj, niobj->next,
+ VM_CALL_ARGS_SPLAT|VM_CALL_KW_SPLAT|VM_CALL_KW_SPLAT_MUT|VM_CALL_ARGS_BLOCKARG, 0, VM_CALL_KW_SPLAT_MUT)) {
+
+ ((INSN*)niobj)->insn_id = BIN(putobject);
+ OPERAND_AT(niobj, 0) = rb_hash_freeze(rb_hash_resurrect(OPERAND_AT(niobj, 0)));
+ }
+ }
+ }
+ }
+ optimized_splat:
+
return COMPILE_OK;
}
@@ -3853,6 +4047,8 @@ insn_set_specialized_instruction(rb_iseq_t *iseq, INSN *iobj, int insn_id)
return COMPILE_OK;
}
+#define vm_ci_simple(ci) (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE)
+
static int
iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
{
@@ -3864,24 +4060,43 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
INSN *niobj = (INSN *)iobj->link.next;
if (IS_INSN_ID(niobj, send)) {
const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(niobj, 0);
- if ((vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE) && vm_ci_argc(ci) == 0) {
+ if (vm_ci_simple(ci) && vm_ci_argc(ci) == 0) {
switch (vm_ci_mid(ci)) {
case idMax:
case idMin:
case idHash:
{
VALUE num = iobj->operands[0];
+ int operand_len = insn_len(BIN(opt_newarray_send)) - 1;
iobj->insn_id = BIN(opt_newarray_send);
- iobj->operands = compile_data_calloc2(iseq, insn_len(iobj->insn_id) - 1, sizeof(VALUE));
+ iobj->operands = compile_data_calloc2(iseq, operand_len, sizeof(VALUE));
iobj->operands[0] = num;
iobj->operands[1] = rb_id2sym(vm_ci_mid(ci));
- iobj->operand_size = insn_len(iobj->insn_id) - 1;
+ iobj->operand_size = operand_len;
ELEM_REMOVE(&niobj->link);
return COMPILE_OK;
}
}
}
}
+ else if ((IS_INSN_ID(niobj, putstring) || IS_INSN_ID(niobj, putchilledstring) ||
+ (IS_INSN_ID(niobj, putobject) && RB_TYPE_P(OPERAND_AT(niobj, 0), T_STRING))) &&
+ IS_NEXT_INSN_ID(&niobj->link, send)) {
+ const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT((INSN *)niobj->link.next, 0);
+ if (vm_ci_simple(ci) && vm_ci_argc(ci) == 1 && vm_ci_mid(ci) == idPack) {
+ VALUE num = iobj->operands[0];
+ int operand_len = insn_len(BIN(opt_newarray_send)) - 1;
+ iobj->insn_id = BIN(opt_newarray_send);
+ iobj->operands = compile_data_calloc2(iseq, operand_len, sizeof(VALUE));
+ iobj->operands[0] = FIXNUM_INC(num, 1);
+ iobj->operands[1] = rb_id2sym(vm_ci_mid(ci));
+ iobj->operand_size = operand_len;
+ ELEM_REMOVE(&iobj->link);
+ ELEM_REMOVE(niobj->link.next);
+ ELEM_INSERT_NEXT(&niobj->link, &iobj->link);
+ return COMPILE_OK;
+ }
+ }
}
if (IS_INSN_ID(iobj, send)) {
@@ -3889,7 +4104,7 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
const rb_iseq_t *blockiseq = (rb_iseq_t *)OPERAND_AT(iobj, 1);
#define SP_INSN(opt) insn_set_specialized_instruction(iseq, iobj, BIN(opt_##opt))
- if (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE) {
+ if (vm_ci_simple(ci)) {
switch (vm_ci_argc(ci)) {
case 0:
switch (vm_ci_mid(ci)) {
@@ -4049,8 +4264,7 @@ new_unified_insn(rb_iseq_t *iseq,
list = list->next;
}
- NODE dummy_line_node = generate_dummy_line_node(iobj->insn_info.line_no, iobj->insn_info.node_id);
- return new_insn_core(iseq, &dummy_line_node, insn_id, argc, operands);
+ return new_insn_core(iseq, iobj->insn_info.line_no, iobj->insn_info.node_id, insn_id, argc, operands);
}
#endif
@@ -4115,7 +4329,7 @@ all_string_result_p(const NODE *node)
{
if (!node) return FALSE;
switch (nd_type(node)) {
- case NODE_STR: case NODE_DSTR:
+ case NODE_STR: case NODE_DSTR: case NODE_FILE:
return TRUE;
case NODE_IF: case NODE_UNLESS:
if (!RNODE_IF(node)->nd_body || !RNODE_IF(node)->nd_else) return FALSE;
@@ -4137,7 +4351,7 @@ static int
compile_dstr_fragments(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int *cntp)
{
const struct RNode_LIST *list = RNODE_DSTR(node)->nd_next;
- VALUE lit = RNODE_DSTR(node)->nd_lit;
+ VALUE lit = rb_node_dstr_string_val(node);
LINK_ELEMENT *first_lit = 0;
int cnt = 0;
@@ -4158,7 +4372,7 @@ compile_dstr_fragments(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *cons
while (list) {
const NODE *const head = list->nd_head;
if (nd_type_p(head, NODE_STR)) {
- lit = rb_fstring(RNODE_STR(head)->nd_lit);
+ lit = rb_node_str_string_val(head);
ADD_INSN1(ret, head, putobject, lit);
RB_OBJ_WRITTEN(iseq, Qundef, lit);
lit = Qnil;
@@ -4197,7 +4411,7 @@ compile_dstr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node)
{
int cnt;
if (!RNODE_DSTR(node)->nd_next) {
- VALUE lit = rb_fstring(RNODE_DSTR(node)->nd_lit);
+ VALUE lit = rb_node_dstr_string_val(node);
ADD_INSN1(ret, node, putstring, lit);
RB_OBJ_WRITTEN(iseq, Qundef, lit);
}
@@ -4209,11 +4423,28 @@ compile_dstr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node)
}
static int
-compile_dregx(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node)
+compile_dregx(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped)
{
int cnt;
+ int cflag = (int)RNODE_DREGX(node)->as.nd_cflag;
+
+ if (!RNODE_DREGX(node)->nd_next) {
+ if (!popped) {
+ VALUE src = rb_node_dregx_string_val(node);
+ VALUE match = rb_reg_compile(src, cflag, NULL, 0);
+ ADD_INSN1(ret, node, putobject, match);
+ RB_OBJ_WRITTEN(iseq, Qundef, match);
+ }
+ return COMPILE_OK;
+ }
+
CHECK(compile_dstr_fragments(iseq, ret, node, &cnt));
- ADD_INSN2(ret, node, toregexp, INT2FIX(RNODE_DREGX(node)->nd_cflag), INT2FIX(cnt));
+ ADD_INSN2(ret, node, toregexp, INT2FIX(cflag), INT2FIX(cnt));
+
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+
return COMPILE_OK;
}
@@ -4307,9 +4538,17 @@ compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *ret, const NODE *cond,
else_label = NEW_LABEL(nd_line(cond));
}
goto again;
- case NODE_LIT: /* NODE_LIT is always true */
+ case NODE_SYM:
+ case NODE_LINE:
+ case NODE_FILE:
+ case NODE_ENCODING:
+ case NODE_INTEGER: /* NODE_INTEGER is always true */
+ case NODE_FLOAT: /* NODE_FLOAT is always true */
+ case NODE_RATIONAL: /* NODE_RATIONAL is always true */
+ case NODE_IMAGINARY: /* NODE_IMAGINARY is always true */
case NODE_TRUE:
case NODE_STR:
+ case NODE_REGX:
case NODE_ZLIST:
case NODE_LAMBDA:
/* printf("useless condition eliminate (%s)\n", ruby_node_name(nd_type(cond))); */
@@ -4375,6 +4614,39 @@ keyword_node_p(const NODE *const node)
return nd_type_p(node, NODE_HASH) && (RNODE_HASH(node)->nd_brace & HASH_BRACE) != HASH_BRACE;
}
+static VALUE
+get_symbol_value(rb_iseq_t *iseq, const NODE *node)
+{
+ switch (nd_type(node)) {
+ case NODE_SYM:
+ return rb_node_sym_string_val(node);
+ default:
+ UNKNOWN_NODE("get_symbol_value", node, Qnil);
+ }
+}
+
+static VALUE
+node_hash_unique_key_index(rb_iseq_t *iseq, rb_node_hash_t *node_hash, int *count_ptr)
+{
+ NODE *node = node_hash->nd_head;
+ VALUE hash = rb_hash_new();
+ VALUE ary = rb_ary_new();
+
+ for (int i = 0; node != NULL; i++, node = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next) {
+ VALUE key = get_symbol_value(iseq, RNODE_LIST(node)->nd_head);
+ VALUE idx = rb_hash_aref(hash, key);
+ if (!NIL_P(idx)) {
+ rb_ary_store(ary, FIX2INT(idx), Qfalse);
+ (*count_ptr)--;
+ }
+ rb_hash_aset(hash, key, INT2FIX(i));
+ rb_ary_store(ary, i, Qtrue);
+ (*count_ptr)++;
+ }
+
+ return ary;
+}
+
static int
compile_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
const NODE *const root_node,
@@ -4393,8 +4665,8 @@ compile_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
const NODE *key_node = RNODE_LIST(node)->nd_head;
seen_nodes++;
- assert(nd_type_p(node, NODE_LIST));
- if (key_node && nd_type_p(key_node, NODE_LIT) && SYMBOL_P(RNODE_LIT(key_node)->nd_lit)) {
+ RUBY_ASSERT(nd_type_p(node, NODE_LIST));
+ if (key_node && nd_type_p(key_node, NODE_SYM)) {
/* can be keywords */
}
else {
@@ -4417,11 +4689,13 @@ compile_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
/* may be keywords */
node = RNODE_HASH(root_node)->nd_head;
{
- int len = (int)RNODE_LIST(node)->as.nd_alen / 2;
+ int len = 0;
+ VALUE key_index = node_hash_unique_key_index(iseq, RNODE_HASH(root_node), &len);
struct rb_callinfo_kwarg *kw_arg =
rb_xmalloc_mul_add(len, sizeof(VALUE), sizeof(struct rb_callinfo_kwarg));
VALUE *keywords = kw_arg->keywords;
int i = 0;
+ int j = 0;
kw_arg->references = 0;
kw_arg->keyword_len = len;
@@ -4430,10 +4704,15 @@ compile_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
for (i=0; node != NULL; i++, node = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next) {
const NODE *key_node = RNODE_LIST(node)->nd_head;
const NODE *val_node = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_head;
- keywords[i] = RNODE_LIT(key_node)->nd_lit;
- NO_CHECK(COMPILE(ret, "keyword values", val_node));
+ int popped = TRUE;
+ if (rb_ary_entry(key_index, i)) {
+ keywords[j] = get_symbol_value(iseq, key_node);
+ j++;
+ popped = FALSE;
+ }
+ NO_CHECK(COMPILE_(ret, "keyword values", val_node, popped));
}
- assert(i == len);
+ RUBY_ASSERT(j == len);
return TRUE;
}
}
@@ -4462,17 +4741,31 @@ compile_args(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, NODE **k
return len;
}
-static inline int
-static_literal_node_p(const NODE *node, const rb_iseq_t *iseq)
+static inline bool
+frozen_string_literal_p(const rb_iseq_t *iseq)
+{
+ return ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal > 0;
+}
+
+static inline bool
+static_literal_node_p(const NODE *node, const rb_iseq_t *iseq, bool hash_key)
{
switch (nd_type(node)) {
- case NODE_LIT:
+ case NODE_SYM:
+ case NODE_REGX:
+ case NODE_LINE:
+ case NODE_ENCODING:
+ case NODE_INTEGER:
+ case NODE_FLOAT:
+ case NODE_RATIONAL:
+ case NODE_IMAGINARY:
case NODE_NIL:
case NODE_TRUE:
case NODE_FALSE:
return TRUE;
case NODE_STR:
- return ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal;
+ case NODE_FILE:
+ return hash_key || frozen_string_literal_p(iseq);
default:
return FALSE;
}
@@ -4482,30 +4775,46 @@ static inline VALUE
static_literal_value(const NODE *node, rb_iseq_t *iseq)
{
switch (nd_type(node)) {
+ case NODE_INTEGER:
+ return rb_node_integer_literal_val(node);
+ case NODE_FLOAT:
+ return rb_node_float_literal_val(node);
+ case NODE_RATIONAL:
+ return rb_node_rational_literal_val(node);
+ case NODE_IMAGINARY:
+ return rb_node_imaginary_literal_val(node);
case NODE_NIL:
return Qnil;
case NODE_TRUE:
return Qtrue;
case NODE_FALSE:
return Qfalse;
+ case NODE_SYM:
+ return rb_node_sym_string_val(node);
+ case NODE_REGX:
+ return rb_node_regx_string_val(node);
+ case NODE_LINE:
+ return rb_node_line_lineno_val(node);
+ case NODE_ENCODING:
+ return rb_node_encoding_val(node);
+ case NODE_FILE:
case NODE_STR:
if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal || RTEST(ruby_debug)) {
- VALUE lit;
VALUE debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq), INT2FIX((int)nd_line(node)));
- lit = rb_str_dup(RNODE_STR(node)->nd_lit);
+ VALUE lit = rb_str_dup(get_string_value(node));
rb_ivar_set(lit, id_debug_created_info, rb_obj_freeze(debug_info));
return rb_str_freeze(lit);
}
else {
- return rb_fstring(RNODE_STR(node)->nd_lit);
+ return get_string_value(node);
}
default:
- return RNODE_LIT(node)->nd_lit;
+ rb_bug("unexpected node: %s", ruby_node_name(nd_type(node)));
}
}
static int
-compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int popped)
+compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int popped, bool first_chunk)
{
const NODE *line_node = node;
@@ -4540,8 +4849,8 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop
*
* [x1,x2,...,x10000] =>
* push x1 ; push x2 ; ...; push x256; newarray 256;
- * push x257; push x258; ...; push x512; newarray 256; concatarray;
- * push x513; push x514; ...; push x768; newarray 256; concatarray;
+ * push x257; push x258; ...; push x512; pushtoarray 256;
+ * push x513; push x514; ...; push x768; pushtoarray 256;
* ...
*
* - Long subarray can be optimized by pre-allocating a hidden array.
@@ -4551,38 +4860,38 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop
*
* [x, 1,2,3,...,100, z] =>
* push x; newarray 1;
- * putobject [1,2,3,...,100] (<- hidden array); concatarray;
- * push z; newarray 1; concatarray
+ * putobject [1,2,3,...,100] (<- hidden array); concattoarray;
+ * push z; pushtoarray 1;
*
- * - If the last element is a keyword, newarraykwsplat should be emitted
- * to check and remove empty keyword arguments hash from array.
+ * - If the last element is a keyword, pushtoarraykwsplat should be emitted
+ * to only push it onto the array if it is not empty
* (Note: a keyword is NODE_HASH which is not static_literal_node_p.)
*
* [1,2,3,**kw] =>
- * putobject 1; putobject 2; putobject 3; push kw; newarraykwsplat
+ * putobject 1; putobject 2; putobject 3; newarray 3; ...; pushtoarraykwsplat kw
*/
const int max_stack_len = 0x100;
const int min_tmp_ary_len = 0x40;
int stack_len = 0;
- int first_chunk = 1;
- /* Convert pushed elements to an array, and concatarray if needed */
-#define FLUSH_CHUNK(newarrayinsn) \
+ /* Either create a new array, or push to the existing array */
+#define FLUSH_CHUNK \
if (stack_len) { \
- ADD_INSN1(ret, line_node, newarrayinsn, INT2FIX(stack_len)); \
- if (!first_chunk) ADD_INSN(ret, line_node, concatarray); \
- first_chunk = stack_len = 0; \
+ if (first_chunk) ADD_INSN1(ret, line_node, newarray, INT2FIX(stack_len)); \
+ else ADD_INSN1(ret, line_node, pushtoarray, INT2FIX(stack_len)); \
+ first_chunk = FALSE; \
+ stack_len = 0; \
}
while (node) {
int count = 1;
/* pre-allocation check (this branch can be omittable) */
- if (static_literal_node_p(RNODE_LIST(node)->nd_head, iseq)) {
+ if (static_literal_node_p(RNODE_LIST(node)->nd_head, iseq, false)) {
/* count the elements that are optimizable */
const NODE *node_tmp = RNODE_LIST(node)->nd_next;
- for (; node_tmp && static_literal_node_p(RNODE_LIST(node_tmp)->nd_head, iseq); node_tmp = RNODE_LIST(node_tmp)->nd_next)
+ for (; node_tmp && static_literal_node_p(RNODE_LIST(node_tmp)->nd_head, iseq, false); node_tmp = RNODE_LIST(node_tmp)->nd_next)
count++;
if ((first_chunk && stack_len == 0 && !node_tmp) || count >= min_tmp_ary_len) {
@@ -4595,14 +4904,14 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop
OBJ_FREEZE(ary);
/* Emit optimized code */
- FLUSH_CHUNK(newarray);
+ FLUSH_CHUNK;
if (first_chunk) {
ADD_INSN1(ret, line_node, duparray, ary);
- first_chunk = 0;
+ first_chunk = FALSE;
}
else {
ADD_INSN1(ret, line_node, putobject, ary);
- ADD_INSN(ret, line_node, concatarray);
+ ADD_INSN(ret, line_node, concattoarray);
}
RB_OBJ_WRITTEN(iseq, Qundef, ary);
}
@@ -4614,48 +4923,37 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop
EXPECT_NODE("compile_array", node, NODE_LIST, -1);
}
- NO_CHECK(COMPILE_(ret, "array element", RNODE_LIST(node)->nd_head, 0));
- stack_len++;
-
if (!RNODE_LIST(node)->nd_next && keyword_node_p(RNODE_LIST(node)->nd_head)) {
- /* Reached the end, and the last element is a keyword */
- FLUSH_CHUNK(newarraykwsplat);
+ /* Create array or push existing non-keyword elements onto array */
+ if (stack_len == 0 && first_chunk) {
+ ADD_INSN1(ret, line_node, newarray, INT2FIX(0));
+ }
+ else {
+ FLUSH_CHUNK;
+ }
+ NO_CHECK(COMPILE_(ret, "array element", RNODE_LIST(node)->nd_head, 0));
+ ADD_INSN(ret, line_node, pushtoarraykwsplat);
return 1;
}
+ else {
+ NO_CHECK(COMPILE_(ret, "array element", RNODE_LIST(node)->nd_head, 0));
+ stack_len++;
+ }
/* If there are many pushed elements, flush them to avoid stack overflow */
- if (stack_len >= max_stack_len) FLUSH_CHUNK(newarray);
+ if (stack_len >= max_stack_len) FLUSH_CHUNK;
}
}
- FLUSH_CHUNK(newarray);
+ FLUSH_CHUNK;
#undef FLUSH_CHUNK
return 1;
}
-/* Compile an array containing the single element represented by node */
-static int
-compile_array_1(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node)
-{
- if (static_literal_node_p(node, iseq)) {
- VALUE ary = rb_ary_hidden_new(1);
- rb_ary_push(ary, static_literal_value(node, iseq));
- OBJ_FREEZE(ary);
-
- ADD_INSN1(ret, node, duparray, ary);
- }
- else {
- CHECK(COMPILE_(ret, "array element", node, FALSE));
- ADD_INSN1(ret, node, newarray, INT2FIX(1));
- }
-
- return 1;
-}
-
static inline int
static_literal_node_pair_p(const NODE *node, const rb_iseq_t *iseq)
{
- return RNODE_LIST(node)->nd_head && static_literal_node_p(RNODE_LIST(node)->nd_head, iseq) && static_literal_node_p(RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_head, iseq);
+ return RNODE_LIST(node)->nd_head && static_literal_node_p(RNODE_LIST(node)->nd_head, iseq, true) && static_literal_node_p(RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_head, iseq, false);
}
static int
@@ -4788,11 +5086,12 @@ compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int meth
FLUSH_CHUNK();
const NODE *kw = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_head;
- int empty_kw = nd_type_p(kw, NODE_LIT) && RB_TYPE_P(RNODE_LIT(kw)->nd_lit, T_HASH); /* foo( ..., **{}, ...) */
+ int empty_kw = nd_type_p(kw, NODE_HASH) && (!RNODE_HASH(kw)->nd_head); /* foo( ..., **{}, ...) */
int first_kw = first_chunk && stack_len == 0; /* foo(1,2,3, **kw, ...) */
int last_kw = !RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next; /* foo( ..., **kw) */
int only_kw = last_kw && first_kw; /* foo(1,2,3, **kw) */
+ empty_kw = empty_kw || nd_type_p(kw, NODE_NIL); /* foo( ..., **nil, ...) */
if (empty_kw) {
if (only_kw && method_call_keywords) {
/* **{} appears at the only keyword argument in method call,
@@ -4852,29 +5151,34 @@ VALUE
rb_node_case_when_optimizable_literal(const NODE *const node)
{
switch (nd_type(node)) {
- case NODE_LIT: {
- VALUE v = RNODE_LIT(node)->nd_lit;
+ case NODE_INTEGER:
+ return rb_node_integer_literal_val(node);
+ case NODE_FLOAT: {
+ VALUE v = rb_node_float_literal_val(node);
double ival;
- if (RB_FLOAT_TYPE_P(v) &&
- modf(RFLOAT_VALUE(v), &ival) == 0.0) {
+
+ if (modf(RFLOAT_VALUE(v), &ival) == 0.0) {
return FIXABLE(ival) ? LONG2FIX((long)ival) : rb_dbl2big(ival);
}
- if (RB_TYPE_P(v, T_RATIONAL) || RB_TYPE_P(v, T_COMPLEX)) {
- return Qundef;
- }
- if (SYMBOL_P(v) || rb_obj_is_kind_of(v, rb_cNumeric)) {
- return v;
- }
- break;
+ return v;
}
+ case NODE_RATIONAL:
+ case NODE_IMAGINARY:
+ return Qundef;
case NODE_NIL:
return Qnil;
case NODE_TRUE:
return Qtrue;
case NODE_FALSE:
return Qfalse;
+ case NODE_SYM:
+ return rb_node_sym_string_val(node);
+ case NODE_LINE:
+ return rb_node_line_lineno_val(node);
case NODE_STR:
- return rb_fstring(RNODE_STR(node)->nd_lit);
+ return rb_node_str_string_val(node);
+ case NODE_FILE:
+ return rb_node_file_path_val(node);
}
return Qundef;
}
@@ -4894,9 +5198,9 @@ when_vals(rb_iseq_t *iseq, LINK_ANCHOR *const cond_seq, const NODE *vals,
rb_hash_aset(literals, lit, (VALUE)(l1) | 1);
}
- if (nd_type_p(val, NODE_STR)) {
- debugp_param("nd_lit", RNODE_STR(val)->nd_lit);
- lit = rb_fstring(RNODE_STR(val)->nd_lit);
+ if (nd_type_p(val, NODE_STR) || nd_type_p(val, NODE_FILE)) {
+ debugp_param("nd_lit", get_string_value(val));
+ lit = get_string_value(val);
ADD_INSN1(cond_seq, val, putobject, lit);
RB_OBJ_WRITTEN(iseq, Qundef, lit);
}
@@ -5097,12 +5401,17 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const
CHECK(COMPILE_POPPED(pre, "masgn lhs (NODE_ATTRASGN)", node));
+ bool safenav_call = false;
LINK_ELEMENT *insn_element = LAST_ELEMENT(pre);
iobj = (INSN *)get_prev_insn((INSN *)insn_element); /* send insn */
ASSUME(iobj);
- ELEM_REMOVE(LAST_ELEMENT(pre));
- ELEM_REMOVE((LINK_ELEMENT *)iobj);
- pre->last = iobj->link.prev;
+ ELEM_REMOVE(insn_element);
+ if (!IS_INSN_ID(iobj, send)) {
+ safenav_call = true;
+ iobj = (INSN *)get_prev_insn(iobj);
+ ELEM_INSERT_NEXT(&iobj->link, insn_element);
+ }
+ (pre->last = iobj->link.prev)->next = 0;
const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(iobj, 0);
int argc = vm_ci_argc(ci) + 1;
@@ -5121,18 +5430,46 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const
return COMPILE_NG;
}
- ADD_ELEM(lhs, (LINK_ELEMENT *)iobj);
+ iobj->link.prev = lhs->last;
+ lhs->last->next = &iobj->link;
+ for (lhs->last = &iobj->link; lhs->last->next; lhs->last = lhs->last->next);
if (vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT) {
int argc = vm_ci_argc(ci);
+ bool dupsplat = false;
ci = ci_argc_set(iseq, ci, argc - 1);
+ if (!(vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT_MUT)) {
+ /* Given h[*a], _ = ary
+ * setup_args sets VM_CALL_ARGS_SPLAT and not VM_CALL_ARGS_SPLAT_MUT
+ * `a` must be dupped, because it will be appended with ary[0]
+ * Since you are dupping `a`, you can set VM_CALL_ARGS_SPLAT_MUT
+ */
+ dupsplat = true;
+ ci = ci_flag_set(iseq, ci, VM_CALL_ARGS_SPLAT_MUT);
+ }
OPERAND_AT(iobj, 0) = (VALUE)ci;
RB_OBJ_WRITTEN(iseq, Qundef, iobj);
- INSERT_BEFORE_INSN1(iobj, line_node, newarray, INT2FIX(1));
- INSERT_BEFORE_INSN(iobj, line_node, concatarray);
+
+ /* Given: h[*a], h[*b, 1] = ary
+ * h[*a] uses splatarray false and does not set VM_CALL_ARGS_SPLAT_MUT,
+ * so this uses splatarray true on a to dup it before using pushtoarray
+ * h[*b, 1] uses splatarray true and sets VM_CALL_ARGS_SPLAT_MUT,
+ * so you can use pushtoarray directly
+ */
+ int line_no = nd_line(line_node);
+ int node_id = nd_node_id(line_node);
+
+ if (dupsplat) {
+ INSERT_BEFORE_INSN(iobj, line_no, node_id, swap);
+ INSERT_BEFORE_INSN1(iobj, line_no, node_id, splatarray, Qtrue);
+ INSERT_BEFORE_INSN(iobj, line_no, node_id, swap);
+ }
+ INSERT_BEFORE_INSN1(iobj, line_no, node_id, pushtoarray, INT2FIX(1));
}
- ADD_INSN(lhs, line_node, pop);
- if (argc != 1) {
+ if (!safenav_call) {
ADD_INSN(lhs, line_node, pop);
+ if (argc != 1) {
+ ADD_INSN(lhs, line_node, pop);
+ }
}
for (int i=0; i < argc; i++) {
ADD_INSN(post, line_node, pop);
@@ -5347,7 +5684,7 @@ compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
while (memo) {
VALUE topn_arg = INT2FIX((state.num_args - memo->argn) + memo->lhs_pos);
for (int i = 0; i < memo->num_args; i++) {
- INSERT_BEFORE_INSN1(memo->before_insn, memo->line_node, topn, topn_arg);
+ INSERT_BEFORE_INSN1(memo->before_insn, nd_line(memo->line_node), nd_node_id(memo->line_node), topn, topn_arg);
}
tmp_memo = memo->next;
free(memo);
@@ -5498,7 +5835,15 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
}
/* fall through */
case NODE_STR:
- case NODE_LIT:
+ case NODE_SYM:
+ case NODE_REGX:
+ case NODE_LINE:
+ case NODE_FILE:
+ case NODE_ENCODING:
+ case NODE_INTEGER:
+ case NODE_FLOAT:
+ case NODE_RATIONAL:
+ case NODE_IMAGINARY:
case NODE_ZLIST:
case NODE_AND:
case NODE_OR:
@@ -5617,6 +5962,7 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
ADD_INSN(ret, line_node, putnil);
ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_YIELD), 0,
PUSH_VAL(DEFINED_YIELD));
+ iseq_set_use_block(ISEQ_BODY(iseq)->local_iseq);
return;
case NODE_BACK_REF:
@@ -5646,11 +5992,12 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
case NODE_IASGN:
case NODE_CDECL:
case NODE_CVASGN:
+ case NODE_OP_CDECL:
expr_type = DEFINED_ASGN;
break;
}
- assert(expr_type != DEFINED_NOT_DEFINED);
+ RUBY_ASSERT(expr_type != DEFINED_NOT_DEFINED);
if (needstr != Qfalse) {
VALUE str = rb_iseq_defined_string(expr_type);
@@ -5664,8 +6011,7 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
static void
build_defined_rescue_iseq(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const void *unused)
{
- NODE dummy_line_node = generate_dummy_line_node(0, -1);
- ADD_INSN(ret, &dummy_line_node, putnil);
+ ADD_SYNTHETIC_INSN(ret, 0, -1, putnil);
iseq_set_exception_local_table(iseq);
}
@@ -5711,7 +6057,7 @@ compile_defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const
lfinish[2] = 0;
defined_expr(iseq, ret, RNODE_DEFINED(node)->nd_head, lfinish, needstr);
if (lfinish[1]) {
- ELEM_INSERT_NEXT(last, &new_insn_body(iseq, line_node, BIN(putnil), 0)->link);
+ ELEM_INSERT_NEXT(last, &new_insn_body(iseq, nd_line(line_node), nd_node_id(line_node), BIN(putnil), 0)->link);
ADD_INSN(ret, line_node, swap);
if (lfinish[2]) {
ADD_LABEL(ret, lfinish[2]);
@@ -5792,7 +6138,7 @@ can_add_ensure_iseq(const rb_iseq_t *iseq)
static void
add_ensure_iseq(LINK_ANCHOR *const ret, rb_iseq_t *iseq, int is_return)
{
- assert(can_add_ensure_iseq(iseq));
+ RUBY_ASSERT(can_add_ensure_iseq(iseq));
struct iseq_compile_data_ensure_node_stack *enlp =
ISEQ_COMPILE_DATA(iseq)->ensure_node_stack;
@@ -5882,18 +6228,23 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
// f(*a)
NO_CHECK(COMPILE(args, "args (splat)", RNODE_SPLAT(argn)->nd_head));
ADD_INSN1(args, argn, splatarray, RBOOL(dup_rest));
- if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
+ if (flag_ptr) {
+ *flag_ptr |= VM_CALL_ARGS_SPLAT;
+ if (dup_rest) *flag_ptr |= VM_CALL_ARGS_SPLAT_MUT;
+ }
RUBY_ASSERT(flag_ptr == NULL || (*flag_ptr & VM_CALL_KW_SPLAT) == 0);
return 1;
}
case NODE_ARGSCAT: {
- if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
+ if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_SPLAT_MUT;
int argc = setup_args_core(iseq, args, RNODE_ARGSCAT(argn)->nd_head, 1, NULL, NULL);
+ bool args_pushed = false;
if (nd_type_p(RNODE_ARGSCAT(argn)->nd_body, NODE_LIST)) {
int rest_len = compile_args(iseq, args, RNODE_ARGSCAT(argn)->nd_body, &kwnode);
if (kwnode) rest_len--;
- ADD_INSN1(args, argn, newarray, INT2FIX(rest_len));
+ ADD_INSN1(args, argn, pushtoarray, INT2FIX(rest_len));
+ args_pushed = true;
}
else {
RUBY_ASSERT(!check_keyword(RNODE_ARGSCAT(argn)->nd_body));
@@ -5904,9 +6255,8 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
ADD_INSN1(args, argn, splatarray, Qtrue);
argc += 1;
}
- else {
- ADD_INSN1(args, argn, splatarray, Qfalse);
- ADD_INSN(args, argn, concatarray);
+ else if (!args_pushed) {
+ ADD_INSN(args, argn, concattoarray);
}
// f(..., *a, ..., k1:1, ...) #=> f(..., *[*a, ...], **{k1:1, ...})
@@ -5921,15 +6271,14 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
return argc;
}
case NODE_ARGSPUSH: {
- if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
+ if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_SPLAT_MUT;
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, 1, NULL, NULL);
if (nd_type_p(RNODE_ARGSPUSH(argn)->nd_body, NODE_LIST)) {
int rest_len = compile_args(iseq, args, RNODE_ARGSPUSH(argn)->nd_body, &kwnode);
if (kwnode) rest_len--;
ADD_INSN1(args, argn, newarray, INT2FIX(rest_len));
- ADD_INSN1(args, argn, newarray, INT2FIX(1));
- ADD_INSN(args, argn, concatarray);
+ ADD_INSN1(args, argn, pushtoarray, INT2FIX(1));
}
else {
if (keyword_node_p(RNODE_ARGSPUSH(argn)->nd_body)) {
@@ -5937,8 +6286,7 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
}
else {
NO_CHECK(COMPILE(args, "args (cat: splat)", RNODE_ARGSPUSH(argn)->nd_body));
- ADD_INSN1(args, argn, newarray, INT2FIX(1));
- ADD_INSN(args, argn, concatarray);
+ ADD_INSN1(args, argn, pushtoarray, INT2FIX(1));
}
}
@@ -6031,7 +6379,7 @@ compile_named_capture_assign(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE
last = ret->last;
NO_CHECK(COMPILE_POPPED(ret, "capture", RNODE_BLOCK(vars)->nd_head));
last = last->next; /* putobject :var */
- cap = new_insn_send(iseq, line_node, idAREF, INT2FIX(1),
+ cap = new_insn_send(iseq, nd_line(line_node), nd_node_id(line_node), idAREF, INT2FIX(1),
NULL, INT2FIX(0), NULL);
ELEM_INSERT_PREV(last->next, (LINK_ELEMENT *)cap);
#if !defined(NAMED_CAPTURE_SINGLE_OPT) || NAMED_CAPTURE_SINGLE_OPT-0
@@ -6071,8 +6419,10 @@ optimizable_range_item_p(const NODE *n)
{
if (!n) return FALSE;
switch (nd_type(n)) {
- case NODE_LIT:
- return RB_INTEGER_TYPE_P(RNODE_LIT(n)->nd_lit);
+ case NODE_LINE:
+ return TRUE;
+ case NODE_INTEGER:
+ return TRUE;
case NODE_NIL:
return TRUE;
default:
@@ -6080,6 +6430,27 @@ optimizable_range_item_p(const NODE *n)
}
}
+static VALUE
+optimized_range_item(const NODE *n)
+{
+ switch (nd_type(n)) {
+ case NODE_LINE:
+ return rb_node_line_lineno_val(n);
+ case NODE_INTEGER:
+ return rb_node_integer_literal_val(n);
+ case NODE_FLOAT:
+ return rb_node_float_literal_val(n);
+ case NODE_RATIONAL:
+ return rb_node_rational_literal_val(n);
+ case NODE_IMAGINARY:
+ return rb_node_imaginary_literal_val(n);
+ case NODE_NIL:
+ return Qnil;
+ default:
+ rb_bug("unexpected node: %s", ruby_node_name(nd_type(n)));
+ }
+}
+
static int
compile_if(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped, const enum node_type type)
{
@@ -6101,7 +6472,7 @@ compile_if(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int
ADD_SEQ(ret, cond_seq);
if (then_label->refcnt && else_label->refcnt) {
- branches = decl_branch_base(iseq, node, type == NODE_IF ? "if" : "unless");
+ branches = decl_branch_base(iseq, PTR2NUM(node), nd_code_loc(node), type == NODE_IF ? "if" : "unless");
}
if (then_label->refcnt) {
@@ -6112,10 +6483,12 @@ compile_if(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int
CHECK(COMPILE_(then_seq, "then", node_body, popped));
if (else_label->refcnt) {
+ const NODE *const coverage_node = node_body ? node_body : node;
add_trace_branch_coverage(
iseq,
ret,
- node_body ? node_body : node,
+ nd_code_loc(coverage_node),
+ nd_node_id(coverage_node),
0,
type == NODE_IF ? "then" : "else",
branches);
@@ -6136,10 +6509,12 @@ compile_if(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int
CHECK(COMPILE_(else_seq, "else", node_else, popped));
if (then_label->refcnt) {
+ const NODE *const coverage_node = node_else ? node_else : node;
add_trace_branch_coverage(
iseq,
ret,
- node_else ? node_else : node,
+ nd_code_loc(coverage_node),
+ nd_node_id(coverage_node),
1,
type == NODE_IF ? "else" : "then",
branches);
@@ -6179,7 +6554,7 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod
CHECK(COMPILE(head, "case base", RNODE_CASE(node)->nd_head));
- branches = decl_branch_base(iseq, node, "case");
+ branches = decl_branch_base(iseq, PTR2NUM(node), nd_code_loc(node), "case");
node = RNODE_CASE(node)->nd_body;
EXPECT_NODE("NODE_CASE", node, NODE_WHEN, COMPILE_NG);
@@ -6198,13 +6573,17 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod
l1 = NEW_LABEL(line);
ADD_LABEL(body_seq, l1);
ADD_INSN(body_seq, line_node, pop);
+
+ const NODE *const coverage_node = RNODE_WHEN(node)->nd_body ? RNODE_WHEN(node)->nd_body : node;
add_trace_branch_coverage(
iseq,
body_seq,
- RNODE_WHEN(node)->nd_body ? RNODE_WHEN(node)->nd_body : node,
+ nd_code_loc(coverage_node),
+ nd_node_id(coverage_node),
branch_id++,
"when",
branches);
+
CHECK(COMPILE_(body_seq, "when body", RNODE_WHEN(node)->nd_body, popped));
ADD_INSNL(body_seq, line_node, jump, endlabel);
@@ -6241,7 +6620,7 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod
if (node) {
ADD_LABEL(cond_seq, elselabel);
ADD_INSN(cond_seq, line_node, pop);
- add_trace_branch_coverage(iseq, cond_seq, node, branch_id, "else", branches);
+ add_trace_branch_coverage(iseq, cond_seq, nd_code_loc(node), nd_node_id(node), branch_id, "else", branches);
CHECK(COMPILE_(cond_seq, "else", node, popped));
ADD_INSNL(cond_seq, line_node, jump, endlabel);
}
@@ -6249,7 +6628,7 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod
debugs("== else (implicit)\n");
ADD_LABEL(cond_seq, elselabel);
ADD_INSN(cond_seq, orig_node, pop);
- add_trace_branch_coverage(iseq, cond_seq, orig_node, branch_id, "else", branches);
+ add_trace_branch_coverage(iseq, cond_seq, nd_code_loc(orig_node), nd_node_id(orig_node), branch_id, "else", branches);
if (!popped) {
ADD_INSN(cond_seq, orig_node, putnil);
}
@@ -6280,7 +6659,7 @@ compile_case2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
VALUE branches = Qfalse;
int branch_id = 0;
- branches = decl_branch_base(iseq, orig_node, "case");
+ branches = decl_branch_base(iseq, PTR2NUM(orig_node), nd_code_loc(orig_node), "case");
INIT_ANCHOR(body_seq);
endlabel = NEW_LABEL(nd_line(node));
@@ -6289,13 +6668,17 @@ compile_case2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
const int line = nd_line(node);
LABEL *l1 = NEW_LABEL(line);
ADD_LABEL(body_seq, l1);
+
+ const NODE *const coverage_node = RNODE_WHEN(node)->nd_body ? RNODE_WHEN(node)->nd_body : node;
add_trace_branch_coverage(
iseq,
body_seq,
- RNODE_WHEN(node)->nd_body ? RNODE_WHEN(node)->nd_body : node,
+ nd_code_loc(coverage_node),
+ nd_node_id(coverage_node),
branch_id++,
"when",
branches);
+
CHECK(COMPILE_(body_seq, "when", RNODE_WHEN(node)->nd_body, popped));
ADD_INSNL(body_seq, node, jump, endlabel);
@@ -6329,10 +6712,12 @@ compile_case2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
node = RNODE_WHEN(node)->nd_next;
}
/* else */
+ const NODE *const coverage_node = node ? node : orig_node;
add_trace_branch_coverage(
iseq,
ret,
- node ? node : orig_node,
+ nd_code_loc(coverage_node),
+ nd_node_id(coverage_node),
branch_id,
"else",
branches);
@@ -6768,7 +7153,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
const NODE *kw_args = RNODE_HASH(RNODE_HSHPTN(node)->nd_pkwargs)->nd_head;
keys = rb_ary_new_capa(kw_args ? RNODE_LIST(kw_args)->as.nd_alen/2 : 0);
while (kw_args) {
- rb_ary_push(keys, RNODE_LIT(RNODE_LIST(kw_args)->nd_head)->nd_lit);
+ rb_ary_push(keys, get_symbol_value(iseq, RNODE_LIST(kw_args)->nd_head));
kw_args = RNODE_LIST(RNODE_LIST(kw_args)->nd_next)->nd_next;
}
}
@@ -6812,12 +7197,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
for (i = 0; i < keys_num; i++) {
NODE *key_node = RNODE_LIST(args)->nd_head;
NODE *value_node = RNODE_LIST(RNODE_LIST(args)->nd_next)->nd_head;
- VALUE key;
-
- if (!nd_type_p(key_node, NODE_LIT)) {
- UNKNOWN_NODE("NODE_IN", key_node, COMPILE_NG);
- }
- key = RNODE_LIT(key_node)->nd_lit;
+ VALUE key = get_symbol_value(iseq, key_node);
ADD_INSN(ret, line_node, dup);
ADD_INSN1(ret, line_node, putobject, key);
@@ -6893,7 +7273,15 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
ADD_INSNL(ret, line_node, jump, unmatched);
break;
}
- case NODE_LIT:
+ case NODE_SYM:
+ case NODE_REGX:
+ case NODE_LINE:
+ case NODE_INTEGER:
+ case NODE_FLOAT:
+ case NODE_RATIONAL:
+ case NODE_IMAGINARY:
+ case NODE_FILE:
+ case NODE_ENCODING:
case NODE_STR:
case NODE_XSTR:
case NODE_DSTR:
@@ -6917,6 +7305,8 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
case NODE_COLON2:
case NODE_COLON3:
case NODE_BEGIN:
+ case NODE_BLOCK:
+ case NODE_ONCE:
CHECK(COMPILE(ret, "case in literal", node)); // (1)
if (in_single_pattern) {
ADD_INSN1(ret, line_node, dupn, INT2FIX(2));
@@ -7266,7 +7656,7 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
INIT_ANCHOR(body_seq);
INIT_ANCHOR(cond_seq);
- branches = decl_branch_base(iseq, node, "case");
+ branches = decl_branch_base(iseq, PTR2NUM(node), nd_code_loc(node), "case");
node = RNODE_CASE3(node)->nd_body;
EXPECT_NODE("NODE_CASE3", node, NODE_IN, COMPILE_NG);
@@ -7300,13 +7690,17 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
l1 = NEW_LABEL(line);
ADD_LABEL(body_seq, l1);
ADD_INSN1(body_seq, line_node, adjuststack, INT2FIX(single_pattern ? 6 : 2));
+
+ const NODE *const coverage_node = RNODE_IN(node)->nd_body ? RNODE_IN(node)->nd_body : node;
add_trace_branch_coverage(
iseq,
body_seq,
- RNODE_IN(node)->nd_body ? RNODE_IN(node)->nd_body : node,
+ nd_code_loc(coverage_node),
+ nd_node_id(coverage_node),
branch_id++,
"in",
branches);
+
CHECK(COMPILE_(body_seq, "in body", RNODE_IN(node)->nd_body, popped));
ADD_INSNL(body_seq, line_node, jump, endlabel);
@@ -7338,7 +7732,7 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
ADD_LABEL(cond_seq, elselabel);
ADD_INSN(cond_seq, line_node, pop);
ADD_INSN(cond_seq, line_node, pop); /* discard cached #deconstruct value */
- add_trace_branch_coverage(iseq, cond_seq, node, branch_id, "else", branches);
+ add_trace_branch_coverage(iseq, cond_seq, nd_code_loc(node), nd_node_id(node), branch_id, "else", branches);
CHECK(COMPILE_(cond_seq, "else", node, popped));
ADD_INSNL(cond_seq, line_node, jump, endlabel);
ADD_INSN(cond_seq, line_node, putnil);
@@ -7349,7 +7743,7 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
else {
debugs("== else (implicit)\n");
ADD_LABEL(cond_seq, elselabel);
- add_trace_branch_coverage(iseq, cond_seq, orig_node, branch_id, "else", branches);
+ add_trace_branch_coverage(iseq, cond_seq, nd_code_loc(orig_node), nd_node_id(orig_node), branch_id, "else", branches);
ADD_INSN1(cond_seq, orig_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
if (single_pattern) {
@@ -7466,14 +7860,18 @@ compile_loop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
if (tmp_label) ADD_LABEL(ret, tmp_label);
ADD_LABEL(ret, redo_label);
- branches = decl_branch_base(iseq, node, type == NODE_WHILE ? "while" : "until");
+ branches = decl_branch_base(iseq, PTR2NUM(node), nd_code_loc(node), type == NODE_WHILE ? "while" : "until");
+
+ const NODE *const coverage_node = RNODE_WHILE(node)->nd_body ? RNODE_WHILE(node)->nd_body : node;
add_trace_branch_coverage(
iseq,
ret,
- RNODE_WHILE(node)->nd_body ? RNODE_WHILE(node)->nd_body : node,
+ nd_code_loc(coverage_node),
+ nd_node_id(coverage_node),
0,
"body",
branches);
+
CHECK(COMPILE_POPPED(ret, "while body", RNODE_WHILE(node)->nd_body));
ADD_LABEL(ret, next_label); /* next */
@@ -7924,9 +8322,7 @@ compile_resbody(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
if (nd_type(RNODE_RESBODY(resq)->nd_body) == NODE_BEGIN && RNODE_BEGIN(RNODE_RESBODY(resq)->nd_body)->nd_body == NULL) {
// empty body
- int lineno = nd_line(RNODE_RESBODY(resq)->nd_body);
- NODE dummy_line_node = generate_dummy_line_node(lineno, -1);
- ADD_INSN(ret, &dummy_line_node, putnil);
+ ADD_SYNTHETIC_INSN(ret, nd_line(RNODE_RESBODY(resq)->nd_body), -1, putnil);
}
else {
CHECK(COMPILE(ret, "resbody body", RNODE_RESBODY(resq)->nd_body));
@@ -7937,7 +8333,7 @@ compile_resbody(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
}
ADD_INSN(ret, line_node, leave);
ADD_LABEL(ret, label_miss);
- resq = RNODE_RESBODY(resq)->nd_head;
+ resq = RNODE_RESBODY(resq)->nd_next;
}
return COMPILE_OK;
}
@@ -7945,7 +8341,7 @@ compile_resbody(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
static int
compile_ensure(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped)
{
- const int line = nd_line(node);
+ const int line = nd_line(RNODE_ENSURE(node)->nd_ensr);
const NODE *line_node = node;
DECL_ANCHOR(ensr);
const rb_iseq_t *ensure = NEW_CHILD_ISEQ(RNODE_ENSURE(node)->nd_ensr,
@@ -8083,11 +8479,11 @@ qcall_branch_start(rb_iseq_t *iseq, LINK_ANCHOR *const recv, VALUE *branches, co
LABEL *else_label = NEW_LABEL(nd_line(line_node));
VALUE br = 0;
- br = decl_branch_base(iseq, node, "&.");
+ br = decl_branch_base(iseq, PTR2NUM(node), nd_code_loc(node), "&.");
*branches = br;
ADD_INSN(recv, line_node, dup);
ADD_INSNL(recv, line_node, branchnil, else_label);
- add_trace_branch_coverage(iseq, recv, node, 0, "then", br);
+ add_trace_branch_coverage(iseq, recv, nd_code_loc(node), nd_node_id(node), 0, "then", br);
return else_label;
}
@@ -8099,7 +8495,7 @@ qcall_branch_end(rb_iseq_t *iseq, LINK_ANCHOR *const ret, LABEL *else_label, VAL
end_label = NEW_LABEL(nd_line(line_node));
ADD_INSNL(ret, line_node, jump, end_label);
ADD_LABEL(ret, else_label);
- add_trace_branch_coverage(iseq, ret, node, 1, "else", branches);
+ add_trace_branch_coverage(iseq, ret, nd_code_loc(node), nd_node_id(node), 1, "else", branches);
ADD_LABEL(ret, end_label);
}
@@ -8109,12 +8505,13 @@ compile_call_precheck_freeze(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE
/* optimization shortcut
* "literal".freeze -> opt_str_freeze("literal")
*/
- if (get_nd_recv(node) && nd_type_p(get_nd_recv(node), NODE_STR) &&
+ if (get_nd_recv(node) &&
+ (nd_type_p(get_nd_recv(node), NODE_STR) || nd_type_p(get_nd_recv(node), NODE_FILE)) &&
(get_node_call_nd_mid(node) == idFreeze || get_node_call_nd_mid(node) == idUMinus) &&
get_nd_args(node) == NULL &&
ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
- VALUE str = rb_fstring(RNODE_STR(get_nd_recv(node))->nd_lit);
+ VALUE str = get_string_value(get_nd_recv(node));
if (get_node_call_nd_mid(node) == idUMinus) {
ADD_INSN2(ret, line_node, opt_str_uminus, str,
new_callinfo(iseq, idUMinus, 0, 0, NULL, FALSE));
@@ -8134,11 +8531,11 @@ compile_call_precheck_freeze(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE
*/
if (get_node_call_nd_mid(node) == idAREF && !private_recv_p(node) && get_nd_args(node) &&
nd_type_p(get_nd_args(node), NODE_LIST) && RNODE_LIST(get_nd_args(node))->as.nd_alen == 1 &&
- nd_type_p(RNODE_LIST(get_nd_args(node))->nd_head, NODE_STR) &&
+ (nd_type_p(RNODE_LIST(get_nd_args(node))->nd_head, NODE_STR) || nd_type_p(RNODE_LIST(get_nd_args(node))->nd_head, NODE_FILE)) &&
ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
- !ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal &&
+ !frozen_string_literal_p(iseq) &&
ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
- VALUE str = rb_fstring(RNODE_STR(RNODE_LIST(get_nd_args(node))->nd_head)->nd_lit);
+ VALUE str = get_string_value(RNODE_LIST(get_nd_args(node))->nd_head);
CHECK(COMPILE(ret, "recv", get_nd_recv(node)));
ADD_INSN2(ret, line_node, opt_aref_with, str,
new_callinfo(iseq, idAREF, 1, 0, NULL, FALSE));
@@ -8281,17 +8678,25 @@ compile_builtin_attr(rb_iseq_t *iseq, const NODE *node)
node = RNODE_LIST(node)->nd_head;
if (!node) goto no_arg;
- if (!nd_type_p(node, NODE_LIT)) goto bad_arg;
+ switch (nd_type(node)) {
+ case NODE_SYM:
+ symbol = rb_node_sym_string_val(node);
+ break;
+ default:
+ goto bad_arg;
+ }
- symbol = RNODE_LIT(node)->nd_lit;
if (!SYMBOL_P(symbol)) goto non_symbol_arg;
string = rb_sym_to_s(symbol);
if (strcmp(RSTRING_PTR(string), "leaf") == 0) {
ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_LEAF;
}
- else if (strcmp(RSTRING_PTR(string), "no_gc") == 0) {
- ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_NO_GC;
+ else if (strcmp(RSTRING_PTR(string), "inline_block") == 0) {
+ ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_INLINE_BLOCK;
+ }
+ else if (strcmp(RSTRING_PTR(string), "use_block") == 0) {
+ iseq_set_use_block(iseq);
}
else {
goto unknown_arg;
@@ -8315,13 +8720,20 @@ compile_builtin_attr(rb_iseq_t *iseq, const NODE *node)
static int
compile_builtin_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, const NODE *line_node, int popped)
{
+ VALUE name;
+
if (!node) goto no_arg;
if (!nd_type_p(node, NODE_LIST)) goto bad_arg;
if (RNODE_LIST(node)->nd_next) goto too_many_arg;
node = RNODE_LIST(node)->nd_head;
if (!node) goto no_arg;
- if (!nd_type_p(node, NODE_LIT)) goto bad_arg;
- VALUE name = RNODE_LIT(node)->nd_lit;
+ switch (nd_type(node)) {
+ case NODE_SYM:
+ name = rb_node_sym_string_val(node);
+ break;
+ default:
+ goto bad_arg;
+ }
if (!SYMBOL_P(name)) goto non_symbol_arg;
if (!popped) {
compile_lvar(iseq, ret, line_node, SYM2ID(name));
@@ -8389,18 +8801,14 @@ compile_builtin_mandatory_only_method(rb_iseq_t *iseq, const NODE *node, const N
scope_node.nd_body = mandatory_node(iseq, node);
scope_node.nd_args = &args_node;
- rb_ast_body_t ast = {
- .root = RNODE(&scope_node),
- .frozen_string_literal = -1,
- .coverage_enabled = -1,
- .script_lines = ISEQ_BODY(iseq)->variable.script_lines,
- };
+ VALUE ast_value = rb_ruby_ast_new(RNODE(&scope_node));
ISEQ_BODY(iseq)->mandatory_only_iseq =
- rb_iseq_new_with_opt(&ast, rb_iseq_base_label(iseq),
+ rb_iseq_new_with_opt(ast_value, rb_iseq_base_label(iseq),
rb_iseq_path(iseq), rb_iseq_realpath(iseq),
nd_line(line_node), NULL, 0,
- ISEQ_TYPE_METHOD, ISEQ_COMPILE_DATA(iseq)->option);
+ ISEQ_TYPE_METHOD, ISEQ_COMPILE_DATA(iseq)->option,
+ ISEQ_BODY(iseq)->variable.script_lines);
ALLOCV_END(idtmp);
return COMPILE_OK;
@@ -8433,7 +8841,6 @@ compile_builtin_function_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NOD
}
else if (strcmp("cinit!", builtin_func) == 0) {
// ignore
- GET_VM()->builtin_inline_index++;
return COMPILE_OK;
}
else if (strcmp("attr!", builtin_func) == 0) {
@@ -8461,10 +8868,7 @@ compile_builtin_function_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NOD
return COMPILE_NG;
}
- if (GET_VM()->builtin_inline_index == INT_MAX) {
- rb_bug("builtin inline function index overflow:%s", builtin_func);
- }
- int inline_index = GET_VM()->builtin_inline_index++;
+ int inline_index = nd_line(node);
snprintf(inline_func, sizeof(inline_func), BUILTIN_INLINE_PREFIX "%d", inline_index);
builtin_func = inline_func;
args_node = NULL;
@@ -8561,20 +8965,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co
labels_table = st_init_numtable();
ISEQ_COMPILE_DATA(iseq)->labels_table = labels_table;
}
- if (nd_type_p(node->nd_args->nd_head, NODE_LIT) &&
- SYMBOL_P(node->nd_args->nd_head->nd_lit)) {
-
- label_name = node->nd_args->nd_head->nd_lit;
- if (!st_lookup(labels_table, (st_data_t)label_name, &data)) {
- label = NEW_LABEL(nd_line(line_node));
- label->position = nd_line(line_node);
- st_insert(labels_table, (st_data_t)label_name, (st_data_t)label);
- }
- else {
- label = (LABEL *)data;
- }
- }
- else {
+ {
COMPILE_ERROR(ERROR_ARGS "invalid goto/label format");
return COMPILE_NG;
}
@@ -8646,6 +9037,9 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co
flag |= VM_CALL_FCALL;
}
+ if ((flag & VM_CALL_ARGS_BLOCKARG) && (flag & VM_CALL_KW_SPLAT) && !(flag & VM_CALL_KW_SPLAT_MUT)) {
+ ADD_INSN(ret, line_node, splatkw);
+ }
ADD_SEND_R(ret, line_node, mid, argc, parent_block, INT2FIX(flag), keywords);
qcall_branch_end(iseq, ret, else_label, branches, node, line_node);
@@ -8663,7 +9057,6 @@ compile_op_asgn1(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
unsigned int flag = 0;
int asgnflag = 0;
ID id = RNODE_OP_ASGN1(node)->nd_mid;
- int boff = 0;
/*
* a[x] (op)= y
@@ -8697,16 +9090,14 @@ compile_op_asgn1(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
case NODE_ZLIST:
argc = INT2FIX(0);
break;
- case NODE_BLOCK_PASS:
- boff = 1;
- /* fall through */
default:
argc = setup_args(iseq, ret, RNODE_OP_ASGN1(node)->nd_index, &flag, NULL);
CHECK(!NIL_P(argc));
}
- ADD_INSN1(ret, node, dupn, FIXNUM_INC(argc, 1 + boff));
+ int dup_argn = FIX2INT(argc) + 1;
+ ADD_INSN1(ret, node, dupn, INT2FIX(dup_argn));
flag |= asgnflag;
- ADD_SEND_WITH_FLAG(ret, node, idAREF, argc, INT2FIX(flag));
+ ADD_SEND_R(ret, node, idAREF, argc, NULL, INT2FIX(flag & ~VM_CALL_ARGS_SPLAT_MUT), NULL);
if (id == idOROP || id == idANDOP) {
/* a[x] ||= y or a[x] &&= y
@@ -8731,62 +9122,61 @@ compile_op_asgn1(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
CHECK(COMPILE(ret, "NODE_OP_ASGN1 nd_rvalue: ", RNODE_OP_ASGN1(node)->nd_rvalue));
if (!popped) {
- ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 2+boff));
+ ADD_INSN1(ret, node, setn, INT2FIX(dup_argn+1));
}
if (flag & VM_CALL_ARGS_SPLAT) {
- ADD_INSN1(ret, node, newarray, INT2FIX(1));
- if (boff > 0) {
- ADD_INSN1(ret, node, dupn, INT2FIX(3));
+ if (!(flag & VM_CALL_ARGS_SPLAT_MUT)) {
ADD_INSN(ret, node, swap);
- ADD_INSN(ret, node, pop);
- }
- ADD_INSN(ret, node, concatarray);
- if (boff > 0) {
- ADD_INSN1(ret, node, setn, INT2FIX(3));
- ADD_INSN(ret, node, pop);
- ADD_INSN(ret, node, pop);
+ ADD_INSN1(ret, node, splatarray, Qtrue);
+ ADD_INSN(ret, node, swap);
+ flag |= VM_CALL_ARGS_SPLAT_MUT;
}
- ADD_SEND_WITH_FLAG(ret, node, idASET, argc, INT2FIX(flag));
+ ADD_INSN1(ret, node, pushtoarray, INT2FIX(1));
+ ADD_SEND_R(ret, node, idASET, argc, NULL, INT2FIX(flag), NULL);
}
else {
- if (boff > 0)
- ADD_INSN(ret, node, swap);
- ADD_SEND_WITH_FLAG(ret, node, idASET, FIXNUM_INC(argc, 1), INT2FIX(flag));
+ ADD_SEND_R(ret, node, idASET, FIXNUM_INC(argc, 1), NULL, INT2FIX(flag), NULL);
}
ADD_INSN(ret, node, pop);
ADD_INSNL(ret, node, jump, lfin);
ADD_LABEL(ret, label);
if (!popped) {
- ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 2+boff));
+ ADD_INSN1(ret, node, setn, INT2FIX(dup_argn+1));
}
- ADD_INSN1(ret, node, adjuststack, FIXNUM_INC(argc, 2+boff));
+ ADD_INSN1(ret, node, adjuststack, INT2FIX(dup_argn+1));
ADD_LABEL(ret, lfin);
}
else {
CHECK(COMPILE(ret, "NODE_OP_ASGN1 nd_rvalue: ", RNODE_OP_ASGN1(node)->nd_rvalue));
ADD_SEND(ret, node, id, INT2FIX(1));
if (!popped) {
- ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 2+boff));
+ ADD_INSN1(ret, node, setn, INT2FIX(dup_argn+1));
}
if (flag & VM_CALL_ARGS_SPLAT) {
- ADD_INSN1(ret, node, newarray, INT2FIX(1));
- if (boff > 0) {
- ADD_INSN1(ret, node, dupn, INT2FIX(3));
+ if (flag & VM_CALL_KW_SPLAT) {
+ ADD_INSN1(ret, node, topn, INT2FIX(2));
+ if (!(flag & VM_CALL_ARGS_SPLAT_MUT)) {
+ ADD_INSN1(ret, node, splatarray, Qtrue);
+ flag |= VM_CALL_ARGS_SPLAT_MUT;
+ }
ADD_INSN(ret, node, swap);
+ ADD_INSN1(ret, node, pushtoarray, INT2FIX(1));
+ ADD_INSN1(ret, node, setn, INT2FIX(2));
ADD_INSN(ret, node, pop);
}
- ADD_INSN(ret, node, concatarray);
- if (boff > 0) {
- ADD_INSN1(ret, node, setn, INT2FIX(3));
- ADD_INSN(ret, node, pop);
- ADD_INSN(ret, node, pop);
+ else {
+ if (!(flag & VM_CALL_ARGS_SPLAT_MUT)) {
+ ADD_INSN(ret, node, swap);
+ ADD_INSN1(ret, node, splatarray, Qtrue);
+ ADD_INSN(ret, node, swap);
+ flag |= VM_CALL_ARGS_SPLAT_MUT;
+ }
+ ADD_INSN1(ret, node, pushtoarray, INT2FIX(1));
}
- ADD_SEND_WITH_FLAG(ret, node, idASET, argc, INT2FIX(flag));
+ ADD_SEND_R(ret, node, idASET, argc, NULL, INT2FIX(flag), NULL);
}
else {
- if (boff > 0)
- ADD_INSN(ret, node, swap);
- ADD_SEND_WITH_FLAG(ret, node, idASET, FIXNUM_INC(argc, 1), INT2FIX(flag));
+ ADD_SEND_R(ret, node, idASET, FIXNUM_INC(argc, 1), NULL, INT2FIX(flag), NULL);
}
ADD_INSN(ret, node, pop);
}
@@ -8913,6 +9303,8 @@ compile_op_asgn2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
return COMPILE_OK;
}
+static int compile_shareable_constant_value(rb_iseq_t *iseq, LINK_ANCHOR *ret, enum rb_parser_shareability shareable, const NODE *lhs, const NODE *value);
+
static int
compile_op_cdecl(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped)
{
@@ -8956,7 +9348,7 @@ compile_op_cdecl(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
/* cref [obj] */
if (!popped) ADD_INSN(ret, node, pop); /* cref */
if (lassign) ADD_LABEL(ret, lassign);
- CHECK(COMPILE(ret, "NODE_OP_CDECL#nd_value", RNODE_OP_CDECL(node)->nd_value));
+ CHECK(compile_shareable_constant_value(iseq, ret, RNODE_OP_CDECL(node)->shareability, RNODE_OP_CDECL(node)->nd_head, RNODE_OP_CDECL(node)->nd_value));
/* cref value */
if (popped)
ADD_INSN1(ret, node, topn, INT2FIX(1)); /* cref value cref */
@@ -8970,7 +9362,7 @@ compile_op_cdecl(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
ADD_INSN(ret, node, pop); /* [value] */
}
else {
- CHECK(COMPILE(ret, "NODE_OP_CDECL#nd_value", RNODE_OP_CDECL(node)->nd_value));
+ CHECK(compile_shareable_constant_value(iseq, ret, RNODE_OP_CDECL(node)->shareability, RNODE_OP_CDECL(node)->nd_head, RNODE_OP_CDECL(node)->nd_value));
/* cref obj value */
ADD_CALL(ret, node, RNODE_OP_CDECL(node)->nd_aid, INT2FIX(1));
/* cref value */
@@ -9038,13 +9430,22 @@ compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
unsigned int flag = 0;
struct rb_callinfo_kwarg *keywords = NULL;
const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(iseq)->current_block;
+ int use_block = 1;
INIT_ANCHOR(args);
ISEQ_COMPILE_DATA(iseq)->current_block = NULL;
+
if (type == NODE_SUPER) {
VALUE vargc = setup_args(iseq, args, RNODE_SUPER(node)->nd_args, &flag, &keywords);
CHECK(!NIL_P(vargc));
argc = FIX2INT(vargc);
+ if ((flag & VM_CALL_ARGS_BLOCKARG) && (flag & VM_CALL_KW_SPLAT) && !(flag & VM_CALL_KW_SPLAT_MUT)) {
+ ADD_INSN(args, node, splatkw);
+ }
+
+ if (flag & VM_CALL_ARGS_BLOCKARG) {
+ use_block = 0;
+ }
}
else {
/* NODE_ZSUPER */
@@ -9076,7 +9477,7 @@ compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
/* rest argument */
int idx = local_body->local_table_size - local_body->param.rest_start;
ADD_GETLOCAL(args, node, idx, lvar_level);
- ADD_INSN1(args, node, splatarray, Qfalse);
+ ADD_INSN1(args, node, splatarray, RBOOL(local_body->param.flags.has_post));
argc = local_body->param.rest_start + 1;
flag |= VM_CALL_ARGS_SPLAT;
@@ -9092,8 +9493,8 @@ compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
int idx = local_body->local_table_size - (post_start + j);
ADD_GETLOCAL(args, node, idx, lvar_level);
}
- ADD_INSN1(args, node, newarray, INT2FIX(j));
- ADD_INSN (args, node, concatarray);
+ ADD_INSN1(args, node, pushtoarray, INT2FIX(j));
+ flag |= VM_CALL_ARGS_SPLAT_MUT;
/* argc is settled at above */
}
else {
@@ -9115,14 +9516,11 @@ compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
if (local_body->param.flags.has_kwrest) {
int idx = local_body->local_table_size - local_kwd->rest_start;
ADD_GETLOCAL(args, node, idx, lvar_level);
- if (local_kwd->num > 0) {
- ADD_SEND (args, node, rb_intern("dup"), INT2FIX(0));
- flag |= VM_CALL_KW_SPLAT_MUT;
- }
+ RUBY_ASSERT(local_kwd->num > 0);
+ ADD_SEND (args, node, rb_intern("dup"), INT2FIX(0));
}
else {
ADD_INSN1(args, node, newhash, INT2FIX(0));
- flag |= VM_CALL_KW_SPLAT_MUT;
}
for (i = 0; i < local_kwd->num; ++i) {
ID id = local_kwd->table[i];
@@ -9131,16 +9529,20 @@ compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
ADD_GETLOCAL(args, node, idx, lvar_level);
}
ADD_SEND(args, node, id_core_hash_merge_ptr, INT2FIX(i * 2 + 1));
- flag |= VM_CALL_KW_SPLAT;
+ flag |= VM_CALL_KW_SPLAT| VM_CALL_KW_SPLAT_MUT;
}
else if (local_body->param.flags.has_kwrest) {
int idx = local_body->local_table_size - local_kwd->rest_start;
ADD_GETLOCAL(args, node, idx, lvar_level);
argc++;
- flag |= VM_CALL_KW_SPLAT | VM_CALL_KW_SPLAT_MUT;
+ flag |= VM_CALL_KW_SPLAT;
}
}
+ if (use_block && parent_block == NULL) {
+ iseq_set_use_block(ISEQ_BODY(iseq)->local_iseq);
+ }
+
flag |= VM_CALL_SUPER | VM_CALL_FCALL;
if (type == NODE_ZSUPER) flag |= VM_CALL_ZSUPER;
ADD_INSN(ret, node, putself);
@@ -9184,6 +9586,7 @@ compile_yield(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
ADD_SEQ(ret, args);
ADD_INSN1(ret, node, invokeblock, new_callinfo(iseq, 0, FIX2INT(argc), flag, keywords, FALSE));
+ iseq_set_use_block(ISEQ_BODY(iseq)->local_iseq);
if (popped) {
ADD_INSN(ret, node, pop);
@@ -9209,7 +9612,7 @@ compile_match(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
INIT_ANCHOR(val);
switch ((int)type) {
case NODE_MATCH:
- ADD_INSN1(recv, node, putobject, RNODE_MATCH(node)->nd_lit);
+ ADD_INSN1(recv, node, putobject, rb_node_regx_string_val(node));
ADD_INSN2(val, node, getspecial, INT2FIX(0),
INT2FIX(0));
break;
@@ -9312,8 +9715,8 @@ compile_dots(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
if (optimizable_range_item_p(b) && optimizable_range_item_p(e)) {
if (!popped) {
- VALUE bv = nd_type_p(b, NODE_LIT) ? RNODE_LIT(b)->nd_lit : Qnil;
- VALUE ev = nd_type_p(e, NODE_LIT) ? RNODE_LIT(e)->nd_lit : Qnil;
+ VALUE bv = optimized_range_item(b);
+ VALUE ev = optimized_range_item(e);
VALUE val = rb_range_new(bv, ev, excl);
ADD_INSN1(ret, node, putobject, val);
RB_OBJ_WRITTEN(iseq, Qundef, val);
@@ -9369,7 +9772,13 @@ compile_kw_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
COMPILE_ERROR(ERROR_ARGS "unreachable");
return COMPILE_NG;
}
- else if (nd_type_p(default_value, NODE_LIT) ||
+ else if (nd_type_p(default_value, NODE_SYM) ||
+ nd_type_p(default_value, NODE_REGX) ||
+ nd_type_p(default_value, NODE_LINE) ||
+ nd_type_p(default_value, NODE_INTEGER) ||
+ nd_type_p(default_value, NODE_FLOAT) ||
+ nd_type_p(default_value, NODE_RATIONAL) ||
+ nd_type_p(default_value, NODE_IMAGINARY) ||
nd_type_p(default_value, NODE_NIL) ||
nd_type_p(default_value, NODE_TRUE) ||
nd_type_p(default_value, NODE_FALSE)) {
@@ -9408,12 +9817,12 @@ compile_attrasgn(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
*/
if (mid == idASET && !private_recv_p(node) && RNODE_ATTRASGN(node)->nd_args &&
nd_type_p(RNODE_ATTRASGN(node)->nd_args, NODE_LIST) && RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->as.nd_alen == 2 &&
- nd_type_p(RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->nd_head, NODE_STR) &&
+ (nd_type_p(RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->nd_head, NODE_STR) || nd_type_p(RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->nd_head, NODE_FILE)) &&
ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
- !ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal &&
+ !frozen_string_literal_p(iseq) &&
ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction)
{
- VALUE str = rb_fstring(RNODE_STR(RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->nd_head)->nd_lit);
+ VALUE str = get_string_value(RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->nd_head);
CHECK(COMPILE(ret, "recv", RNODE_ATTRASGN(node)->nd_recv));
CHECK(COMPILE(ret, "value", RNODE_LIST(RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->nd_next)->nd_head));
if (!popped) {
@@ -9449,16 +9858,7 @@ compile_attrasgn(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
ADD_SEQ(ret, recv);
ADD_SEQ(ret, args);
- if (flag & VM_CALL_ARGS_BLOCKARG) {
- ADD_INSN1(ret, node, topn, INT2FIX(1));
- if (flag & VM_CALL_ARGS_SPLAT) {
- ADD_INSN1(ret, node, putobject, INT2FIX(-1));
- ADD_SEND_WITH_FLAG(ret, node, idAREF, INT2FIX(1), INT2FIX(asgnflag));
- }
- ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 3));
- ADD_INSN (ret, node, pop);
- }
- else if (flag & VM_CALL_ARGS_SPLAT) {
+ if (flag & VM_CALL_ARGS_SPLAT) {
ADD_INSN(ret, node, dup);
ADD_INSN1(ret, node, putobject, INT2FIX(-1));
ADD_SEND_WITH_FLAG(ret, node, idAREF, INT2FIX(1), INT2FIX(asgnflag));
@@ -9479,6 +9879,367 @@ compile_attrasgn(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
return COMPILE_OK;
}
+static int
+compile_make_shareable_node(rb_iseq_t *iseq, LINK_ANCHOR *ret, LINK_ANCHOR *sub, const NODE *value, bool copy)
+{
+ ADD_INSN1(ret, value, putobject, rb_mRubyVMFrozenCore);
+ ADD_SEQ(ret, sub);
+
+ if (copy) {
+ /*
+ * NEW_CALL(fcore, rb_intern("make_shareable_copy"),
+ * NEW_LIST(value, loc), loc);
+ */
+ ADD_SEND_WITH_FLAG(ret, value, rb_intern("make_shareable_copy"), INT2FIX(1), INT2FIX(VM_CALL_ARGS_SIMPLE));
+ }
+ else {
+ /*
+ * NEW_CALL(fcore, rb_intern("make_shareable"),
+ * NEW_LIST(value, loc), loc);
+ */
+ ADD_SEND_WITH_FLAG(ret, value, rb_intern("make_shareable"), INT2FIX(1), INT2FIX(VM_CALL_ARGS_SIMPLE));
+ }
+
+ return COMPILE_OK;
+}
+
+static VALUE
+node_const_decl_val(const NODE *node)
+{
+ VALUE path;
+ switch (nd_type(node)) {
+ case NODE_CDECL:
+ if (RNODE_CDECL(node)->nd_vid) {
+ path = rb_id2str(RNODE_CDECL(node)->nd_vid);
+ goto end;
+ }
+ else {
+ node = RNODE_CDECL(node)->nd_else;
+ }
+ break;
+ case NODE_COLON2:
+ break;
+ case NODE_COLON3:
+ // ::Const
+ path = rb_str_new_cstr("::");
+ rb_str_append(path, rb_id2str(RNODE_COLON3(node)->nd_mid));
+ goto end;
+ default:
+ rb_bug("unexpected node: %s", ruby_node_name(nd_type(node)));
+ UNREACHABLE_RETURN(0);
+ }
+
+ path = rb_ary_new();
+ if (node) {
+ for (; node && nd_type_p(node, NODE_COLON2); node = RNODE_COLON2(node)->nd_head) {
+ rb_ary_push(path, rb_id2str(RNODE_COLON2(node)->nd_mid));
+ }
+ if (node && nd_type_p(node, NODE_CONST)) {
+ // Const::Name
+ rb_ary_push(path, rb_id2str(RNODE_CONST(node)->nd_vid));
+ }
+ else if (node && nd_type_p(node, NODE_COLON3)) {
+ // ::Const::Name
+ rb_ary_push(path, rb_id2str(RNODE_COLON3(node)->nd_mid));
+ rb_ary_push(path, rb_str_new(0, 0));
+ }
+ else {
+ // expression::Name
+ rb_ary_push(path, rb_str_new_cstr("..."));
+ }
+ path = rb_ary_join(rb_ary_reverse(path), rb_str_new_cstr("::"));
+ }
+ end:
+ path = rb_fstring(path);
+ return path;
+}
+
+static VALUE
+const_decl_path(NODE *dest)
+{
+ VALUE path = Qnil;
+ if (!nd_type_p(dest, NODE_CALL)) {
+ path = node_const_decl_val(dest);
+ }
+ return path;
+}
+
+static int
+compile_ensure_shareable_node(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *dest, const NODE *value)
+{
+ /*
+ *. RubyVM::FrozenCore.ensure_shareable(value, const_decl_path(dest))
+ */
+ VALUE path = const_decl_path(dest);
+ ADD_INSN1(ret, value, putobject, rb_mRubyVMFrozenCore);
+ CHECK(COMPILE(ret, "compile_ensure_shareable_node", value));
+ ADD_INSN1(ret, value, putobject, path);
+ RB_OBJ_WRITTEN(iseq, Qundef, path);
+ ADD_SEND_WITH_FLAG(ret, value, rb_intern("ensure_shareable"), INT2FIX(2), INT2FIX(VM_CALL_ARGS_SIMPLE));
+
+ return COMPILE_OK;
+}
+
+#ifndef SHAREABLE_BARE_EXPRESSION
+#define SHAREABLE_BARE_EXPRESSION 1
+#endif
+
+static int
+compile_shareable_literal_constant(rb_iseq_t *iseq, LINK_ANCHOR *ret, enum rb_parser_shareability shareable, NODE *dest, const NODE *node, size_t level, VALUE *value_p, int *shareable_literal_p)
+{
+# define compile_shareable_literal_constant_next(node, anchor, value_p, shareable_literal_p) \
+ compile_shareable_literal_constant(iseq, anchor, shareable, dest, node, level+1, value_p, shareable_literal_p)
+ VALUE lit = Qnil;
+ DECL_ANCHOR(anchor);
+
+ enum node_type type = nd_type(node);
+ switch (type) {
+ case NODE_TRUE:
+ *value_p = Qtrue;
+ goto compile;
+ case NODE_FALSE:
+ *value_p = Qfalse;
+ goto compile;
+ case NODE_NIL:
+ *value_p = Qnil;
+ goto compile;
+ case NODE_SYM:
+ *value_p = rb_node_sym_string_val(node);
+ goto compile;
+ case NODE_REGX:
+ *value_p = rb_node_regx_string_val(node);
+ goto compile;
+ case NODE_LINE:
+ *value_p = rb_node_line_lineno_val(node);
+ goto compile;
+ case NODE_INTEGER:
+ *value_p = rb_node_integer_literal_val(node);
+ goto compile;
+ case NODE_FLOAT:
+ *value_p = rb_node_float_literal_val(node);
+ goto compile;
+ case NODE_RATIONAL:
+ *value_p = rb_node_rational_literal_val(node);
+ goto compile;
+ case NODE_IMAGINARY:
+ *value_p = rb_node_imaginary_literal_val(node);
+ goto compile;
+ case NODE_ENCODING:
+ *value_p = rb_node_encoding_val(node);
+
+ compile:
+ CHECK(COMPILE(ret, "shareable_literal_constant", node));
+ *shareable_literal_p = 1;
+ return COMPILE_OK;
+
+ case NODE_DSTR:
+ CHECK(COMPILE(ret, "shareable_literal_constant", node));
+ if (shareable == rb_parser_shareable_literal) {
+ /*
+ * NEW_CALL(node, idUMinus, 0, loc);
+ *
+ * -"#{var}"
+ */
+ ADD_SEND_WITH_FLAG(ret, node, idUMinus, INT2FIX(0), INT2FIX(VM_CALL_ARGS_SIMPLE));
+ }
+ *value_p = Qundef;
+ *shareable_literal_p = 1;
+ return COMPILE_OK;
+
+ case NODE_STR:{
+ VALUE lit = rb_node_str_string_val(node);
+ ADD_INSN1(ret, node, putobject, lit);
+ RB_OBJ_WRITTEN(iseq, Qundef, lit);
+ *value_p = lit;
+ *shareable_literal_p = 1;
+
+ return COMPILE_OK;
+ }
+
+ case NODE_FILE:{
+ VALUE lit = rb_node_file_path_val(node);
+ ADD_INSN1(ret, node, putobject, lit);
+ RB_OBJ_WRITTEN(iseq, Qundef, lit);
+ *value_p = lit;
+ *shareable_literal_p = 1;
+
+ return COMPILE_OK;
+ }
+
+ case NODE_ZLIST:{
+ VALUE lit = rb_ary_new();
+ OBJ_FREEZE(lit);
+ ADD_INSN1(ret, node, putobject, lit);
+ RB_OBJ_WRITTEN(iseq, Qundef, lit);
+ *value_p = lit;
+ *shareable_literal_p = 1;
+
+ return COMPILE_OK;
+ }
+
+ case NODE_LIST:{
+ INIT_ANCHOR(anchor);
+ lit = rb_ary_new();
+ for (NODE *n = (NODE *)node; n; n = RNODE_LIST(n)->nd_next) {
+ VALUE val;
+ int shareable_literal_p2;
+ NODE *elt = RNODE_LIST(n)->nd_head;
+ if (elt) {
+ CHECK(compile_shareable_literal_constant_next(elt, anchor, &val, &shareable_literal_p2));
+ if (shareable_literal_p2) {
+ /* noop */
+ }
+ else if (RTEST(lit)) {
+ rb_ary_clear(lit);
+ lit = Qfalse;
+ }
+ }
+ if (RTEST(lit)) {
+ if (!UNDEF_P(val)) {
+ rb_ary_push(lit, val);
+ }
+ else {
+ rb_ary_clear(lit);
+ lit = Qnil; /* make shareable at runtime */
+ }
+ }
+ }
+ break;
+ }
+ case NODE_HASH:{
+ if (!RNODE_HASH(node)->nd_brace) {
+ *value_p = Qundef;
+ *shareable_literal_p = 0;
+ return COMPILE_OK;
+ }
+
+ INIT_ANCHOR(anchor);
+ lit = rb_hash_new();
+ for (NODE *n = RNODE_HASH(node)->nd_head; n; n = RNODE_LIST(RNODE_LIST(n)->nd_next)->nd_next) {
+ VALUE key_val;
+ VALUE value_val;
+ int shareable_literal_p2;
+ NODE *key = RNODE_LIST(n)->nd_head;
+ NODE *val = RNODE_LIST(RNODE_LIST(n)->nd_next)->nd_head;
+ if (key) {
+ CHECK(compile_shareable_literal_constant_next(key, anchor, &key_val, &shareable_literal_p2));
+ if (shareable_literal_p2) {
+ /* noop */
+ }
+ else if (RTEST(lit)) {
+ rb_hash_clear(lit);
+ lit = Qfalse;
+ }
+ }
+ if (val) {
+ CHECK(compile_shareable_literal_constant_next(val, anchor, &value_val, &shareable_literal_p2));
+ if (shareable_literal_p2) {
+ /* noop */
+ }
+ else if (RTEST(lit)) {
+ rb_hash_clear(lit);
+ lit = Qfalse;
+ }
+ }
+ if (RTEST(lit)) {
+ if (!UNDEF_P(key_val) && !UNDEF_P(value_val)) {
+ rb_hash_aset(lit, key_val, value_val);
+ }
+ else {
+ rb_hash_clear(lit);
+ lit = Qnil; /* make shareable at runtime */
+ }
+ }
+ }
+ break;
+ }
+
+ default:
+ if (shareable == rb_parser_shareable_literal &&
+ (SHAREABLE_BARE_EXPRESSION || level > 0)) {
+ CHECK(compile_ensure_shareable_node(iseq, ret, dest, node));
+ *value_p = Qundef;
+ *shareable_literal_p = 1;
+ return COMPILE_OK;
+ }
+ CHECK(COMPILE(ret, "shareable_literal_constant", node));
+ *value_p = Qundef;
+ *shareable_literal_p = 0;
+ return COMPILE_OK;
+ }
+
+ /* Array or Hash */
+ if (!lit) {
+ if (nd_type(node) == NODE_LIST) {
+ ADD_INSN1(anchor, node, newarray, INT2FIX(RNODE_LIST(node)->as.nd_alen));
+ }
+ else if (nd_type(node) == NODE_HASH) {
+ int len = (int)RNODE_LIST(RNODE_HASH(node)->nd_head)->as.nd_alen;
+ ADD_INSN1(anchor, node, newhash, INT2FIX(len));
+ }
+ *value_p = Qundef;
+ *shareable_literal_p = 0;
+ ADD_SEQ(ret, anchor);
+ return COMPILE_OK;
+ }
+ if (NIL_P(lit)) {
+ // if shareable_literal, all elements should have been ensured
+ // as shareable
+ if (nd_type(node) == NODE_LIST) {
+ ADD_INSN1(anchor, node, newarray, INT2FIX(RNODE_LIST(node)->as.nd_alen));
+ }
+ else if (nd_type(node) == NODE_HASH) {
+ int len = (int)RNODE_LIST(RNODE_HASH(node)->nd_head)->as.nd_alen;
+ ADD_INSN1(anchor, node, newhash, INT2FIX(len));
+ }
+ CHECK(compile_make_shareable_node(iseq, ret, anchor, node, false));
+ *value_p = Qundef;
+ *shareable_literal_p = 1;
+ }
+ else {
+ VALUE val = rb_ractor_make_shareable(lit);
+ ADD_INSN1(ret, node, putobject, val);
+ RB_OBJ_WRITTEN(iseq, Qundef, val);
+ *value_p = val;
+ *shareable_literal_p = 1;
+ }
+
+ return COMPILE_OK;
+}
+
+static int
+compile_shareable_constant_value(rb_iseq_t *iseq, LINK_ANCHOR *ret, enum rb_parser_shareability shareable, const NODE *lhs, const NODE *value)
+{
+ int literal_p = 0;
+ VALUE val;
+ DECL_ANCHOR(anchor);
+ INIT_ANCHOR(anchor);
+
+ switch (shareable) {
+ case rb_parser_shareable_none:
+ CHECK(COMPILE(ret, "compile_shareable_constant_value", value));
+ return COMPILE_OK;
+
+ case rb_parser_shareable_literal:
+ CHECK(compile_shareable_literal_constant(iseq, anchor, shareable, (NODE *)lhs, value, 0, &val, &literal_p));
+ ADD_SEQ(ret, anchor);
+ return COMPILE_OK;
+
+ case rb_parser_shareable_copy:
+ case rb_parser_shareable_everything:
+ CHECK(compile_shareable_literal_constant(iseq, anchor, shareable, (NODE *)lhs, value, 0, &val, &literal_p));
+ if (!literal_p) {
+ CHECK(compile_make_shareable_node(iseq, ret, anchor, value, shareable == rb_parser_shareable_copy));
+ }
+ else {
+ ADD_SEQ(ret, anchor);
+ }
+ return COMPILE_OK;
+ default:
+ rb_bug("unexpected rb_parser_shareability: %d", shareable);
+ }
+}
+
static int iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped);
/**
compile each node
@@ -9495,8 +10256,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, const NODE *node, int poppe
int lineno = ISEQ_COMPILE_DATA(iseq)->last_line;
if (lineno == 0) lineno = FIX2INT(rb_iseq_first_lineno(iseq));
debugs("node: NODE_NIL(implicit)\n");
- NODE dummy_line_node = generate_dummy_line_node(lineno, -1);
- ADD_INSN(ret, &dummy_line_node, putnil);
+ ADD_SYNTHETIC_INSN(ret, lineno, -1, putnil);
}
return COMPILE_OK;
}
@@ -9662,7 +10422,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
}
case NODE_CDECL:{
if (RNODE_CDECL(node)->nd_vid) {
- CHECK(COMPILE(ret, "lvalue", RNODE_CDECL(node)->nd_value));
+ CHECK(compile_shareable_constant_value(iseq, ret, RNODE_CDECL(node)->shareability, node, RNODE_CDECL(node)->nd_value));
if (!popped) {
ADD_INSN(ret, node, dup);
@@ -9674,7 +10434,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
}
else {
compile_cpath(ret, iseq, RNODE_CDECL(node)->nd_else);
- CHECK(COMPILE(ret, "lvalue", RNODE_CDECL(node)->nd_value));
+ CHECK(compile_shareable_constant_value(iseq, ret, RNODE_CDECL(node)->shareability, node, RNODE_CDECL(node)->nd_value));
ADD_INSN(ret, node, swap);
if (!popped) {
@@ -9726,7 +10486,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
CHECK(compile_super(iseq, ret, node, popped, type));
break;
case NODE_LIST:{
- CHECK(compile_array(iseq, ret, node, popped) >= 0);
+ CHECK(compile_array(iseq, ret, node, popped, TRUE) >= 0);
break;
}
case NODE_ZLIST:{
@@ -9831,35 +10591,86 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
case NODE_MATCH3:
CHECK(compile_match(iseq, ret, node, popped, type));
break;
- case NODE_LIT:{
- debugp_param("lit", RNODE_LIT(node)->nd_lit);
+ case NODE_SYM:{
+ if (!popped) {
+ ADD_INSN1(ret, node, putobject, rb_node_sym_string_val(node));
+ }
+ break;
+ }
+ case NODE_LINE:{
+ if (!popped) {
+ ADD_INSN1(ret, node, putobject, rb_node_line_lineno_val(node));
+ }
+ break;
+ }
+ case NODE_ENCODING:{
+ if (!popped) {
+ ADD_INSN1(ret, node, putobject, rb_node_encoding_val(node));
+ }
+ break;
+ }
+ case NODE_INTEGER:{
+ VALUE lit = rb_node_integer_literal_val(node);
+ debugp_param("integer", lit);
+ if (!popped) {
+ ADD_INSN1(ret, node, putobject, lit);
+ RB_OBJ_WRITTEN(iseq, Qundef, lit);
+ }
+ break;
+ }
+ case NODE_FLOAT:{
+ VALUE lit = rb_node_float_literal_val(node);
+ debugp_param("float", lit);
+ if (!popped) {
+ ADD_INSN1(ret, node, putobject, lit);
+ RB_OBJ_WRITTEN(iseq, Qundef, lit);
+ }
+ break;
+ }
+ case NODE_RATIONAL:{
+ VALUE lit = rb_node_rational_literal_val(node);
+ debugp_param("rational", lit);
if (!popped) {
- ADD_INSN1(ret, node, putobject, RNODE_LIT(node)->nd_lit);
- RB_OBJ_WRITTEN(iseq, Qundef, RNODE_LIT(node)->nd_lit);
+ ADD_INSN1(ret, node, putobject, lit);
+ RB_OBJ_WRITTEN(iseq, Qundef, lit);
}
break;
}
+ case NODE_IMAGINARY:{
+ VALUE lit = rb_node_imaginary_literal_val(node);
+ debugp_param("imaginary", lit);
+ if (!popped) {
+ ADD_INSN1(ret, node, putobject, lit);
+ RB_OBJ_WRITTEN(iseq, Qundef, lit);
+ }
+ break;
+ }
+ case NODE_FILE:
case NODE_STR:{
- debugp_param("nd_lit", RNODE_STR(node)->nd_lit);
+ debugp_param("nd_lit", get_string_value(node));
if (!popped) {
- VALUE lit = RNODE_STR(node)->nd_lit;
- if (!ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal) {
- lit = rb_fstring(lit);
+ VALUE lit = get_string_value(node);
+ switch (ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal) {
+ case ISEQ_FROZEN_STRING_LITERAL_UNSET:
+ ADD_INSN1(ret, node, putchilledstring, lit);
+ RB_OBJ_WRITTEN(iseq, Qundef, lit);
+ break;
+ case ISEQ_FROZEN_STRING_LITERAL_DISABLED:
ADD_INSN1(ret, node, putstring, lit);
RB_OBJ_WRITTEN(iseq, Qundef, lit);
- }
- else {
+ break;
+ case ISEQ_FROZEN_STRING_LITERAL_ENABLED:
if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal || RTEST(ruby_debug)) {
VALUE debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq), INT2FIX(line));
lit = rb_str_dup(lit);
rb_ivar_set(lit, id_debug_created_info, rb_obj_freeze(debug_info));
lit = rb_str_freeze(lit);
}
- else {
- lit = rb_fstring(lit);
- }
ADD_INSN1(ret, node, putobject, lit);
RB_OBJ_WRITTEN(iseq, Qundef, lit);
+ break;
+ default:
+ rb_bug("invalid frozen_string_literal");
}
}
break;
@@ -9874,7 +10685,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
}
case NODE_XSTR:{
ADD_CALL_RECEIVER(ret, node);
- VALUE str = rb_fstring(RNODE_XSTR(node)->nd_lit);
+ VALUE str = rb_node_str_string_val(node);
ADD_INSN1(ret, node, putobject, str);
RB_OBJ_WRITTEN(iseq, Qundef, str);
ADD_CALL(ret, node, idBackquote, INT2FIX(1));
@@ -9897,14 +10708,17 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
case NODE_EVSTR:
CHECK(compile_evstr(iseq, ret, RNODE_EVSTR(node)->nd_body, popped));
break;
- case NODE_DREGX:{
- compile_dregx(iseq, ret, node);
-
- if (popped) {
- ADD_INSN(ret, node, pop);
+ case NODE_REGX:{
+ if (!popped) {
+ VALUE lit = rb_node_regx_string_val(node);
+ ADD_INSN1(ret, node, putobject, lit);
+ RB_OBJ_WRITTEN(iseq, Qundef, lit);
}
break;
}
+ case NODE_DREGX:
+ compile_dregx(iseq, ret, node, popped);
+ break;
case NODE_ONCE:{
int ic_index = body->ise_size++;
const rb_iseq_t *block_iseq;
@@ -9929,8 +10743,14 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
}
else {
CHECK(COMPILE(ret, "argscat head", RNODE_ARGSCAT(node)->nd_head));
- CHECK(COMPILE(ret, "argscat body", RNODE_ARGSCAT(node)->nd_body));
- ADD_INSN(ret, node, concatarray);
+ const NODE *body_node = RNODE_ARGSCAT(node)->nd_body;
+ if (nd_type_p(body_node, NODE_LIST)) {
+ CHECK(compile_array(iseq, ret, body_node, popped, FALSE) >= 0);
+ }
+ else {
+ CHECK(COMPILE(ret, "argscat body", body_node));
+ ADD_INSN(ret, node, concattoarray);
+ }
}
break;
}
@@ -9943,8 +10763,19 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
}
else {
CHECK(COMPILE(ret, "argspush head", RNODE_ARGSPUSH(node)->nd_head));
- CHECK(compile_array_1(iseq, ret, RNODE_ARGSPUSH(node)->nd_body));
- ADD_INSN(ret, node, concatarray);
+ const NODE *body_node = RNODE_ARGSPUSH(node)->nd_body;
+ if (keyword_node_p(body_node)) {
+ CHECK(COMPILE_(ret, "array element", body_node, FALSE));
+ ADD_INSN(ret, node, pushtoarraykwsplat);
+ }
+ else if (static_literal_node_p(body_node, iseq, false)) {
+ ADD_INSN1(ret, body_node, putobject, static_literal_value(body_node, iseq));
+ ADD_INSN1(ret, node, pushtoarray, INT2FIX(1));
+ }
+ else {
+ CHECK(COMPILE_(ret, "array element", body_node, FALSE));
+ ADD_INSN1(ret, node, pushtoarray, INT2FIX(1));
+ }
}
break;
}
@@ -10355,7 +11186,7 @@ dump_disasm_list_with_cursor(const LINK_ELEMENT *link, const LINK_ELEMENT *curr,
case ISEQ_ELEMENT_LABEL:
{
lobj = (LABEL *)link;
- printf(LABEL_FORMAT" [sp: %d]%s\n", lobj->label_no, lobj->sp,
+ printf(LABEL_FORMAT" [sp: %d, unremovable: %d, refcnt: %d]%s\n", lobj->label_no, lobj->sp, lobj->unremovable, lobj->refcnt,
dest == lobj ? " <---" : "");
break;
}
@@ -10587,7 +11418,7 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor,
{
/* TODO: body should be frozen */
long i, len = RARRAY_LEN(body);
- struct st_table *labels_table = DATA_PTR(labels_wrapper);
+ struct st_table *labels_table = RTYPEDDATA_DATA(labels_wrapper);
int j;
int line_no = 0, node_id = -1, insn_idx = 0;
int ret = COMPILE_OK;
@@ -10647,9 +11478,8 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor,
argv = compile_data_calloc2(iseq, sizeof(VALUE), argc);
// add element before operand setup to make GC root
- NODE dummy_line_node = generate_dummy_line_node(line_no, node_id);
ADD_ELEM(anchor,
- (LINK_ELEMENT*)new_insn_core(iseq, &dummy_line_node,
+ (LINK_ELEMENT*)new_insn_core(iseq, line_no, node_id,
(enum ruby_vminsn_type)insn_id, argc, argv));
for (j=0; j<argc; j++) {
@@ -10757,9 +11587,8 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor,
}
}
else {
- NODE dummy_line_node = generate_dummy_line_node(line_no, node_id);
ADD_ELEM(anchor,
- (LINK_ELEMENT*)new_insn_core(iseq, &dummy_line_node,
+ (LINK_ELEMENT*)new_insn_core(iseq, line_no, node_id,
(enum ruby_vminsn_type)insn_id, argc, NULL));
}
}
@@ -10767,7 +11596,8 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor,
rb_raise(rb_eTypeError, "unexpected object for instruction");
}
}
- DATA_PTR(labels_wrapper) = 0;
+ RTYPEDDATA_DATA(labels_wrapper) = 0;
+ RB_GC_GUARD(labels_wrapper);
validate_labels(iseq, labels_table);
if (!ret) return ret;
return iseq_setup(iseq, anchor);
@@ -10861,13 +11691,13 @@ iseq_build_kw(rb_iseq_t *iseq, VALUE params, VALUE keywords)
}
static void
-iseq_insn_each_object_mark_and_move(VALUE *obj_ptr, VALUE _)
+iseq_insn_each_object_mark_and_pin(VALUE obj, VALUE _)
{
- rb_gc_mark_and_move(obj_ptr);
+ rb_gc_mark(obj);
}
void
-rb_iseq_mark_and_move_insn_storage(struct iseq_compile_data_storage *storage)
+rb_iseq_mark_and_pin_insn_storage(struct iseq_compile_data_storage *storage)
{
INSN *iobj = 0;
size_t size = sizeof(INSN);
@@ -10892,13 +11722,22 @@ rb_iseq_mark_and_move_insn_storage(struct iseq_compile_data_storage *storage)
iobj = (INSN *)&storage->buff[pos];
if (iobj->operands) {
- iseq_insn_each_markable_object(iobj, iseq_insn_each_object_mark_and_move, (VALUE)0);
+ iseq_insn_each_markable_object(iobj, iseq_insn_each_object_mark_and_pin, (VALUE)0);
}
pos += (int)size;
}
}
}
+static const rb_data_type_t labels_wrapper_type = {
+ .wrap_struct_name = "compiler/labels_wrapper",
+ .function = {
+ .dmark = (RUBY_DATA_FUNC)rb_mark_set,
+ .dfree = (RUBY_DATA_FUNC)st_free_table,
+ },
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
void
rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params,
VALUE exception, VALUE body)
@@ -10908,7 +11747,7 @@ rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params,
unsigned int arg_size, local_size, stack_max;
ID *tbl;
struct st_table *labels_table = st_init_numtable();
- VALUE labels_wrapper = Data_Wrap_Struct(0, rb_mark_set, st_free_table, labels_table);
+ VALUE labels_wrapper = TypedData_Wrap_Struct(0, &labels_wrapper_type, labels_table);
VALUE arg_opt_labels = rb_hash_aref(params, SYM(opt));
VALUE keywords = rb_hash_aref(params, SYM(keyword));
VALUE sym_arg_rest = ID2SYM(rb_intern_const("#arg_rest"));
@@ -10990,6 +11829,10 @@ rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params,
ISEQ_BODY(iseq)->param.flags.ambiguous_param0 = TRUE;
}
+ if (Qtrue == rb_hash_aref(params, SYM(use_block))) {
+ ISEQ_BODY(iseq)->param.flags.use_block = TRUE;
+ }
+
if (int_param(&i, params, SYM(kwrest))) {
struct rb_iseq_param_keyword *keyword = (struct rb_iseq_param_keyword *)ISEQ_BODY(iseq)->param.keyword;
if (keyword == NULL) {
@@ -11131,7 +11974,7 @@ struct ibf_load {
struct pinned_list {
long size;
- VALUE * buffer;
+ VALUE buffer[1];
};
static void
@@ -11146,25 +11989,14 @@ pinned_list_mark(void *ptr)
}
}
-static void
-pinned_list_free(void *ptr)
-{
- struct pinned_list *list = (struct pinned_list *)ptr;
- xfree(list->buffer);
- xfree(ptr);
-}
-
-static size_t
-pinned_list_memsize(const void *ptr)
-{
- struct pinned_list *list = (struct pinned_list *)ptr;
- return sizeof(struct pinned_list) + (list->size * sizeof(VALUE *));
-}
-
static const rb_data_type_t pinned_list_type = {
"pinned_list",
- {pinned_list_mark, pinned_list_free, pinned_list_memsize,},
- 0, 0, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
+ {
+ pinned_list_mark,
+ RUBY_DEFAULT_FREE,
+ NULL, // No external memory to report,
+ },
+ 0, 0, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_EMBEDDABLE
};
static VALUE
@@ -11198,13 +12030,10 @@ pinned_list_store(VALUE list, long offset, VALUE object)
static VALUE
pinned_list_new(long size)
{
- struct pinned_list * ptr;
- VALUE obj_list =
- TypedData_Make_Struct(0, struct pinned_list, &pinned_list_type, ptr);
-
- ptr->buffer = xcalloc(size, sizeof(VALUE));
+ size_t memsize = offsetof(struct pinned_list, buffer) + size * sizeof(VALUE);
+ VALUE obj_list = rb_data_typed_object_zalloc(0, memsize, &pinned_list_type);
+ struct pinned_list * ptr = RTYPEDDATA_GET_DATA(obj_list);
ptr->size = size;
-
return obj_list;
}
@@ -11353,6 +12182,10 @@ ibf_load_id(const struct ibf_load *load, const ID id_index)
return 0;
}
VALUE sym = ibf_load_object(load, id_index);
+ if (rb_integer_type_p(sym)) {
+ /* Load hidden local variables as indexes */
+ return NUM2ULONG(sym);
+ }
return rb_sym2id(sym);
}
@@ -11552,7 +12385,7 @@ ibf_dump_code(struct ibf_dump *dump, const rb_iseq_t *iseq)
ibf_dump_write_small_value(dump, wv);
skip_wv:;
}
- assert(insn_len(insn) == op_index+1);
+ RUBY_ASSERT(insn_len(insn) == op_index+1);
}
return offset;
@@ -11717,8 +12550,8 @@ ibf_load_code(const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t bytecod
}
}
- assert(code_index == iseq_size);
- assert(reading_pos == bytecode_offset + bytecode_size);
+ RUBY_ASSERT(code_index == iseq_size);
+ RUBY_ASSERT(reading_pos == bytecode_offset + bytecode_size);
return code;
}
@@ -11876,7 +12709,12 @@ ibf_dump_local_table(struct ibf_dump *dump, const rb_iseq_t *iseq)
int i;
for (i=0; i<size; i++) {
- table[i] = ibf_dump_id(dump, body->local_table[i]);
+ VALUE v = ibf_dump_id(dump, body->local_table[i]);
+ if (v == 0) {
+ /* Dump hidden local variables as indexes, so load_from_binary will work with them */
+ v = ibf_dump_object(dump, ULONG2NUM(body->local_table[i]));
+ }
+ table[i] = v;
}
IBF_W_ALIGN(ID);
@@ -12128,7 +12966,7 @@ ibf_load_outer_variables(const struct ibf_load * load, ibf_offset_t outer_variab
static ibf_offset_t
ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq)
{
- assert(dump->current_buffer == &dump->global_buffer);
+ RUBY_ASSERT(dump->current_buffer == &dump->global_buffer);
unsigned int *positions;
@@ -12187,7 +13025,10 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq)
(body->param.flags.has_block << 6) |
(body->param.flags.ambiguous_param0 << 7) |
(body->param.flags.accepts_no_kwarg << 8) |
- (body->param.flags.ruby2_keywords << 9);
+ (body->param.flags.ruby2_keywords << 9) |
+ (body->param.flags.anon_rest << 10) |
+ (body->param.flags.anon_kwrest << 11) |
+ (body->param.flags.use_block << 12);
#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
# define IBF_BODY_OFFSET(x) (x)
@@ -12238,6 +13079,7 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq)
ibf_dump_write_small_value(dump, body->ci_size);
ibf_dump_write_small_value(dump, body->stack_max);
ibf_dump_write_small_value(dump, body->builtin_attrs);
+ ibf_dump_write_small_value(dump, body->prism ? 1 : 0);
#undef IBF_BODY_OFFSET
@@ -12350,6 +13192,7 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
const unsigned int ci_size = (unsigned int)ibf_load_small_value(load, &reading_pos);
const unsigned int stack_max = (unsigned int)ibf_load_small_value(load, &reading_pos);
const unsigned int builtin_attrs = (unsigned int)ibf_load_small_value(load, &reading_pos);
+ const bool prism = (bool)ibf_load_small_value(load, &reading_pos);
// setup fname and dummy frame
VALUE path = ibf_load_object(load, location_pathobj_index);
@@ -12399,6 +13242,9 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
load_body->param.flags.ambiguous_param0 = (param_flags >> 7) & 1;
load_body->param.flags.accepts_no_kwarg = (param_flags >> 8) & 1;
load_body->param.flags.ruby2_keywords = (param_flags >> 9) & 1;
+ load_body->param.flags.anon_rest = (param_flags >> 10) & 1;
+ load_body->param.flags.anon_kwrest = (param_flags >> 11) & 1;
+ load_body->param.flags.use_block = (param_flags >> 12) & 1;
load_body->param.size = param_size;
load_body->param.lead_num = param_lead_num;
load_body->param.opt_num = param_opt_num;
@@ -12422,6 +13268,7 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
load_body->location.code_location.end_pos.lineno = location_code_location_end_pos_lineno;
load_body->location.code_location.end_pos.column = location_code_location_end_pos_column;
load_body->builtin_attrs = builtin_attrs;
+ load_body->prism = prism;
load_body->ivc_size = ivc_size;
load_body->icvarc_size = icvarc_size;
@@ -12706,7 +13553,7 @@ ibf_load_object_string(const struct ibf_load *load, const struct ibf_object_head
VALUE str;
if (header->frozen && !header->internal) {
- str = rb_enc_interned_str(ptr, len, rb_enc_from_index(encindex));
+ str = rb_enc_literal_str(ptr, len, rb_enc_from_index(encindex));
}
else {
str = rb_enc_str_new(ptr, len, rb_enc_from_index(encindex));
@@ -12873,8 +13720,12 @@ ibf_load_object_bignum(const struct ibf_load *load, const struct ibf_object_head
const struct ibf_object_bignum *bignum = IBF_OBJBODY(struct ibf_object_bignum, offset);
int sign = bignum->slen > 0;
ssize_t len = sign > 0 ? bignum->slen : -1 * bignum->slen;
- VALUE obj = rb_integer_unpack(bignum->digits, len * 2, 2, 0,
- INTEGER_PACK_LITTLE_ENDIAN | (sign == 0 ? INTEGER_PACK_NEGATIVE : 0));
+ const int big_unpack_flags = /* c.f. rb_big_unpack() */
+ INTEGER_PACK_LSWORD_FIRST |
+ INTEGER_PACK_NATIVE_BYTE_ORDER;
+ VALUE obj = rb_integer_unpack(bignum->digits, len, sizeof(BDIGIT), 0,
+ big_unpack_flags |
+ (sign == 0 ? INTEGER_PACK_NEGATIVE : 0));
if (header->internal) rb_obj_hide(obj);
if (header->frozen) rb_obj_freeze(obj);
return obj;
@@ -13202,14 +14053,13 @@ ibf_dump_free(void *ptr)
st_free_table(dump->iseq_table);
dump->iseq_table = 0;
}
- ruby_xfree(dump);
}
static size_t
ibf_dump_memsize(const void *ptr)
{
struct ibf_dump *dump = (struct ibf_dump *)ptr;
- size_t size = sizeof(*dump);
+ size_t size = 0;
if (dump->iseq_table) size += st_memsize(dump->iseq_table);
if (dump->global_buffer.obj_table) size += st_memsize(dump->global_buffer.obj_table);
return size;
@@ -13218,7 +14068,7 @@ ibf_dump_memsize(const void *ptr)
static const rb_data_type_t ibf_dump_type = {
"ibf_dump",
{ibf_dump_mark, ibf_dump_free, ibf_dump_memsize,},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_EMBEDDABLE
};
static void
@@ -13281,8 +14131,6 @@ rb_iseq_ibf_dump(const rb_iseq_t *iseq, VALUE opt)
ibf_dump_overwrite(dump, &header, sizeof(header), 0);
str = dump->global_buffer.str;
- ibf_dump_free(dump);
- DATA_PTR(dump_obj) = NULL;
RB_GC_GUARD(dump_obj);
return str;
}
@@ -13418,6 +14266,8 @@ ibf_load_setup_bytes(struct ibf_load *load, VALUE loader_obj, const char *bytes,
static void
ibf_load_setup(struct ibf_load *load, VALUE loader_obj, VALUE str)
{
+ StringValue(str);
+
if (RSTRING_LENINT(str) < (int)sizeof(struct ibf_header)) {
rb_raise(rb_eRuntimeError, "broken binary format");
}
diff --git a/complex.c b/complex.c
index c9272778bb..f562ed3161 100644
--- a/complex.c
+++ b/complex.c
@@ -24,6 +24,7 @@
#include "internal/numeric.h"
#include "internal/object.h"
#include "internal/rational.h"
+#include "internal/string.h"
#include "ruby_assert.h"
#define ZERO INT2FIX(0)
@@ -396,7 +397,7 @@ nucomp_s_new_internal(VALUE klass, VALUE real, VALUE imag)
RCOMPLEX_SET_REAL(obj, real);
RCOMPLEX_SET_IMAG(obj, imag);
- OBJ_FREEZE_RAW((VALUE)obj);
+ OBJ_FREEZE((VALUE)obj);
return (VALUE)obj;
}
@@ -410,15 +411,15 @@ nucomp_s_alloc(VALUE klass)
inline static VALUE
f_complex_new_bang1(VALUE klass, VALUE x)
{
- assert(!RB_TYPE_P(x, T_COMPLEX));
+ RUBY_ASSERT(!RB_TYPE_P(x, T_COMPLEX));
return nucomp_s_new_internal(klass, x, ZERO);
}
inline static VALUE
f_complex_new_bang2(VALUE klass, VALUE x, VALUE y)
{
- assert(!RB_TYPE_P(x, T_COMPLEX));
- assert(!RB_TYPE_P(y, T_COMPLEX));
+ RUBY_ASSERT(!RB_TYPE_P(x, T_COMPLEX));
+ RUBY_ASSERT(!RB_TYPE_P(y, T_COMPLEX));
return nucomp_s_new_internal(klass, x, y);
}
@@ -431,7 +432,7 @@ nucomp_real_check(VALUE num)
!RB_TYPE_P(num, T_RATIONAL)) {
if (RB_TYPE_P(num, T_COMPLEX) && nucomp_real_p(num)) {
VALUE real = RCOMPLEX(num)->real;
- assert(!RB_TYPE_P(real, T_COMPLEX));
+ RUBY_ASSERT(!RB_TYPE_P(real, T_COMPLEX));
return real;
}
if (!k_numeric_p(num) || !f_real_p(num))
@@ -474,12 +475,19 @@ nucomp_s_canonicalize_internal(VALUE klass, VALUE real, VALUE imag)
/*
* call-seq:
- * Complex.rect(real[, imag]) -> complex
- * Complex.rectangular(real[, imag]) -> complex
+ * Complex.rect(real, imag = 0) -> complex
*
- * Returns a complex object which denotes the given rectangular form.
+ * Returns a new \Complex object formed from the arguments,
+ * each of which must be an instance of Numeric,
+ * or an instance of one of its subclasses:
+ * \Complex, Float, Integer, Rational;
+ * see {Rectangular Coordinates}[rdoc-ref:Complex@Rectangular+Coordinates]:
*
- * Complex.rectangular(1, 2) #=> (1+2i)
+ * Complex.rect(3) # => (3+0i)
+ * Complex.rect(3, Math::PI) # => (3+3.141592653589793i)
+ * Complex.rect(-3, -Math::PI) # => (-3-3.141592653589793i)
+ *
+ * \Complex.rectangular is an alias for \Complex.rect.
*/
static VALUE
nucomp_s_new(int argc, VALUE *argv, VALUE klass)
@@ -516,39 +524,54 @@ static VALUE nucomp_s_convert(int argc, VALUE *argv, VALUE klass);
/*
* call-seq:
- * Complex(x[, y], exception: true) -> numeric or nil
- *
- * Returns x+i*y;
- *
- * Complex(1, 2) #=> (1+2i)
- * Complex('1+2i') #=> (1+2i)
- * Complex(nil) #=> TypeError
- * Complex(1, nil) #=> TypeError
- *
- * Complex(1, nil, exception: false) #=> nil
- * Complex('1+2', exception: false) #=> nil
- *
- * Syntax of string form:
- *
- * string form = extra spaces , complex , extra spaces ;
- * complex = real part | [ sign ] , imaginary part
- * | real part , sign , imaginary part
- * | rational , "@" , rational ;
- * real part = rational ;
- * imaginary part = imaginary unit | unsigned rational , imaginary unit ;
- * rational = [ sign ] , unsigned rational ;
- * unsigned rational = numerator | numerator , "/" , denominator ;
- * numerator = integer part | fractional part | integer part , fractional part ;
- * denominator = digits ;
- * integer part = digits ;
- * fractional part = "." , digits , [ ( "e" | "E" ) , [ sign ] , digits ] ;
- * imaginary unit = "i" | "I" | "j" | "J" ;
- * sign = "-" | "+" ;
- * digits = digit , { digit | "_" , digit };
- * digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
- * extra spaces = ? \s* ? ;
- *
- * See String#to_c.
+ * Complex(real, imag = 0, exception: true) -> complex or nil
+ * Complex(s, exception: true) -> complex or nil
+ *
+ * Returns a new \Complex object if the arguments are valid;
+ * otherwise raises an exception if +exception+ is +true+;
+ * otherwise returns +nil+.
+ *
+ * With Numeric arguments +real+ and +imag+,
+ * returns <tt>Complex.rect(real, imag)</tt> if the arguments are valid.
+ *
+ * With string argument +s+, returns a new \Complex object if the argument is valid;
+ * the string may have:
+ *
+ * - One or two numeric substrings,
+ * each of which specifies a Complex, Float, Integer, Numeric, or Rational value,
+ * specifying {rectangular coordinates}[rdoc-ref:Complex@Rectangular+Coordinates]:
+ *
+ * - Sign-separated real and imaginary numeric substrings
+ * (with trailing character <tt>'i'</tt>):
+ *
+ * Complex('1+2i') # => (1+2i)
+ * Complex('+1+2i') # => (1+2i)
+ * Complex('+1-2i') # => (1-2i)
+ * Complex('-1+2i') # => (-1+2i)
+ * Complex('-1-2i') # => (-1-2i)
+ *
+ * - Real-only numeric string (without trailing character <tt>'i'</tt>):
+ *
+ * Complex('1') # => (1+0i)
+ * Complex('+1') # => (1+0i)
+ * Complex('-1') # => (-1+0i)
+ *
+ * - Imaginary-only numeric string (with trailing character <tt>'i'</tt>):
+ *
+ * Complex('1i') # => (0+1i)
+ * Complex('+1i') # => (0+1i)
+ * Complex('-1i') # => (0-1i)
+ *
+ * - At-sign separated real and imaginary rational substrings,
+ * each of which specifies a Rational value,
+ * specifying {polar coordinates}[rdoc-ref:Complex@Polar+Coordinates]:
+ *
+ * Complex('1/2@3/4') # => (0.36584443443691045+0.34081938001166706i)
+ * Complex('+1/2@+3/4') # => (0.36584443443691045+0.34081938001166706i)
+ * Complex('+1/2@-3/4') # => (0.36584443443691045-0.34081938001166706i)
+ * Complex('-1/2@+3/4') # => (-0.36584443443691045-0.34081938001166706i)
+ * Complex('-1/2@-3/4') # => (-0.36584443443691045+0.34081938001166706i)
+ *
*/
static VALUE
nucomp_f_complex(int argc, VALUE *argv, VALUE klass)
@@ -698,14 +721,19 @@ rb_dbl_complex_new_polar_pi(double abs, double ang)
/*
* call-seq:
- * Complex.polar(abs[, arg]) -> complex
+ * Complex.polar(abs, arg = 0) -> complex
*
- * Returns a complex object which denotes the given polar form.
+ * Returns a new \Complex object formed from the arguments,
+ * each of which must be an instance of Numeric,
+ * or an instance of one of its subclasses:
+ * \Complex, Float, Integer, Rational.
+ * Argument +arg+ is given in radians;
+ * see {Polar Coordinates}[rdoc-ref:Complex@Polar+Coordinates]:
+ *
+ * Complex.polar(3) # => (3+0i)
+ * Complex.polar(3, 2.0) # => (-1.2484405096414273+2.727892280477045i)
+ * Complex.polar(-3, -2.0) # => (1.2484405096414273+2.727892280477045i)
*
- * Complex.polar(3, 0) #=> (3.0+0.0i)
- * Complex.polar(3, Math::PI/2) #=> (1.836909530733566e-16+3.0i)
- * Complex.polar(3, Math::PI) #=> (-3.0+3.673819061467132e-16i)
- * Complex.polar(3, -Math::PI/2) #=> (1.836909530733566e-16-3.0i)
*/
static VALUE
nucomp_s_polar(int argc, VALUE *argv, VALUE klass)
@@ -725,12 +753,19 @@ nucomp_s_polar(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * cmp.real -> real
+ * real -> numeric
+ *
+ * Returns the real value for +self+:
+ *
+ * Complex.rect(7).real # => 7
+ * Complex.rect(9, -4).real # => 9
+ *
+ * If +self+ was created with
+ * {polar coordinates}[rdoc-ref:Complex@Polar+Coordinates], the returned value
+ * is computed, and may be inexact:
*
- * Returns the real part.
+ * Complex.polar(1, Math::PI/4).real # => 0.7071067811865476 # Square root of 2.
*
- * Complex(7).real #=> 7
- * Complex(9, -4).real #=> 9
*/
VALUE
rb_complex_real(VALUE self)
@@ -741,13 +776,19 @@ rb_complex_real(VALUE self)
/*
* call-seq:
- * cmp.imag -> real
- * cmp.imaginary -> real
+ * imag -> numeric
*
- * Returns the imaginary part.
+ * Returns the imaginary value for +self+:
+ *
+ * Complex.rect(7).imag # => 0
+ * Complex.rect(9, -4).imag # => -4
+ *
+ * If +self+ was created with
+ * {polar coordinates}[rdoc-ref:Complex@Polar+Coordinates], the returned value
+ * is computed, and may be inexact:
+ *
+ * Complex.polar(1, Math::PI/4).imag # => 0.7071067811865476 # Square root of 2.
*
- * Complex(7).imaginary #=> 0
- * Complex(9, -4).imaginary #=> -4
*/
VALUE
rb_complex_imag(VALUE self)
@@ -758,11 +799,13 @@ rb_complex_imag(VALUE self)
/*
* call-seq:
- * -cmp -> complex
+ * -complex -> new_complex
*
- * Returns negation of the value.
+ * Returns the negation of +self+, which is the negation of each of its parts:
+ *
+ * -Complex.rect(1, 2) # => (-1-2i)
+ * -Complex.rect(-1, -2) # => (1+2i)
*
- * -Complex(1, 2) #=> (-1-2i)
*/
VALUE
rb_complex_uminus(VALUE self)
@@ -774,15 +817,16 @@ rb_complex_uminus(VALUE self)
/*
* call-seq:
- * cmp + numeric -> complex
+ * complex + numeric -> new_complex
+ *
+ * Returns the sum of +self+ and +numeric+:
*
- * Performs addition.
+ * Complex.rect(2, 3) + Complex.rect(2, 3) # => (4+6i)
+ * Complex.rect(900) + Complex.rect(1) # => (901+0i)
+ * Complex.rect(-2, 9) + Complex.rect(-9, 2) # => (-11+11i)
+ * Complex.rect(9, 8) + 4 # => (13+8i)
+ * Complex.rect(20, 9) + 9.8 # => (29.8+9i)
*
- * Complex(2, 3) + Complex(2, 3) #=> (4+6i)
- * Complex(900) + Complex(1) #=> (901+0i)
- * Complex(-2, 9) + Complex(-9, 2) #=> (-11+11i)
- * Complex(9, 8) + 4 #=> (13+8i)
- * Complex(20, 9) + 9.8 #=> (29.8+9i)
*/
VALUE
rb_complex_plus(VALUE self, VALUE other)
@@ -808,15 +852,16 @@ rb_complex_plus(VALUE self, VALUE other)
/*
* call-seq:
- * cmp - numeric -> complex
+ * complex - numeric -> new_complex
*
- * Performs subtraction.
+ * Returns the difference of +self+ and +numeric+:
+ *
+ * Complex.rect(2, 3) - Complex.rect(2, 3) # => (0+0i)
+ * Complex.rect(900) - Complex.rect(1) # => (899+0i)
+ * Complex.rect(-2, 9) - Complex.rect(-9, 2) # => (7+7i)
+ * Complex.rect(9, 8) - 4 # => (5+8i)
+ * Complex.rect(20, 9) - 9.8 # => (10.2+9i)
*
- * Complex(2, 3) - Complex(2, 3) #=> (0+0i)
- * Complex(900) - Complex(1) #=> (899+0i)
- * Complex(-2, 9) - Complex(-9, 2) #=> (7+7i)
- * Complex(9, 8) - 4 #=> (5+8i)
- * Complex(20, 9) - 9.8 #=> (10.2+9i)
*/
VALUE
rb_complex_minus(VALUE self, VALUE other)
@@ -868,15 +913,16 @@ comp_mul(VALUE areal, VALUE aimag, VALUE breal, VALUE bimag, VALUE *real, VALUE
/*
* call-seq:
- * cmp * numeric -> complex
+ * complex * numeric -> new_complex
+ *
+ * Returns the product of +self+ and +numeric+:
*
- * Performs multiplication.
+ * Complex.rect(2, 3) * Complex.rect(2, 3) # => (-5+12i)
+ * Complex.rect(900) * Complex.rect(1) # => (900+0i)
+ * Complex.rect(-2, 9) * Complex.rect(-9, 2) # => (0-85i)
+ * Complex.rect(9, 8) * 4 # => (36+32i)
+ * Complex.rect(20, 9) * 9.8 # => (196.0+88.2i)
*
- * Complex(2, 3) * Complex(2, 3) #=> (-5+12i)
- * Complex(900) * Complex(1) #=> (900+0i)
- * Complex(-2, 9) * Complex(-9, 2) #=> (0-85i)
- * Complex(9, 8) * 4 #=> (36+32i)
- * Complex(20, 9) * 9.8 #=> (196.0+88.2i)
*/
VALUE
rb_complex_mul(VALUE self, VALUE other)
@@ -943,16 +989,16 @@ f_divide(VALUE self, VALUE other,
/*
* call-seq:
- * cmp / numeric -> complex
- * cmp.quo(numeric) -> complex
+ * complex / numeric -> new_complex
+ *
+ * Returns the quotient of +self+ and +numeric+:
*
- * Performs division.
+ * Complex.rect(2, 3) / Complex.rect(2, 3) # => (1+0i)
+ * Complex.rect(900) / Complex.rect(1) # => (900+0i)
+ * Complex.rect(-2, 9) / Complex.rect(-9, 2) # => ((36/85)-(77/85)*i)
+ * Complex.rect(9, 8) / 4 # => ((9/4)+2i)
+ * Complex.rect(20, 9) / 9.8 # => (2.0408163265306123+0.9183673469387754i)
*
- * Complex(2, 3) / Complex(2, 3) #=> ((1/1)+(0/1)*i)
- * Complex(900) / Complex(1) #=> ((900/1)+(0/1)*i)
- * Complex(-2, 9) / Complex(-9, 2) #=> ((36/85)-(77/85)*i)
- * Complex(9, 8) / 4 #=> ((9/4)+(2/1)*i)
- * Complex(20, 9) / 9.8 #=> (2.0408163265306123+0.9183673469387754i)
*/
VALUE
rb_complex_div(VALUE self, VALUE other)
@@ -964,11 +1010,12 @@ rb_complex_div(VALUE self, VALUE other)
/*
* call-seq:
- * cmp.fdiv(numeric) -> complex
+ * fdiv(numeric) -> new_complex
*
- * Performs division as each part is a float, never returns a float.
+ * Returns <tt>Complex.rect(self.real/numeric, self.imag/numeric)</tt>:
+ *
+ * Complex.rect(11, 22).fdiv(3) # => (3.6666666666666665+7.333333333333333i)
*
- * Complex(11, 22).fdiv(3) #=> (3.6666666666666665+7.333333333333333i)
*/
static VALUE
nucomp_fdiv(VALUE self, VALUE other)
@@ -982,14 +1029,95 @@ f_reciprocal(VALUE x)
return f_quo(ONE, x);
}
+static VALUE
+zero_for(VALUE x)
+{
+ if (RB_FLOAT_TYPE_P(x))
+ return DBL2NUM(0);
+ if (RB_TYPE_P(x, T_RATIONAL))
+ return rb_rational_new(INT2FIX(0), INT2FIX(1));
+
+ return INT2FIX(0);
+}
+
+static VALUE
+complex_pow_for_special_angle(VALUE self, VALUE other)
+{
+ if (!rb_integer_type_p(other)) {
+ return Qundef;
+ }
+
+ get_dat1(self);
+ VALUE x = Qundef;
+ int dir;
+ if (f_zero_p(dat->imag)) {
+ x = dat->real;
+ dir = 0;
+ }
+ else if (f_zero_p(dat->real)) {
+ x = dat->imag;
+ dir = 2;
+ }
+ else if (f_eqeq_p(dat->real, dat->imag)) {
+ x = dat->real;
+ dir = 1;
+ }
+ else if (f_eqeq_p(dat->real, f_negate(dat->imag))) {
+ x = dat->imag;
+ dir = 3;
+ } else {
+ dir = 0;
+ }
+
+ if (UNDEF_P(x)) return x;
+
+ if (f_negative_p(x)) {
+ x = f_negate(x);
+ dir += 4;
+ }
+
+ VALUE zx;
+ if (dir % 2 == 0) {
+ zx = rb_num_pow(x, other);
+ }
+ else {
+ zx = rb_num_pow(
+ rb_funcall(rb_int_mul(TWO, x), '*', 1, x),
+ rb_int_div(other, TWO)
+ );
+ if (rb_int_odd_p(other)) {
+ zx = rb_funcall(zx, '*', 1, x);
+ }
+ }
+ static const int dirs[][2] = {
+ {1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}
+ };
+ int z_dir = FIX2INT(rb_int_modulo(rb_int_mul(INT2FIX(dir), other), INT2FIX(8)));
+
+ VALUE zr = Qfalse, zi = Qfalse;
+ switch (dirs[z_dir][0]) {
+ case 0: zr = zero_for(zx); break;
+ case 1: zr = zx; break;
+ case -1: zr = f_negate(zx); break;
+ }
+ switch (dirs[z_dir][1]) {
+ case 0: zi = zero_for(zx); break;
+ case 1: zi = zx; break;
+ case -1: zi = f_negate(zx); break;
+ }
+ return nucomp_s_new_internal(CLASS_OF(self), zr, zi);
+}
+
+
/*
* call-seq:
- * cmp ** numeric -> complex
+ * complex ** numeric -> new_complex
+ *
+ * Returns +self+ raised to power +numeric+:
*
- * Performs exponentiation.
+ * Complex.rect(0, 1) ** 2 # => (-1+0i)
+ * Complex.rect(-8) ** Rational(1, 3) # => (1.0000000000000002+1.7320508075688772i)
*
- * Complex('i') ** 2 #=> (-1+0i)
- * Complex(-8) ** Rational(1, 3) #=> (1.0000000000000002+1.7320508075688772i)
*/
VALUE
rb_complex_pow(VALUE self, VALUE other)
@@ -1007,6 +1135,14 @@ rb_complex_pow(VALUE self, VALUE other)
other = dat->real; /* c14n */
}
+ if (other == ONE) {
+ get_dat1(self);
+ return nucomp_s_new_internal(CLASS_OF(self), dat->real, dat->imag);
+ }
+
+ VALUE result = complex_pow_for_special_angle(self, other);
+ if (!UNDEF_P(result)) return result;
+
if (RB_TYPE_P(other, T_COMPLEX)) {
VALUE r, theta, nr, ntheta;
@@ -1079,15 +1215,13 @@ rb_complex_pow(VALUE self, VALUE other)
/*
* call-seq:
- * cmp == object -> true or false
+ * complex == object -> true or false
+ *
+ * Returns +true+ if <tt>self.real == object.real</tt>
+ * and <tt>self.imag == object.imag</tt>:
*
- * Returns true if cmp equals object numerically.
+ * Complex.rect(2, 3) == Complex.rect(2.0, 3.0) # => true
*
- * Complex(2, 3) == Complex(2, 3) #=> true
- * Complex(5) == 5 #=> true
- * Complex(0) == 0.0 #=> true
- * Complex('1/3') == 0.33 #=> false
- * Complex('1/2') == '1/2' #=> false
*/
static VALUE
nucomp_eqeq_p(VALUE self, VALUE other)
@@ -1115,17 +1249,26 @@ nucomp_real_p(VALUE self)
/*
* call-seq:
- * cmp <=> object -> 0, 1, -1, or nil
+ * complex <=> object -> -1, 0, 1, or nil
*
- * If +cmp+'s imaginary part is zero, and +object+ is also a
- * real number (or a Complex number where the imaginary part is zero),
- * compare the real part of +cmp+ to object. Otherwise, return nil.
+ * Returns:
+ *
+ * - <tt>self.real <=> object.real</tt> if both of the following are true:
+ *
+ * - <tt>self.imag == 0</tt>.
+ * - <tt>object.imag == 0</tt>. # Always true if object is numeric but not complex.
+ *
+ * - +nil+ otherwise.
+ *
+ * Examples:
+ *
+ * Complex.rect(2) <=> 3 # => -1
+ * Complex.rect(2) <=> 2 # => 0
+ * Complex.rect(2) <=> 1 # => 1
+ * Complex.rect(2, 1) <=> 1 # => nil # self.imag not zero.
+ * Complex.rect(1) <=> Complex.rect(1, 1) # => nil # object.imag not zero.
+ * Complex.rect(1) <=> 'Foo' # => nil # object.imag not defined.
*
- * Complex(2, 3) <=> Complex(2, 3) #=> nil
- * Complex(2, 3) <=> 1 #=> nil
- * Complex(2) <=> 1 #=> 1
- * Complex(2) <=> 2 #=> 0
- * Complex(2) <=> 3 #=> -1
*/
static VALUE
nucomp_cmp(VALUE self, VALUE other)
@@ -1170,13 +1313,19 @@ nucomp_coerce(VALUE self, VALUE other)
/*
* call-seq:
- * cmp.abs -> real
- * cmp.magnitude -> real
+ * abs -> float
*
- * Returns the absolute part of its polar form.
+ * Returns the absolute value (magnitude) for +self+;
+ * see {polar coordinates}[rdoc-ref:Complex@Polar+Coordinates]:
+ *
+ * Complex.polar(-1, 0).abs # => 1.0
+ *
+ * If +self+ was created with
+ * {rectangular coordinates}[rdoc-ref:Complex@Rectangular+Coordinates], the returned value
+ * is computed, and may be inexact:
+ *
+ * Complex.rectangular(1, 1).abs # => 1.4142135623730951 # The square root of 2.
*
- * Complex(-1).abs #=> 1
- * Complex(3.0, -4.0).abs #=> 5.0
*/
VALUE
rb_complex_abs(VALUE self)
@@ -1200,12 +1349,19 @@ rb_complex_abs(VALUE self)
/*
* call-seq:
- * cmp.abs2 -> real
+ * abs2 -> float
+ *
+ * Returns square of the absolute value (magnitude) for +self+;
+ * see {polar coordinates}[rdoc-ref:Complex@Polar+Coordinates]:
*
- * Returns square of the absolute value.
+ * Complex.polar(2, 2).abs2 # => 4.0
+ *
+ * If +self+ was created with
+ * {rectangular coordinates}[rdoc-ref:Complex@Rectangular+Coordinates], the returned value
+ * is computed, and may be inexact:
+ *
+ * Complex.rectangular(1.0/3, 1.0/3).abs2 # => 0.2222222222222222
*
- * Complex(-1).abs2 #=> 1
- * Complex(3.0, -4.0).abs2 #=> 25.0
*/
static VALUE
nucomp_abs2(VALUE self)
@@ -1217,13 +1373,19 @@ nucomp_abs2(VALUE self)
/*
* call-seq:
- * cmp.arg -> float
- * cmp.angle -> float
- * cmp.phase -> float
+ * arg -> float
+ *
+ * Returns the argument (angle) for +self+ in radians;
+ * see {polar coordinates}[rdoc-ref:Complex@Polar+Coordinates]:
+ *
+ * Complex.polar(3, Math::PI/2).arg # => 1.57079632679489660
+ *
+ * If +self+ was created with
+ * {rectangular coordinates}[rdoc-ref:Complex@Rectangular+Coordinates], the returned value
+ * is computed, and may be inexact:
*
- * Returns the angle part of its polar form.
+ * Complex.polar(1, 1.0/3).arg # => 0.33333333333333326
*
- * Complex.polar(3, Math::PI/2).arg #=> 1.5707963267948966
*/
VALUE
rb_complex_arg(VALUE self)
@@ -1234,12 +1396,22 @@ rb_complex_arg(VALUE self)
/*
* call-seq:
- * cmp.rect -> array
- * cmp.rectangular -> array
+ * rect -> array
+ *
+ * Returns the array <tt>[self.real, self.imag]</tt>:
+ *
+ * Complex.rect(1, 2).rect # => [1, 2]
+ *
+ * See {Rectangular Coordinates}[rdoc-ref:Complex@Rectangular+Coordinates].
+ *
+ * If +self+ was created with
+ * {polar coordinates}[rdoc-ref:Complex@Polar+Coordinates], the returned value
+ * is computed, and may be inexact:
+ *
+ * Complex.polar(1.0, 1.0).rect # => [0.5403023058681398, 0.8414709848078965]
*
- * Returns an array; [cmp.real, cmp.imag].
*
- * Complex(1, 2).rectangular #=> [1, 2]
+ * Complex#rectangular is an alias for Complex#rect.
*/
static VALUE
nucomp_rect(VALUE self)
@@ -1250,11 +1422,20 @@ nucomp_rect(VALUE self)
/*
* call-seq:
- * cmp.polar -> array
+ * polar -> array
*
- * Returns an array; [cmp.abs, cmp.arg].
+ * Returns the array <tt>[self.abs, self.arg]</tt>:
+ *
+ * Complex.polar(1, 2).polar # => [1.0, 2.0]
+ *
+ * See {Polar Coordinates}[rdoc-ref:Complex@Polar+Coordinates].
+ *
+ * If +self+ was created with
+ * {rectangular coordinates}[rdoc-ref:Complex@Rectangular+Coordinates], the returned value
+ * is computed, and may be inexact:
+ *
+ * Complex.rect(1, 1).polar # => [1.4142135623730951, 0.7853981633974483]
*
- * Complex(1, 2).polar #=> [2.23606797749979, 1.1071487177940904]
*/
static VALUE
nucomp_polar(VALUE self)
@@ -1264,12 +1445,12 @@ nucomp_polar(VALUE self)
/*
* call-seq:
- * cmp.conj -> complex
- * cmp.conjugate -> complex
+ * conj -> complex
+ *
+ * Returns the conjugate of +self+, <tt>Complex.rect(self.imag, self.real)</tt>:
*
- * Returns the complex conjugate.
+ * Complex.rect(1, 2).conj # => (1-2i)
*
- * Complex(1, 2).conjugate #=> (1-2i)
*/
VALUE
rb_complex_conjugate(VALUE self)
@@ -1280,10 +1461,9 @@ rb_complex_conjugate(VALUE self)
/*
* call-seq:
- * Complex(1).real? -> false
- * Complex(1, 2).real? -> false
+ * real? -> false
*
- * Returns false, even if the complex number has no imaginary part.
+ * Returns +false+; for compatibility with Numeric#real?.
*/
static VALUE
nucomp_real_p_m(VALUE self)
@@ -1293,11 +1473,17 @@ nucomp_real_p_m(VALUE self)
/*
* call-seq:
- * cmp.denominator -> integer
+ * denominator -> integer
*
- * Returns the denominator (lcm of both denominator - real and imag).
+ * Returns the denominator of +self+, which is
+ * the {least common multiple}[https://en.wikipedia.org/wiki/Least_common_multiple]
+ * of <tt>self.real.denominator</tt> and <tt>self.imag.denominator</tt>:
*
- * See numerator.
+ * Complex.rect(Rational(1, 2), Rational(2, 3)).denominator # => 6
+ *
+ * Note that <tt>n.denominator</tt> of a non-rational numeric is +1+.
+ *
+ * Related: Complex#numerator.
*/
static VALUE
nucomp_denominator(VALUE self)
@@ -1308,21 +1494,23 @@ nucomp_denominator(VALUE self)
/*
* call-seq:
- * cmp.numerator -> numeric
+ * numerator -> new_complex
*
- * Returns the numerator.
+ * Returns the \Complex object created from the numerators
+ * of the real and imaginary parts of +self+,
+ * after converting each part to the
+ * {lowest common denominator}[https://en.wikipedia.org/wiki/Lowest_common_denominator]
+ * of the two:
*
- * 1 2 3+4i <- numerator
- * - + -i -> ----
- * 2 3 6 <- denominator
+ * c = Complex.rect(Rational(2, 3), Rational(3, 4)) # => ((2/3)+(3/4)*i)
+ * c.numerator # => (8+9i)
*
- * c = Complex('1/2+2/3i') #=> ((1/2)+(2/3)*i)
- * n = c.numerator #=> (3+4i)
- * d = c.denominator #=> 6
- * n / d #=> ((1/2)+(2/3)*i)
- * Complex(Rational(n.real, d), Rational(n.imag, d))
- * #=> ((1/2)+(2/3)*i)
- * See denominator.
+ * In this example, the lowest common denominator of the two parts is 12;
+ * the two converted parts may be thought of as \Rational(8, 12) and \Rational(9, 12),
+ * whose numerators, respectively, are 8 and 9;
+ * so the returned value of <tt>c.numerator</tt> is <tt>Complex.rect(8, 9)</tt>.
+ *
+ * Related: Complex#denominator.
*/
static VALUE
nucomp_numerator(VALUE self)
@@ -1355,6 +1543,18 @@ rb_complex_hash(VALUE self)
return v;
}
+/*
+ * :call-seq:
+ * hash -> integer
+ *
+ * Returns the integer hash value for +self+.
+ *
+ * Two \Complex objects created from the same values will have the same hash value
+ * (and will compare using #eql?):
+ *
+ * Complex.rect(1, 2).hash == Complex.rect(1, 2).hash # => true
+ *
+ */
static VALUE
nucomp_hash(VALUE self)
{
@@ -1415,15 +1615,16 @@ f_format(VALUE self, VALUE (*func)(VALUE))
/*
* call-seq:
- * cmp.to_s -> string
+ * to_s -> string
*
- * Returns the value as a string.
+ * Returns a string representation of +self+:
+ *
+ * Complex.rect(2).to_s # => "2+0i"
+ * Complex.rect(-8, 6).to_s # => "-8+6i"
+ * Complex.rect(0, Rational(1, 2)).to_s # => "0+1/2i"
+ * Complex.rect(0, Float::INFINITY).to_s # => "0+Infinity*i"
+ * Complex.rect(Float::NAN, Float::NAN).to_s # => "NaN+NaN*i"
*
- * Complex(2).to_s #=> "2+0i"
- * Complex('-8/6').to_s #=> "-4/3+0i"
- * Complex('1/2i').to_s #=> "0+1/2i"
- * Complex(0, Float::INFINITY).to_s #=> "0+Infinity*i"
- * Complex(Float::NAN, Float::NAN).to_s #=> "NaN+NaN*i"
*/
static VALUE
nucomp_to_s(VALUE self)
@@ -1433,15 +1634,16 @@ nucomp_to_s(VALUE self)
/*
* call-seq:
- * cmp.inspect -> string
+ * inspect -> string
+ *
+ * Returns a string representation of +self+:
*
- * Returns the value as a string for inspection.
+ * Complex.rect(2).inspect # => "(2+0i)"
+ * Complex.rect(-8, 6).inspect # => "(-8+6i)"
+ * Complex.rect(0, Rational(1, 2)).inspect # => "(0+(1/2)*i)"
+ * Complex.rect(0, Float::INFINITY).inspect # => "(0+Infinity*i)"
+ * Complex.rect(Float::NAN, Float::NAN).inspect # => "(NaN+NaN*i)"
*
- * Complex(2).inspect #=> "(2+0i)"
- * Complex('-8/6').inspect #=> "((-4/3)+0i)"
- * Complex('1/2i').inspect #=> "(0+(1/2)*i)"
- * Complex(0, Float::INFINITY).inspect #=> "(0+Infinity*i)"
- * Complex(Float::NAN, Float::NAN).inspect #=> "(NaN+NaN*i)"
*/
static VALUE
nucomp_inspect(VALUE self)
@@ -1459,10 +1661,15 @@ nucomp_inspect(VALUE self)
/*
* call-seq:
- * cmp.finite? -> true or false
+ * finite? -> true or false
+ *
+ * Returns +true+ if both <tt>self.real.finite?</tt> and <tt>self.imag.finite?</tt>
+ * are true, +false+ otherwise:
*
- * Returns +true+ if +cmp+'s real and imaginary parts are both finite numbers,
- * otherwise returns +false+.
+ * Complex.rect(1, 1).finite? # => true
+ * Complex.rect(Float::INFINITY, 0).finite? # => false
+ *
+ * Related: Numeric#finite?, Float#finite?.
*/
static VALUE
rb_complex_finite_p(VALUE self)
@@ -1474,15 +1681,15 @@ rb_complex_finite_p(VALUE self)
/*
* call-seq:
- * cmp.infinite? -> nil or 1
+ * infinite? -> 1 or nil
*
- * Returns +1+ if +cmp+'s real or imaginary part is an infinite number,
- * otherwise returns +nil+.
+ * Returns +1+ if either <tt>self.real.infinite?</tt> or <tt>self.imag.infinite?</tt>
+ * is true, +nil+ otherwise:
*
- * For example:
+ * Complex.rect(Float::INFINITY, 0).infinite? # => 1
+ * Complex.rect(1, 1).infinite? # => nil
*
- * (1+1i).infinite? #=> nil
- * (Float::INFINITY + 1i).infinite? #=> 1
+ * Related: Numeric#infinite?, Float#infinite?.
*/
static VALUE
rb_complex_infinite_p(VALUE self)
@@ -1510,7 +1717,7 @@ nucomp_loader(VALUE self, VALUE a)
RCOMPLEX_SET_REAL(dat, rb_ivar_get(a, id_i_real));
RCOMPLEX_SET_IMAG(dat, rb_ivar_get(a, id_i_imag));
- OBJ_FREEZE_RAW(self);
+ OBJ_FREEZE(self);
return self;
}
@@ -1580,14 +1787,15 @@ rb_dbl_complex_new(double real, double imag)
/*
* call-seq:
- * cmp.to_i -> integer
+ * to_i -> integer
*
- * Returns the value as an integer if possible (the imaginary part
- * should be exactly zero).
+ * Returns the value of <tt>self.real</tt> as an Integer, if possible:
*
- * Complex(1, 0).to_i #=> 1
- * Complex(1, 0.0).to_i # RangeError
- * Complex(1, 2).to_i # RangeError
+ * Complex.rect(1, 0).to_i # => 1
+ * Complex.rect(1, Rational(0, 1)).to_i # => 1
+ *
+ * Raises RangeError if <tt>self.imag</tt> is not exactly zero
+ * (either <tt>Integer(0)</tt> or <tt>Rational(0, _n_)</tt>).
*/
static VALUE
nucomp_to_i(VALUE self)
@@ -1603,14 +1811,15 @@ nucomp_to_i(VALUE self)
/*
* call-seq:
- * cmp.to_f -> float
+ * to_f -> float
+ *
+ * Returns the value of <tt>self.real</tt> as a Float, if possible:
*
- * Returns the value as a float if possible (the imaginary part should
- * be exactly zero).
+ * Complex.rect(1, 0).to_f # => 1.0
+ * Complex.rect(1, Rational(0, 1)).to_f # => 1.0
*
- * Complex(1, 0).to_f #=> 1.0
- * Complex(1, 0.0).to_f # RangeError
- * Complex(1, 2).to_f # RangeError
+ * Raises RangeError if <tt>self.imag</tt> is not exactly zero
+ * (either <tt>Integer(0)</tt> or <tt>Rational(0, _n_)</tt>).
*/
static VALUE
nucomp_to_f(VALUE self)
@@ -1626,41 +1835,69 @@ nucomp_to_f(VALUE self)
/*
* call-seq:
- * cmp.to_r -> rational
+ * to_r -> rational
+ *
+ * Returns the value of <tt>self.real</tt> as a Rational, if possible:
*
- * Returns the value as a rational if possible (the imaginary part
- * should be exactly zero).
+ * Complex.rect(1, 0).to_r # => (1/1)
+ * Complex.rect(1, Rational(0, 1)).to_r # => (1/1)
+ * Complex.rect(1, 0.0).to_r # => (1/1)
*
- * Complex(1, 0).to_r #=> (1/1)
- * Complex(1, 0.0).to_r # RangeError
- * Complex(1, 2).to_r # RangeError
+ * Raises RangeError if <tt>self.imag</tt> is not exactly zero
+ * (either <tt>Integer(0)</tt> or <tt>Rational(0, _n_)</tt>)
+ * and <tt>self.imag.to_r</tt> is not exactly zero.
*
- * See rationalize.
+ * Related: Complex#rationalize.
*/
static VALUE
nucomp_to_r(VALUE self)
{
get_dat1(self);
- if (!k_exact_zero_p(dat->imag)) {
- rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Rational",
- self);
+ if (RB_FLOAT_TYPE_P(dat->imag) && FLOAT_ZERO_P(dat->imag)) {
+ /* Do nothing here */
+ }
+ else if (!k_exact_zero_p(dat->imag)) {
+ VALUE imag = rb_check_convert_type_with_id(dat->imag, T_RATIONAL, "Rational", idTo_r);
+ if (NIL_P(imag) || !k_exact_zero_p(imag)) {
+ rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Rational",
+ self);
+ }
}
return f_to_r(dat->real);
}
/*
* call-seq:
- * cmp.rationalize([eps]) -> rational
- *
- * Returns the value as a rational if possible (the imaginary part
- * should be exactly zero).
- *
- * Complex(1.0/3, 0).rationalize #=> (1/3)
- * Complex(1, 0.0).rationalize # RangeError
- * Complex(1, 2).rationalize # RangeError
- *
- * See to_r.
+ * rationalize(epsilon = nil) -> rational
+ *
+ * Returns a Rational object whose value is exactly or approximately
+ * equivalent to that of <tt>self.real</tt>.
+ *
+ * With no argument +epsilon+ given, returns a \Rational object
+ * whose value is exactly equal to that of <tt>self.real.rationalize</tt>:
+ *
+ * Complex.rect(1, 0).rationalize # => (1/1)
+ * Complex.rect(1, Rational(0, 1)).rationalize # => (1/1)
+ * Complex.rect(3.14159, 0).rationalize # => (314159/100000)
+ *
+ * With argument +epsilon+ given, returns a \Rational object
+ * whose value is exactly or approximately equal to that of <tt>self.real</tt>
+ * to the given precision:
+ *
+ * Complex.rect(3.14159, 0).rationalize(0.1) # => (16/5)
+ * Complex.rect(3.14159, 0).rationalize(0.01) # => (22/7)
+ * Complex.rect(3.14159, 0).rationalize(0.001) # => (201/64)
+ * Complex.rect(3.14159, 0).rationalize(0.0001) # => (333/106)
+ * Complex.rect(3.14159, 0).rationalize(0.00001) # => (355/113)
+ * Complex.rect(3.14159, 0).rationalize(0.000001) # => (7433/2366)
+ * Complex.rect(3.14159, 0).rationalize(0.0000001) # => (9208/2931)
+ * Complex.rect(3.14159, 0).rationalize(0.00000001) # => (47460/15107)
+ * Complex.rect(3.14159, 0).rationalize(0.000000001) # => (76149/24239)
+ * Complex.rect(3.14159, 0).rationalize(0.0000000001) # => (314159/100000)
+ * Complex.rect(3.14159, 0).rationalize(0.0) # => (3537115888337719/1125899906842624)
+ *
+ * Related: Complex#to_r.
*/
static VALUE
nucomp_rationalize(int argc, VALUE *argv, VALUE self)
@@ -1678,12 +1915,9 @@ nucomp_rationalize(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * complex.to_c -> self
- *
- * Returns self.
+ * to_c -> self
*
- * Complex(2).to_c #=> (2+0i)
- * Complex(-8, 6).to_c #=> (-8+6i)
+ * Returns +self+.
*/
static VALUE
nucomp_to_c(VALUE self)
@@ -1708,9 +1942,9 @@ nilclass_to_c(VALUE self)
/*
* call-seq:
- * num.to_c -> complex
+ * to_c -> complex
*
- * Returns the value as a complex.
+ * Returns +self+ as a Complex object.
*/
static VALUE
numeric_to_c(VALUE self)
@@ -1990,23 +2224,14 @@ string_to_c_strict(VALUE self, int raise)
rb_must_asciicompat(self);
- s = RSTRING_PTR(self);
-
- if (!s || memchr(s, '\0', RSTRING_LEN(self))) {
- if (!raise) return Qnil;
- rb_raise(rb_eArgError, "string contains null byte");
+ if (raise) {
+ s = StringValueCStr(self);
}
-
- if (s && s[RSTRING_LEN(self)]) {
- rb_str_modify(self);
- s = RSTRING_PTR(self);
- s[RSTRING_LEN(self)] = '\0';
+ else if (!(s = rb_str_to_cstr(self))) {
+ return Qnil;
}
- if (!s)
- s = (char *)"";
-
- if (!parse_comp(s, 1, &num)) {
+ if (!parse_comp(s, TRUE, &num)) {
if (!raise) return Qnil;
rb_raise(rb_eArgError, "invalid value for convert(): %+"PRIsVALUE,
self);
@@ -2017,53 +2242,39 @@ string_to_c_strict(VALUE self, int raise)
/*
* call-seq:
- * str.to_c -> complex
- *
- * Returns a complex which denotes the string form. The parser
- * ignores leading whitespaces and trailing garbage. Any digit
- * sequences can be separated by an underscore. Returns zero for null
- * or garbage string.
- *
- * '9'.to_c #=> (9+0i)
- * '2.5'.to_c #=> (2.5+0i)
- * '2.5/1'.to_c #=> ((5/2)+0i)
- * '-3/2'.to_c #=> ((-3/2)+0i)
- * '-i'.to_c #=> (0-1i)
- * '45i'.to_c #=> (0+45i)
- * '3-4i'.to_c #=> (3-4i)
- * '-4e2-4e-2i'.to_c #=> (-400.0-0.04i)
- * '-0.0-0.0i'.to_c #=> (-0.0-0.0i)
- * '1/2+3/4i'.to_c #=> ((1/2)+(3/4)*i)
- * 'ruby'.to_c #=> (0+0i)
- *
- * Polar form:
- * include Math
- * "1.0@0".to_c #=> (1+0.0i)
- * "1.0@#{PI/2}".to_c #=> (0.0+1i)
- * "1.0@#{PI}".to_c #=> (-1+0.0i)
- *
- * See Kernel.Complex.
+ * to_c -> complex
+ *
+ * Returns +self+ interpreted as a Complex object;
+ * leading whitespace and trailing garbage are ignored:
+ *
+ * '9'.to_c # => (9+0i)
+ * '2.5'.to_c # => (2.5+0i)
+ * '2.5/1'.to_c # => ((5/2)+0i)
+ * '-3/2'.to_c # => ((-3/2)+0i)
+ * '-i'.to_c # => (0-1i)
+ * '45i'.to_c # => (0+45i)
+ * '3-4i'.to_c # => (3-4i)
+ * '-4e2-4e-2i'.to_c # => (-400.0-0.04i)
+ * '-0.0-0.0i'.to_c # => (-0.0-0.0i)
+ * '1/2+3/4i'.to_c # => ((1/2)+(3/4)*i)
+ * '1.0@0'.to_c # => (1+0.0i)
+ * "1.0@#{Math::PI/2}".to_c # => (0.0+1i)
+ * "1.0@#{Math::PI}".to_c # => (-1+0.0i)
+ *
+ * Returns \Complex zero if the string cannot be converted:
+ *
+ * 'ruby'.to_c # => (0+0i)
+ *
+ * See Kernel#Complex.
*/
static VALUE
string_to_c(VALUE self)
{
- char *s;
VALUE num;
rb_must_asciicompat(self);
- s = RSTRING_PTR(self);
-
- if (s && s[RSTRING_LEN(self)]) {
- rb_str_modify(self);
- s = RSTRING_PTR(self);
- s[RSTRING_LEN(self)] = '\0';
- }
-
- if (!s)
- s = (char *)"";
-
- (void)parse_comp(s, 0, &num);
+ (void)parse_comp(rb_str_fill_terminator(self, 1), FALSE, &num);
return num;
}
@@ -2120,8 +2331,11 @@ nucomp_convert(VALUE klass, VALUE a1, VALUE a2, int raise)
return a1;
/* should raise exception for consistency */
if (!k_numeric_p(a1)) {
- if (!raise)
- return rb_protect(to_complex, a1, NULL);
+ if (!raise) {
+ a1 = rb_protect(to_complex, a1, NULL);
+ rb_set_errinfo(Qnil);
+ return a1;
+ }
return to_complex(a1);
}
}
@@ -2165,9 +2379,9 @@ nucomp_s_convert(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * num.abs2 -> real
+ * abs2 -> real
*
- * Returns square of self.
+ * Returns the square of +self+.
*/
static VALUE
numeric_abs2(VALUE self)
@@ -2177,11 +2391,9 @@ numeric_abs2(VALUE self)
/*
* call-seq:
- * num.arg -> 0 or float
- * num.angle -> 0 or float
- * num.phase -> 0 or float
+ * arg -> 0 or Math::PI
*
- * Returns 0 if the value is positive, pi otherwise.
+ * Returns zero if +self+ is positive, Math::PI otherwise.
*/
static VALUE
numeric_arg(VALUE self)
@@ -2193,10 +2405,9 @@ numeric_arg(VALUE self)
/*
* call-seq:
- * num.rect -> array
- * num.rectangular -> array
+ * rect -> array
*
- * Returns an array; [num, 0].
+ * Returns array <tt>[self, 0]</tt>.
*/
static VALUE
numeric_rect(VALUE self)
@@ -2206,9 +2417,9 @@ numeric_rect(VALUE self)
/*
* call-seq:
- * num.polar -> array
+ * polar -> array
*
- * Returns an array; [num.abs, num.arg].
+ * Returns array <tt>[self.abs, self.arg]</tt>.
*/
static VALUE
numeric_polar(VALUE self)
@@ -2236,11 +2447,9 @@ numeric_polar(VALUE self)
/*
* call-seq:
- * flo.arg -> 0 or float
- * flo.angle -> 0 or float
- * flo.phase -> 0 or float
+ * arg -> 0 or Math::PI
*
- * Returns 0 if the value is positive, pi otherwise.
+ * Returns 0 if +self+ is positive, Math::PI otherwise.
*/
static VALUE
float_arg(VALUE self)
@@ -2253,45 +2462,137 @@ float_arg(VALUE self)
}
/*
- * A complex number can be represented as a paired real number with
- * imaginary unit; a+bi. Where a is real part, b is imaginary part
- * and i is imaginary unit. Real a equals complex a+0i
- * mathematically.
+ * A \Complex object houses a pair of values,
+ * given when the object is created as either <i>rectangular coordinates</i>
+ * or <i>polar coordinates</i>.
+ *
+ * == Rectangular Coordinates
+ *
+ * The rectangular coordinates of a complex number
+ * are called the _real_ and _imaginary_ parts;
+ * see {Complex number definition}[https://en.wikipedia.org/wiki/Complex_number#Definition_and_basic_operations].
+ *
+ * You can create a \Complex object from rectangular coordinates with:
+ *
+ * - A {complex literal}[rdoc-ref:doc/syntax/literals.rdoc@Complex+Literals].
+ * - \Method Complex.rect.
+ * - \Method Kernel#Complex, either with numeric arguments or with certain string arguments.
+ * - \Method String#to_c, for certain strings.
+ *
+ * Note that each of the stored parts may be a an instance one of the classes
+ * Complex, Float, Integer, or Rational;
+ * they may be retrieved:
+ *
+ * - Separately, with methods Complex#real and Complex#imaginary.
+ * - Together, with method Complex#rect.
+ *
+ * The corresponding (computed) polar values may be retrieved:
+ *
+ * - Separately, with methods Complex#abs and Complex#arg.
+ * - Together, with method Complex#polar.
+ *
+ * == Polar Coordinates
+ *
+ * The polar coordinates of a complex number
+ * are called the _absolute_ and _argument_ parts;
+ * see {Complex polar plane}[https://en.wikipedia.org/wiki/Complex_number#Polar_form].
+ *
+ * In this class, the argument part
+ * in expressed {radians}[https://en.wikipedia.org/wiki/Radian]
+ * (not {degrees}[https://en.wikipedia.org/wiki/Degree_(angle)]).
+ *
+ * You can create a \Complex object from polar coordinates with:
+ *
+ * - \Method Complex.polar.
+ * - \Method Kernel#Complex, with certain string arguments.
+ * - \Method String#to_c, for certain strings.
+ *
+ * Note that each of the stored parts may be a an instance one of the classes
+ * Complex, Float, Integer, or Rational;
+ * they may be retrieved:
+ *
+ * - Separately, with methods Complex#abs and Complex#arg.
+ * - Together, with method Complex#polar.
+ *
+ * The corresponding (computed) rectangular values may be retrieved:
+ *
+ * - Separately, with methods Complex#real and Complex#imag.
+ * - Together, with method Complex#rect.
+ *
+ * == What's Here
+ *
+ * First, what's elsewhere:
+ *
+ * - \Class \Complex inherits (directly or indirectly)
+ * from classes {Numeric}[rdoc-ref:Numeric@What-27s+Here]
+ * and {Object}[rdoc-ref:Object@What-27s+Here].
+ * - Includes (indirectly) module {Comparable}[rdoc-ref:Comparable@What-27s+Here].
+ *
+ * Here, class \Complex has methods for:
+ *
+ * === Creating \Complex Objects
+ *
+ * - ::polar: Returns a new \Complex object based on given polar coordinates.
+ * - ::rect (and its alias ::rectangular):
+ * Returns a new \Complex object based on given rectangular coordinates.
+ *
+ * === Querying
+ *
+ * - #abs (and its alias #magnitude): Returns the absolute value for +self+.
+ * - #arg (and its aliases #angle and #phase):
+ * Returns the argument (angle) for +self+ in radians.
+ * - #denominator: Returns the denominator of +self+.
+ * - #finite?: Returns whether both +self.real+ and +self.image+ are finite.
+ * - #hash: Returns the integer hash value for +self+.
+ * - #imag (and its alias #imaginary): Returns the imaginary value for +self+.
+ * - #infinite?: Returns whether +self.real+ or +self.image+ is infinite.
+ * - #numerator: Returns the numerator of +self+.
+ * - #polar: Returns the array <tt>[self.abs, self.arg]</tt>.
+ * - #inspect: Returns a string representation of +self+.
+ * - #real: Returns the real value for +self+.
+ * - #real?: Returns +false+; for compatibility with Numeric#real?.
+ * - #rect (and its alias #rectangular):
+ * Returns the array <tt>[self.real, self.imag]</tt>.
*
- * You can create a \Complex object explicitly with:
+ * === Comparing
*
- * - A {complex literal}[rdoc-ref:syntax/literals.rdoc@Complex+Literals].
+ * - #<=>: Returns whether +self+ is less than, equal to, or greater than the given argument.
+ * - #==: Returns whether +self+ is equal to the given argument.
*
- * You can convert certain objects to \Complex objects with:
+ * === Converting
*
- * - \Method #Complex.
+ * - #rationalize: Returns a Rational object whose value is exactly
+ * or approximately equivalent to that of <tt>self.real</tt>.
+ * - #to_c: Returns +self+.
+ * - #to_d: Returns the value as a BigDecimal object.
+ * - #to_f: Returns the value of <tt>self.real</tt> as a Float, if possible.
+ * - #to_i: Returns the value of <tt>self.real</tt> as an Integer, if possible.
+ * - #to_r: Returns the value of <tt>self.real</tt> as a Rational, if possible.
+ * - #to_s: Returns a string representation of +self+.
*
- * Complex object can be created as literal, and also by using
- * Kernel#Complex, Complex::rect, Complex::polar or to_c method.
+ * === Performing Complex Arithmetic
*
- * 2+1i #=> (2+1i)
- * Complex(1) #=> (1+0i)
- * Complex(2, 3) #=> (2+3i)
- * Complex.polar(2, 3) #=> (-1.9799849932008908+0.2822400161197344i)
- * 3.to_c #=> (3+0i)
+ * - #*: Returns the product of +self+ and the given numeric.
+ * - #**: Returns +self+ raised to power of the given numeric.
+ * - #+: Returns the sum of +self+ and the given numeric.
+ * - #-: Returns the difference of +self+ and the given numeric.
+ * - #-@: Returns the negation of +self+.
+ * - #/: Returns the quotient of +self+ and the given numeric.
+ * - #abs2: Returns square of the absolute value (magnitude) for +self+.
+ * - #conj (and its alias #conjugate): Returns the conjugate of +self+.
+ * - #fdiv: Returns <tt>Complex.rect(self.real/numeric, self.imag/numeric)</tt>.
*
- * You can also create complex object from floating-point numbers or
- * strings.
+ * === Working with JSON
*
- * Complex(0.3) #=> (0.3+0i)
- * Complex('0.3-0.5i') #=> (0.3-0.5i)
- * Complex('2/3+3/4i') #=> ((2/3)+(3/4)*i)
- * Complex('1@2') #=> (-0.4161468365471424+0.9092974268256817i)
+ * - ::json_create: Returns a new \Complex object,
+ * deserialized from the given serialized hash.
+ * - #as_json: Returns a serialized hash constructed from +self+.
+ * - #to_json: Returns a JSON string representing +self+.
*
- * 0.3.to_c #=> (0.3+0i)
- * '0.3-0.5i'.to_c #=> (0.3-0.5i)
- * '2/3+3/4i'.to_c #=> ((2/3)+(3/4)*i)
- * '1@2'.to_c #=> (-0.4161468365471424+0.9092974268256817i)
+ * These methods are provided by the {JSON gem}[https://github.com/flori/json]. To make these methods available:
*
- * A complex object is either an exact or an inexact number.
+ * require 'json/add/complex'
*
- * Complex(1, 1) / 2 #=> ((1/2)+(1/2)*i)
- * Complex(1, 1) / 2.0 #=> (0.5+0.5i)
*/
void
Init_Complex(void)
@@ -2412,13 +2713,17 @@ Init_Complex(void)
rb_define_method(rb_cFloat, "phase", float_arg, 0);
/*
- * The imaginary unit.
+ * Equivalent
+ * to <tt>Complex.rect(0, 1)</tt>:
+ *
+ * Complex::I # => (0+1i)
+ *
*/
rb_define_const(rb_cComplex, "I",
f_complex_new_bang2(rb_cComplex, ZERO, ONE));
#if !USE_FLONUM
- rb_gc_register_mark_object(RFLOAT_0 = DBL2NUM(0.0));
+ rb_vm_register_global_object(RFLOAT_0 = DBL2NUM(0.0));
#endif
rb_provide("complex.so"); /* for backward compatibility */
diff --git a/configure.ac b/configure.ac
index e0057d974f..ac059bf862 100644
--- a/configure.ac
+++ b/configure.ac
@@ -9,43 +9,50 @@ tooldir="$srcdir/tool"
AC_DISABLE_OPTION_CHECKING
-m4_include([tool/m4/_colorize_result_prepare.m4])dnl
-m4_include([tool/m4/ac_msg_result.m4])dnl
-m4_include([tool/m4/colorize_result.m4])dnl
-m4_include([tool/m4/ruby_append_option.m4])dnl
-m4_include([tool/m4/ruby_append_options.m4])dnl
-m4_include([tool/m4/ruby_check_builtin_func.m4])dnl
-m4_include([tool/m4/ruby_check_builtin_setjmp.m4])dnl
-m4_include([tool/m4/ruby_check_printf_prefix.m4])dnl
-m4_include([tool/m4/ruby_check_setjmp.m4])dnl
-m4_include([tool/m4/ruby_check_signedness.m4])dnl
-m4_include([tool/m4/ruby_check_sizeof.m4])dnl
-m4_include([tool/m4/ruby_check_sysconf.m4])dnl
-m4_include([tool/m4/ruby_cppoutfile.m4])dnl
-m4_include([tool/m4/ruby_decl_attribute.m4])dnl
-m4_include([tool/m4/ruby_default_arch.m4])dnl
-m4_include([tool/m4/ruby_define_if.m4])dnl
-m4_include([tool/m4/ruby_defint.m4])dnl
-m4_include([tool/m4/ruby_dtrace_available.m4])dnl
-m4_include([tool/m4/ruby_dtrace_postprocess.m4])dnl
-m4_include([tool/m4/ruby_func_attribute.m4])dnl
-m4_include([tool/m4/ruby_mingw32.m4])dnl
-m4_include([tool/m4/ruby_prepend_option.m4])dnl
-m4_include([tool/m4/ruby_prog_gnu_ld.m4])dnl
-m4_include([tool/m4/ruby_prog_makedirs.m4])dnl
-m4_include([tool/m4/ruby_replace_funcs.m4])dnl
-m4_include([tool/m4/ruby_replace_type.m4])dnl
-m4_include([tool/m4/ruby_require_funcs.m4])dnl
-m4_include([tool/m4/ruby_rm_recursive.m4])dnl
-m4_include([tool/m4/ruby_setjmp_type.m4])dnl
-m4_include([tool/m4/ruby_stack_grow_direction.m4])dnl
-m4_include([tool/m4/ruby_thread.m4])dnl
-m4_include([tool/m4/ruby_try_cflags.m4])dnl
-m4_include([tool/m4/ruby_try_cxxflags.m4])dnl
-m4_include([tool/m4/ruby_try_ldflags.m4])dnl
-m4_include([tool/m4/ruby_universal_arch.m4])dnl
-m4_include([tool/m4/ruby_wasm_tools.m4])dnl
-m4_include([tool/m4/ruby_werror_flag.m4])dnl
+m4_define([RUBY_M4_INCLUDED], [])dnl
+AC_DEFUN([RUBY_M4_INCLUDE], [m4_include([tool/m4/$1])dnl
+ m4_append([RUBY_M4_INCLUDED], [ \
+ $(tooldir)/m4/$1])dnl
+])
+RUBY_M4_INCLUDE([_colorize_result_prepare.m4])dnl
+RUBY_M4_INCLUDE([ac_msg_result.m4])dnl
+RUBY_M4_INCLUDE([colorize_result.m4])dnl
+RUBY_M4_INCLUDE([ruby_append_option.m4])dnl
+RUBY_M4_INCLUDE([ruby_append_options.m4])dnl
+RUBY_M4_INCLUDE([ruby_check_builtin_func.m4])dnl
+RUBY_M4_INCLUDE([ruby_check_builtin_setjmp.m4])dnl
+RUBY_M4_INCLUDE([ruby_check_header.m4])dnl
+RUBY_M4_INCLUDE([ruby_check_printf_prefix.m4])dnl
+RUBY_M4_INCLUDE([ruby_check_setjmp.m4])dnl
+RUBY_M4_INCLUDE([ruby_check_signedness.m4])dnl
+RUBY_M4_INCLUDE([ruby_check_sizeof.m4])dnl
+RUBY_M4_INCLUDE([ruby_check_sysconf.m4])dnl
+RUBY_M4_INCLUDE([ruby_cppoutfile.m4])dnl
+RUBY_M4_INCLUDE([ruby_decl_attribute.m4])dnl
+RUBY_M4_INCLUDE([ruby_default_arch.m4])dnl
+RUBY_M4_INCLUDE([ruby_define_if.m4])dnl
+RUBY_M4_INCLUDE([ruby_defint.m4])dnl
+RUBY_M4_INCLUDE([ruby_dtrace_available.m4])dnl
+RUBY_M4_INCLUDE([ruby_dtrace_postprocess.m4])dnl
+RUBY_M4_INCLUDE([ruby_func_attribute.m4])dnl
+RUBY_M4_INCLUDE([ruby_mingw32.m4])dnl
+RUBY_M4_INCLUDE([ruby_prepend_option.m4])dnl
+RUBY_M4_INCLUDE([ruby_prog_gnu_ld.m4])dnl
+RUBY_M4_INCLUDE([ruby_prog_makedirs.m4])dnl
+RUBY_M4_INCLUDE([ruby_replace_funcs.m4])dnl
+RUBY_M4_INCLUDE([ruby_replace_type.m4])dnl
+RUBY_M4_INCLUDE([ruby_require_funcs.m4])dnl
+RUBY_M4_INCLUDE([ruby_rm_recursive.m4])dnl
+RUBY_M4_INCLUDE([ruby_setjmp_type.m4])dnl
+RUBY_M4_INCLUDE([ruby_shared_gc.m4])dnl
+RUBY_M4_INCLUDE([ruby_stack_grow_direction.m4])dnl
+RUBY_M4_INCLUDE([ruby_thread.m4])dnl
+RUBY_M4_INCLUDE([ruby_try_cflags.m4])dnl
+RUBY_M4_INCLUDE([ruby_try_cxxflags.m4])dnl
+RUBY_M4_INCLUDE([ruby_try_ldflags.m4])dnl
+RUBY_M4_INCLUDE([ruby_universal_arch.m4])dnl
+RUBY_M4_INCLUDE([ruby_wasm_tools.m4])dnl
+RUBY_M4_INCLUDE([ruby_werror_flag.m4])dnl
AS_IF([test "x${GITHUB_ACTIONS}" = xtrue],
[AC_REQUIRE([_COLORIZE_RESULT_PREPARE])dnl
@@ -75,8 +82,10 @@ AC_ARG_WITH(baseruby,
[
AC_PATH_PROG([BASERUBY], [ruby], [false])
])
-# BASERUBY must be >= 2.5.0. Note that `"2.5.0" > "2.5"` is true.
-AS_IF([test "$HAVE_BASERUBY" != no -a "`RUBYOPT=- $BASERUBY --disable=gems -e 'print 42 if RUBY_VERSION > "2.5"' 2>/dev/null`" = 42], [
+AS_IF([test "$HAVE_BASERUBY" != no], [
+ RUBYOPT=- $BASERUBY --disable=gems "${tooldir}/missing-baseruby.bat" || HAVE_BASERUBY=no
+])
+AS_IF([test "${HAVE_BASERUBY:=no}" != no], [
AS_CASE(["$build_os"], [mingw*], [
# Can MSys shell run a command with a drive letter?
RUBYOPT=- `cygpath -ma "$BASERUBY"` --disable=gems -e exit 2>/dev/null || HAVE_BASERUBY=no
@@ -84,12 +93,10 @@ AS_IF([test "$HAVE_BASERUBY" != no -a "`RUBYOPT=- $BASERUBY --disable=gems -e 'p
RUBY_APPEND_OPTION(BASERUBY, "--disable=gems")
BASERUBY_VERSION=`$BASERUBY -v`
$BASERUBY -C "$srcdir" tool/downloader.rb -d tool -e gnu config.guess config.sub >&AS_MESSAGE_FD
-], [
- HAVE_BASERUBY=no
])
AS_IF([test "$HAVE_BASERUBY" = no], [
AS_IF([test "$cross_compiling" = yes], [AC_MSG_ERROR([executable host ruby is required for cross-compiling])])
- BASERUBY="echo executable host ruby is required. use --with-baseruby option.; false"
+ BASERUBY=${tooldir}/missing-baseruby.bat
])
AC_SUBST(BASERUBY)
AC_SUBST(HAVE_BASERUBY)
@@ -225,15 +232,23 @@ AS_CASE(["/${rb_CC} "],
[*clang*], [
# Ditto for LLVM. Note however that llvm-as is a LLVM-IR to LLVM bitcode
# assembler that does not target your machine native binary.
+
+ # Xcode has its own version tools that may be incompatible with
+ # genuine LLVM tools, use the tools in the same directory.
+
+ AS_IF([$rb_CC -E -dM -xc - < /dev/null | grep -F __apple_build_version__ > /dev/null],
+ [llvm_prefix=], [llvm_prefix=llvm-])
+ # AC_PREPROC_IFELSE cannot be used before AC_USE_SYSTEM_EXTENSIONS
+
RUBY_CHECK_PROG_FOR_CC([LD], [s/clang/ld/]) # ... maybe try lld ?
- RUBY_CHECK_PROG_FOR_CC([AR], [s/clang/llvm-ar/])
-# RUBY_CHECK_PROG_FOR_CC([AS], [s/clang/llvm-as/])
+ RUBY_CHECK_PROG_FOR_CC([AR], [s/clang/${llvm_prefix}ar/])
+# RUBY_CHECK_PROG_FOR_CC([AS], [s/clang/${llvm_prefix}as/])
RUBY_CHECK_PROG_FOR_CC([CXX], [s/clang/clang++/])
- RUBY_CHECK_PROG_FOR_CC([NM], [s/clang/llvm-nm/])
- RUBY_CHECK_PROG_FOR_CC([OBJCOPY], [s/clang/llvm-objcopy/])
- RUBY_CHECK_PROG_FOR_CC([OBJDUMP], [s/clang/llvm-objdump/])
- RUBY_CHECK_PROG_FOR_CC([RANLIB], [s/clang/llvm-ranlib/])
- RUBY_CHECK_PROG_FOR_CC([STRIP], [s/clang/llvm-strip/])
+ RUBY_CHECK_PROG_FOR_CC([NM], [s/clang/${llvm_prefix}nm/])
+ RUBY_CHECK_PROG_FOR_CC([OBJCOPY], [s/clang/${llvm_prefix}objcopy/])
+ RUBY_CHECK_PROG_FOR_CC([OBJDUMP], [s/clang/${llvm_prefix}objdump/])
+ RUBY_CHECK_PROG_FOR_CC([RANLIB], [s/clang/${llvm_prefix}ranlib/])
+ RUBY_CHECK_PROG_FOR_CC([STRIP], [s/clang/${llvm_prefix}strip/])
])
AS_UNSET(rb_CC)
AS_UNSET(rb_dummy)
@@ -244,12 +259,6 @@ AS_CASE(["${build_os}"],
],
[aix*], [
AC_PATH_TOOL([NM], [nm], [/usr/ccs/bin/nm], [/usr/ccs/bin:$PATH])
-],
-[darwin*], [
- # For Apple clang version 14.0.3 (clang-1403.0.22.14.1)
- ac_cv_prog_ac_ct_AR=`$CC -print-prog-name=ar`
- ac_cv_prog_ac_ct_LD=`$CC -print-prog-name=ld`
- ac_cv_prog_ac_ct_NM=`$CC -print-prog-name=nm`
])
AS_CASE(["${target_os}"],
[cygwin*|msys*|mingw*|darwin*], [
@@ -277,7 +286,7 @@ AC_CHECK_TOOLS([STRIP], [gstrip strip], [:])
# nm errors with Rust's LLVM bitcode when Rust uses a newer LLVM version than nm.
# In case we're working with llvm-nm, tell it to not worry about the bitcode.
-AS_IF([${NM} --help | grep -q 'llvm-bc'], [NM="$NM --no-llvm-bc"])
+AS_IF([${NM} --help 2>&1 | grep -q 'llvm-bc'], [NM="$NM --no-llvm-bc"])
AS_IF([test ! $rb_test_CFLAGS], [AS_UNSET(CFLAGS)]); AS_UNSET(rb_test_CFLAGS)
AS_IF([test ! $rb_test_CXXFLAGS], [AS_UNSET(CXXFLAGS)]); AS_UNSET(rb_save_CXXFLAGS)
@@ -426,15 +435,20 @@ AS_CASE(["$build_os"],
# default spec.
# Xcode linker warns for deprecated architecture and wrongly
# installed TBD files.
- CC_WRAPPER="" CC_NO_WRAPPER="$CC"
+ AC_MSG_CHECKING(for $CC linker warning)
+ suppress_ld_waring=no
echo 'int main(void) {return 0;}' > conftest.c
AS_IF([$CC -framework Foundation -o conftest conftest.c 2>&1 |
- grep -e '^ld: warning: ignoring duplicate libraries:' \
- -e '^ld: warning: text-based stub file' >/dev/null], [
- CC_WRAPPER=`cd -P "${tooldir}" && pwd`/darwin-cc
- CC="$CC_WRAPPER $CC"
+ grep \
+ -e '^ld: warning: ignoring duplicate libraries:' \
+ -e '^ld: warning: text-based stub file' \
+ -e '^ld: warning: -multiply_defined is obsolete' \
+ >/dev/null], [
+ suppress_ld_waring=yes
])
rm -fr conftest*
+ test $suppress_ld_waring = yes && warnflags="${warnflags:+${warnflags} }-Wl,-w"
+ AC_MSG_RESULT($suppress_ld_waring)
])
AS_CASE(["$target_os"],
[wasi*], [
@@ -461,8 +475,8 @@ AC_SUBST(CC_VERSION_MESSAGE, $cc_version_message)
: ${DLDFLAGS="$LDFLAGS"}
RUBY_UNIVERSAL_ARCH
-AS_IF([test "$target_cpu" != "$host_cpu" -a "$GCC" = yes -a "$cross_compiling" = no -a "${universal_binary:-no}" = no], [
- RUBY_DEFAULT_ARCH("$target_cpu")
+AS_IF([test "$target_cpu" != "$host_cpu" -a "$GCC" = yes -a "${universal_binary:-no}" = no], [
+ RUBY_DEFAULT_ARCH($target_cpu)
])
host_os=$target_os
host_vendor=$target_vendor
@@ -506,13 +520,10 @@ AS_CASE(["$target_os"],
])
rb_cv_binary_elf=no
: ${enable_shared=yes}
-],
-[darwin*], [
- : ${enable_shared=yes}
-],
+ AS_IF([$WINDRES --version | grep LLVM > /dev/null], [USE_LLVM_WINDRES=yes], [USE_LLVM_WINDRES=no])
+ ],
[hiuxmpp*], [AC_DEFINE(__HIUX_MPP__)]) # by TOYODA Eizi <toyoda@npd.kishou.go.jp>
-
AC_PROG_LN_S
AC_PROG_MAKE_SET
AC_PROG_INSTALL
@@ -833,7 +844,10 @@ AS_IF([test "$GCC" = yes], [
AS_FOR(option, opt, [-mbranch-protection=pac-ret -msign-return-address=all], [
RUBY_TRY_CFLAGS(option, [branch_protection=yes], [branch_protection=no])
AS_IF([test "x$branch_protection" = xyes], [
+ # C compiler and assembler must be consistent for -mbranch-protection
+ # since they both check `__ARM_FEATURE_PAC_DEFAULT` definition.
RUBY_APPEND_OPTION(XCFLAGS, option)
+ RUBY_APPEND_OPTION(ASFLAGS, option)
break
])
])
@@ -890,9 +904,9 @@ AS_IF([test "$GCC" = yes], [
# suppress annoying -Wstrict-overflow warnings
RUBY_TRY_CFLAGS(-fno-strict-overflow, [RUBY_APPEND_OPTION(XCFLAGS, -fno-strict-overflow)])
- test "${debugflags+set}" || {RUBY_TRY_CFLAGS(-ggdb3, [debugflags=-ggdb3])}
- test "${debugflags+set}" || {RUBY_TRY_CFLAGS(-ggdb, [debugflags=-ggdb])}
- test "${debugflags+set}" || {RUBY_TRY_CFLAGS(-g3, [debugflags=-g3])}
+ test "${debugflags+set}" || {RUBY_TRY_LDFLAGS(-ggdb3, [debugflags=-ggdb3])}
+ test "${debugflags+set}" || {RUBY_TRY_LDFLAGS(-ggdb, [debugflags=-ggdb])}
+ test "${debugflags+set}" || {RUBY_TRY_LDFLAGS(-g3, [debugflags=-g3])}
])
test $ac_cv_prog_cc_g = yes && : ${debugflags=-g}
@@ -980,7 +994,6 @@ AC_SUBST(incflags, "$INCFLAGS")
test -z "${ac_env_CFLAGS_set}" -a -n "${cflags+set}" && eval CFLAGS="\"$cflags $ARCH_FLAG\""
test -z "${ac_env_CXXFLAGS_set}" -a -n "${cxxflags+set}" && eval CXXFLAGS="\"$cxxflags $ARCH_FLAG\""
-}
AC_CACHE_CHECK([whether compiler has statement and declarations in expressions],
rb_cv_have_stmt_and_decl_in_expr,
@@ -990,6 +1003,7 @@ AC_CACHE_CHECK([whether compiler has statement and declarations in expressions],
AS_IF([test "$rb_cv_have_stmt_and_decl_in_expr" = yes], [
AC_DEFINE(HAVE_STMT_AND_DECL_IN_EXPR)
])
+}
[begin]_group "header and library section" && {
AC_ARG_WITH(winnt-ver,
@@ -1102,19 +1116,15 @@ main()
])
AC_CHECK_PROGS(dsymutil, $dsymutils dsymutil)
AS_IF([test -n "$codesign"], [
- POSTLINK="{ test -z '\$(RUBY_CODESIGN)' || $codesign -s '\$(RUBY_CODESIGN)' -f \$@; }${POSTLINK:+; $POSTLINK}"
+ POSTLINK="{ test -z '\$(RUBY_CODESIGN)' || $codesign -s '\$(RUBY_CODESIGN)' \$@; }${POSTLINK:+; $POSTLINK}"
])
AS_IF([test -n "$dsymutil"], [
POSTLINK="$dsymutil \$@ 2>/dev/null${POSTLINK:+; $POSTLINK}"
])
- AS_IF([test -n "${POSTLINK}"], [
- LINK_SO="$LINK_SO
-\$(POSTLINK)"
- ])
AC_CHECK_HEADERS(crt_externs.h, [], [], [
#include <crt_externs.h>
])
- cleanlibs='$(TARGET_SO).dSYM'
+ cleanlibs='$(TARGET_SO:=.dSYM)'
],
[solaris*], [ LIBS="-lm $LIBS"
ac_cv_func_vfork=no
@@ -1249,7 +1259,8 @@ main()
# __builtin_longjmp in ppc64* Linux does not restore
# the TOC register (r2), which is problematic
# when a global exit happens from JITted .so code.
- AS_CASE(["$target_cpu"], [powerpc64*], [
+ # __builtin_setjmp can have issues on arm64 linux (see [Bug #14480]).
+ AS_CASE(["$target_cpu"], [powerpc64*|arm64|aarch64], [
ac_cv_func___builtin_setjmp=no
])
# With gcc-8's -fcf-protection, RJIT's __builtin_longjmp fails.
@@ -1267,7 +1278,7 @@ main()
[wasi*],[ LIBS="-lm -lwasi-emulated-mman -lwasi-emulated-signal -lwasi-emulated-getpid -lwasi-emulated-process-clocks $LIBS"
RUBY_APPEND_OPTIONS(CFLAGS, -D_WASI_EMULATED_SIGNAL -D_WASI_EMULATED_MMAN -D_WASI_EMULATED_GETPID -D_WASI_EMULATED_PROCESS_CLOCKS)
RUBY_APPEND_OPTIONS(CPPFLAGS, -D_WASI_EMULATED_SIGNAL -D_WASI_EMULATED_MMAN -D_WASI_EMULATED_GETPID -D_WASI_EMULATED_PROCESS_CLOCKS)
- POSTLINK="\$(WASMOPT) --asyncify \$(wasmoptflags) --pass-arg=asyncify-ignore-imports -o \$@ \$@${POSTLINK:+; $POSTLINK}"
+ POSTLINK="\$(WASMOPT) --asyncify \$(wasmoptflags) -o \$@ \$@${POSTLINK:+; $POSTLINK}"
# wasi-libc's sys/socket.h is not compatible with -std=gnu99,
# so re-declare shutdown in include/ruby/missing.h
ac_cv_func_shutdown=no
@@ -1275,6 +1286,13 @@ main()
[ LIBS="-lm $LIBS"])
: ${ORIG_LIBS=$LIBS}
+AS_IF([test -n "${POSTLINK}"], [
+ # NOTE: A (part of) link commands used link shared extension libraries. If
+ # the first line of the value is empty, mkmf prepends default link steps.
+ LINK_SO="$LINK_SO
+\$(POSTLINK)"
+])
+
AS_IF([test -n "${rb_there_is_in_fact_no_gplusplus_but_autoconf_is_cheating_us}"], [
AC_MSG_NOTICE([Test skipped due to lack of a C++ compiler.])
],
@@ -1355,6 +1373,8 @@ AC_CHECK_HEADERS(time.h)
AC_CHECK_HEADERS(ucontext.h)
AC_CHECK_HEADERS(utime.h)
AC_CHECK_HEADERS(sys/epoll.h)
+AC_CHECK_HEADERS(sys/event.h)
+AC_CHECK_HEADERS(stdckdint.h)
AS_CASE("$target_cpu", [x64|x86_64|i[3-6]86*], [
AC_CHECK_HEADERS(x86intrin.h)
@@ -1362,7 +1382,7 @@ AS_CASE("$target_cpu", [x64|x86_64|i[3-6]86*], [
RUBY_UNIVERSAL_CHECK_HEADER([x86_64, i386], x86intrin.h)
AS_IF([test "x$with_gmp" != xno],
- [AC_CHECK_HEADERS(gmp.h)
+ [RUBY_CHECK_HEADER(gmp.h)
AS_IF([test "x$ac_cv_header_gmp_h" != xno],
AC_SEARCH_LIBS([__gmpz_init], [gmp],
[AC_DEFINE(HAVE_LIBGMP, 1)]))])
@@ -1372,6 +1392,8 @@ AC_ARG_WITH([jemalloc],
[with_jemalloc=$withval], [with_jemalloc=no])
AS_IF([test "x$with_jemalloc" != xno],[
# find jemalloc header first
+ save_CPPFLAGS="${CPPFLAGS}"
+ CPPFLAGS="${INCFLAGS} ${CPPFLAGS}"
malloc_header=
AC_CHECK_HEADER(jemalloc/jemalloc.h, [malloc_header=jemalloc/jemalloc.h], [
AC_CHECK_HEADER(jemalloc.h, [malloc_header=jemalloc.h])
@@ -1403,6 +1425,8 @@ AS_IF([test "x$with_jemalloc" != xno],[
done
done
])
+ CPPFLAGS="${save_CPPFLAGS}"
+ unset save_CPPFLAGS
with_jemalloc=${rb_cv_jemalloc_library}
AS_CASE(["$with_jemalloc"],
[no],
@@ -1428,7 +1452,7 @@ AC_SYS_LARGEFILE
# which is not added by AC_SYS_LARGEFILE.
AS_IF([test x"$enable_largefile" != xno], [
AS_CASE(["$target_os"], [solaris*], [
- AC_MSG_CHECKING([wheather _LARGEFILE_SOURCE should be defined])
+ AC_MSG_CHECKING([whether _LARGEFILE_SOURCE should be defined])
AS_CASE(["${ac_cv_sys_file_offset_bits}:${ac_cv_sys_large_files}"],
["64:"|"64:no"|"64:unknown"], [
# insert _LARGEFILE_SOURCE before _FILE_OFFSET_BITS line
@@ -1737,7 +1761,7 @@ AS_IF([test "$GCC" = yes], [
AC_CACHE_CHECK(for exported function attribute, rb_cv_func_exported, [
rb_cv_func_exported=no
RUBY_WERROR_FLAG([
-for mac in '__attribute__ ((__visibility__("default")))' '__declspec(dllexport)'; do
+for mac in '__declspec(dllexport)' '__attribute__ ((__visibility__("default")))'; do
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@define RUBY_FUNC_EXPORTED $mac extern
RUBY_FUNC_EXPORTED void conftest_attribute_check(void);]], [[]])],
[rb_cv_func_exported="$mac"; break])
@@ -1763,7 +1787,7 @@ AC_CACHE_CHECK(for function name string predefined identifier,
[AS_CASE(["$target_os"],[openbsd*],[
rb_cv_function_name_string=__func__
],[
- rb_cv_function_name_string=no
+ rb_cv_function_name_string=no
RUBY_WERROR_FLAG([
for func in __func__ __FUNCTION__; do
AC_LINK_IFELSE([AC_LANG_PROGRAM([[@%:@include <stdio.h>]],
@@ -1771,7 +1795,8 @@ AC_CACHE_CHECK(for function name string predefined identifier,
[rb_cv_function_name_string=$func
break])
done
- ])])]
+ ])
+ ])]
)
AS_IF([test "$rb_cv_function_name_string" != no], [
AC_DEFINE_UNQUOTED(RUBY_FUNCTION_NAME_STRING, [$rb_cv_function_name_string])
@@ -2095,7 +2120,6 @@ AC_CHECK_FUNCS(gettimeofday) # for making ac_cv_func_gettimeofday
AC_CHECK_FUNCS(getuid)
AC_CHECK_FUNCS(getuidx)
AC_CHECK_FUNCS(gmtime_r)
-AC_CHECK_FUNCS(grantpt)
AC_CHECK_FUNCS(initgroups)
AC_CHECK_FUNCS(ioctl)
AC_CHECK_FUNCS(isfinite)
@@ -2667,6 +2691,9 @@ AS_CASE([$coroutine_type], [yes|''], [
[*86-mingw*], [
coroutine_type=win32
],
+ [aarch64-mingw*], [
+ coroutine_type=arm64
+ ],
[arm*-linux*], [
coroutine_type=arm32
],
@@ -2966,7 +2993,7 @@ AS_IF([test "x$ac_cv_func_ioctl" = xyes], [
}
[begin]_group "runtime section" && {
-dnl wheather use dln_a_out or not
+dnl whether use dln_a_out or not
AC_ARG_WITH(dln-a-out,
AS_HELP_STRING([--with-dln-a-out], [dln_a_out is deprecated]),
[
@@ -3153,6 +3180,7 @@ AC_SUBST(EXTOBJS)
[hiuxmpp], [ : ${LDSHARED='$(LD) -r'}],
[atheos*], [ : ${LDSHARED='$(CC) -shared'}
rb_cv_dlopen=yes],
+ [wasi*], [ : ${LDSHARED='$(LD) -shared -Xlinker --export-dynamic'}],
[ : ${LDSHARED='$(LD)'}])
AC_MSG_RESULT($rb_cv_dlopen)
}
@@ -3551,7 +3579,7 @@ AS_CASE("$enable_shared", [yes], [
RUBY_APPEND_OPTIONS(LIBRUBY_DLDFLAGS, ['-Wl,-soname,$(LIBRUBY_SONAME)' "$LDFLAGS_OPTDIR"])
LIBRUBY_ALIASES='$(LIBRUBY_SONAME) lib$(RUBY_SO_NAME).$(SOEXT)'
AS_IF([test "$load_relative" = yes], [
- libprefix="'\$\${ORIGIN}/../${libdir_basename}'"
+ libprefix="'\$\${ORIGIN}/../${multiarch+../../}${libdir_basename}'"
LIBRUBY_RPATHFLAGS="-Wl,-rpath,${libprefix}"
LIBRUBY_RELATIVE=yes
])
@@ -3563,7 +3591,7 @@ AS_CASE("$enable_shared", [yes], [
LIBRUBY_SO="$LIBRUBY_SO.\$(TEENY)"
LIBRUBY_ALIASES=''
], [test "$load_relative" = yes], [
- libprefix="'\$\$ORIGIN/../${libdir_basename}'"
+ libprefix="'\$\$ORIGIN/../${multiarch+../../}${libdir_basename}'"
LIBRUBY_RPATHFLAGS="-Wl,-rpath,${libprefix}"
LIBRUBY_RELATIVE=yes
])
@@ -3587,7 +3615,7 @@ AS_CASE("$enable_shared", [yes], [
LIBRUBY_ALIASES='$(LIBRUBY_SONAME) lib$(RUBY_SO_NAME).$(SOEXT)'
RUBY_APPEND_OPTIONS(LIBRUBY_DLDFLAGS, ["${linker_flag}-h${linker_flag:+,}"'$(@F)'])
AS_IF([test "$load_relative" = yes], [
- libprefix="'\$\$ORIGIN/../${libdir_basename}'"
+ libprefix="'\$\$ORIGIN/../${multiarch+../../}${libdir_basename}'"
LIBRUBY_RPATHFLAGS="-R${libprefix}"
LIBRUBY_RELATIVE=yes
], [
@@ -3604,7 +3632,7 @@ AS_CASE("$enable_shared", [yes], [
LIBRUBY_SONAME='$(LIBRUBY_SO)'
LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).$(SOEXT)'
AS_IF([test "$load_relative" = yes], [
- libprefix="@executable_path/../${libdir_basename}"
+ libprefix="@executable_path/../${multiarch+../../}${libdir_basename}"
LIBRUBY_RELATIVE=yes
])
LIBRUBY_DLDFLAGS="$LIBRUBY_DLDFLAGS -install_name ${libprefix}"'/$(LIBRUBY_SONAME)'
@@ -3743,6 +3771,7 @@ AS_IF([test x"$gcov" = xyes], [
])
RUBY_SETJMP_TYPE
+RUBY_SHARED_GC
}
[begin]_group "installation section" && {
@@ -3916,49 +3945,42 @@ AC_SUBST(CARGO_BUILD_ARGS)dnl for selecting Rust build profiles
AC_SUBST(YJIT_LIBS)dnl for optionally building the Rust parts of YJIT
AC_SUBST(YJIT_OBJ)dnl for optionally building the C parts of YJIT
-dnl Currently, RJIT only supports Unix x86_64 platforms.
+dnl RJIT supports only x86_64 platforms, but allows arm64/aarch64 for custom JITs.
RJIT_TARGET_OK=no
AS_IF([test "$cross_compiling" = no],
AS_CASE(["$target_cpu-$target_os"],
[*android*], [
RJIT_TARGET_OK=no
],
- [x86_64-darwin*], [
+ [arm64-darwin*|aarch64-darwin*|x86_64-darwin*], [
RJIT_TARGET_OK=yes
],
- [x86_64-*linux*], [
+ [arm64-*linux*|aarch64-*linux*|x86_64-*linux*], [
RJIT_TARGET_OK=yes
],
- [x86_64-*bsd*], [
+ [arm64-*bsd*|aarch64-*bsd*|x86_64-*bsd*], [
RJIT_TARGET_OK=yes
]
)
)
-dnl Build RJIT on Unix x86_64 platforms or if --enable-rjit is specified.
+dnl Build RJIT on supported platforms or if --enable-rjit is specified.
AC_ARG_ENABLE(rjit,
AS_HELP_STRING([--enable-rjit],
[enable pure-Ruby JIT compiler. enabled by default on Unix x86_64 platforms]),
[RJIT_SUPPORT=$enableval],
- [AS_CASE(["$YJIT_TARGET_OK"],
+ [AS_CASE(["$RJIT_TARGET_OK"],
[yes], [RJIT_SUPPORT=yes],
[RJIT_SUPPORT=no]
)]
)
AS_CASE(["$RJIT_SUPPORT"],
-[yes|dev|disasm], [
+[yes|dev], [
AS_CASE(["$RJIT_SUPPORT"],
[dev], [
# Link libcapstone for --rjit-dump-disasm
AC_CHECK_LIB([capstone], [cs_disasm])
-
- # Enable extra stats (vm_insns_count, ratio_in_rjit)
- AC_DEFINE(RJIT_STATS, 1)
- ],
- [disasm], [
- # Link libcapstone for --rjit-dump-disasm
- AC_CHECK_LIB([capstone], [cs_disasm])
])
AC_DEFINE(USE_RJIT, 1)
@@ -4242,6 +4264,7 @@ AC_SUBST(MINIOBJS)
AC_SUBST(THREAD_MODEL)
AC_SUBST(COROUTINE_TYPE, ${coroutine_type})
AC_SUBST(PLATFORM_DIR)
+AC_SUBST(USE_LLVM_WINDRES)
firstmf=`echo $FIRSTMAKEFILE | sed 's/:.*//'`
firsttmpl=`echo $FIRSTMAKEFILE | sed 's/.*://'`
@@ -4589,6 +4612,9 @@ AC_CONFIG_FILES(Makefile:template/Makefile.in, [
], [
echo 'distclean-local::; @$(RM) GNUmakefile uncommon.mk'
])
+
+ echo; echo '$(srcdir)/$(CONFIGURE):RUBY_M4_INCLUDED \
+ $(empty)'
} > $tmpmk && AS_IF([! grep '^ruby:' $tmpmk > /dev/null], [
AS_IF([test "${gnumake}" = yes], [
tmpgmk=confgmk$$.tmp
@@ -4655,6 +4681,7 @@ config_summary "target OS" "$target_os"
config_summary "compiler" "$CC"
config_summary "with thread" "$THREAD_MODEL"
config_summary "with coroutine" "$coroutine_type"
+config_summary "with shared GC" "$with_shared_gc"
config_summary "enable shared libs" "$ENABLE_SHARED"
config_summary "dynamic library ext" "$DLEXT"
config_summary "CFLAGS" "$cflags"
diff --git a/cont.c b/cont.c
index 621de351cb..8f222dfef8 100644
--- a/cont.c
+++ b/cont.c
@@ -275,6 +275,12 @@ struct rb_fiber_struct {
static struct fiber_pool shared_fiber_pool = {NULL, NULL, 0, 0, 0, 0};
+void
+rb_free_shared_fiber_pool(void)
+{
+ xfree(shared_fiber_pool.allocations);
+}
+
static ID fiber_initialize_keywords[3] = {0};
/*
@@ -790,6 +796,9 @@ static inline void
ec_switch(rb_thread_t *th, rb_fiber_t *fiber)
{
rb_execution_context_t *ec = &fiber->cont.saved_ec;
+#ifdef RUBY_ASAN_ENABLED
+ ec->machine.asan_fake_stack_handle = asan_get_thread_fake_stack_handle();
+#endif
rb_ractor_set_current_ec(th->ractor, th->ec = ec);
// ruby_current_execution_context_ptr = th->ec = ec;
@@ -1017,13 +1026,8 @@ cont_mark(void *ptr)
cont->machine.stack + cont->machine.stack_size);
}
else {
- /* fiber */
- const rb_fiber_t *fiber = (rb_fiber_t*)cont;
-
- if (!FIBER_TERMINATED_P(fiber)) {
- rb_gc_mark_locations(cont->machine.stack,
- cont->machine.stack + cont->machine.stack_size);
- }
+ /* fiber machine context is marked as part of rb_execution_context_mark, no need to
+ * do anything here. */
}
}
@@ -1290,18 +1294,37 @@ rb_jit_cont_each_iseq(rb_iseq_callback callback, void *data)
if (cont->ec->vm_stack == NULL)
continue;
- const rb_control_frame_t *cfp;
- for (cfp = RUBY_VM_END_CONTROL_FRAME(cont->ec) - 1; ; cfp = RUBY_VM_NEXT_CONTROL_FRAME(cfp)) {
- const rb_iseq_t *iseq;
- if (cfp->pc && (iseq = cfp->iseq) != NULL && imemo_type((VALUE)iseq) == imemo_iseq) {
- callback(iseq, data);
+ const rb_control_frame_t *cfp = cont->ec->cfp;
+ while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(cont->ec, cfp)) {
+ if (cfp->pc && cfp->iseq && imemo_type((VALUE)cfp->iseq) == imemo_iseq) {
+ callback(cfp->iseq, data);
}
+ cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
+ }
+ }
+}
+
+#if USE_YJIT
+// Update the jit_return of all CFPs to leave_exit unless it's leave_exception or not set.
+// This prevents jit_exec_exception from jumping to the caller after invalidation.
+void
+rb_yjit_cancel_jit_return(void *leave_exit, void *leave_exception)
+{
+ struct rb_jit_cont *cont;
+ for (cont = first_jit_cont; cont != NULL; cont = cont->next) {
+ if (cont->ec->vm_stack == NULL)
+ continue;
- if (cfp == cont->ec->cfp)
- break; // reached the most recent cfp
+ const rb_control_frame_t *cfp = cont->ec->cfp;
+ while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(cont->ec, cfp)) {
+ if (cfp->jit_return && cfp->jit_return != leave_exception) {
+ ((rb_control_frame_t *)cfp)->jit_return = leave_exit;
+ }
+ cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
}
}
}
+#endif
// Finish working with jit_cont.
void
@@ -1543,11 +1566,10 @@ fiber_setcontext(rb_fiber_t *new_fiber, rb_fiber_t *old_fiber)
}
}
- /* exchange machine_stack_start between old_fiber and new_fiber */
+ /* these values are used in rb_gc_mark_machine_context to mark the fiber's stack. */
old_fiber->cont.saved_ec.machine.stack_start = th->ec->machine.stack_start;
+ old_fiber->cont.saved_ec.machine.stack_end = FIBER_TERMINATED_P(old_fiber) ? NULL : th->ec->machine.stack_end;
- /* old_fiber->machine.stack_end should be NULL */
- old_fiber->cont.saved_ec.machine.stack_end = NULL;
// if (DEBUG) fprintf(stderr, "fiber_setcontext: %p[%p] -> %p[%p]\n", (void*)old_fiber, old_fiber->stack.base, (void*)new_fiber, new_fiber->stack.base);
@@ -1750,6 +1772,13 @@ rb_callcc(VALUE self)
return rb_yield(val);
}
}
+#ifdef RUBY_ASAN_ENABLED
+/* callcc can't possibly work with ASAN; see bug #20273. Also this function
+ * definition below avoids a "defined and not used" warning. */
+MAYBE_UNUSED(static void notusing_callcc(void)) { rb_callcc(Qnil); }
+# define rb_callcc rb_f_notimplement
+#endif
+
static VALUE
make_passing_arg(int argc, const VALUE *argv)
@@ -2353,7 +2382,7 @@ rb_fiber_initialize(int argc, VALUE* argv, VALUE self)
VALUE
rb_fiber_new_storage(rb_block_call_func_t func, VALUE obj, VALUE storage)
{
- return fiber_initialize(fiber_alloc(rb_cFiber), rb_proc_new(func, obj), rb_fiber_pool_default(Qnil), 1, storage);
+ return fiber_initialize(fiber_alloc(rb_cFiber), rb_proc_new(func, obj), rb_fiber_pool_default(Qnil), 0, storage);
}
VALUE
@@ -2540,11 +2569,10 @@ rb_fiber_start(rb_fiber_t *fiber)
void
rb_threadptr_root_fiber_setup(rb_thread_t *th)
{
- rb_fiber_t *fiber = ruby_mimmalloc(sizeof(rb_fiber_t));
+ rb_fiber_t *fiber = ruby_mimcalloc(1, sizeof(rb_fiber_t));
if (!fiber) {
rb_bug("%s", strerror(errno)); /* ... is it possible to call rb_bug here? */
}
- MEMZERO(fiber, rb_fiber_t, 1);
fiber->cont.type = FIBER_CONTEXT;
fiber->cont.saved_ec.fiber_ptr = fiber;
fiber->cont.saved_ec.thread_ptr = th;
@@ -2562,12 +2590,12 @@ rb_threadptr_root_fiber_release(rb_thread_t *th)
/* ignore. A root fiber object will free th->ec */
}
else {
- rb_execution_context_t *ec = GET_EC();
+ rb_execution_context_t *ec = rb_current_execution_context(false);
VM_ASSERT(th->ec->fiber_ptr->cont.type == FIBER_CONTEXT);
VM_ASSERT(th->ec->fiber_ptr->cont.self == 0);
- if (th->ec == ec) {
+ if (ec && th->ec == ec) {
rb_ractor_set_current_ec(th->ractor, NULL);
}
fiber_free(th->ec->fiber_ptr);
@@ -3198,7 +3226,13 @@ rb_fiber_s_yield(int argc, VALUE *argv, VALUE klass)
static VALUE
fiber_raise(rb_fiber_t *fiber, VALUE exception)
{
- if (FIBER_SUSPENDED_P(fiber) && !fiber->yielding) {
+ if (fiber == fiber_current()) {
+ rb_exc_raise(exception);
+ }
+ else if (fiber->resuming_fiber) {
+ return fiber_raise(fiber->resuming_fiber, exception);
+ }
+ else if (FIBER_SUSPENDED_P(fiber) && !fiber->yielding) {
return fiber_transfer_kw(fiber, -1, &exception, RB_NO_KEYWORDS);
}
else {
@@ -3234,6 +3268,10 @@ rb_fiber_raise(VALUE fiber, int argc, const VALUE *argv)
* the exception, and the third parameter is an array of callback information.
* Exceptions are caught by the +rescue+ clause of <code>begin...end</code>
* blocks.
+ *
+ * Raises +FiberError+ if called on a Fiber belonging to another +Thread+.
+ *
+ * See Kernel#raise for more information.
*/
static VALUE
rb_fiber_m_raise(int argc, VALUE *argv, VALUE self)
@@ -3245,12 +3283,18 @@ rb_fiber_m_raise(int argc, VALUE *argv, VALUE self)
* call-seq:
* fiber.kill -> nil
*
- * Terminates +fiber+ by raising an uncatchable exception, returning
- * the terminated Fiber.
+ * Terminates the fiber by raising an uncatchable exception.
+ * It only terminates the given fiber and no other fiber, returning +nil+ to
+ * another fiber if that fiber was calling #resume or #transfer.
+ *
+ * <tt>Fiber#kill</tt> only interrupts another fiber when it is in Fiber.yield.
+ * If called on the current fiber then it raises that exception at the <tt>Fiber#kill</tt> call site.
*
* If the fiber has not been started, transition directly to the terminated state.
*
* If the fiber is already terminated, does nothing.
+ *
+ * Raises FiberError if called on a fiber belonging to another thread.
*/
static VALUE
rb_fiber_m_kill(VALUE self)
@@ -3266,7 +3310,8 @@ rb_fiber_m_kill(VALUE self)
else if (fiber->status != FIBER_TERMINATED) {
if (fiber_current() == fiber) {
fiber_check_killed(fiber);
- } else {
+ }
+ else {
fiber_raise(fiber_ptr(self), Qnil);
}
}
diff --git a/coroutine/arm64/Context.S b/coroutine/arm64/Context.S
index 07d50d30df..5251ab214d 100644
--- a/coroutine/arm64/Context.S
+++ b/coroutine/arm64/Context.S
@@ -18,11 +18,25 @@
.align 2
#endif
+## NOTE(PAC): Use we HINT mnemonics instead of PAC mnemonics to
+## keep compatibility with those assemblers that don't support PAC.
+##
+## See "Providing protection for complex software" for more details about PAC/BTI
+## https://developer.arm.com/architectures/learn-the-architecture/providing-protection-for-complex-software
+
.global PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer)
PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
+#if defined(__ARM_FEATURE_PAC_DEFAULT) && (__ARM_FEATURE_PAC_DEFAULT != 0)
+ # paciasp (it also acts as BTI landing pad, so no need to insert BTI also)
+ hint #25
+#elif defined(__ARM_FEATURE_BTI_DEFAULT) && (__ARM_FEATURE_BTI_DEFAULT != 0)
+ # For the case PAC is not enabled but BTI is.
+ # bti c
+ hint #34
+#endif
# Make space on the stack for caller registers
- sub sp, sp, 0xb0
+ sub sp, sp, 0xa0
# Save caller registers
stp d8, d9, [sp, 0x00]
@@ -36,9 +50,6 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
stp x27, x28, [sp, 0x80]
stp x29, x30, [sp, 0x90]
- # Save return address
- str x30, [sp, 0xa0]
-
# Save stack pointer to x0 (first argument)
mov x2, sp
str x2, [x0, 0]
@@ -59,15 +70,51 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
ldp x27, x28, [sp, 0x80]
ldp x29, x30, [sp, 0x90]
- # Load return address into x4
- ldr x4, [sp, 0xa0]
-
# Pop stack frame
- add sp, sp, 0xb0
+ add sp, sp, 0xa0
- # Jump to return address (in x4)
- ret x4
+#if defined(__ARM_FEATURE_PAC_DEFAULT) && (__ARM_FEATURE_PAC_DEFAULT != 0)
+ # autiasp: Authenticate x30 (LR) with SP and key A
+ hint #29
+#endif
+
+ # Jump to return address (in x30)
+ ret
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
#endif
+
+#if __ARM_FEATURE_BTI_DEFAULT != 0 || __ARM_FEATURE_PAC_DEFAULT != 0
+/* See "ELF for the Arm 64-bit Architecture (AArch64)"
+ https://github.com/ARM-software/abi-aa/blob/2023Q3/aaelf64/aaelf64.rst#program-property */
+# define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1<<0)
+# define GNU_PROPERTY_AARCH64_FEATURE_1_PAC (1<<1)
+
+# if __ARM_FEATURE_BTI_DEFAULT != 0
+# define BTI_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_BTI
+# else
+# define BTI_FLAG 0
+# endif
+# if __ARM_FEATURE_PAC_DEFAULT != 0
+# define PAC_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_PAC
+# else
+# define PAC_FLAG 0
+# endif
+
+ # The note section format is described by Note Section in Chapter 5
+ # of "System V Application Binary Interface, Edition 4.1".
+ .pushsection .note.gnu.property, "a"
+ .p2align 3
+ .long 0x4 /* Name size ("GNU\0") */
+ .long 0x10 /* Descriptor size */
+ .long 0x5 /* Type: NT_GNU_PROPERTY_TYPE_0 */
+ .asciz "GNU" /* Name */
+ # Begin descriptor
+ .long 0xc0000000 /* Property type: GNU_PROPERTY_AARCH64_FEATURE_1_AND */
+ .long 0x4 /* Property size */
+ .long (BTI_FLAG|PAC_FLAG)
+ .long 0x0 /* 8-byte alignment padding */
+ # End descriptor
+ .popsection
+#endif
diff --git a/coroutine/arm64/Context.h b/coroutine/arm64/Context.h
index 1472621f48..eb66fbea0f 100644
--- a/coroutine/arm64/Context.h
+++ b/coroutine/arm64/Context.h
@@ -17,7 +17,7 @@
#define COROUTINE __attribute__((noreturn)) void
-enum {COROUTINE_REGISTERS = 0xb0 / 8};
+enum {COROUTINE_REGISTERS = 0xa0 / 8};
#if defined(__SANITIZE_ADDRESS__)
#define COROUTINE_SANITIZE_ADDRESS
@@ -50,6 +50,20 @@ static inline void coroutine_initialize_main(struct coroutine_context * context)
context->stack_pointer = NULL;
}
+static inline void *ptrauth_sign_instruction_addr(void *addr, void *modifier) {
+#if defined(__ARM_FEATURE_PAC_DEFAULT) && __ARM_FEATURE_PAC_DEFAULT != 0
+ // Sign the given instruction address with the given modifier and key A
+ register void *r17 __asm("r17") = addr;
+ register void *r16 __asm("r16") = modifier;
+ // Use HINT mnemonic instead of PACIA1716 for compatibility with older assemblers.
+ __asm ("hint #8;" : "+r"(r17) : "r"(r16));
+ addr = r17;
+#else
+ // No-op if PAC is not enabled
+#endif
+ return addr;
+}
+
static inline void coroutine_initialize(
struct coroutine_context *context,
coroutine_start start,
@@ -66,12 +80,13 @@ static inline void coroutine_initialize(
// Stack grows down. Force 16-byte alignment.
char * top = (char*)stack + size;
- context->stack_pointer = (void**)((uintptr_t)top & ~0xF);
+ top = (char *)((uintptr_t)top & ~0xF);
+ context->stack_pointer = (void**)top;
context->stack_pointer -= COROUTINE_REGISTERS;
memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS);
- context->stack_pointer[0xa0 / 8] = (void*)start;
+ context->stack_pointer[0x98 / 8] = ptrauth_sign_instruction_addr((void*)start, (void*)top);
}
struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target);
diff --git a/coroutine/asyncify/Context.h b/coroutine/asyncify/Context.h
index 7dba829a1d..71791a4004 100644
--- a/coroutine/asyncify/Context.h
+++ b/coroutine/asyncify/Context.h
@@ -13,6 +13,7 @@
#include <stddef.h>
#include <stdio.h>
+#include <stdint.h>
#include "wasm/asyncify.h"
#include "wasm/machine.h"
#include "wasm/fiber.h"
@@ -47,10 +48,13 @@ static inline void coroutine_initialize_main(struct coroutine_context * context)
static inline void coroutine_initialize(struct coroutine_context *context, coroutine_start start, void *stack, size_t size)
{
- if (ASYNCIFY_CORO_DEBUG) fprintf(stderr, "[%s] entry (context = %p, stack = %p ... %p)\n", __func__, context, stack, (char *)stack + size);
+ // Linear stack pointer must be always aligned down to 16 bytes.
+ // https://github.com/WebAssembly/tool-conventions/blob/c74267a5897c1bdc9aa60adeaf41816387d3cd12/BasicCABI.md#the-linear-stack
+ uintptr_t sp = ((uintptr_t)stack + size) & ~0xF;
+ if (ASYNCIFY_CORO_DEBUG) fprintf(stderr, "[%s] entry (context = %p, stack = %p ... %p)\n", __func__, context, stack, (char *)sp);
rb_wasm_init_context(&context->fc, coroutine_trampoline, start, context);
// record the initial stack pointer position to restore it after resumption
- context->current_sp = (char *)stack + size;
+ context->current_sp = (char *)sp;
context->stack_base = stack;
context->size = size;
}
diff --git a/coroutine/win64/Context.h b/coroutine/win64/Context.h
index aaa4caeaf9..d85ebf8e0e 100644
--- a/coroutine/win64/Context.h
+++ b/coroutine/win64/Context.h
@@ -30,7 +30,7 @@ struct coroutine_context
typedef void(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self);
-void coroutine_trampoline();
+void coroutine_trampoline(void);
static inline void coroutine_initialize_main(struct coroutine_context * context) {
context->stack_pointer = NULL;
diff --git a/cygwin/GNUmakefile.in b/cygwin/GNUmakefile.in
index 0929859030..192a8cc711 100644
--- a/cygwin/GNUmakefile.in
+++ b/cygwin/GNUmakefile.in
@@ -3,9 +3,14 @@ gnumake = yes
include Makefile
DLLWRAP = @DLLWRAP@ --target=$(target_os) --driver-name="$(CC)"
-windres-cpp := $(CPP) -xc
-windres-cpp := --preprocessor=$(firstword $(windres-cpp)) \
- $(addprefix --preprocessor-arg=,$(wordlist 2,$(words $(windres-cpp)),$(windres-cpp)))
+ifeq (@USE_LLVM_WINDRES@,yes) # USE_LLVM_WINDRES
+ # llvm-windres fails when preprocessor options are added
+ windres-cpp :=
+else
+ windres-cpp := $(CPP) -xc
+ windres-cpp := --preprocessor=$(firstword $(windres-cpp)) \
+ $(addprefix --preprocessor-arg=,$(wordlist 2,$(words $(windres-cpp)),$(windres-cpp)))
+endif
WINDRES = @WINDRES@ $(windres-cpp) -DRC_INVOKED
STRIP = @STRIP@
diff --git a/darray.h b/darray.h
index 8e1e576355..d24e3c3eb5 100644
--- a/darray.h
+++ b/darray.h
@@ -6,7 +6,6 @@
#include <stdlib.h>
#include "internal/bits.h"
-#include "internal/gc.h"
// Type for a dynamic array. Use to declare a dynamic array.
// It is a pointer so it fits in st_table nicely. Designed
@@ -45,16 +44,12 @@
* void rb_darray_append(rb_darray(T) *ptr_to_ary, T element);
*/
#define rb_darray_append(ptr_to_ary, element) \
- rb_darray_append_impl(ptr_to_ary, element, rb_xrealloc_mul_add)
+ rb_darray_append_impl(ptr_to_ary, element)
-#define rb_darray_append_without_gc(ptr_to_ary, element) \
- rb_darray_append_impl(ptr_to_ary, element, rb_darray_realloc_mul_add_without_gc)
-
-#define rb_darray_append_impl(ptr_to_ary, element, realloc_func) do { \
+#define rb_darray_append_impl(ptr_to_ary, element) do { \
rb_darray_ensure_space((ptr_to_ary), \
sizeof(**(ptr_to_ary)), \
- sizeof((*(ptr_to_ary))->data[0]), \
- realloc_func); \
+ sizeof((*(ptr_to_ary))->data[0])); \
rb_darray_set(*(ptr_to_ary), \
(*(ptr_to_ary))->meta.size, \
(element)); \
@@ -79,21 +74,15 @@
* void rb_darray_make(rb_darray(T) *ptr_to_ary, size_t size);
*/
#define rb_darray_make(ptr_to_ary, size) \
- rb_darray_make_impl((ptr_to_ary), size, sizeof(**(ptr_to_ary)), \
- sizeof((*(ptr_to_ary))->data[0]), rb_xcalloc_mul_add)
-
-#define rb_darray_make_without_gc(ptr_to_ary, size) \
- rb_darray_make_impl((ptr_to_ary), size, sizeof(**(ptr_to_ary)), \
- sizeof((*(ptr_to_ary))->data[0]), rb_darray_calloc_mul_add_without_gc)
+ rb_darray_make_impl((ptr_to_ary), size, sizeof(**(ptr_to_ary)), sizeof((*(ptr_to_ary))->data[0]))
/* Resize the darray to a new capacity. The new capacity must be greater than
* or equal to the size of the darray.
*
* void rb_darray_resize_capa(rb_darray(T) *ptr_to_ary, size_t capa);
*/
-#define rb_darray_resize_capa_without_gc(ptr_to_ary, capa) \
- rb_darray_resize_capa_impl((ptr_to_ary), rb_darray_next_power_of_two(capa), sizeof(**(ptr_to_ary)), \
- sizeof((*(ptr_to_ary))->data[0]), rb_darray_realloc_mul_add_without_gc)
+#define rb_darray_resize_capa(ptr_to_ary, capa) \
+ rb_darray_resize_capa_impl((ptr_to_ary), capa, sizeof(**(ptr_to_ary)), sizeof((*(ptr_to_ary))->data[0]))
#define rb_darray_data_ptr(ary) ((ary)->data)
@@ -135,60 +124,18 @@ rb_darray_capa(const void *ary)
static inline void
rb_darray_free(void *ary)
{
- rb_darray_meta_t *meta = ary;
- if (meta) ruby_sized_xfree(ary, meta->capa);
-}
-
-static inline void
-rb_darray_free_without_gc(void *ary)
-{
- free(ary);
-}
-
-/* Internal function. Like rb_xcalloc_mul_add but does not trigger GC and does
- * not check for overflow in arithmetic. */
-static inline void *
-rb_darray_calloc_mul_add_without_gc(size_t x, size_t y, size_t z)
-{
- size_t size = (x * y) + z;
-
- void *ptr = calloc(1, size);
- if (ptr == NULL) rb_bug("rb_darray_calloc_mul_add_without_gc: failed");
-
- return ptr;
-}
-
-/* Internal function. Like rb_xrealloc_mul_add but does not trigger GC and does
- * not check for overflow in arithmetic. */
-static inline void *
-rb_darray_realloc_mul_add_without_gc(const void *orig_ptr, size_t x, size_t y, size_t z)
-{
- size_t size = (x * y) + z;
-
- void *ptr = realloc((void *)orig_ptr, size);
- if (ptr == NULL) rb_bug("rb_darray_realloc_mul_add_without_gc: failed");
-
- return ptr;
-}
-
-/* Internal function. Returns the next power of two that is greater than or
- * equal to n. */
-static inline size_t
-rb_darray_next_power_of_two(size_t n)
-{
- return (size_t)(1 << (64 - nlz_int64(n)));
+ xfree(ary);
}
/* Internal function. Resizes the capacity of a darray. The new capacity must
* be greater than or equal to the size of the darray. */
static inline void
-rb_darray_resize_capa_impl(void *ptr_to_ary, size_t new_capa, size_t header_size, size_t element_size,
- void *(*realloc_mul_add_impl)(const void *, size_t, size_t, size_t))
+rb_darray_resize_capa_impl(void *ptr_to_ary, size_t new_capa, size_t header_size, size_t element_size)
{
rb_darray_meta_t **ptr_to_ptr_to_meta = ptr_to_ary;
rb_darray_meta_t *meta = *ptr_to_ptr_to_meta;
- rb_darray_meta_t *new_ary = realloc_mul_add_impl(meta, new_capa, element_size, header_size);
+ rb_darray_meta_t *new_ary = xrealloc(meta, new_capa * element_size + header_size);
if (meta == NULL) {
/* First allocation. Initialize size. On subsequence allocations
@@ -196,7 +143,7 @@ rb_darray_resize_capa_impl(void *ptr_to_ary, size_t new_capa, size_t header_size
new_ary->size = 0;
}
- assert(new_ary->size <= new_capa);
+ RUBY_ASSERT(new_ary->size <= new_capa);
new_ary->capa = new_capa;
@@ -209,8 +156,7 @@ rb_darray_resize_capa_impl(void *ptr_to_ary, size_t new_capa, size_t header_size
// Ensure there is space for one more element.
// Note: header_size can be bigger than sizeof(rb_darray_meta_t) when T is __int128_t, for example.
static inline void
-rb_darray_ensure_space(void *ptr_to_ary, size_t header_size, size_t element_size,
- void *(*realloc_mul_add_impl)(const void *, size_t, size_t, size_t))
+rb_darray_ensure_space(void *ptr_to_ary, size_t header_size, size_t element_size)
{
rb_darray_meta_t **ptr_to_ptr_to_meta = ptr_to_ary;
rb_darray_meta_t *meta = *ptr_to_ptr_to_meta;
@@ -220,12 +166,11 @@ rb_darray_ensure_space(void *ptr_to_ary, size_t header_size, size_t element_size
// Double the capacity
size_t new_capa = current_capa == 0 ? 1 : current_capa * 2;
- rb_darray_resize_capa_impl(ptr_to_ary, new_capa, header_size, element_size, realloc_mul_add_impl);
+ rb_darray_resize_capa_impl(ptr_to_ary, new_capa, header_size, element_size);
}
static inline void
-rb_darray_make_impl(void *ptr_to_ary, size_t array_size, size_t header_size, size_t element_size,
- void *(*calloc_mul_add_impl)(size_t, size_t, size_t))
+rb_darray_make_impl(void *ptr_to_ary, size_t array_size, size_t header_size, size_t element_size)
{
rb_darray_meta_t **ptr_to_ptr_to_meta = ptr_to_ary;
if (array_size == 0) {
@@ -233,7 +178,7 @@ rb_darray_make_impl(void *ptr_to_ary, size_t array_size, size_t header_size, siz
return;
}
- rb_darray_meta_t *meta = calloc_mul_add_impl(array_size, element_size, header_size);
+ rb_darray_meta_t *meta = xcalloc(array_size * element_size + header_size, 1);
meta->size = array_size;
meta->capa = array_size;
diff --git a/debug.c b/debug.c
index e84e3d602a..4717a0bc9c 100644
--- a/debug.c
+++ b/debug.c
@@ -147,13 +147,21 @@ NODE *
ruby_debug_print_node(int level, int debug_level, const char *header, const NODE *node)
{
if (level < debug_level) {
- fprintf(stderr, "DBG> %s: %s (%u)\n", header,
- ruby_node_name(nd_type(node)), nd_line(node));
+ fprintf(stderr, "DBG> %s: %s (id: %d, line: %d, location: (%d,%d)-(%d,%d))\n",
+ header, ruby_node_name(nd_type(node)), nd_node_id(node), nd_line(node),
+ nd_first_lineno(node), nd_first_column(node),
+ nd_last_lineno(node), nd_last_column(node));
}
return (NODE *)node;
}
void
+ruby_debug_print_n(const NODE *node)
+{
+ ruby_debug_print_node(0, 1, "", node);
+}
+
+void
ruby_debug_breakpoint(void)
{
/* */
@@ -177,9 +185,9 @@ ruby_env_debug_option(const char *str, int len, void *arg)
int ov;
size_t retlen;
unsigned long n;
+#define NAME_MATCH(name) (len == sizeof(name) - 1 && strncmp(str, (name), len) == 0)
#define SET_WHEN(name, var, val) do { \
- if (len == sizeof(name) - 1 && \
- strncmp(str, (name), len) == 0) { \
+ if (NAME_MATCH(name)) { \
(var) = (val); \
return 1; \
} \
@@ -207,31 +215,31 @@ ruby_env_debug_option(const char *str, int len, void *arg)
--len; \
} \
if (len > 0) { \
- fprintf(stderr, "ignored "name" option: `%.*s'\n", len, str); \
+ fprintf(stderr, "ignored "name" option: '%.*s'\n", len, str); \
} \
} while (0)
#define SET_WHEN_UINT(name, vals, num, req) \
- if (NAME_MATCH_VALUE(name)) SET_UINT_LIST(name, vals, num);
+ if (NAME_MATCH_VALUE(name)) { \
+ if (!len) req; \
+ else SET_UINT_LIST(name, vals, num); \
+ return 1; \
+ }
- SET_WHEN("gc_stress", *ruby_initial_gc_stress_ptr, Qtrue);
- SET_WHEN("core", ruby_enable_coredump, 1);
- SET_WHEN("ci", ruby_on_ci, 1);
- if (NAME_MATCH_VALUE("rgengc")) {
- if (!len) ruby_rgengc_debug = 1;
- else SET_UINT_LIST("rgengc", &ruby_rgengc_debug, 1);
+ if (NAME_MATCH("gc_stress")) {
+ rb_gc_initial_stress_set(Qtrue);
return 1;
}
+ SET_WHEN("core", ruby_enable_coredump, 1);
+ SET_WHEN("ci", ruby_on_ci, 1);
+ SET_WHEN_UINT("rgengc", &ruby_rgengc_debug, 1, ruby_rgengc_debug = 1);
#if defined _WIN32
# if RUBY_MSVCRT_VERSION >= 80
SET_WHEN("rtc_error", ruby_w32_rtc_error, 1);
# endif
#endif
#if defined _WIN32 || defined __CYGWIN__
- if (NAME_MATCH_VALUE("codepage")) {
- if (!len) fprintf(stderr, "missing codepage argument");
- else SET_UINT_LIST("codepage", ruby_w32_codepage, numberof(ruby_w32_codepage));
- return 1;
- }
+ SET_WHEN_UINT("codepage", ruby_w32_codepage, numberof(ruby_w32_codepage),
+ fprintf(stderr, "missing codepage argument"));
#endif
return 0;
}
@@ -675,7 +683,7 @@ debug_log_dump(FILE *out, unsigned int n)
int index = current_index - size + i;
if (index < 0) index += MAX_DEBUG_LOG;
VM_ASSERT(index <= MAX_DEBUG_LOG);
- const char *mesg = RUBY_DEBUG_LOG_MEM_ENTRY(index);;
+ const char *mesg = RUBY_DEBUG_LOG_MEM_ENTRY(index);
fprintf(out, "%4u: %s\n", debug_log.cnt - size + i, mesg);
}
}
diff --git a/debug_counter.h b/debug_counter.h
index a8b95edded..481a0727e6 100644
--- a/debug_counter.h
+++ b/debug_counter.h
@@ -356,7 +356,7 @@ RB_DEBUG_COUNTER(load_path_is_not_realpath)
enum rb_debug_counter_type {
#define RB_DEBUG_COUNTER(name) RB_DEBUG_COUNTER_##name,
-#include __FILE__
+#include "debug_counter.h"
RB_DEBUG_COUNTER_MAX
#undef RB_DEBUG_COUNTER
};
diff --git a/defs/gmake.mk b/defs/gmake.mk
index 5489b017b3..b34e8420ba 100644
--- a/defs/gmake.mk
+++ b/defs/gmake.mk
@@ -37,7 +37,7 @@ TEST_TARGETS := $(patsubst test,test-short,$(TEST_TARGETS))
TEST_DEPENDS := $(filter-out test $(TEST_TARGETS),$(TEST_DEPENDS))
TEST_TARGETS := $(patsubst test-short,btest-ruby test-knownbug test-basic,$(TEST_TARGETS))
TEST_TARGETS := $(patsubst test-basic,test-basic test-leaked-globals,$(TEST_TARGETS))
-TEST_TARGETS := $(patsubst test-bundled-gems,test-bundled-gems-run,$(TEST_TARGETS))
+TEST_TARGETS := $(patsubst test-bundled-gems,test-bundled-gems-spec test-bundled-gems-run,$(TEST_TARGETS))
TEST_TARGETS := $(patsubst test-bundled-gems-run,test-bundled-gems-run $(PREPARE_BUNDLED_GEMS),$(TEST_TARGETS))
TEST_TARGETS := $(patsubst test-bundled-gems-prepare,test-bundled-gems-prepare $(PRECHECK_BUNDLED_GEMS) test-bundled-gems-fetch,$(TEST_TARGETS))
TEST_TARGETS := $(patsubst test-bundler-parallel,test-bundler-parallel $(PREPARE_BUNDLER),$(TEST_TARGETS))
@@ -97,6 +97,7 @@ ORDERED_TEST_TARGETS := $(filter $(TEST_TARGETS), \
test-bundler-prepare test-bundler test-bundler-parallel \
test-bundled-gems-precheck test-bundled-gems-fetch \
test-bundled-gems-prepare test-bundled-gems-run \
+ test-bundled-gems-spec \
)
# grep ^yes-test-.*-precheck: template/Makefile.in defs/gmake.mk common.mk
@@ -193,7 +194,7 @@ $(SCRIPTBINDIR):
$(Q) mkdir $@
.PHONY: commit
-COMMIT_PREPARE := $(filter-out commit do-commit,$(MAKECMDGOALS)) up
+COMMIT_PREPARE := $(subst :,\:,$(filter-out commit do-commit,$(MAKECMDGOALS))) up
commit: pre-commit $(DOT_WAIT) do-commit $(DOT_WAIT) post_commit
pre-commit: $(COMMIT_PREPARE)
@@ -469,6 +470,10 @@ benchmark/%: miniruby$(EXEEXT) update-benchmark-driver PHONY
--executables="built-ruby::$(BENCH_RUBY) --disable-gem" \
$(srcdir)/$@ $(BENCH_OPTS) $(OPTS)
+clean-local:: TARGET_SO = $(PROGRAM) $(WPROGRAM) $(LIBRUBY_SO) $(STATIC_RUBY) miniruby goruby
+clean-local::
+ -$(Q)$(RMALL) $(cleanlibs)
+
clean-srcs-ext::
$(Q)$(RM) $(patsubst $(srcdir)/%,%,$(EXT_SRCS))
@@ -504,12 +509,17 @@ $(RUBYSPEC_CAPIEXT)/%.$(DLEXT): $(srcdir)/$(RUBYSPEC_CAPIEXT)/%.c $(srcdir)/$(RU
$(ECHO) building $@
$(Q) $(MAKEDIRS) $(@D)
$(Q) $(DLDSHARED) -L. $(XDLDFLAGS) $(XLDFLAGS) $(LDFLAGS) $(INCFLAGS) $(CPPFLAGS) $(OUTFLAG)$@ $< $(LIBRUBYARG)
+ifneq ($(POSTLINK),)
+ $(Q) $(POSTLINK)
+endif
$(Q) $(RMALL) $@.*
-rubyspec-capiext: $(patsubst %.c,$(RUBYSPEC_CAPIEXT)/%.$(DLEXT),$(notdir $(wildcard $(srcdir)/$(RUBYSPEC_CAPIEXT)/*.c)))
+RUBYSPEC_CAPIEXT_SO := $(patsubst %.c,$(RUBYSPEC_CAPIEXT)/%.$(DLEXT),$(notdir $(wildcard $(srcdir)/$(RUBYSPEC_CAPIEXT)/*.c)))
+rubyspec-capiext: $(RUBYSPEC_CAPIEXT_SO)
@ $(NULLCMD)
ifeq ($(ENABLE_SHARED),yes)
+ruby: $(if $(LIBRUBY_SO_UPDATE),$(RUBYSPEC_CAPIEXT_SO))
exts: rubyspec-capiext
endif
@@ -519,14 +529,29 @@ spec/%/ spec/%_spec.rb: programs exts PHONY
ruby.pc: $(filter-out ruby.pc,$(ruby_pc))
matz: up
+ $(eval OLD := $(MAJOR).$(MINOR).0)
$(eval MINOR := $(shell expr $(MINOR) + 1))
- $(eval message := Development of $(MAJOR).$(MINOR).0 started.)
+ $(eval NEW := $(MAJOR).$(MINOR).0)
+ $(eval message := Development of $(NEW) started.)
$(eval files := include/ruby/version.h include/ruby/internal/abi.h)
+ $(GIT) -C $(srcdir) mv -f NEWS.md doc/NEWS/NEWS-$(OLD).md
+ $(GIT) -C $(srcdir) commit -m "[DOC] Flush NEWS.md"
sed -i~ \
-e "s/^\(#define RUBY_API_VERSION_MINOR\) .*/\1 $(MINOR)/" \
-e "s/^\(#define RUBY_ABI_VERSION\) .*/\1 0/" \
$(files:%=$(srcdir)/%)
- $(GIT) -C $(srcdir) commit -m "$(message)" $(files)
+ $(GIT) -C $(srcdir) add $(files)
+ $(BASERUBY) -C $(srcdir) -p -00 \
+ -e 'BEGIN {old, new = ARGV.shift(2); STDOUT.reopen("NEWS.md")}' \
+ -e 'case $$.' \
+ -e 'when 1; $$_.sub!(/Ruby \K[0-9.]+/, new)' \
+ -e 'when 2; $$_.sub!(/\*\*\K[0-9.]+(?=\*\*)/, old)' \
+ -e 'end' \
+ -e 'next if /^[\[ *]/ =~ $$_' \
+ -e '$$_.sub!(/\n{2,}\z/, "\n\n")' \
+ $(OLD) $(NEW) doc/NEWS/NEWS-$(OLD).md
+ $(GIT) -C $(srcdir) add NEWS.md
+ $(GIT) -C $(srcdir) commit -m "$(message)"
tags:
$(MAKE) GIT="$(GIT)" -C "$(srcdir)" -f defs/tags.mk
diff --git a/defs/id.def b/defs/id.def
index 2ddde7be70..71baa4f968 100644
--- a/defs/id.def
+++ b/defs/id.def
@@ -59,6 +59,7 @@ firstline, predefined = __LINE__+1, %[\
name
nil
path
+ pack
_ UScore
diff --git a/defs/known_errors.def b/defs/known_errors.def
index e9694cfbda..23e9e53507 100644
--- a/defs/known_errors.def
+++ b/defs/known_errors.def
@@ -1,157 +1,157 @@
-E2BIG
-EACCES
-EADDRINUSE
-EADDRNOTAVAIL
-EADV
-EAFNOSUPPORT
-EAGAIN
-EALREADY
-EAUTH
-EBADARCH
-EBADE
-EBADEXEC
-EBADF
-EBADFD
-EBADMACHO
-EBADMSG
-EBADR
-EBADRPC
-EBADRQC
-EBADSLT
-EBFONT
-EBUSY
-ECANCELED
-ECAPMODE
-ECHILD
-ECHRNG
-ECOMM
-ECONNABORTED
-ECONNREFUSED
-ECONNRESET
-EDEADLK
-EDEADLOCK
-EDESTADDRREQ
-EDEVERR
-EDOM
-EDOOFUS
-EDOTDOT
-EDQUOT
-EEXIST
-EFAULT
-EFBIG
-EFTYPE
-EHOSTDOWN
-EHOSTUNREACH
-EHWPOISON
-EIDRM
-EILSEQ
-EINPROGRESS
-EINTR
-EINVAL
-EIO
-EIPSEC
-EISCONN
-EISDIR
-EISNAM
-EKEYEXPIRED
-EKEYREJECTED
-EKEYREVOKED
-EL2HLT
-EL2NSYNC
-EL3HLT
-EL3RST
-ELAST
-ELIBACC
-ELIBBAD
-ELIBEXEC
-ELIBMAX
-ELIBSCN
-ELNRNG
-ELOOP
-EMEDIUMTYPE
-EMFILE
-EMLINK
-EMSGSIZE
-EMULTIHOP
-ENAMETOOLONG
-ENAVAIL
-ENEEDAUTH
-ENETDOWN
-ENETRESET
-ENETUNREACH
-ENFILE
-ENOANO
-ENOATTR
-ENOBUFS
-ENOCSI
-ENODATA
-ENODEV
-ENOENT
-ENOEXEC
-ENOKEY
-ENOLCK
-ENOLINK
-ENOMEDIUM
-ENOMEM
-ENOMSG
-ENONET
-ENOPKG
-ENOPOLICY
-ENOPROTOOPT
-ENOSPC
-ENOSR
-ENOSTR
-ENOSYS
-ENOTBLK
-ENOTCAPABLE
-ENOTCONN
-ENOTDIR
-ENOTEMPTY
-ENOTNAM
-ENOTRECOVERABLE
-ENOTSOCK
-ENOTSUP
-ENOTTY
-ENOTUNIQ
-ENXIO
-EOPNOTSUPP
-EOVERFLOW
-EOWNERDEAD
-EPERM
-EPFNOSUPPORT
-EPIPE
-EPROCLIM
-EPROCUNAVAIL
-EPROGMISMATCH
-EPROGUNAVAIL
-EPROTO
-EPROTONOSUPPORT
-EPROTOTYPE
-EPWROFF
-EQFULL
-ERANGE
-EREMCHG
-EREMOTE
-EREMOTEIO
-ERESTART
-ERFKILL
-EROFS
-ERPCMISMATCH
-ESHLIBVERS
-ESHUTDOWN
-ESOCKTNOSUPPORT
-ESPIPE
-ESRCH
-ESRMNT
-ESTALE
-ESTRPIPE
-ETIME
-ETIMEDOUT
-ETOOMANYREFS
-ETXTBSY
-EUCLEAN
-EUNATCH
-EUSERS
-EWOULDBLOCK
-EXDEV
-EXFULL
+E2BIG Argument list too long
+EACCES Permission denied
+EADDRINUSE Address already in use
+EADDRNOTAVAIL Address not available
+EADV Advertise error
+EAFNOSUPPORT Address family not supported
+EAGAIN Resource temporarily unavailable, try again (may be the same value as EWOULDBLOCK)
+EALREADY Connection already in progress
+EAUTH Authentication error
+EBADARCH Bad CPU type in executable
+EBADE Bad exchange
+EBADEXEC Bad executable
+EBADF Bad file descriptor
+EBADFD File descriptor in bad state
+EBADMACHO Malformed Macho file
+EBADMSG Bad message
+EBADR Invalid request descriptor
+EBADRPC RPC struct is bad
+EBADRQC Invalid request code
+EBADSLT Invalid slot
+EBFONT Bad font file format
+EBUSY Device or resource busy
+ECANCELED Operation canceled
+ECAPMODE Not permitted in capability mode
+ECHILD No child processes
+ECHRNG Channel number out of range
+ECOMM Communication error on send
+ECONNABORTED Connection aborted
+ECONNREFUSED Connection refused
+ECONNRESET Connection reset
+EDEADLK Resource deadlock avoided
+EDEADLOCK File locking deadlock error
+EDESTADDRREQ Destination address required
+EDEVERR Device error; e.g., printer paper out
+EDOM Mathematics argument out of domain of function
+EDOOFUS Improper function use
+EDOTDOT RFS specific error
+EDQUOT Disk quota exceeded
+EEXIST File exists
+EFAULT Bad address
+EFBIG File too large
+EFTYPE Invalid file type or format
+EHOSTDOWN Host is down
+EHOSTUNREACH Host is unreachable
+EHWPOISON Memory page has hardware error
+EIDRM Identifier removed
+EILSEQ Invalid or incomplete multibyte or wide character
+EINPROGRESS Operation in progress
+EINTR Interrupted function call
+EINVAL Invalid argument
+EIO Input/output error
+EIPSEC IPsec processing failure
+EISCONN Socket is connected
+EISDIR Is a directory
+EISNAM Is a named file type
+EKEYEXPIRED Key has expired
+EKEYREJECTED Key was rejected by service
+EKEYREVOKED Key has been revoked
+EL2HLT Level 2 halted
+EL2NSYNC Level 2 not synchronized
+EL3HLT Level 3 halted
+EL3RST Level 3 reset
+ELIBACC Cannot access a needed shared library
+ELIBBAD Accessing a corrupted shared library
+ELIBEXEC Cannot exec a shared library directly
+ELIBMAX Attempting to link in too many shared libraries
+ELIBSCN .lib section in a.out corrupted
+ELNRNG Link number out of range
+ELOOP Too many levels of symbolic links
+EMEDIUMTYPE Wrong medium type
+EMFILE Too many open files
+EMLINK Too many links
+EMSGSIZE Message too long
+EMULTIHOP Multihop attempted
+ENAMETOOLONG Filename too long
+ENAVAIL No XENIX semaphores available
+ENEEDAUTH Need authenticator
+ENETDOWN Network is down
+ENETRESET Connection aborted by network
+ENETUNREACH Network unreachable
+ENFILE Too many open files in system
+ENOANO No anode
+ENOATTR Attribute not found
+ENOBUFS No buffer space available
+ENOCSI No CSI structure available
+ENODATA No data available
+ENODEV No such device
+ENOENT No such file or directory
+ENOEXEC Exec format error
+ENOKEY Required key not available
+ENOLCK No locks available
+ENOLINK Link has been severed
+ENOMEDIUM No medium found
+ENOMEM Not enough space/cannot allocate memory
+ENOMSG No message of the desired type
+ENONET Machine is not on the network
+ENOPKG Package not installed
+ENOPOLICY No such policy
+ENOPROTOOPT Protocol not available
+ENOSPC No space left on device
+ENOSR No STREAM resources
+ENOSTR Not a STREAM
+ENOSYS Functionality not implemented
+ENOTBLK Block device required
+ENOTCAPABLE Capabilities insufficient
+ENOTCONN The socket is not connected
+ENOTDIR Not a directory
+ENOTEMPTY Directory not empty
+ENOTNAM Not a XENIX named type file
+ENOTRECOVERABLE State not recoverable
+ENOTSOCK Not a socket
+ENOTSUP Operation not supported
+ENOTTY Inappropriate I/O control operation
+ENOTUNIQ Name not unique on network
+ENXIO No such device or address
+EOPNOTSUPP Operation not supported on socket
+EOVERFLOW Value too large to be stored in data type
+EOWNERDEAD Owner died
+EPERM Operation not permitted
+EPFNOSUPPORT Protocol family not supported
+EPIPE Broken pipe
+EPROCLIM Too many processes
+EPROCUNAVAIL Bad procedure for program
+EPROGMISMATCH Program version wrong
+EPROGUNAVAIL RPC program isn't available
+EPROTO Protocol error
+EPROTONOSUPPORT Protocol not supported
+EPROTOTYPE Protocol wrong type for socket
+EPWROFF Device power is off
+EQFULL Interface output queue is full
+ERANGE Result too large
+EREMCHG Remote address changed
+EREMOTE Object is remote
+EREMOTEIO Remote I/O error
+ERESTART Interrupted system call should be restarted
+ERFKILL Operation not possible due to RF-kill
+EROFS Read-only file system
+ERPCMISMATCH RPC version wrong
+ESHLIBVERS Shared library version mismatch
+ESHUTDOWN Cannot send after transport endpoint shutdown
+ESOCKTNOSUPPORT Socket type not supported
+ESPIPE Illegal seek
+ESRCH No such process
+ESRMNT Server mount error
+ESTALE Stale file handle
+ESTRPIPE Streams pipe error
+ETIME Timer expired
+ETIMEDOUT Connection timed out
+ETOOMANYREFS Too many references: cannot splice
+ETXTBSY Text file busy
+EUCLEAN Structure needs cleaning
+EUNATCH Protocol driver not attached
+EUSERS Too many users
+EWOULDBLOCK Operation would block
+EXDEV Invalid cross-device link
+EXFULL Exchange full
+ELAST Largest errno value
diff --git a/dir.c b/dir.c
index 21b1acada3..0a22ad7901 100644
--- a/dir.c
+++ b/dir.c
@@ -113,6 +113,7 @@ char *strchr(char*,char);
#include "internal/gc.h"
#include "internal/io.h"
#include "internal/object.h"
+#include "internal/imemo.h"
#include "internal/vm.h"
#include "ruby/encoding.h"
#include "ruby/ruby.h"
@@ -471,23 +472,21 @@ dir_free(void *ptr)
struct dir_data *dir = ptr;
if (dir->dir) closedir(dir->dir);
- xfree(dir);
}
-static size_t
-dir_memsize(const void *ptr)
-{
- return sizeof(struct dir_data);
-}
-
-RUBY_REFERENCES_START(dir_refs)
- REF_EDGE(dir_data, path),
-RUBY_REFERENCES_END
+RUBY_REFERENCES(dir_refs) = {
+ RUBY_REF_EDGE(struct dir_data, path),
+ RUBY_REF_END
+};
static const rb_data_type_t dir_data_type = {
"dir",
- {REFS_LIST_PTR(dir_refs), dir_free, dir_memsize,},
- 0, NULL, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_DECL_MARKING
+ {
+ RUBY_REFS_LIST_PTR(dir_refs),
+ dir_free,
+ NULL, // Nothing allocated externally, so don't need a memsize function
+ },
+ 0, NULL, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_DECL_MARKING | RUBY_TYPED_EMBEDDABLE
};
static VALUE dir_close(VALUE);
@@ -521,7 +520,7 @@ opendir_without_gvl(const char *path)
u.in = path;
- return rb_thread_call_without_gvl(nogvl_opendir, u.out, RUBY_UBF_IO, 0);
+ return IO_WITHOUT_GVL(nogvl_opendir, u.out);
}
else
return opendir(path);
@@ -1043,12 +1042,64 @@ dir_chdir0(VALUE path)
rb_sys_fail_path(path);
}
-static int chdir_blocking = 0;
-static VALUE chdir_thread = Qnil;
+static struct {
+ VALUE thread;
+ VALUE path;
+ int line;
+ int blocking;
+} chdir_lock = {
+ .blocking = 0, .thread = Qnil,
+ .path = Qnil, .line = 0,
+};
+
+static void
+chdir_enter(void)
+{
+ if (chdir_lock.blocking == 0) {
+ chdir_lock.path = rb_source_location(&chdir_lock.line);
+ }
+ chdir_lock.blocking++;
+ if (NIL_P(chdir_lock.thread)) {
+ chdir_lock.thread = rb_thread_current();
+ }
+}
+
+static void
+chdir_leave(void)
+{
+ chdir_lock.blocking--;
+ if (chdir_lock.blocking == 0) {
+ chdir_lock.thread = Qnil;
+ chdir_lock.path = Qnil;
+ chdir_lock.line = 0;
+ }
+}
+
+static int
+chdir_alone_block_p(void)
+{
+ int block_given = rb_block_given_p();
+ if (chdir_lock.blocking > 0) {
+ if (rb_thread_current() != chdir_lock.thread)
+ rb_raise(rb_eRuntimeError, "conflicting chdir during another chdir block");
+ if (!block_given) {
+ if (!NIL_P(chdir_lock.path)) {
+ rb_warn("conflicting chdir during another chdir block\n"
+ "%" PRIsVALUE ":%d: note: previous chdir was here",
+ chdir_lock.path, chdir_lock.line);
+ }
+ else {
+ rb_warn("conflicting chdir during another chdir block");
+ }
+ }
+ }
+ return block_given;
+}
struct chdir_data {
VALUE old_path, new_path;
int done;
+ bool yield_path;
};
static VALUE
@@ -1057,10 +1108,8 @@ chdir_yield(VALUE v)
struct chdir_data *args = (void *)v;
dir_chdir0(args->new_path);
args->done = TRUE;
- chdir_blocking++;
- if (NIL_P(chdir_thread))
- chdir_thread = rb_thread_current();
- return rb_yield(args->new_path);
+ chdir_enter();
+ return args->yield_path ? rb_yield(args->new_path) : rb_yield_values2(0, NULL);
}
static VALUE
@@ -1068,14 +1117,34 @@ chdir_restore(VALUE v)
{
struct chdir_data *args = (void *)v;
if (args->done) {
- chdir_blocking--;
- if (chdir_blocking == 0)
- chdir_thread = Qnil;
+ chdir_leave();
dir_chdir0(args->old_path);
}
return Qnil;
}
+static VALUE
+chdir_path(VALUE path, bool yield_path)
+{
+ if (chdir_alone_block_p()) {
+ struct chdir_data args;
+
+ args.old_path = rb_str_encode_ospath(rb_dir_getwd());
+ args.new_path = path;
+ args.done = FALSE;
+ args.yield_path = yield_path;
+ return rb_ensure(chdir_yield, (VALUE)&args, chdir_restore, (VALUE)&args);
+ }
+ else {
+ char *p = RSTRING_PTR(path);
+ int r = IO_WITHOUT_GVL_INT(nogvl_chdir, p);
+ if (r < 0)
+ rb_sys_fail_path(path);
+ }
+
+ return INT2FIX(0);
+}
+
/*
* call-seq:
* Dir.chdir(new_dirpath) -> 0
@@ -1102,7 +1171,7 @@ chdir_restore(VALUE v)
*
* - Calls the block with the argument.
* - Changes to the given directory.
- * - Executes the block
+ * - Executes the block (yielding the new path).
* - Restores the previous working directory.
* - Returns the block's return value.
*
@@ -1156,30 +1225,7 @@ dir_s_chdir(int argc, VALUE *argv, VALUE obj)
path = rb_str_new2(dist);
}
- if (chdir_blocking > 0) {
- if (rb_thread_current() != chdir_thread)
- rb_raise(rb_eRuntimeError, "conflicting chdir during another chdir block");
- if (!rb_block_given_p())
- rb_warn("conflicting chdir during another chdir block");
- }
-
- if (rb_block_given_p()) {
- struct chdir_data args;
-
- args.old_path = rb_str_encode_ospath(rb_dir_getwd());
- args.new_path = path;
- args.done = FALSE;
- return rb_ensure(chdir_yield, (VALUE)&args, chdir_restore, (VALUE)&args);
- }
- else {
- char *p = RSTRING_PTR(path);
- int r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_chdir, p,
- RUBY_UBF_IO, 0);
- if (r < 0)
- rb_sys_fail_path(path);
- }
-
- return INT2FIX(0);
+ return chdir_path(path, true);
}
#if defined(HAVE_FCHDIR) && defined(HAVE_DIRFD) && HAVE_FCHDIR && HAVE_DIRFD
@@ -1210,9 +1256,7 @@ fchdir_yield(VALUE v)
struct fchdir_data *args = (void *)v;
dir_fchdir(args->fd);
args->done = TRUE;
- chdir_blocking++;
- if (NIL_P(chdir_thread))
- chdir_thread = rb_thread_current();
+ chdir_enter();
return rb_yield_values(0);
}
@@ -1221,9 +1265,7 @@ fchdir_restore(VALUE v)
{
struct fchdir_data *args = (void *)v;
if (args->done) {
- chdir_blocking--;
- if (chdir_blocking == 0)
- chdir_thread = Qnil;
+ chdir_leave();
dir_fchdir(RB_NUM2INT(dir_fileno(args->old_dir)));
}
dir_close(args->old_dir);
@@ -1248,16 +1290,14 @@ fchdir_restore(VALUE v)
* Dir.pwd # => "/var/spool/mail"
* dir = Dir.new('/usr')
* fd = dir.fileno
- * Dir.fchdir(fd) do
- * Dir.pwd # => "/usr"
- * end
- * Dir.pwd # => "/var/spool/mail"
+ * Dir.fchdir(fd)
+ * Dir.pwd # => "/usr"
*
* With a block, temporarily changes the working directory:
*
* - Calls the block with the argument.
* - Changes to the given directory.
- * - Executes the block
+ * - Executes the block (yields no args).
* - Restores the previous working directory.
* - Returns the block's return value.
*
@@ -1265,7 +1305,9 @@ fchdir_restore(VALUE v)
*
* Dir.chdir('/var/spool/mail')
* Dir.pwd # => "/var/spool/mail"
- * Dir.chdir('/tmp') do
+ * dir = Dir.new('/tmp')
+ * fd = dir.fileno
+ * Dir.fchdir(fd) do
* Dir.pwd # => "/tmp"
* end
* Dir.pwd # => "/var/spool/mail"
@@ -1287,14 +1329,7 @@ dir_s_fchdir(VALUE klass, VALUE fd_value)
{
int fd = RB_NUM2INT(fd_value);
- if (chdir_blocking > 0) {
- if (rb_thread_current() != chdir_thread)
- rb_raise(rb_eRuntimeError, "conflicting chdir during another chdir block");
- if (!rb_block_given_p())
- rb_warn("conflicting chdir during another chdir block");
- }
-
- if (rb_block_given_p()) {
+ if (chdir_alone_block_p()) {
struct fchdir_data args;
args.old_dir = dir_s_alloc(klass);
dir_initialize(NULL, args.old_dir, rb_fstring_cstr("."), Qnil);
@@ -1303,8 +1338,7 @@ dir_s_fchdir(VALUE klass, VALUE fd_value)
return rb_ensure(fchdir_yield, (VALUE)&args, fchdir_restore, (VALUE)&args);
}
else {
- int r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_fchdir, &fd,
- RUBY_UBF_IO, 0);
+ int r = IO_WITHOUT_GVL_INT(nogvl_fchdir, &fd);
if (r < 0)
rb_sys_fail("fchdir");
}
@@ -1317,27 +1351,35 @@ dir_s_fchdir(VALUE klass, VALUE fd_value)
/*
* call-seq:
- * chdir -> nil
+ * chdir -> 0
+ * chdir { ... } -> object
*
- * Changes the current working directory to the path of +self+:
+ * Changes the current working directory to +self+:
*
* Dir.pwd # => "/"
* dir = Dir.new('example')
* dir.chdir
- * dir.pwd # => "/example"
+ * Dir.pwd # => "/example"
+ *
+ * With a block, temporarily changes the working directory:
*
+ * - Calls the block.
+ * - Changes to the given directory.
+ * - Executes the block (yields no args).
+ * - Restores the previous working directory.
+ * - Returns the block's return value.
+ *
+ * Uses Dir.fchdir if available, and Dir.chdir if not, see those
+ * methods for caveats.
*/
static VALUE
dir_chdir(VALUE dir)
{
#if defined(HAVE_FCHDIR) && defined(HAVE_DIRFD) && HAVE_FCHDIR && HAVE_DIRFD
- dir_s_fchdir(rb_cDir, dir_fileno(dir));
+ return dir_s_fchdir(rb_cDir, dir_fileno(dir));
#else
- VALUE path = dir_get(dir)->path;
- dir_s_chdir(1, &path, rb_cDir);
+ return chdir_path(dir_get(dir)->path, false);
#endif
-
- return Qnil;
}
#ifndef _WIN32
@@ -1348,19 +1390,15 @@ rb_dir_getwd_ospath(void)
VALUE cwd;
VALUE path_guard;
-#undef RUBY_UNTYPED_DATA_WARNING
-#define RUBY_UNTYPED_DATA_WARNING 0
- path_guard = Data_Wrap_Struct((VALUE)0, NULL, RUBY_DEFAULT_FREE, NULL);
+ path_guard = rb_imemo_tmpbuf_auto_free_pointer();
path = ruby_getcwd();
- DATA_PTR(path_guard) = path;
+ rb_imemo_tmpbuf_set_ptr(path_guard, path);
#ifdef __APPLE__
cwd = rb_str_normalize_ospath(path, strlen(path));
#else
cwd = rb_str_new2(path);
#endif
- DATA_PTR(path_guard) = 0;
-
- xfree(path);
+ rb_free_tmp_buffer(&path_guard);
return cwd;
}
#endif
@@ -1492,7 +1530,7 @@ dir_s_mkdir(int argc, VALUE *argv, VALUE obj)
path = check_dirname(path);
m.path = RSTRING_PTR(path);
- r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_mkdir, &m, RUBY_UBF_IO, 0);
+ r = IO_WITHOUT_GVL_INT(nogvl_mkdir, &m);
if (r < 0)
rb_sys_fail_path(path);
@@ -1525,7 +1563,7 @@ dir_s_rmdir(VALUE obj, VALUE dir)
dir = check_dirname(dir);
p = RSTRING_PTR(dir);
- r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_rmdir, (void *)p, RUBY_UBF_IO, 0);
+ r = IO_WITHOUT_GVL_INT(nogvl_rmdir, (void *)p);
if (r < 0)
rb_sys_fail_path(dir);
@@ -1744,7 +1782,7 @@ opendir_at(int basefd, const char *path)
oaa.path = path;
if (vm_initialized)
- return rb_thread_call_without_gvl(nogvl_opendir_at, &oaa, RUBY_UBF_IO, 0);
+ return IO_WITHOUT_GVL(nogvl_opendir_at, &oaa);
else
return nogvl_opendir_at(&oaa);
}
@@ -3116,7 +3154,7 @@ push_glob(VALUE ary, VALUE str, VALUE base, int flags)
fd = AT_FDCWD;
if (!NIL_P(base)) {
if (!RB_TYPE_P(base, T_STRING) || !rb_enc_check(str, base)) {
- struct dir_data *dirp = DATA_PTR(base);
+ struct dir_data *dirp = RTYPEDDATA_GET_DATA(base);
if (!dirp->dir) dir_closed();
#ifdef HAVE_DIRFD
if ((fd = dirfd(dirp->dir)) == -1)
@@ -3478,6 +3516,9 @@ file_s_fnmatch(int argc, VALUE *argv, VALUE obj)
* call-seq:
* Dir.home(user_name = nil) -> dirpath
*
+ * Retruns the home directory path of the user specified with +user_name+
+ * if it is not +nil+, or the current login user:
+ *
* Dir.home # => "/home/me"
* Dir.home('root') # => "/root"
*
@@ -3492,7 +3533,7 @@ dir_s_home(int argc, VALUE *argv, VALUE obj)
rb_check_arity(argc, 0, 1);
user = (argc > 0) ? argv[0] : Qnil;
if (!NIL_P(user)) {
- SafeStringValue(user);
+ StringValue(user);
rb_must_asciicompat(user);
u = StringValueCStr(user);
if (*u) {
@@ -3514,6 +3555,7 @@ dir_s_home(int argc, VALUE *argv, VALUE obj)
* Dir.exist?('/nosuch') # => false
* Dir.exist?('/example/main.rb') # => false
*
+ * Same as File.directory?.
*
*/
VALUE
@@ -3600,8 +3642,7 @@ rb_dir_s_empty_p(VALUE obj, VALUE dirname)
}
#endif
- result = (VALUE)rb_thread_call_without_gvl(nogvl_dir_empty_p, (void *)path,
- RUBY_UBF_IO, 0);
+ result = (VALUE)IO_WITHOUT_GVL(nogvl_dir_empty_p, (void *)path);
if (FIXNUM_P(result)) {
rb_syserr_fail_path((int)FIX2LONG(result), orig);
}
@@ -3611,6 +3652,9 @@ rb_dir_s_empty_p(VALUE obj, VALUE dirname)
void
Init_Dir(void)
{
+ rb_gc_register_address(&chdir_lock.path);
+ rb_gc_register_address(&chdir_lock.thread);
+
rb_cDir = rb_define_class("Dir", rb_cObject);
rb_include_module(rb_cDir, rb_mEnumerable);
@@ -3654,12 +3698,27 @@ Init_Dir(void)
rb_define_singleton_method(rb_cFile,"fnmatch", file_s_fnmatch, -1);
rb_define_singleton_method(rb_cFile,"fnmatch?", file_s_fnmatch, -1);
+
+ /* Document-const: FNM_NOESCAPE
+ * {File::FNM_NOESCAPE}[rdoc-ref:File::Constants@File-3A-3AFNM_NOESCAPE] */
rb_file_const("FNM_NOESCAPE", INT2FIX(FNM_NOESCAPE));
+ /* Document-const: FNM_PATHNAME
+ * {File::FNM_PATHNAME}[rdoc-ref:File::Constants@File-3A-3AFNM_PATHNAME] */
rb_file_const("FNM_PATHNAME", INT2FIX(FNM_PATHNAME));
+ /* Document-const: FNM_DOTMATCH
+ * {File::FNM_DOTMATCH}[rdoc-ref:File::Constants@File-3A-3AFNM_DOTMATCH] */
rb_file_const("FNM_DOTMATCH", INT2FIX(FNM_DOTMATCH));
+ /* Document-const: FNM_CASEFOLD
+ * {File::FNM_CASEFOLD}[rdoc-ref:File::Constants@File-3A-3AFNM_CASEFOLD] */
rb_file_const("FNM_CASEFOLD", INT2FIX(FNM_CASEFOLD));
+ /* Document-const: FNM_EXTGLOB
+ * {File::FNM_EXTGLOB}[rdoc-ref:File::Constants@File-3A-3AFNM_EXTGLOB] */
rb_file_const("FNM_EXTGLOB", INT2FIX(FNM_EXTGLOB));
+ /* Document-const: FNM_SYSCASE
+ * {File::FNM_SYSCASE}[rdoc-ref:File::Constants@File-3A-3AFNM_SYSCASE] */
rb_file_const("FNM_SYSCASE", INT2FIX(FNM_SYSCASE));
+ /* Document-const: FNM_SHORTNAME
+ * {File::FNM_SHORTNAME}[rdoc-ref:File::Constants@File-3A-3AFNM_SHORTNAME] */
rb_file_const("FNM_SHORTNAME", INT2FIX(FNM_SHORTNAME));
}
diff --git a/dir.rb b/dir.rb
index 7de62da921..42b475ab2c 100644
--- a/dir.rb
+++ b/dir.rb
@@ -320,7 +320,7 @@ class Dir
# Dir.glob('io.?') # => ["io.c"]
#
# - <tt>'[_set_]'</tt>: Matches any one character in the string _set_;
- # behaves like a {Regexp character class}[rdoc-ref:regexp.rdoc@Character+Classes],
+ # behaves like a {Regexp character class}[rdoc-ref:Regexp@Character+Classes],
# including set negation (<tt>'[^a-z]'</tt>):
#
# Dir.glob('*.[a-z][a-z]').take(3)
@@ -328,7 +328,7 @@ class Dir
#
# - <tt>'{_abc_,_xyz_}'</tt>:
# Matches either string _abc_ or string _xyz_;
- # behaves like {Regexp alternation}[rdoc-ref:regexp.rdoc@Alternation]:
+ # behaves like {Regexp alternation}[rdoc-ref:Regexp@Alternation]:
#
# Dir.glob('{LEGAL,BSDL}') # => ["LEGAL", "BSDL"]
#
@@ -408,6 +408,7 @@ class Dir
# specifies that patterns may match short names if they exist; Windows only.
#
def self.glob(pattern, _flags = 0, flags: _flags, base: nil, sort: true)
+ Primitive.attr! :use_block
Primitive.dir_s_glob(pattern, flags, base, sort)
end
end
diff --git a/dln.c b/dln.c
index 77bfe91b28..89f16b54f0 100644
--- a/dln.c
+++ b/dln.c
@@ -76,6 +76,12 @@ void *xrealloc();
# include <unistd.h>
#endif
+bool
+dln_supported_p(void)
+{
+ return true;
+}
+
#ifndef dln_loaderror
static void
dln_loaderror(const char *format, ...)
@@ -107,36 +113,45 @@ dln_loaderror(const char *format, ...)
#endif
#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
-static size_t
-init_funcname_len(const char **file)
+struct string_part {
+ const char *ptr;
+ size_t len;
+};
+
+static struct string_part
+init_funcname_len(const char *file)
{
- const char *p = *file, *base, *dot = NULL;
+ const char *p = file, *base, *dot = NULL;
/* Load the file as an object one */
for (base = p; *p; p++) { /* Find position of last '/' */
if (*p == '.' && !dot) dot = p;
if (isdirsep(*p)) base = p+1, dot = NULL;
}
- *file = base;
/* Delete suffix if it exists */
- return (dot ? dot : p) - base;
+ const size_t len = (dot ? dot : p) - base;
+ return (struct string_part){base, len};
+}
+
+static inline char *
+concat_funcname(char *buf, const char *prefix, size_t plen, const struct string_part base)
+{
+ if (!buf) {
+ dln_memerror();
+ }
+ memcpy(buf, prefix, plen);
+ memcpy(buf + plen, base.ptr, base.len);
+ buf[plen + base.len] = '\0';
+ return buf;
}
-static const char funcname_prefix[sizeof(FUNCNAME_PREFIX) - 1] = FUNCNAME_PREFIX;
-
-#define init_funcname(buf, file) do {\
- const char *base = (file);\
- const size_t flen = init_funcname_len(&base);\
- const size_t plen = sizeof(funcname_prefix);\
- char *const tmp = ALLOCA_N(char, plen+flen+1);\
- if (!tmp) {\
- dln_memerror();\
- }\
- memcpy(tmp, funcname_prefix, plen);\
- memcpy(tmp+plen, base, flen);\
- tmp[plen+flen] = '\0';\
- *(buf) = tmp;\
+#define build_funcname(prefix, buf, file) do {\
+ const struct string_part f = init_funcname_len(file);\
+ const size_t plen = sizeof(prefix "") - 1;\
+ *(buf) = concat_funcname(ALLOCA_N(char, plen+f.len+1), prefix, plen, f);\
} while (0)
+
+#define init_funcname(buf, file) build_funcname(FUNCNAME_PREFIX, buf, file)
#endif
#ifdef USE_DLN_DLOPEN
@@ -185,7 +200,6 @@ dln_strerror(char *message, size_t size)
}
return message;
}
-#define dln_strerror() dln_strerror(message, sizeof message)
#elif defined USE_DLN_DLOPEN
static const char *
dln_strerror(void)
@@ -272,13 +286,15 @@ rb_w32_check_imported(HMODULE ext, HMODULE mine)
static bool
dln_incompatible_func(void *handle, const char *funcname, void *const fp, const char **libname)
{
- Dl_info dli;
void *ex = dlsym(handle, funcname);
if (!ex) return false;
if (ex == fp) return false;
+# if defined(HAVE_DLADDR)
+ Dl_info dli;
if (dladdr(ex, &dli)) {
*libname = dli.dli_fname;
}
+# endif
return true;
}
@@ -328,16 +344,13 @@ dln_disable_dlclose(void)
#endif
#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
-static void *
-dln_open(const char *file)
+void *
+dln_open(const char *file, char *error, size_t size)
{
static const char incompatible[] = "incompatible library version";
- const char *error = NULL;
void *handle;
#if defined(_WIN32)
- char message[1024];
-
/* Convert the file path to wide char */
WCHAR *winfile = rb_w32_mbstr_to_wstr(CP_UTF8, file, -1, NULL);
if (!winfile) {
@@ -349,15 +362,15 @@ dln_open(const char *file)
free(winfile);
if (!handle) {
- error = dln_strerror();
- goto failed;
+ strlcpy(error, dln_strerror(error, size), size);
+ return NULL;
}
# if defined(RUBY_EXPORT)
if (!rb_w32_check_imported(handle, rb_libruby_handle())) {
FreeLibrary(handle);
- error = incompatible;
- goto failed;
+ strlcpy(error, incompatible, size);
+ return NULL;
}
# endif
@@ -376,8 +389,8 @@ dln_open(const char *file)
/* Load file */
handle = dlopen(file, RTLD_LAZY|RTLD_GLOBAL);
if (handle == NULL) {
- error = dln_strerror();
- goto failed;
+ strlcpy(error, dln_strerror(), size);
+ return NULL;
}
# if defined(RUBY_EXPORT)
@@ -399,11 +412,15 @@ dln_open(const char *file)
libruby_name = tmp;
}
dlclose(handle);
+
if (libruby_name) {
- dln_loaderror("linked to incompatible %s - %s", libruby_name, file);
+ snprintf(error, size, "linked to incompatible %s - %s", libruby_name, file);
+ }
+ else {
+ strlcpy(error, incompatible, size);
}
- error = incompatible;
- goto failed;
+
+ return NULL;
}
}
}
@@ -411,41 +428,68 @@ dln_open(const char *file)
#endif
return handle;
-
- failed:
- dln_loaderror("%s - %s", error, file);
}
-static void *
+void *
dln_sym(void *handle, const char *symbol)
{
- void *func;
- const char *error;
-
#if defined(_WIN32)
- char message[1024];
+ return GetProcAddress(handle, symbol);
+#elif defined(USE_DLN_DLOPEN)
+ return dlsym(handle, symbol);
+#endif
+}
- func = GetProcAddress(handle, symbol);
- if (func == NULL) {
- error = dln_strerror();
- goto failed;
- }
+static void *
+dln_sym_func(void *handle, const char *symbol)
+{
+ void *func = dln_sym(handle, symbol);
-#elif defined(USE_DLN_DLOPEN)
- func = dlsym(handle, symbol);
if (func == NULL) {
+ const char *error;
+#if defined(_WIN32)
+ char message[1024];
+ error = dln_strerror(message, sizeof(message));
+#elif defined(USE_DLN_DLOPEN)
const size_t errlen = strlen(error = dln_strerror()) + 1;
error = memcpy(ALLOCA_N(char, errlen), error, errlen);
- goto failed;
- }
#endif
-
+ dln_loaderror("%s - %s", error, symbol);
+ }
return func;
-
- failed:
- dln_loaderror("%s - %s", error, symbol);
}
+
+#define dln_sym_callable(rettype, argtype, handle, symbol) \
+ (*(rettype (*)argtype)dln_sym_func(handle, symbol))
+#endif
+
+void *
+dln_symbol(void *handle, const char *symbol)
+{
+#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
+ if (EXTERNAL_PREFIX[0]) {
+ const size_t symlen = strlen(symbol);
+ char *const tmp = ALLOCA_N(char, symlen + sizeof(EXTERNAL_PREFIX));
+ if (!tmp) dln_memerror();
+ memcpy(tmp, EXTERNAL_PREFIX, sizeof(EXTERNAL_PREFIX) - 1);
+ memcpy(tmp + sizeof(EXTERNAL_PREFIX) - 1, symbol, symlen + 1);
+ symbol = tmp;
+ }
+ if (handle == NULL) {
+# if defined(USE_DLN_DLOPEN)
+ handle = dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL);
+# elif defined(_WIN32)
+ handle = rb_libruby_handle();
+# else
+ return NULL;
+# endif
+ }
+ return dln_sym(handle, symbol);
+#else
+ return NULL;
#endif
+}
+
#if defined(RUBY_DLN_CHECK_ABI) && defined(USE_DLN_DLOPEN)
static bool
@@ -460,22 +504,27 @@ void *
dln_load(const char *file)
{
#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
- void *handle = dln_open(file);
+ char error[1024];
+ void *handle = dln_open(file, error, sizeof(error));
+
+ if (handle == NULL) {
+ dln_loaderror("%s - %s", error, file);
+ }
#ifdef RUBY_DLN_CHECK_ABI
- unsigned long long (*abi_version_fct)(void) = (unsigned long long(*)(void))dln_sym(handle, "ruby_abi_version");
- unsigned long long binary_abi_version = (*abi_version_fct)();
- if (binary_abi_version != ruby_abi_version() && abi_check_enabled_p()) {
+ typedef unsigned long long abi_version_number;
+ abi_version_number binary_abi_version =
+ dln_sym_callable(abi_version_number, (void), handle, EXTERNAL_PREFIX "ruby_abi_version")();
+ if (binary_abi_version != RUBY_ABI_VERSION && abi_check_enabled_p()) {
dln_loaderror("incompatible ABI version of binary - %s", file);
}
#endif
char *init_fct_name;
init_funcname(&init_fct_name, file);
- void (*init_fct)(void) = (void(*)(void))dln_sym(handle, init_fct_name);
/* Call the init code */
- (*init_fct)();
+ dln_sym_callable(void, (void), handle, init_fct_name)();
return handle;
diff --git a/dln.h b/dln.h
index 902f753450..26df5266f7 100644
--- a/dln.h
+++ b/dln.h
@@ -22,9 +22,12 @@ RUBY_SYMBOL_EXPORT_BEGIN
#define DLN_FIND_EXTRA_ARG_DECL
#endif
+bool dln_supported_p(void);
char *dln_find_exe_r(const char*,const char*,char*,size_t DLN_FIND_EXTRA_ARG_DECL);
char *dln_find_file_r(const char*,const char*,char*,size_t DLN_FIND_EXTRA_ARG_DECL);
void *dln_load(const char*);
+void *dln_open(const char *file, char *error, size_t size);
+void *dln_symbol(void*,const char*);
RUBY_SYMBOL_EXPORT_END
diff --git a/dln_find.c b/dln_find.c
index 91c51394a9..ae37b9dde4 100644
--- a/dln_find.c
+++ b/dln_find.c
@@ -11,11 +11,9 @@
#ifdef RUBY_EXPORT
#include "ruby/ruby.h"
-#define dln_warning rb_warning
-#define dln_warning_arg
+#define dln_warning(...) rb_warning(__VA_ARGS__)
#else
-#define dln_warning fprintf
-#define dln_warning_arg stderr,
+#define dln_warning(...) fprintf(stderr, __VA_ARGS__)
#endif
#include "dln.h"
@@ -109,7 +107,7 @@ dln_find_1(const char *fname, const char *path, char *fbuf, size_t size,
static const char pathname_too_long[] = "openpath: pathname too long (ignored)\n\
\tDirectory \"%.*s\"%s\n\tFile \"%.*s\"%s\n";
-#define PATHNAME_TOO_LONG() dln_warning(dln_warning_arg pathname_too_long, \
+#define PATHNAME_TOO_LONG() dln_warning(pathname_too_long, \
((bp - fbuf) > 100 ? 100 : (int)(bp - fbuf)), fbuf, \
((bp - fbuf) > 100 ? "..." : ""), \
(fnlen > 100 ? 100 : (int)fnlen), fname, \
@@ -120,8 +118,7 @@ dln_find_1(const char *fname, const char *path, char *fbuf, size_t size,
RETURN_IF(!fname);
fnlen = strlen(fname);
if (fnlen >= size) {
- dln_warning(dln_warning_arg
- "openpath: pathname too long (ignored)\n\tFile \"%.*s\"%s\n",
+ dln_warning("openpath: pathname too long (ignored)\n\tFile \"%.*s\"%s\n",
(fnlen > 100 ? 100 : (int)fnlen), fname,
(fnlen > 100 ? "..." : ""));
return NULL;
diff --git a/dmydln.c b/dmydln.c
index d05cda0b8e..1f5b59022b 100644
--- a/dmydln.c
+++ b/dmydln.c
@@ -1,5 +1,14 @@
+// This file is used by miniruby, not ruby.
+// ruby uses dln.c.
+
#include "ruby/ruby.h"
+bool
+dln_supported_p(void)
+{
+ return false;
+}
+
NORETURN(void *dln_load(const char *));
void*
dln_load(const char *file)
@@ -8,3 +17,21 @@ dln_load(const char *file)
UNREACHABLE_RETURN(NULL);
}
+
+NORETURN(void *dln_symbol(void*,const char*));
+void*
+dln_symbol(void *handle, const char *symbol)
+{
+ rb_loaderror("this executable file can't load extension libraries");
+
+ UNREACHABLE_RETURN(NULL);
+}
+
+void*
+dln_open(const char *library, char *error, size_t size)
+{
+ static const char *error_str = "this executable file can't load extension libraries";
+ strlcpy(error, error_str, size);
+ return NULL;
+}
+
diff --git a/dmyenc.c b/dmyenc.c
index 75b8a2da43..4771841281 100644
--- a/dmyenc.c
+++ b/dmyenc.c
@@ -1,3 +1,17 @@
+// This file is used by dynamically-linked ruby, which has no
+// statically-linked encodings other than the builtin encodings.
+//
+// - miniruby does not use this Init_enc. Instead, "miniinit.c"
+// provides Init_enc, which defines only the builtin encodings.
+//
+// - Dynamically-linked ruby uses this Init_enc, which requires
+// "enc/encdb.so" to load the builtin encodings and set up the
+// optional encodings.
+//
+// - Statically-linked ruby does not use this Init_enc. Instead,
+// "enc/encinit.c" (which is a generated file) defines Init_enc,
+// which activates the encodings.
+
#define require(name) ruby_require_internal(name, (unsigned int)sizeof(name)-1)
int ruby_require_internal(const char *, int);
diff --git a/dmyext.c b/dmyext.c
index 4d273f7faf..66be95ab4e 100644
--- a/dmyext.c
+++ b/dmyext.c
@@ -1,3 +1,17 @@
+// This file is used by dynamically-linked ruby, which has no
+// statically-linked extension libraries.
+//
+// - miniruby does not use this Init_ext. Instead, "miniinit.c"
+// provides Init_enc, which does nothing too. It does not support
+// require'ing extension libraries.
+//
+// - Dynamically-linked ruby uses this Init_ext, which does
+// nothing. It loads extension libraries by dlopen, etc.
+//
+// - Statically-linked ruby does not use this Init_ext. Instead,
+// "ext/extinit.c" (which is a generated file) defines Init_ext,
+// which activates the (statically-linked) extension libraries.
+
void
Init_ext(void)
{
diff --git a/doc/.document b/doc/.document
index 4b90648377..8174394f48 100644
--- a/doc/.document
+++ b/doc/.document
@@ -1,10 +1,12 @@
*.md
*.rb
-*.rdoc
+[^_]*.rdoc
contributing
NEWS
syntax
optparse
rdoc
regexp
+rjit
yjit
+ruby
diff --git a/doc/ChangeLog/ChangeLog-2.1.0 b/doc/ChangeLog/ChangeLog-2.1.0
index 5b670b31c9..7964a682eb 100644
--- a/doc/ChangeLog/ChangeLog-2.1.0
+++ b/doc/ChangeLog/ChangeLog-2.1.0
@@ -659,7 +659,7 @@ Mon Dec 9 02:10:32 2013 NARUSE, Yui <naruse@ruby-lang.org>
* lib/net/http/responses.rb:
Add `HTTPIMUsed`, as it is also supported by rack/rails.
- RFC - http://tools.ietf.org/html/rfc3229
+ RFC - https://www.rfc-editor.org/rfc/rfc3229
by Vipul A M <vipulnsward@gmail.com>
https://github.com/ruby/ruby/pull/447 fix GH-447
diff --git a/doc/ChangeLog/ChangeLog-2.2.0 b/doc/ChangeLog/ChangeLog-2.2.0
index 5a7dbf826d..0edcf0122b 100644
--- a/doc/ChangeLog/ChangeLog-2.2.0
+++ b/doc/ChangeLog/ChangeLog-2.2.0
@@ -5648,7 +5648,7 @@ Wed Aug 6 04:16:05 2014 NARUSE, Yui <naruse@ruby-lang.org>
* lib/net/http/requests.rb (Net::HTTP::Options::RESPONSE_HAS_BODY):
OPTIONS requests may have response bodies. [Feature #8429]
- http://tools.ietf.org/html/rfc7231#section-4.3.7
+ https://www.rfc-editor.org/rfc/rfc7231#section-4.3.7
Wed Aug 6 03:18:04 2014 NARUSE, Yui <naruse@ruby-lang.org>
diff --git a/doc/ChangeLog/ChangeLog-2.4.0 b/doc/ChangeLog/ChangeLog-2.4.0
index a297a579d1..30e9ccab3d 100644
--- a/doc/ChangeLog/ChangeLog-2.4.0
+++ b/doc/ChangeLog/ChangeLog-2.4.0
@@ -7356,7 +7356,7 @@ Thu Mar 17 11:51:48 2016 NARUSE, Yui <naruse@ruby-lang.org>
Note: CryptGenRandom function is PRNG and doesn't check its entropy,
so it won't block. [Bug #12139]
https://msdn.microsoft.com/ja-jp/library/windows/desktop/aa379942.aspx
- https://tools.ietf.org/html/rfc4086#section-7.1.3
+ https://www.rfc-editor.org/rfc/rfc4086#section-7.1.3
https://eprint.iacr.org/2007/419.pdf
http://www.cs.huji.ac.il/~dolev/pubs/thesis/msc-thesis-leo.pdf
diff --git a/doc/NEWS/NEWS-3.3.0.md b/doc/NEWS/NEWS-3.3.0.md
new file mode 100644
index 0000000000..364786d754
--- /dev/null
+++ b/doc/NEWS/NEWS-3.3.0.md
@@ -0,0 +1,529 @@
+# NEWS for Ruby 3.3.0
+
+This document is a list of user-visible feature changes
+since the **3.2.0** release, except for bug fixes.
+
+Note that each entry is kept to a minimum, see links for details.
+
+## Command line options
+
+* A new `performance` warning category was introduced.
+ They are not displayed by default even in verbose mode.
+ Turn them on with `-W:performance` or `Warning[:performance] = true`. [[Feature #19538]]
+
+* A new `RUBY_CRASH_REPORT` environment variable was introduced to allow
+ redirecting Ruby crash reports to a file or sub command. See the `BUG REPORT ENVIRONMENT`
+ section of the ruby manpage for further details. [[Feature #19790]]
+
+## Core classes updates
+
+Note: We're only listing outstanding class updates.
+
+* Array
+
+ * Array#pack now raises ArgumentError for unknown directives. [[Bug #19150]]
+
+* Dir
+
+ * Dir.for_fd added for returning a Dir object for the directory specified
+ by the provided directory file descriptor. [[Feature #19347]]
+ * Dir.fchdir added for changing the directory to the directory specified
+ by the provided directory file descriptor. [[Feature #19347]]
+ * Dir#chdir added for changing the directory to the directory specified by
+ the provided `Dir` object. [[Feature #19347]]
+
+* Encoding
+
+ * `Encoding#replicate` has been removed, it was already deprecated. [[Feature #18949]]
+
+* Fiber
+
+ * Introduce Fiber#kill. [[Bug #595]]
+
+ ```ruby
+ fiber = Fiber.new do
+ while true
+ puts "Yielding..."
+ Fiber.yield
+ end
+ ensure
+ puts "Exiting..."
+ end
+
+ fiber.resume
+ # Yielding...
+ fiber.kill
+ # Exiting...
+ ```
+
+* MatchData
+
+ * MatchData#named_captures now accepts optional `symbolize_names`
+ keyword. [[Feature #19591]]
+
+* Module
+
+ * Module#set_temporary_name added for setting a temporary name for a
+ module. [[Feature #19521]]
+
+* ObjectSpace::WeakKeyMap
+
+ * New core class to build collections with weak references.
+ The class use equality semantic to lookup keys like a regular hash,
+ but it doesn't hold strong references on the keys. [[Feature #18498]]
+
+* ObjectSpace::WeakMap
+
+ * ObjectSpace::WeakMap#delete was added to eagerly clear weak map
+ entries. [[Feature #19561]]
+
+* Proc
+ * Now Proc#dup and Proc#clone call `#initialize_dup` and `#initialize_clone`
+ hooks respectively. [[Feature #19362]]
+
+* Process
+
+ * New Process.warmup method that notify the Ruby virtual machine that the boot sequence is finished,
+ and that now is a good time to optimize the application. This is useful
+ for long-running applications. The actual optimizations performed are entirely
+ implementation-specific and may change in the future without notice. [[Feature #18885]]
+
+* Process::Status
+
+ * Process::Status#& and Process::Status#>> are deprecated. [[Bug #19868]]
+
+* Range
+
+ * Range#reverse_each can now process beginless ranges with an Integer endpoint. [[Feature #18515]]
+ * Range#reverse_each now raises TypeError for endless ranges. [[Feature #18551]]
+ * Range#overlap? added for checking if two ranges overlap. [[Feature #19839]]
+
+* Refinement
+
+ * Add Refinement#target as an alternative of Refinement#refined_class.
+ Refinement#refined_class is deprecated and will be removed in Ruby
+ 3.4. [[Feature #19714]]
+
+* Regexp
+
+ * The cache-based optimization now supports lookarounds and atomic groupings. That is, match
+ for Regexp containing these extensions can now also be performed in linear time to the length
+ of the input string. However, these cannot contain captures and cannot be nested. [[Feature #19725]]
+
+* String
+
+ * String#unpack now raises ArgumentError for unknown directives. [[Bug #19150]]
+ * String#bytesplice now accepts new arguments index/length or range of the
+ source string to be copied. [[Feature #19314]]
+
+* Thread::Queue
+
+ * Thread::Queue#freeze now raises TypeError. [[Bug #17146]]
+
+* Thread::SizedQueue
+
+ * Thread::SizedQueue#freeze now raises TypeError. [[Bug #17146]]
+
+* Time
+
+ * Time.new with a string argument became stricter. [[Bug #19293]]
+
+ ```ruby
+ Time.new('2023-12-20')
+ # no time information (ArgumentError)
+ ```
+
+* TracePoint
+
+ * TracePoint supports `rescue` event. When the raised exception was rescued,
+ the TracePoint will fire the hook. `rescue` event only supports Ruby-level
+ `rescue`. [[Feature #19572]]
+
+## Stdlib updates
+
+* RubyGems and Bundler warn if users do `require` the following gems without adding them to Gemfile or gemspec.
+ This is because they will become the bundled gems in the future version of Ruby. This warning is suppressed
+ if you use bootsnap gem. We recommend to run your application with `DISABLE_BOOTSNAP=1` environmental variable
+ at least once. This is limitation of this version.
+ [[Feature #19351]] [[Feature #19776]] [[Feature #19843]]
+ * abbrev
+ * base64
+ * bigdecimal
+ * csv
+ * drb
+ * getoptlong
+ * mutex_m
+ * nkf
+ * observer
+ * racc
+ * resolv-replace
+ * rinda
+ * syslog
+
+* Socket#recv and Socket#recv_nonblock returns `nil` instead of an empty string on closed
+ connections. Socket#recvmsg and Socket#recvmsg_nonblock returns `nil` instead of an empty packet on closed
+ connections. [[Bug #19012]]
+
+* Name resolution such as Socket.getaddrinfo, Socket.getnameinfo, Addrinfo.getaddrinfo, etc.
+ can now be interrupted. [[Feature #19965]]
+
+* Random::Formatter#alphanumeric is extended to accept optional `chars`
+ keyword argument. [[Feature #18183]]
+
+The following default gem is added.
+
+* prism 0.19.0
+
+The following default gems are updated.
+
+* RubyGems 3.5.3
+* abbrev 0.1.2
+* base64 0.2.0
+* benchmark 0.3.0
+* bigdecimal 3.1.5
+* bundler 2.5.3
+* cgi 0.4.1
+* csv 3.2.8
+* date 3.3.4
+* delegate 0.3.1
+* drb 2.2.0
+* english 0.8.0
+* erb 4.0.3
+* error_highlight 0.6.0
+* etc 1.4.3
+* fcntl 1.1.0
+* fiddle 1.1.2
+* fileutils 1.7.2
+* find 0.2.0
+* getoptlong 0.2.1
+* io-console 0.7.1
+* io-nonblock 0.3.0
+* io-wait 0.3.1
+* ipaddr 1.2.6
+* irb 1.11.0
+* json 2.7.1
+* logger 1.6.0
+* mutex_m 0.2.0
+* net-http 0.4.0
+* net-protocol 0.2.2
+* nkf 0.1.3
+* observer 0.1.2
+* open-uri 0.4.1
+* open3 0.2.1
+* openssl 3.2.0
+* optparse 0.4.0
+* ostruct 0.6.0
+* pathname 0.3.0
+* pp 0.5.0
+* prettyprint 0.2.0
+* pstore 0.1.3
+* psych 5.1.2
+* rdoc 6.6.2
+* readline 0.0.4
+* reline 0.4.1
+* resolv 0.3.0
+* rinda 0.2.0
+* securerandom 0.3.1
+* set 1.1.0
+* shellwords 0.2.0
+* singleton 0.2.0
+* stringio 3.1.0
+* strscan 3.0.7
+* syntax_suggest 2.0.0
+* syslog 0.1.2
+* tempfile 0.2.1
+* time 0.3.0
+* timeout 0.4.1
+* tmpdir 0.2.0
+* tsort 0.2.0
+* un 0.3.0
+* uri 0.13.0
+* weakref 0.1.3
+* win32ole 1.8.10
+* yaml 0.3.0
+* zlib 3.1.0
+
+The following bundled gem is promoted from default gems.
+
+* racc 1.7.3
+
+The following bundled gems are updated.
+
+* minitest 5.20.0
+* rake 13.1.0
+* test-unit 3.6.1
+* rexml 3.2.6
+* rss 0.3.0
+* net-ftp 0.3.3
+* net-imap 0.4.9
+* net-smtp 0.4.0
+* rbs 3.4.0
+* typeprof 0.21.9
+* debug 1.9.1
+
+See GitHub releases like [Logger](https://github.com/ruby/logger/releases) or
+changelog for details of the default gems or bundled gems.
+
+### Prism
+
+* Introduced [the Prism parser](https://github.com/ruby/prism) as a default gem
+ * Prism is a portable, error tolerant, and maintainable recursive descent parser for the Ruby language
+* Prism is production ready and actively maintained, you can use it in place of Ripper
+ * There is [extensive documentation](https://ruby.github.io/prism/) on how to use Prism
+ * Prism is both a C library that will be used internally by CRuby and a Ruby gem that can be used by any tooling which needs to parse Ruby code
+ * Notable methods in the Prism API are:
+ * `Prism.parse(source)` which returns the AST as part of a parse result object
+ * `Prism.parse_comments(source)` which returns the comments
+ * `Prism.parse_success?(source)` which returns true if there are no errors
+* You can make pull requests or issues directly on [the Prism repository](https://github.com/ruby/prism) if you are interested in contributing
+* You can now use `ruby --parser=prism` or `RUBYOPT="--parser=prism"` to experiment with the Prism compiler. Please note that this flag is for debugging only.
+
+## Compatibility issues
+
+* Subprocess creation/forking via the following file open methods is deprecated. [[Feature #19630]]
+ * Kernel#open
+ * URI.open
+ * IO.binread
+ * IO.foreach
+ * IO.readlines
+ * IO.read
+ * IO.write
+
+* When given a non-lambda, non-literal block, Kernel#lambda with now raises
+ ArgumentError instead of returning it unmodified. These usages have been
+ issuing warnings under the `Warning[:deprecated]` category since Ruby 3.0.0.
+ [[Feature #19777]]
+
+* The `RUBY_GC_HEAP_INIT_SLOTS` environment variable has been deprecated and
+ removed. Environment variables `RUBY_GC_HEAP_%d_INIT_SLOTS` should be
+ used instead. [[Feature #19785]]
+
+* `it` calls without arguments in a block with no ordinary parameters are
+ deprecated. `it` will be a reference to the first block parameter in Ruby 3.4.
+ [[Feature #18980]]
+
+* Error message for NoMethodError have changed to not use the target object's `#inspect`
+ for efficiency, and says "instance of ClassName" instead. [[Feature #18285]]
+
+ ```ruby
+ ([1] * 100).nonexisting
+ # undefined method `nonexisting' for an instance of Array (NoMethodError)
+ ```
+
+* Now anonymous parameters forwarding is disallowed inside a block
+ that uses anonymous parameters. [[Feature #19370]]
+
+## Stdlib compatibility issues
+
+* `racc` is promoted to bundled gems.
+ * You need to add `racc` to your `Gemfile` if you use `racc` under bundler environment.
+* `ext/readline` is retired
+ * We have `reline` that is pure Ruby implementation compatible with `ext/readline` API.
+ We rely on `reline` in the future. If you need to use `ext/readline`, you can install
+ `ext/readline` via rubygems.org with `gem install readline-ext`.
+ * We no longer need to install libraries like `libreadline` or `libedit`.
+
+## C API updates
+
+* `rb_postponed_job` updates
+ * New APIs and deprecated APIs (see comments for details)
+ * added: `rb_postponed_job_preregister()`
+ * added: `rb_postponed_job_trigger()`
+ * deprecated: `rb_postponed_job_register()` (and semantic change. see below)
+ * deprecated: `rb_postponed_job_register_one()`
+ * The postponed job APIs have been changed to address some rare crashes.
+ To solve the issue, we introduced new two APIs and deprecated current APIs.
+ The semantics of these functions have also changed slightly; `rb_postponed_job_register`
+ now behaves like the `once` variant in that multiple calls with the same
+ `func` might be coalesced into a single execution of the `func`
+ [[Feature #20057]]
+
+* Some updates for internal thread event hook APIs
+ * `rb_internal_thread_event_data_t` with a target Ruby thread (VALUE)
+ and callback functions (`rb_internal_thread_event_callback`) receive it.
+ https://github.com/ruby/ruby/pull/8885
+ * The following functions are introduced to manipulate Ruby thread local data
+ from internal thread event hook APIs (they are introduced since Ruby 3.2).
+ https://github.com/ruby/ruby/pull/8936
+ * `rb_internal_thread_specific_key_create()`
+ * `rb_internal_thread_specific_get()`
+ * `rb_internal_thread_specific_set()`
+
+* `rb_profile_thread_frames()` is introduced to get a frames from
+ a specific thread.
+ [[Feature #10602]]
+
+* `rb_data_define()` is introduced to define `Data`. [[Feature #19757]]
+
+* `rb_ext_resolve_symbol()` is introduced to search a function from
+ extension libraries. [[Feature #20005]]
+
+* IO related updates:
+ * The details of `rb_io_t` will be hidden and deprecated attributes
+ are added for each members. [[Feature #19057]]
+ * `rb_io_path(VALUE io)` is introduced to get a path of `io`.
+ * `rb_io_closed_p(VALUE io)` to get opening or closing of `io`.
+ * `rb_io_mode(VALUE io)` to get the mode of `io`.
+ * `rb_io_open_descriptor()` is introduced to make an IO object from a file
+ descriptor.
+
+## Implementation improvements
+
+### Parser
+
+* Replace Bison with [Lrama LALR parser generator](https://github.com/ruby/lrama).
+ No need to install Bison to build Ruby from source code anymore.
+ We will no longer suffer bison compatibility issues and we can use new features by just implementing it to Lrama. [[Feature #19637]]
+ * See [The future vision of Ruby Parser](https://rubykaigi.org/2023/presentations/spikeolaf.html) for detail.
+ * Lrama internal parser is a LR parser generated by Racc for maintainability.
+ * Parameterizing Rules `(?, *, +)` are supported, it will be used in Ruby parse.y.
+
+### GC / Memory management
+
+* Major performance improvements over Ruby 3.2
+ * Young objects referenced by old objects are no longer immediately
+ promoted to the old generation. This significantly reduces the frequency of
+ major GC collections. [[Feature #19678]]
+ * A new `REMEMBERED_WB_UNPROTECTED_OBJECTS_LIMIT_RATIO` tuning variable was
+ introduced to control the number of unprotected objects cause a major GC
+ collection to trigger. The default is set to `0.01` (1%). This significantly
+ reduces the frequency of major GC collection. [[Feature #19571]]
+ * Write Barriers were implemented for many core types that were missing them,
+ notably `Time`, `Enumerator`, `MatchData`, `Method`, `File::Stat`, `BigDecimal`
+ and several others. This significantly reduces minor GC collection time and major
+ GC collection frequency.
+ * Most core classes are now using Variable Width Allocation, notably `Hash`, `Time`,
+ `Thread::Backtrace`, `Thread::Backtrace::Location`, `File::Stat`, `Method`.
+ This makes these classes faster to allocate and free, use less memory and reduce
+ heap fragmentation.
+* `defined?(@ivar)` is optimized with Object Shapes.
+
+### YJIT
+
+* Major performance improvements over Ruby 3.2
+ * Support for splat and rest arguments has been improved.
+ * Registers are allocated for stack operations of the virtual machine.
+ * More calls with optional arguments are compiled. Exception handlers are also compiled.
+ * Unsupported call types and megamorphic call sites no longer exit to the interpreter.
+ * Basic methods like Rails `#blank?` and
+ [specialized `#present?`](https://github.com/rails/rails/pull/49909) are inlined.
+ * `Integer#*`, `Integer#!=`, `String#!=`, `String#getbyte`,
+ `Kernel#block_given?`, `Kernel#is_a?`, `Kernel#instance_of?`, and `Module#===`
+ are specially optimized.
+ * Compilation speed is now slightly faster than Ruby 3.2.
+ * Now more than 3x faster than the interpreter on Optcarrot!
+* Significantly improved memory usage over Ruby 3.2
+ * Metadata for compiled code uses a lot less memory.
+ * `--yjit-call-threshold` is automatically raised from 30 to 120
+ when the application has more than 40,000 ISEQs.
+ * `--yjit-cold-threshold` is added to skip compiling cold ISEQs.
+ * More compact code is generated on Arm64.
+* Code GC is now disabled by default
+ * `--yjit-exec-mem-size` is treated as a hard limit where compilation of new code stops.
+ * No sudden drops in performance due to code GC.
+ Better copy-on-write behavior on servers reforking with
+ [Pitchfork](https://github.com/shopify/pitchfork).
+ * You can still enable code GC if desired with `--yjit-code-gc`
+* Add `RubyVM::YJIT.enable` that can enable YJIT at run-time
+ * You can start YJIT without modifying command-line arguments or environment variables.
+ Rails 7.2 will [enable YJIT by default](https://github.com/rails/rails/pull/49947)
+ using this method.
+ * This can also be used to enable YJIT only once your application is
+ done booting. `--yjit-disable` can be used if you want to use other
+ YJIT options while disabling YJIT at boot.
+* More YJIT stats are available by default
+ * `yjit_alloc_size` and several more metadata-related stats are now available by default.
+ * `ratio_in_yjit` stat produced by `--yjit-stats` is now available in release builds,
+ a special stats or dev build is no longer required to access most stats.
+* Add more profiling capabilities
+ * `--yjit-perf` is added to facilitate profiling with Linux perf.
+ * `--yjit-trace-exits` now supports sampling with `--yjit-trace-exits-sample-rate=N`
+* More thorough testing and multiple bug fixes
+* `--yjit-stats=quiet` is added to avoid printing stats on exit.
+
+### MJIT
+
+* MJIT is removed.
+ * `--disable-jit-support` is removed. Consider using `--disable-yjit --disable-rjit` instead.
+
+### RJIT
+
+* Introduced a pure-Ruby JIT compiler RJIT.
+ * RJIT supports only x86\_64 architecture on Unix platforms.
+ * Unlike MJIT, it doesn't require a C compiler at runtime.
+* RJIT exists only for experimental purposes.
+ * You should keep using YJIT in production.
+
+### M:N Thread scheduler
+
+* M:N Thread scheduler is introduced. [[Feature #19842]]
+ * Background: Ruby 1.8 and before, M:1 thread scheduler (M Ruby threads
+ with 1 native thread. Called as User level threads or Green threads)
+ is used. Ruby 1.9 and later, 1:1 thread scheduler (1 Ruby thread with
+ 1 native thread). M:1 threads takes lower resources compare with 1:1
+ threads because it needs only 1 native threads. However it is difficult
+ to support context switching for all of blocking operation so 1:1
+ threads are employed from Ruby 1.9. M:N thread scheduler uses N native
+ threads for M Ruby threads (N is small number in general). It doesn't
+ need same number of native threads as Ruby threads (similar to the M:1
+ thread scheduler). Also our M:N threads supports blocking operations
+ well same as 1:1 threads. See the ticket for more details.
+ Our M:N thread scheduler refers on the goroutine scheduler in the
+ Go language.
+ * In a ractor, only 1 thread can run in a same time because of
+ implementation. Therefore, applications that use only one Ractor
+ (most applications) M:N thread scheduler works as M:1 thread scheduler
+ with further extension from Ruby 1.8.
+ * M:N thread scheduler can introduce incompatibility for C-extensions,
+ so it is disabled by default on the main Ractors.
+ `RUBY_MN_THREADS=1` environment variable will enable it.
+ On non-main Ractors, M:N thread scheduler is enabled (and can not
+ disable it now).
+ * `N` (the number of native threads) can be specified with `RUBY_MAX_CPU`
+ environment variable. The default is 8.
+ Note that more than `N` native threads are used to support many kind of
+ blocking operations.
+
+[Bug #595]: https://bugs.ruby-lang.org/issues/595
+[Feature #10602]: https://bugs.ruby-lang.org/issues/10602
+[Bug #17146]: https://bugs.ruby-lang.org/issues/17146
+[Feature #18183]: https://bugs.ruby-lang.org/issues/18183
+[Feature #18285]: https://bugs.ruby-lang.org/issues/18285
+[Feature #18498]: https://bugs.ruby-lang.org/issues/18498
+[Feature #18515]: https://bugs.ruby-lang.org/issues/18515
+[Feature #18551]: https://bugs.ruby-lang.org/issues/18551
+[Feature #18885]: https://bugs.ruby-lang.org/issues/18885
+[Feature #18949]: https://bugs.ruby-lang.org/issues/18949
+[Feature #18980]: https://bugs.ruby-lang.org/issues/18980
+[Bug #19012]: https://bugs.ruby-lang.org/issues/19012
+[Feature #19057]: https://bugs.ruby-lang.org/issues/19057
+[Bug #19150]: https://bugs.ruby-lang.org/issues/19150
+[Bug #19293]: https://bugs.ruby-lang.org/issues/19293
+[Feature #19314]: https://bugs.ruby-lang.org/issues/19314
+[Feature #19347]: https://bugs.ruby-lang.org/issues/19347
+[Feature #19351]: https://bugs.ruby-lang.org/issues/19351
+[Feature #19362]: https://bugs.ruby-lang.org/issues/19362
+[Feature #19370]: https://bugs.ruby-lang.org/issues/19370
+[Feature #19521]: https://bugs.ruby-lang.org/issues/19521
+[Feature #19538]: https://bugs.ruby-lang.org/issues/19538
+[Feature #19561]: https://bugs.ruby-lang.org/issues/19561
+[Feature #19571]: https://bugs.ruby-lang.org/issues/19571
+[Feature #19572]: https://bugs.ruby-lang.org/issues/19572
+[Feature #19591]: https://bugs.ruby-lang.org/issues/19591
+[Feature #19630]: https://bugs.ruby-lang.org/issues/19630
+[Feature #19637]: https://bugs.ruby-lang.org/issues/19637
+[Feature #19678]: https://bugs.ruby-lang.org/issues/19678
+[Feature #19714]: https://bugs.ruby-lang.org/issues/19714
+[Feature #19725]: https://bugs.ruby-lang.org/issues/19725
+[Feature #19757]: https://bugs.ruby-lang.org/issues/19757
+[Feature #19776]: https://bugs.ruby-lang.org/issues/19776
+[Feature #19777]: https://bugs.ruby-lang.org/issues/19777
+[Feature #19785]: https://bugs.ruby-lang.org/issues/19785
+[Feature #19790]: https://bugs.ruby-lang.org/issues/19790
+[Feature #19839]: https://bugs.ruby-lang.org/issues/19839
+[Feature #19842]: https://bugs.ruby-lang.org/issues/19842
+[Feature #19843]: https://bugs.ruby-lang.org/issues/19843
+[Bug #19868]: https://bugs.ruby-lang.org/issues/19868
+[Feature #19965]: https://bugs.ruby-lang.org/issues/19965
+[Feature #20005]: https://bugs.ruby-lang.org/issues/20005
+[Feature #20057]: https://bugs.ruby-lang.org/issues/20057
diff --git a/doc/_regexp.rdoc b/doc/_regexp.rdoc
new file mode 100644
index 0000000000..7b71eee984
--- /dev/null
+++ b/doc/_regexp.rdoc
@@ -0,0 +1,1276 @@
+A {regular expression}[https://en.wikipedia.org/wiki/Regular_expression]
+(also called a _regexp_) is a <i>match pattern</i> (also simply called a _pattern_).
+
+A common notation for a regexp uses enclosing slash characters:
+
+ /foo/
+
+A regexp may be applied to a <i>target string</i>;
+The part of the string (if any) that matches the pattern is called a _match_,
+and may be said <i>to match</i>:
+
+ re = /red/
+ re.match?('redirect') # => true # Match at beginning of target.
+ re.match?('bored') # => true # Match at end of target.
+ re.match?('credit') # => true # Match within target.
+ re.match?('foo') # => false # No match.
+
+== \Regexp Uses
+
+A regexp may be used:
+
+- To extract substrings based on a given pattern:
+
+ re = /foo/ # => /foo/
+ re.match('food') # => #<MatchData "foo">
+ re.match('good') # => nil
+
+ See sections {Method match}[rdoc-ref:Regexp@Method+match]
+ and {Operator =~}[rdoc-ref:Regexp@Operator+-3D~].
+
+- To determine whether a string matches a given pattern:
+
+ re.match?('food') # => true
+ re.match?('good') # => false
+
+ See section {Method match?}[rdoc-ref:Regexp@Method+match-3F].
+
+- As an argument for calls to certain methods in other classes and modules;
+ most such methods accept an argument that may be either a string
+ or the (much more powerful) regexp.
+
+ See {Regexp Methods}[rdoc-ref:regexp/methods.rdoc].
+
+== \Regexp Objects
+
+A regexp object has:
+
+- A source; see {Sources}[rdoc-ref:Regexp@Sources].
+
+- Several modes; see {Modes}[rdoc-ref:Regexp@Modes].
+
+- A timeout; see {Timeouts}[rdoc-ref:Regexp@Timeouts].
+
+- An encoding; see {Encodings}[rdoc-ref:Regexp@Encodings].
+
+== Creating a \Regexp
+
+A regular expression may be created with:
+
+- A regexp literal using slash characters
+ (see {Regexp Literals}[rdoc-ref:syntax/literals.rdoc@Regexp+Literals]):
+
+ # This is a very common usage.
+ /foo/ # => /foo/
+
+- A <tt>%r</tt> regexp literal
+ (see {%r: Regexp Literals}[rdoc-ref:syntax/literals.rdoc@25r-3A+Regexp+Literals]):
+
+ # Same delimiter character at beginning and end;
+ # useful for avoiding escaping characters
+ %r/name\/value pair/ # => /name\/value pair/
+ %r:name/value pair: # => /name\/value pair/
+ %r|name/value pair| # => /name\/value pair/
+
+ # Certain "paired" characters can be delimiters.
+ %r[foo] # => /foo/
+ %r{foo} # => /foo/
+ %r(foo) # => /foo/
+ %r<foo> # => /foo/
+
+- \Method Regexp.new.
+
+== \Method <tt>match</tt>
+
+Each of the methods Regexp#match, String#match, and Symbol#match
+returns a MatchData object if a match was found, +nil+ otherwise;
+each also sets {global variables}[rdoc-ref:Regexp@Global+Variables]:
+
+ 'food'.match(/foo/) # => #<MatchData "foo">
+ 'food'.match(/bar/) # => nil
+
+== Operator <tt>=~</tt>
+
+Each of the operators Regexp#=~, String#=~, and Symbol#=~
+returns an integer offset if a match was found, +nil+ otherwise;
+each also sets {global variables}[rdoc-ref:Regexp@Global+Variables]:
+
+ /bar/ =~ 'foo bar' # => 4
+ 'foo bar' =~ /bar/ # => 4
+ /baz/ =~ 'foo bar' # => nil
+
+== \Method <tt>match?</tt>
+
+Each of the methods Regexp#match?, String#match?, and Symbol#match?
+returns +true+ if a match was found, +false+ otherwise;
+none sets {global variables}[rdoc-ref:Regexp@Global+Variables]:
+
+ 'food'.match?(/foo/) # => true
+ 'food'.match?(/bar/) # => false
+
+== Global Variables
+
+Certain regexp-oriented methods assign values to global variables:
+
+- <tt>#match</tt>: see {Method match}[rdoc-ref:Regexp@Method+match].
+- <tt>#=~</tt>: see {Operator =~}[rdoc-ref:Regexp@Operator+-3D~].
+
+The affected global variables are:
+
+- <tt>$~</tt>: Returns a MatchData object, or +nil+.
+- <tt>$&</tt>: Returns the matched part of the string, or +nil+.
+- <tt>$`</tt>: Returns the part of the string to the left of the match, or +nil+.
+- <tt>$'</tt>: Returns the part of the string to the right of the match, or +nil+.
+- <tt>$+</tt>: Returns the last group matched, or +nil+.
+- <tt>$1</tt>, <tt>$2</tt>, etc.: Returns the first, second, etc.,
+ matched group, or +nil+.
+ Note that <tt>$0</tt> is quite different;
+ it returns the name of the currently executing program.
+
+Examples:
+
+ # Matched string, but no matched groups.
+ 'foo bar bar baz'.match('bar')
+ $~ # => #<MatchData "bar">
+ $& # => "bar"
+ $` # => "foo "
+ $' # => " bar baz"
+ $+ # => nil
+ $1 # => nil
+
+ # Matched groups.
+ /s(\w{2}).*(c)/.match('haystack')
+ $~ # => #<MatchData "stac" 1:"ta" 2:"c">
+ $& # => "stac"
+ $` # => "hay"
+ $' # => "k"
+ $+ # => "c"
+ $1 # => "ta"
+ $2 # => "c"
+ $3 # => nil
+
+ # No match.
+ 'foo'.match('bar')
+ $~ # => nil
+ $& # => nil
+ $` # => nil
+ $' # => nil
+ $+ # => nil
+ $1 # => nil
+
+Note that Regexp#match?, String#match?, and Symbol#match?
+do not set global variables.
+
+== Sources
+
+As seen above, the simplest regexp uses a literal expression as its source:
+
+ re = /foo/ # => /foo/
+ re.match('food') # => #<MatchData "foo">
+ re.match('good') # => nil
+
+A rich collection of available _subexpressions_
+gives the regexp great power and flexibility:
+
+- {Special characters}[rdoc-ref:Regexp@Special+Characters]
+- {Source literals}[rdoc-ref:Regexp@Source+Literals]
+- {Character classes}[rdoc-ref:Regexp@Character+Classes]
+- {Shorthand character classes}[rdoc-ref:Regexp@Shorthand+Character+Classes]
+- {Anchors}[rdoc-ref:Regexp@Anchors]
+- {Alternation}[rdoc-ref:Regexp@Alternation]
+- {Quantifiers}[rdoc-ref:Regexp@Quantifiers]
+- {Groups and captures}[rdoc-ref:Regexp@Groups+and+Captures]
+- {Unicode}[rdoc-ref:Regexp@Unicode]
+- {POSIX Bracket Expressions}[rdoc-ref:Regexp@POSIX+Bracket+Expressions]
+- {Comments}[rdoc-ref:Regexp@Comments]
+
+=== Special Characters
+
+\Regexp special characters, called _metacharacters_,
+have special meanings in certain contexts;
+depending on the context, these are sometimes metacharacters:
+
+ . ? - + * ^ \ | $ ( ) [ ] { }
+
+To match a metacharacter literally, backslash-escape it:
+
+ # Matches one or more 'o' characters.
+ /o+/.match('foo') # => #<MatchData "oo">
+ # Would match 'o+'.
+ /o\+/.match('foo') # => nil
+
+To match a backslash literally, backslash-escape it:
+
+ /\./.match('\.') # => #<MatchData ".">
+ /\\./.match('\.') # => #<MatchData "\\.">
+
+Method Regexp.escape returns an escaped string:
+
+ Regexp.escape('.?-+*^\|$()[]{}')
+ # => "\\.\\?\\-\\+\\*\\^\\\\\\|\\$\\(\\)\\[\\]\\{\\}"
+
+=== Source Literals
+
+The source literal largely behaves like a double-quoted string;
+see {String Literals}[rdoc-ref:syntax/literals.rdoc@String+Literals].
+
+In particular, a source literal may contain interpolated expressions:
+
+ s = 'foo' # => "foo"
+ /#{s}/ # => /foo/
+ /#{s.capitalize}/ # => /Foo/
+ /#{2 + 2}/ # => /4/
+
+There are differences between an ordinary string literal and a source literal;
+see {Shorthand Character Classes}[rdoc-ref:Regexp@Shorthand+Character+Classes].
+
+- <tt>\s</tt> in an ordinary string literal is equivalent to a space character;
+ in a source literal, it's shorthand for matching a whitespace character.
+- In an ordinary string literal, these are (needlessly) escaped characters;
+ in a source literal, they are shorthands for various matching characters:
+
+ \w \W \d \D \h \H \S \R
+
+=== Character Classes
+
+A <i>character class</i> is delimited by square brackets;
+it specifies that certain characters match at a given point in the target string:
+
+ # This character class will match any vowel.
+ re = /B[aeiou]rd/
+ re.match('Bird') # => #<MatchData "Bird">
+ re.match('Bard') # => #<MatchData "Bard">
+ re.match('Byrd') # => nil
+
+A character class may contain hyphen characters to specify ranges of characters:
+
+ # These regexps have the same effect.
+ /[abcdef]/.match('foo') # => #<MatchData "f">
+ /[a-f]/.match('foo') # => #<MatchData "f">
+ /[a-cd-f]/.match('foo') # => #<MatchData "f">
+
+When the first character of a character class is a caret (<tt>^</tt>),
+the sense of the class is inverted: it matches any character _except_ those specified.
+
+ /[^a-eg-z]/.match('f') # => #<MatchData "f">
+
+A character class may contain another character class.
+By itself this isn't useful because <tt>[a-z[0-9]]</tt>
+describes the same set as <tt>[a-z0-9]</tt>.
+
+However, character classes also support the <tt>&&</tt> operator,
+which performs set intersection on its arguments.
+The two can be combined as follows:
+
+ /[a-w&&[^c-g]z]/ # ([a-w] AND ([^c-g] OR z))
+
+This is equivalent to:
+
+ /[abh-w]/
+
+=== Shorthand Character Classes
+
+Each of the following metacharacters serves as a shorthand
+for a character class:
+
+- <tt>/./</tt>: Matches any character except a newline:
+
+ /./.match('foo') # => #<MatchData "f">
+ /./.match("\n") # => nil
+
+- <tt>/./m</tt>: Matches any character, including a newline;
+ see {Multiline Mode}[rdoc-ref:Regexp@Multiline+Mode]:
+
+ /./m.match("\n") # => #<MatchData "\n">
+
+- <tt>/\w/</tt>: Matches a word character: equivalent to <tt>[a-zA-Z0-9_]</tt>:
+
+ /\w/.match(' foo') # => #<MatchData "f">
+ /\w/.match(' _') # => #<MatchData "_">
+ /\w/.match(' ') # => nil
+
+- <tt>/\W/</tt>: Matches a non-word character: equivalent to <tt>[^a-zA-Z0-9_]</tt>:
+
+ /\W/.match(' ') # => #<MatchData " ">
+ /\W/.match('_') # => nil
+
+- <tt>/\d/</tt>: Matches a digit character: equivalent to <tt>[0-9]</tt>:
+
+ /\d/.match('THX1138') # => #<MatchData "1">
+ /\d/.match('foo') # => nil
+
+- <tt>/\D/</tt>: Matches a non-digit character: equivalent to <tt>[^0-9]</tt>:
+
+ /\D/.match('123Jump!') # => #<MatchData "J">
+ /\D/.match('123') # => nil
+
+- <tt>/\h/</tt>: Matches a hexdigit character: equivalent to <tt>[0-9a-fA-F]</tt>:
+
+ /\h/.match('xyz fedcba9876543210') # => #<MatchData "f">
+ /\h/.match('xyz') # => nil
+
+- <tt>/\H/</tt>: Matches a non-hexdigit character: equivalent to <tt>[^0-9a-fA-F]</tt>:
+
+ /\H/.match('fedcba9876543210xyz') # => #<MatchData "x">
+ /\H/.match('fedcba9876543210') # => nil
+
+- <tt>/\s/</tt>: Matches a whitespace character: equivalent to <tt>/[ \t\r\n\f\v]/</tt>:
+
+ /\s/.match('foo bar') # => #<MatchData " ">
+ /\s/.match('foo') # => nil
+
+- <tt>/\S/</tt>: Matches a non-whitespace character: equivalent to <tt>/[^ \t\r\n\f\v]/</tt>:
+
+ /\S/.match(" \t\r\n\f\v foo") # => #<MatchData "f">
+ /\S/.match(" \t\r\n\f\v") # => nil
+
+- <tt>/\R/</tt>: Matches a linebreak, platform-independently:
+
+ /\R/.match("\r") # => #<MatchData "\r"> # Carriage return (CR)
+ /\R/.match("\n") # => #<MatchData "\n"> # Newline (LF)
+ /\R/.match("\f") # => #<MatchData "\f"> # Formfeed (FF)
+ /\R/.match("\v") # => #<MatchData "\v"> # Vertical tab (VT)
+ /\R/.match("\r\n") # => #<MatchData "\r\n"> # CRLF
+ /\R/.match("\u0085") # => #<MatchData "\u0085"> # Next line (NEL)
+ /\R/.match("\u2028") # => #<MatchData "\u2028"> # Line separator (LSEP)
+ /\R/.match("\u2029") # => #<MatchData "\u2029"> # Paragraph separator (PSEP)
+
+=== Anchors
+
+An anchor is a metasequence that matches a zero-width position between
+characters in the target string.
+
+For a subexpression with no anchor,
+matching may begin anywhere in the target string:
+
+ /real/.match('surrealist') # => #<MatchData "real">
+
+For a subexpression with an anchor,
+matching must begin at the matched anchor.
+
+==== Boundary Anchors
+
+Each of these anchors matches a boundary:
+
+- <tt>^</tt>: Matches the beginning of a line:
+
+ /^bar/.match("foo\nbar") # => #<MatchData "bar">
+ /^ar/.match("foo\nbar") # => nil
+
+- <tt>$</tt>: Matches the end of a line:
+
+ /bar$/.match("foo\nbar") # => #<MatchData "bar">
+ /ba$/.match("foo\nbar") # => nil
+
+- <tt>\A</tt>: Matches the beginning of the string:
+
+ /\Afoo/.match('foo bar') # => #<MatchData "foo">
+ /\Afoo/.match(' foo bar') # => nil
+
+- <tt>\Z</tt>: Matches the end of the string;
+ if string ends with a single newline,
+ it matches just before the ending newline:
+
+ /foo\Z/.match('bar foo') # => #<MatchData "foo">
+ /foo\Z/.match('foo bar') # => nil
+ /foo\Z/.match("bar foo\n") # => #<MatchData "foo">
+ /foo\Z/.match("bar foo\n\n") # => nil
+
+- <tt>\z</tt>: Matches the end of the string:
+
+ /foo\z/.match('bar foo') # => #<MatchData "foo">
+ /foo\z/.match('foo bar') # => nil
+ /foo\z/.match("bar foo\n") # => nil
+
+- <tt>\b</tt>: Matches word boundary when not inside brackets;
+ matches backspace (<tt>"0x08"</tt>) when inside brackets:
+
+ /foo\b/.match('foo bar') # => #<MatchData "foo">
+ /foo\b/.match('foobar') # => nil
+
+- <tt>\B</tt>: Matches non-word boundary:
+
+ /foo\B/.match('foobar') # => #<MatchData "foo">
+ /foo\B/.match('foo bar') # => nil
+
+- <tt>\G</tt>: Matches first matching position:
+
+ In methods like String#gsub and String#scan, it changes on each iteration.
+ It initially matches the beginning of subject, and in each following iteration it matches where the last match finished.
+
+ " a b c".gsub(/ /, '_') # => "____a_b_c"
+ " a b c".gsub(/\G /, '_') # => "____a b c"
+
+ In methods like Regexp#match and String#match
+ that take an optional offset, it matches where the search begins.
+
+ "hello, world".match(/,/, 3) # => #<MatchData ",">
+ "hello, world".match(/\G,/, 3) # => nil
+
+==== Lookaround Anchors
+
+Lookahead anchors:
+
+- <tt>(?=_pat_)</tt>: Positive lookahead assertion:
+ ensures that the following characters match _pat_,
+ but doesn't include those characters in the matched substring.
+
+- <tt>(?!_pat_)</tt>: Negative lookahead assertion:
+ ensures that the following characters <i>do not</i> match _pat_,
+ but doesn't include those characters in the matched substring.
+
+Lookbehind anchors:
+
+- <tt>(?<=_pat_)</tt>: Positive lookbehind assertion:
+ ensures that the preceding characters match _pat_, but
+ doesn't include those characters in the matched substring.
+
+- <tt>(?<!_pat_)</tt>: Negative lookbehind assertion:
+ ensures that the preceding characters do not match
+ _pat_, but doesn't include those characters in the matched substring.
+
+The pattern below uses positive lookahead and positive lookbehind to match
+text appearing in <tt><b></tt>...<tt></b></tt> tags
+without including the tags in the match:
+
+ /(?<=<b>)\w+(?=<\/b>)/.match("Fortune favors the <b>bold</b>.")
+ # => #<MatchData "bold">
+
+==== Match-Reset Anchor
+
+- <tt>\K</tt>: Match reset:
+ the matched content preceding <tt>\K</tt> in the regexp is excluded from the result.
+ For example, the following two regexps are almost equivalent:
+
+ /ab\Kc/.match('abc') # => #<MatchData "c">
+ /(?<=ab)c/.match('abc') # => #<MatchData "c">
+
+ These match same string and <tt>$&</tt> equals <tt>'c'</tt>,
+ while the matched position is different.
+
+ As are the following two regexps:
+
+ /(a)\K(b)\Kc/
+ /(?<=(?<=(a))(b))c/
+
+=== Alternation
+
+The vertical bar metacharacter (<tt>|</tt>) may be used within parentheses
+to express alternation:
+two or more subexpressions any of which may match the target string.
+
+Two alternatives:
+
+ re = /(a|b)/
+ re.match('foo') # => nil
+ re.match('bar') # => #<MatchData "b" 1:"b">
+
+Four alternatives:
+
+ re = /(a|b|c|d)/
+ re.match('shazam') # => #<MatchData "a" 1:"a">
+ re.match('cold') # => #<MatchData "c" 1:"c">
+
+Each alternative is a subexpression, and may be composed of other subexpressions:
+
+ re = /([a-c]|[x-z])/
+ re.match('bar') # => #<MatchData "b" 1:"b">
+ re.match('ooz') # => #<MatchData "z" 1:"z">
+
+\Method Regexp.union provides a convenient way to construct
+a regexp with alternatives.
+
+=== Quantifiers
+
+A simple regexp matches one character:
+
+ /\w/.match('Hello') # => #<MatchData "H">
+
+An added _quantifier_ specifies how many matches are required or allowed:
+
+- <tt>*</tt> - Matches zero or more times:
+
+ /\w*/.match('')
+ # => #<MatchData "">
+ /\w*/.match('x')
+ # => #<MatchData "x">
+ /\w*/.match('xyz')
+ # => #<MatchData "yz">
+
+- <tt>+</tt> - Matches one or more times:
+
+ /\w+/.match('') # => nil
+ /\w+/.match('x') # => #<MatchData "x">
+ /\w+/.match('xyz') # => #<MatchData "xyz">
+
+- <tt>?</tt> - Matches zero or one times:
+
+ /\w?/.match('') # => #<MatchData "">
+ /\w?/.match('x') # => #<MatchData "x">
+ /\w?/.match('xyz') # => #<MatchData "x">
+
+- <tt>{</tt>_n_<tt>}</tt> - Matches exactly _n_ times:
+
+ /\w{2}/.match('') # => nil
+ /\w{2}/.match('x') # => nil
+ /\w{2}/.match('xyz') # => #<MatchData "xy">
+
+- <tt>{</tt>_min_<tt>,}</tt> - Matches _min_ or more times:
+
+ /\w{2,}/.match('') # => nil
+ /\w{2,}/.match('x') # => nil
+ /\w{2,}/.match('xy') # => #<MatchData "xy">
+ /\w{2,}/.match('xyz') # => #<MatchData "xyz">
+
+- <tt>{,</tt>_max_<tt>}</tt> - Matches _max_ or fewer times:
+
+ /\w{,2}/.match('') # => #<MatchData "">
+ /\w{,2}/.match('x') # => #<MatchData "x">
+ /\w{,2}/.match('xyz') # => #<MatchData "xy">
+
+- <tt>{</tt>_min_<tt>,</tt>_max_<tt>}</tt> -
+ Matches at least _min_ times and at most _max_ times:
+
+ /\w{1,2}/.match('') # => nil
+ /\w{1,2}/.match('x') # => #<MatchData "x">
+ /\w{1,2}/.match('xyz') # => #<MatchData "xy">
+
+==== Greedy, Lazy, or Possessive Matching
+
+Quantifier matching may be greedy, lazy, or possessive:
+
+- In _greedy_ matching, as many occurrences as possible are matched
+ while still allowing the overall match to succeed.
+ Greedy quantifiers: <tt>*</tt>, <tt>+</tt>, <tt>?</tt>,
+ <tt>{min, max}</tt> and its variants.
+- In _lazy_ matching, the minimum number of occurrences are matched.
+ Lazy quantifiers: <tt>*?</tt>, <tt>+?</tt>, <tt>??</tt>,
+ <tt>{min, max}?</tt> and its variants.
+- In _possessive_ matching, once a match is found, there is no backtracking;
+ that match is retained, even if it jeopardises the overall match.
+ Possessive quantifiers: <tt>*+</tt>, <tt>++</tt>, <tt>?+</tt>.
+ Note that <tt>{min, max}</tt> and its variants do _not_ support possessive matching.
+
+More:
+
+- About greedy and lazy matching, see
+ {Choosing Minimal or Maximal Repetition}[https://doc.lagout.org/programmation/Regular%20Expressions/Regular%20Expressions%20Cookbook_%20Detailed%20Solutions%20in%20Eight%20Programming%20Languages%20%282nd%20ed.%29%20%5BGoyvaerts%20%26%20Levithan%202012-09-06%5D.pdf#tutorial-backtrack].
+- About possessive matching, see
+ {Eliminate Needless Backtracking}[https://doc.lagout.org/programmation/Regular%20Expressions/Regular%20Expressions%20Cookbook_%20Detailed%20Solutions%20in%20Eight%20Programming%20Languages%20%282nd%20ed.%29%20%5BGoyvaerts%20%26%20Levithan%202012-09-06%5D.pdf#tutorial-backtrack].
+
+=== Groups and Captures
+
+A simple regexp has (at most) one match:
+
+ re = /\d\d\d\d-\d\d-\d\d/
+ re.match('1943-02-04') # => #<MatchData "1943-02-04">
+ re.match('1943-02-04').size # => 1
+ re.match('foo') # => nil
+
+Adding one or more pairs of parentheses, <tt>(_subexpression_)</tt>,
+defines _groups_, which may result in multiple matched substrings,
+called _captures_:
+
+ re = /(\d\d\d\d)-(\d\d)-(\d\d)/
+ re.match('1943-02-04') # => #<MatchData "1943-02-04" 1:"1943" 2:"02" 3:"04">
+ re.match('1943-02-04').size # => 4
+
+The first capture is the entire matched string;
+the other captures are the matched substrings from the groups.
+
+A group may have a {quantifier}[rdoc-ref:Regexp@Quantifiers]:
+
+ re = /July 4(th)?/
+ re.match('July 4') # => #<MatchData "July 4" 1:nil>
+ re.match('July 4th') # => #<MatchData "July 4th" 1:"th">
+
+ re = /(foo)*/
+ re.match('') # => #<MatchData "" 1:nil>
+ re.match('foo') # => #<MatchData "foo" 1:"foo">
+ re.match('foofoo') # => #<MatchData "foofoo" 1:"foo">
+
+ re = /(foo)+/
+ re.match('') # => nil
+ re.match('foo') # => #<MatchData "foo" 1:"foo">
+ re.match('foofoo') # => #<MatchData "foofoo" 1:"foo">
+
+The returned \MatchData object gives access to the matched substrings:
+
+ re = /(\d\d\d\d)-(\d\d)-(\d\d)/
+ md = re.match('1943-02-04')
+ # => #<MatchData "1943-02-04" 1:"1943" 2:"02" 3:"04">
+ md[0] # => "1943-02-04"
+ md[1] # => "1943"
+ md[2] # => "02"
+ md[3] # => "04"
+
+==== Non-Capturing Groups
+
+A group may be made non-capturing;
+it is still a group (and, for example, can have a quantifier),
+but its matching substring is not included among the captures.
+
+A non-capturing group begins with <tt>?:</tt> (inside the parentheses):
+
+ # Don't capture the year.
+ re = /(?:\d\d\d\d)-(\d\d)-(\d\d)/
+ md = re.match('1943-02-04') # => #<MatchData "1943-02-04" 1:"02" 2:"04">
+
+==== Backreferences
+
+A group match may also be referenced within the regexp itself;
+such a reference is called a +backreference+:
+
+ /[csh](..) [csh]\1 in/.match('The cat sat in the hat')
+ # => #<MatchData "cat sat in" 1:"at">
+
+This table shows how each subexpression in the regexp above
+matches a substring in the target string:
+
+ | Subexpression in Regexp | Matching Substring in Target String |
+ |---------------------------|-------------------------------------|
+ | First '[csh]' | Character 'c' |
+ | '(..)' | First substring 'at' |
+ | First space ' ' | First space character ' ' |
+ | Second '[csh]' | Character 's' |
+ | '\1' (backreference 'at') | Second substring 'at' |
+ | ' in' | Substring ' in' |
+
+A regexp may contain any number of groups:
+
+- For a large number of groups:
+
+ - The ordinary <tt>\\_n_</tt> notation applies only for _n_ in range (1..9).
+ - The <tt>MatchData[_n_]</tt> notation applies for any non-negative _n_.
+
+- <tt>\0</tt> is a special backreference, referring to the entire matched string;
+ it may not be used within the regexp itself,
+ but may be used outside it (for example, in a substitution method call):
+
+ 'The cat sat in the hat'.gsub(/[csh]at/, '\0s')
+ # => "The cats sats in the hats"
+
+==== Named Captures
+
+As seen above, a capture can be referred to by its number.
+A capture can also have a name,
+prefixed as <tt>?<_name_></tt> or <tt>?'_name_'</tt>,
+and the name (symbolized) may be used as an index in <tt>MatchData[]</tt>:
+
+ md = /\$(?<dollars>\d+)\.(?'cents'\d+)/.match("$3.67")
+ # => #<MatchData "$3.67" dollars:"3" cents:"67">
+ md[:dollars] # => "3"
+ md[:cents] # => "67"
+ # The capture numbers are still valid.
+ md[2] # => "67"
+
+When a regexp contains a named capture, there are no unnamed captures:
+
+ /\$(?<dollars>\d+)\.(\d+)/.match("$3.67")
+ # => #<MatchData "$3.67" dollars:"3">
+
+A named group may be backreferenced as <tt>\k<_name_></tt>:
+
+ /(?<vowel>[aeiou]).\k<vowel>.\k<vowel>/.match('ototomy')
+ # => #<MatchData "ototo" vowel:"o">
+
+When (and only when) a regexp contains named capture groups
+and appears before the <tt>=~</tt> operator,
+the captured substrings are assigned to local variables with corresponding names:
+
+ /\$(?<dollars>\d+)\.(?<cents>\d+)/ =~ '$3.67'
+ dollars # => "3"
+ cents # => "67"
+
+\Method Regexp#named_captures returns a hash of the capture names and substrings;
+method Regexp#names returns an array of the capture names.
+
+==== Atomic Grouping
+
+A group may be made _atomic_ with <tt>(?></tt>_subexpression_<tt>)</tt>.
+
+This causes the subexpression to be matched
+independently of the rest of the expression,
+so that the matched substring becomes fixed for the remainder of the match,
+unless the entire subexpression must be abandoned and subsequently revisited.
+
+In this way _subexpression_ is treated as a non-divisible whole.
+Atomic grouping is typically used to optimise patterns
+to prevent needless backtracking .
+
+Example (without atomic grouping):
+
+ /".*"/.match('"Quote"') # => #<MatchData "\"Quote\"">
+
+Analysis:
+
+1. The leading subexpression <tt>"</tt> in the pattern matches the first character
+ <tt>"</tt> in the target string.
+2. The next subexpression <tt>.*</tt> matches the next substring <tt>Quote“</tt>
+ (including the trailing double-quote).
+3. Now there is nothing left in the target string to match
+ the trailing subexpression <tt>"</tt> in the pattern;
+ this would cause the overall match to fail.
+4. The matched substring is backtracked by one position: <tt>Quote</tt>.
+5. The final subexpression <tt>"</tt> now matches the final substring <tt>"</tt>,
+ and the overall match succeeds.
+
+If subexpression <tt>.*</tt> is grouped atomically,
+the backtracking is disabled, and the overall match fails:
+
+ /"(?>.*)"/.match('"Quote"') # => nil
+
+Atomic grouping can affect performance;
+see {Atomic Group}[https://www.regular-expressions.info/atomic.html].
+
+==== Subexpression Calls
+
+As seen above, a backreference number (<tt>\\_n_</tt>) or name (<tt>\k<_name_></tt>)
+gives access to a captured _substring_;
+the corresponding regexp _subexpression_ may also be accessed,
+via the number (<tt>\\g<i>n</i></tt>) or name (<tt>\g<_name_></tt>):
+
+ /\A(?<paren>\(\g<paren>*\))*\z/.match('(())')
+ # ^1
+ # ^2
+ # ^3
+ # ^4
+ # ^5
+ # ^6
+ # ^7
+ # ^8
+ # ^9
+ # ^10
+
+The pattern:
+
+1. Matches at the beginning of the string, i.e. before the first character.
+2. Enters a named group +paren+.
+3. Matches the first character in the string, <tt>'('</tt>.
+4. Calls the +paren+ group again, i.e. recurses back to the second step.
+5. Re-enters the +paren+ group.
+6. Matches the second character in the string, <tt>'('</tt>.
+7. Attempts to call +paren+ a third time,
+ but fails because doing so would prevent an overall successful match.
+8. Matches the third character in the string, <tt>')'</tt>;
+ marks the end of the second recursive call
+9. Matches the fourth character in the string, <tt>')'</tt>.
+10. Matches the end of the string.
+
+See {Subexpression calls}[https://learnbyexample.github.io/Ruby_Regexp/groupings-and-backreferences.html?highlight=subexpression#subexpression-calls].
+
+==== Conditionals
+
+The conditional construct takes the form <tt>(?(_cond_)_yes_|_no_)</tt>, where:
+
+- _cond_ may be a capture number or name.
+- The match to be applied is _yes_ if _cond_ is captured;
+ otherwise the match to be applied is _no_.
+- If not needed, <tt>|_no_</tt> may be omitted.
+
+Examples:
+
+ re = /\A(foo)?(?(1)(T)|(F))\z/
+ re.match('fooT') # => #<MatchData "fooT" 1:"foo" 2:"T" 3:nil>
+ re.match('F') # => #<MatchData "F" 1:nil 2:nil 3:"F">
+ re.match('fooF') # => nil
+ re.match('T') # => nil
+
+ re = /\A(?<xyzzy>foo)?(?(<xyzzy>)(T)|(F))\z/
+ re.match('fooT') # => #<MatchData "fooT" xyzzy:"foo">
+ re.match('F') # => #<MatchData "F" xyzzy:nil>
+ re.match('fooF') # => nil
+ re.match('T') # => nil
+
+
+==== Absence Operator
+
+The absence operator is a special group that matches anything which does _not_ match the contained subexpressions.
+
+ /(?~real)/.match('surrealist') # => #<MatchData "surrea">
+ /(?~real)ist/.match('surrealist') # => #<MatchData "ealist">
+ /sur(?~real)ist/.match('surrealist') # => nil
+
+=== Unicode
+
+==== Unicode Properties
+
+The <tt>/\p{_property_name_}/</tt> construct (with lowercase +p+)
+matches characters using a Unicode property name,
+much like a character class;
+property +Alpha+ specifies alphabetic characters:
+
+ /\p{Alpha}/.match('a') # => #<MatchData "a">
+ /\p{Alpha}/.match('1') # => nil
+
+A property can be inverted
+by prefixing the name with a caret character (<tt>^</tt>):
+
+ /\p{^Alpha}/.match('1') # => #<MatchData "1">
+ /\p{^Alpha}/.match('a') # => nil
+
+Or by using <tt>\P</tt> (uppercase +P+):
+
+ /\P{Alpha}/.match('1') # => #<MatchData "1">
+ /\P{Alpha}/.match('a') # => nil
+
+See {Unicode Properties}[rdoc-ref:regexp/unicode_properties.rdoc]
+for regexps based on the numerous properties.
+
+Some commonly-used properties correspond to POSIX bracket expressions:
+
+- <tt>/\p{Alnum}/</tt>: Alphabetic and numeric character
+- <tt>/\p{Alpha}/</tt>: Alphabetic character
+- <tt>/\p{Blank}/</tt>: Space or tab
+- <tt>/\p{Cntrl}/</tt>: Control character
+- <tt>/\p{Digit}/</tt>: Digit
+ characters, and similar)
+- <tt>/\p{Lower}/</tt>: Lowercase alphabetical character
+- <tt>/\p{Print}/</tt>: Like <tt>\p{Graph}</tt>, but includes the space character
+- <tt>/\p{Punct}/</tt>: Punctuation character
+- <tt>/\p{Space}/</tt>: Whitespace character (<tt>[:blank:]</tt>, newline,
+ carriage return, etc.)
+- <tt>/\p{Upper}/</tt>: Uppercase alphabetical
+- <tt>/\p{XDigit}/</tt>: Digit allowed in a hexadecimal number (i.e., 0-9a-fA-F)
+
+These are also commonly used:
+
+- <tt>/\p{Emoji}/</tt>: Unicode emoji.
+- <tt>/\p{Graph}/</tt>: Non-blank character
+ (excludes spaces, control characters, and similar).
+- <tt>/\p{Word}/</tt>: A member in one of these Unicode character
+ categories (see below) or having one of these Unicode properties:
+
+ - Unicode categories:
+ - +Mark+ (+M+).
+ - <tt>Decimal Number</tt> (+Nd+)
+ - <tt>Connector Punctuation</tt> (+Pc+).
+
+ - Unicode properties:
+ - +Alpha+
+ - <tt>Join_Control</tt>
+
+- <tt>/\p{ASCII}/</tt>: A character in the ASCII character set.
+- <tt>/\p{Any}/</tt>: Any Unicode character (including unassigned characters).
+- <tt>/\p{Assigned}/</tt>: An assigned character.
+
+==== Unicode Character Categories
+
+A Unicode character category name:
+
+- May be either its full name or its abbreviated name.
+- Is case-insensitive.
+- Treats a space, a hyphen, and an underscore as equivalent.
+
+Examples:
+
+ /\p{lu}/ # => /\p{lu}/
+ /\p{LU}/ # => /\p{LU}/
+ /\p{Uppercase Letter}/ # => /\p{Uppercase Letter}/
+ /\p{Uppercase_Letter}/ # => /\p{Uppercase_Letter}/
+ /\p{UPPERCASE-LETTER}/ # => /\p{UPPERCASE-LETTER}/
+
+Below are the Unicode character category abbreviations and names.
+Enumerations of characters in each category are at the links.
+
+Letters:
+
+- +L+, +Letter+: +LC+, +Lm+, or +Lo+.
+- +LC+, +Cased_Letter+: +Ll+, +Lt+, or +Lu+.
+- {Lu, Lowercase_Letter}[https://www.compart.com/en/unicode/category/Ll].
+- {Lu, Modifier_Letter}[https://www.compart.com/en/unicode/category/Lm].
+- {Lu, Other_Letter}[https://www.compart.com/en/unicode/category/Lo].
+- {Lu, Titlecase_Letter}[https://www.compart.com/en/unicode/category/Lt].
+- {Lu, Uppercase_Letter}[https://www.compart.com/en/unicode/category/Lu].
+
+Marks:
+
+- +M+, +Mark+: +Mc+, +Me+, or +Mn+.
+- {Mc, Spacing_Mark}[https://www.compart.com/en/unicode/category/Mc].
+- {Me, Enclosing_Mark}[https://www.compart.com/en/unicode/category/Me].
+- {Mn, Nonapacing_Mark}[https://www.compart.com/en/unicode/category/Mn].
+
+Numbers:
+
+- +N+, +Number+: +Nd+, +Nl+, or +No+.
+- {Nd, Decimal_Number}[https://www.compart.com/en/unicode/category/Nd].
+- {Nl, Letter_Number}[https://www.compart.com/en/unicode/category/Nl].
+- {No, Other_Number}[https://www.compart.com/en/unicode/category/No].
+
+Punctation:
+
+- +P+, +Punctuation+: +Pc+, +Pd+, +Pe+, +Pf+, +Pi+, +Po+, or +Ps+.
+- {Pc, Connector_Punctuation}[https://www.compart.com/en/unicode/category/Pc].
+- {Pd, Dash_Punctuation}[https://www.compart.com/en/unicode/category/Pd].
+- {Pe, Close_Punctuation}[https://www.compart.com/en/unicode/category/Pe].
+- {Pf, Final_Punctuation}[https://www.compart.com/en/unicode/category/Pf].
+- {Pi, Initial_Punctuation}[https://www.compart.com/en/unicode/category/Pi].
+- {Po, Other_Punctuation}[https://www.compart.com/en/unicode/category/Po].
+- {Ps, Open_Punctuation}[https://www.compart.com/en/unicode/category/Ps].
+
+- +S+, +Symbol+: +Sc+, +Sk+, +Sm+, or +So+.
+- {Sc, Currency_Symbol}[https://www.compart.com/en/unicode/category/Sc].
+- {Sk, Modifier_Symbol}[https://www.compart.com/en/unicode/category/Sk].
+- {Sm, Math_Symbol}[https://www.compart.com/en/unicode/category/Sm].
+- {So, Other_Symbol}[https://www.compart.com/en/unicode/category/So].
+
+- +Z+, +Separator+: +Zl+, +Zp+, or +Zs+.
+- {Zl, Line_Separator}[https://www.compart.com/en/unicode/category/Zl].
+- {Zp, Paragraph_Separator}[https://www.compart.com/en/unicode/category/Zp].
+- {Zs, Space_Separator}[https://www.compart.com/en/unicode/category/Zs].
+
+- +C+, +Other+: +Cc+, +Cf+, +Cn+, +Co+, or +Cs+.
+- {Cc, Control}[https://www.compart.com/en/unicode/category/Cc].
+- {Cf, Format}[https://www.compart.com/en/unicode/category/Cf].
+- {Cn, Unassigned}[https://www.compart.com/en/unicode/category/Cn].
+- {Co, Private_Use}[https://www.compart.com/en/unicode/category/Co].
+- {Cs, Surrogate}[https://www.compart.com/en/unicode/category/Cs].
+
+==== Unicode Scripts and Blocks
+
+Among the Unicode properties are:
+
+- {Unicode scripts}[https://en.wikipedia.org/wiki/Script_(Unicode)];
+ see {supported scripts}[https://www.unicode.org/standard/supported.html].
+- {Unicode blocks}[https://en.wikipedia.org/wiki/Unicode_block];
+ see {supported blocks}[http://www.unicode.org/Public/UNIDATA/Blocks.txt].
+
+=== POSIX Bracket Expressions
+
+A POSIX <i>bracket expression</i> is also similar to a character class.
+These expressions provide a portable alternative to the above,
+with the added benefit of encompassing non-ASCII characters:
+
+- <tt>/\d/</tt> matches only ASCII decimal digits +0+ through +9+.
+- <tt>/[[:digit:]]/</tt> matches any character in the Unicode
+ <tt>Decimal Number</tt> (+Nd+) category;
+ see below.
+
+The POSIX bracket expressions:
+
+- <tt>/[[:digit:]]/</tt>: Matches a {Unicode digit}[https://www.compart.com/en/unicode/category/Nd]:
+
+ /[[:digit:]]/.match('9') # => #<MatchData "9">
+ /[[:digit:]]/.match("\u1fbf9") # => #<MatchData "9">
+
+- <tt>/[[:xdigit:]]/</tt>: Matches a digit allowed in a hexadecimal number;
+ equivalent to <tt>[0-9a-fA-F]</tt>.
+
+- <tt>/[[:upper:]]/</tt>: Matches a {Unicode uppercase letter}[https://www.compart.com/en/unicode/category/Lu]:
+
+ /[[:upper:]]/.match('A') # => #<MatchData "A">
+ /[[:upper:]]/.match("\u00c6") # => #<MatchData "Æ">
+
+- <tt>/[[:lower:]]/</tt>: Matches a {Unicode lowercase letter}[https://www.compart.com/en/unicode/category/Ll]:
+
+ /[[:lower:]]/.match('a') # => #<MatchData "a">
+ /[[:lower:]]/.match("\u01fd") # => #<MatchData "ǽ">
+
+- <tt>/[[:alpha:]]/</tt>: Matches <tt>/[[:upper:]]/</tt> or <tt>/[[:lower:]]/</tt>.
+
+- <tt>/[[:alnum:]]/</tt>: Matches <tt>/[[:alpha:]]/</tt> or <tt>/[[:digit:]]/</tt>.
+
+- <tt>/[[:space:]]/</tt>: Matches {Unicode space character}[https://www.compart.com/en/unicode/category/Zs]:
+
+ /[[:space:]]/.match(' ') # => #<MatchData " ">
+ /[[:space:]]/.match("\u2005") # => #<MatchData " ">
+
+- <tt>/[[:blank:]]/</tt>: Matches <tt>/[[:space:]]/</tt> or tab character:
+
+ /[[:blank:]]/.match(' ') # => #<MatchData " ">
+ /[[:blank:]]/.match("\u2005") # => #<MatchData " ">
+ /[[:blank:]]/.match("\t") # => #<MatchData "\t">
+
+- <tt>/[[:cntrl:]]/</tt>: Matches {Unicode control character}[https://www.compart.com/en/unicode/category/Cc]:
+
+ /[[:cntrl:]]/.match("\u0000") # => #<MatchData "\u0000">
+ /[[:cntrl:]]/.match("\u009f") # => #<MatchData "\u009F">
+
+- <tt>/[[:graph:]]/</tt>: Matches any character
+ except <tt>/[[:space:]]/</tt> or <tt>/[[:cntrl:]]/</tt>.
+
+- <tt>/[[:print:]]/</tt>: Matches <tt>/[[:graph:]]/</tt> or space character.
+
+- <tt>/[[:punct:]]/</tt>: Matches any (Unicode punctuation character}[https://www.compart.com/en/unicode/category/Po]:
+
+Ruby also supports these (non-POSIX) bracket expressions:
+
+- <tt>/[[:ascii:]]/</tt>: Matches a character in the ASCII character set.
+- <tt>/[[:word:]]/</tt>: Matches a character in one of these Unicode character
+ categories or having one of these Unicode properties:
+
+ - Unicode categories:
+ - +Mark+ (+M+).
+ - <tt>Decimal Number</tt> (+Nd+)
+ - <tt>Connector Punctuation</tt> (+Pc+).
+
+ - Unicode properties:
+ - +Alpha+
+ - <tt>Join_Control</tt>
+
+=== Comments
+
+A comment may be included in a regexp pattern
+using the <tt>(?#</tt>_comment_<tt>)</tt> construct,
+where _comment_ is a substring that is to be ignored.
+arbitrary text ignored by the regexp engine:
+
+ /foo(?#Ignore me)bar/.match('foobar') # => #<MatchData "foobar">
+
+The comment may not include an unescaped terminator character.
+
+See also {Extended Mode}[rdoc-ref:Regexp@Extended+Mode].
+
+== Modes
+
+Each of these modifiers sets a mode for the regexp:
+
+- +i+: <tt>/_pattern_/i</tt> sets
+ {Case-Insensitive Mode}[rdoc-ref:Regexp@Case-Insensitive+Mode].
+- +m+: <tt>/_pattern_/m</tt> sets
+ {Multiline Mode}[rdoc-ref:Regexp@Multiline+Mode].
+- +x+: <tt>/_pattern_/x</tt> sets
+ {Extended Mode}[rdoc-ref:Regexp@Extended+Mode].
+- +o+: <tt>/_pattern_/o</tt> sets
+ {Interpolation Mode}[rdoc-ref:Regexp@Interpolation+Mode].
+
+Any, all, or none of these may be applied.
+
+Modifiers +i+, +m+, and +x+ may be applied to subexpressions:
+
+- <tt>(?_modifier_)</tt> turns the mode "on" for ensuing subexpressions
+- <tt>(?-_modifier_)</tt> turns the mode "off" for ensuing subexpressions
+- <tt>(?_modifier_:_subexp_)</tt> turns the mode "on" for _subexp_ within the group
+- <tt>(?-_modifier_:_subexp_)</tt> turns the mode "off" for _subexp_ within the group
+
+Example:
+
+ re = /(?i)te(?-i)st/
+ re.match('test') # => #<MatchData "test">
+ re.match('TEst') # => #<MatchData "TEst">
+ re.match('TEST') # => nil
+ re.match('teST') # => nil
+
+ re = /t(?i:e)st/
+ re.match('test') # => #<MatchData "test">
+ re.match('tEst') # => #<MatchData "tEst">
+ re.match('tEST') # => nil
+
+\Method Regexp#options returns an integer whose value showing
+the settings for case-insensitivity mode, multiline mode, and extended mode.
+
+=== Case-Insensitive Mode
+
+By default, a regexp is case-sensitive:
+
+ /foo/.match('FOO') # => nil
+
+Modifier +i+ enables case-insensitive mode:
+
+ /foo/i.match('FOO')
+ # => #<MatchData "FOO">
+
+\Method Regexp#casefold? returns whether the mode is case-insensitive.
+
+=== Multiline Mode
+
+The multiline-mode in Ruby is what is commonly called a "dot-all mode":
+
+- Without the +m+ modifier, the subexpression <tt>.</tt> does not match newlines:
+
+ /a.c/.match("a\nc") # => nil
+
+- With the modifier, it does match:
+
+ /a.c/m.match("a\nc") # => #<MatchData "a\nc">
+
+Unlike other languages, the modifier +m+ does not affect the anchors <tt>^</tt> and <tt>$</tt>.
+These anchors always match at line-boundaries in Ruby.
+
+=== Extended Mode
+
+Modifier +x+ enables extended mode, which means that:
+
+- Literal white space in the pattern is to be ignored.
+- Character <tt>#</tt> marks the remainder of its containing line as a comment,
+ which is also to be ignored for matching purposes.
+
+In extended mode, whitespace and comments may be used
+to form a self-documented regexp.
+
+Regexp not in extended mode (matches some Roman numerals):
+
+ pattern = '^M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$'
+ re = /#{pattern}/
+ re.match('MCMXLIII') # => #<MatchData "MCMXLIII" 1:"CM" 2:"XL" 3:"III">
+
+Regexp in extended mode:
+
+ pattern = <<-EOT
+ ^ # beginning of string
+ M{0,3} # thousands - 0 to 3 Ms
+ (CM|CD|D?C{0,3}) # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 Cs),
+ # or 500-800 (D, followed by 0 to 3 Cs)
+ (XC|XL|L?X{0,3}) # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 Xs),
+ # or 50-80 (L, followed by 0 to 3 Xs)
+ (IX|IV|V?I{0,3}) # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 Is),
+ # or 5-8 (V, followed by 0 to 3 Is)
+ $ # end of string
+ EOT
+ re = /#{pattern}/x
+ re.match('MCMXLIII') # => #<MatchData "MCMXLIII" 1:"CM" 2:"XL" 3:"III">
+
+=== Interpolation Mode
+
+Modifier +o+ means that the first time a literal regexp with interpolations
+is encountered,
+the generated Regexp object is saved and used for all future evaluations
+of that literal regexp.
+Without modifier +o+, the generated Regexp is not saved,
+so each evaluation of the literal regexp generates a new Regexp object.
+
+Without modifier +o+:
+
+ def letters; sleep 5; /[A-Z][a-z]/; end
+ words = %w[abc def xyz]
+ start = Time.now
+ words.each {|word| word.match(/\A[#{letters}]+\z/) }
+ Time.now - start # => 15.0174892
+
+With modifier +o+:
+
+ start = Time.now
+ words.each {|word| word.match(/\A[#{letters}]+\z/o) }
+ Time.now - start # => 5.0010866
+
+Note that if the literal regexp does not have interpolations,
+the +o+ behavior is the default.
+
+== Encodings
+
+By default, a regexp with only US-ASCII characters has US-ASCII encoding:
+
+ re = /foo/
+ re.source.encoding # => #<Encoding:US-ASCII>
+ re.encoding # => #<Encoding:US-ASCII>
+
+A regular expression containing non-US-ASCII characters
+is assumed to use the source encoding.
+This can be overridden with one of the following modifiers.
+
+- <tt>/_pat_/n</tt>: US-ASCII if only containing US-ASCII characters,
+ otherwise ASCII-8BIT:
+
+ /foo/n.encoding # => #<Encoding:US-ASCII>
+ /foo\xff/n.encoding # => #<Encoding:ASCII-8BIT>
+ /foo\x7f/n.encoding # => #<Encoding:US-ASCII>
+
+- <tt>/_pat_/u</tt>: UTF-8
+
+ /foo/u.encoding # => #<Encoding:UTF-8>
+
+- <tt>/_pat_/e</tt>: EUC-JP
+
+ /foo/e.encoding # => #<Encoding:EUC-JP>
+
+- <tt>/_pat_/s</tt>: Windows-31J
+
+ /foo/s.encoding # => #<Encoding:Windows-31J>
+
+A regexp can be matched against a target string when either:
+
+- They have the same encoding.
+- The regexp's encoding is a fixed encoding and the string
+ contains only ASCII characters.
+ Method Regexp#fixed_encoding? returns whether the regexp
+ has a <i>fixed</i> encoding.
+
+If a match between incompatible encodings is attempted an
+<tt>Encoding::CompatibilityError</tt> exception is raised.
+
+Example:
+
+ re = eval("# encoding: ISO-8859-1\n/foo\\xff?/")
+ re.encoding # => #<Encoding:ISO-8859-1>
+ re =~ "foo".encode("UTF-8") # => 0
+ re =~ "foo\u0100" # Raises Encoding::CompatibilityError
+
+The encoding may be explicitly fixed by including Regexp::FIXEDENCODING
+in the second argument for Regexp.new:
+
+ # Regexp with encoding ISO-8859-1.
+ re = Regexp.new("a".force_encoding('iso-8859-1'), Regexp::FIXEDENCODING)
+ re.encoding # => #<Encoding:ISO-8859-1>
+ # Target string with encoding UTF-8.
+ s = "a\u3042"
+ s.encoding # => #<Encoding:UTF-8>
+ re.match(s) # Raises Encoding::CompatibilityError.
+
+== Timeouts
+
+When either a regexp source or a target string comes from untrusted input,
+malicious values could become a denial-of-service attack;
+to prevent such an attack, it is wise to set a timeout.
+
+\Regexp has two timeout values:
+
+- A class default timeout, used for a regexp whose instance timeout is +nil+;
+ this default is initially +nil+, and may be set by method Regexp.timeout=:
+
+ Regexp.timeout # => nil
+ Regexp.timeout = 3.0
+ Regexp.timeout # => 3.0
+
+- An instance timeout, which defaults to +nil+ and may be set in Regexp.new:
+
+ re = Regexp.new('foo', timeout: 5.0)
+ re.timeout # => 5.0
+
+When regexp.timeout is +nil+, the timeout "falls through" to Regexp.timeout;
+when regexp.timeout is non-+nil+, that value controls timing out:
+
+ | regexp.timeout Value | Regexp.timeout Value | Result |
+ |----------------------|----------------------|-----------------------------|
+ | nil | nil | Never times out. |
+ | nil | Float | Times out in Float seconds. |
+ | Float | Any | Times out in Float seconds. |
+
+== Optimization
+
+For certain values of the pattern and target string,
+matching time can grow polynomially or exponentially in relation to the input size;
+the potential vulnerability arising from this is the {regular expression denial-of-service}[https://en.wikipedia.org/wiki/ReDoS] (ReDoS) attack.
+
+\Regexp matching can apply an optimization to prevent ReDoS attacks.
+When the optimization is applied, matching time increases linearly (not polynomially or exponentially)
+in relation to the input size, and a ReDoS attach is not possible.
+
+This optimization is applied if the pattern meets these criteria:
+
+- No backreferences.
+- No subexpression calls.
+- No nested lookaround anchors or atomic groups.
+- No nested quantifiers with counting (i.e. no nested <tt>{n}</tt>,
+ <tt>{min,}</tt>, <tt>{,max}</tt>, or <tt>{min,max}</tt> style quantifiers)
+
+You can use method Regexp.linear_time? to determine whether a pattern meets these criteria:
+
+ Regexp.linear_time?(/a*/) # => true
+ Regexp.linear_time?('a*') # => true
+ Regexp.linear_time?(/(a*)\1/) # => false
+
+However, an untrusted source may not be safe even if the method returns +true+,
+because the optimization uses memoization (which may invoke large memory consumption).
+
+== References
+
+Read (online PDF books):
+
+- {Mastering Regular Expressions}[https://ia902508.us.archive.org/10/items/allitebooks-02/Mastering%20Regular%20Expressions%2C%203rd%20Edition.pdf]
+ by Jeffrey E.F. Friedl.
+- {Regular Expressions Cookbook}[https://doc.lagout.org/programmation/Regular%20Expressions/Regular%20Expressions%20Cookbook_%20Detailed%20Solutions%20in%20Eight%20Programming%20Languages%20%282nd%20ed.%29%20%5BGoyvaerts%20%26%20Levithan%202012-09-06%5D.pdf]
+ by Jan Goyvaerts & Steven Levithan.
+
+Explore, test (interactive online editor):
+
+- {Rubular}[https://rubular.com/].
diff --git a/doc/_timezones.rdoc b/doc/_timezones.rdoc
new file mode 100644
index 0000000000..c5230ea67d
--- /dev/null
+++ b/doc/_timezones.rdoc
@@ -0,0 +1,156 @@
+== Timezone Specifiers
+
+Certain +Time+ methods accept arguments that specify timezones:
+
+- Time.at: keyword argument +in:+.
+- Time.new: positional argument +zone+ or keyword argument +in:+.
+- Time.now: keyword argument +in:+.
+- Time#getlocal: positional argument +zone+.
+- Time#localtime: positional argument +zone+.
+
+The value given with any of these must be one of the following
+(each detailed below):
+
+- {Hours/minutes offset}[rdoc-ref:Time@Hours-2FMinutes+Offsets].
+- {Single-letter offset}[rdoc-ref:Time@Single-Letter+Offsets].
+- {Integer offset}[rdoc-ref:Time@Integer+Offsets].
+- {Timezone object}[rdoc-ref:Time@Timezone+Objects].
+- {Timezone name}[rdoc-ref:Time@Timezone+Names].
+
+=== Hours/Minutes Offsets
+
+The zone value may be a string offset from UTC
+in the form <tt>'+HH:MM'</tt> or <tt>'-HH:MM'</tt>,
+where:
+
+- +HH+ is the 2-digit hour in the range <tt>0..23</tt>.
+- +MM+ is the 2-digit minute in the range <tt>0..59</tt>.
+
+Examples:
+
+ t = Time.utc(2000, 1, 1, 20, 15, 1) # => 2000-01-01 20:15:01 UTC
+ Time.at(t, in: '-23:59') # => 1999-12-31 20:16:01 -2359
+ Time.at(t, in: '+23:59') # => 2000-01-02 20:14:01 +2359
+
+=== Single-Letter Offsets
+
+The zone value may be a letter in the range <tt>'A'..'I'</tt>
+or <tt>'K'..'Z'</tt>;
+see {List of military time zones}[https://en.wikipedia.org/wiki/List_of_military_time_zones]:
+
+ t = Time.utc(2000, 1, 1, 20, 15, 1) # => 2000-01-01 20:15:01 UTC
+ Time.at(t, in: 'A') # => 2000-01-01 21:15:01 +0100
+ Time.at(t, in: 'I') # => 2000-01-02 05:15:01 +0900
+ Time.at(t, in: 'K') # => 2000-01-02 06:15:01 +1000
+ Time.at(t, in: 'Y') # => 2000-01-01 08:15:01 -1200
+ Time.at(t, in: 'Z') # => 2000-01-01 20:15:01 UTC
+
+=== \Integer Offsets
+
+The zone value may be an integer number of seconds
+in the range <tt>-86399..86399</tt>:
+
+ t = Time.utc(2000, 1, 1, 20, 15, 1) # => 2000-01-01 20:15:01 UTC
+ Time.at(t, in: -86399) # => 1999-12-31 20:15:02 -235959
+ Time.at(t, in: 86399) # => 2000-01-02 20:15:00 +235959
+
+=== Timezone Objects
+
+The zone value may be an object responding to certain timezone methods, an
+instance of {Timezone}[https://github.com/panthomakos/timezone] and
+{TZInfo}[https://tzinfo.github.io] for example.
+
+The timezone methods are:
+
+- +local_to_utc+:
+
+ - Called when Time.new is invoked with +tz+
+ as the value of positional argument +zone+ or keyword argument +in:+.
+ - Argument: a {Time-like object}[rdoc-ref:Time@Time-Like+Objects].
+ - Returns: a {Time-like object}[rdoc-ref:Time@Time-Like+Objects] in the UTC timezone.
+
+- +utc_to_local+:
+
+ - Called when Time.at or Time.now is invoked with +tz+
+ as the value for keyword argument +in:+,
+ and when Time#getlocal or Time#localtime is called with +tz+
+ as the value for positional argument +zone+.
+ - Argument: a {Time-like object}[rdoc-ref:Time@Time-Like+Objects].
+ - Returns: a {Time-like object}[rdoc-ref:Time@Time-Like+Objects] in the local timezone.
+
+A custom timezone class may have these instance methods,
+which will be called if defined:
+
+- +abbr+:
+
+ - Called when Time#strftime is invoked with a format involving <tt>%Z</tt>.
+ - Argument: a {Time-like object}[rdoc-ref:Time@Time-Like+Objects].
+ - Returns: a string abbreviation for the timezone name.
+
+- +dst?+:
+
+ - Called when Time.at or Time.now is invoked with +tz+
+ as the value for keyword argument +in:+,
+ and when Time#getlocal or Time#localtime is called with +tz+
+ as the value for positional argument +zone+.
+ - Argument: a {Time-like object}[rdoc-ref:Time@Time-Like+Objects].
+ - Returns: whether the time is daylight saving time.
+
+- +name+:
+
+ - Called when <tt>Marshal.dump(t)</tt> is invoked
+ - Argument: none.
+ - Returns: the string name of the timezone.
+
+==== +Time+-Like Objects
+
+A +Time+-like object is a container object capable of interfacing with
+timezone libraries for timezone conversion.
+
+The argument to the timezone conversion methods above will have attributes
+similar to Time, except that timezone related attributes are meaningless.
+
+The objects returned by +local_to_utc+ and +utc_to_local+ methods of the
+timezone object may be of the same class as their arguments, of arbitrary
+object classes, or of class Integer.
+
+For a returned class other than +Integer+, the class must have the
+following methods:
+
+- +year+
+- +mon+
+- +mday+
+- +hour+
+- +min+
+- +sec+
+- +isdst+
+- +to_i+
+
+For a returned +Integer+, its components, decomposed in UTC, are
+interpreted as times in the specified timezone.
+
+=== Timezone Names
+
+If the class (the receiver of class methods, or the class of the receiver
+of instance methods) has +find_timezone+ singleton method, this method is
+called to achieve the corresponding timezone object from a timezone name.
+
+For example, using {Timezone}[https://github.com/panthomakos/timezone]:
+ class TimeWithTimezone < Time
+ require 'timezone'
+ def self.find_timezone(z) = Timezone[z]
+ end
+
+ TimeWithTimezone.now(in: "America/New_York") #=> 2023-12-25 00:00:00 -0500
+ TimeWithTimezone.new("2023-12-25 America/New_York") #=> 2023-12-25 00:00:00 -0500
+
+Or, using {TZInfo}[https://tzinfo.github.io]:
+ class TimeWithTZInfo < Time
+ require 'tzinfo'
+ def self.find_timezone(z) = TZInfo::Timezone.get(z)
+ end
+
+ TimeWithTZInfo.now(in: "America/New_York") #=> 2023-12-25 00:00:00 -0500
+ TimeWithTZInfo.new("2023-12-25 America/New_York") #=> 2023-12-25 00:00:00 -0500
+
+You can define this method per subclasses, or on the toplevel Time class.
diff --git a/doc/bsearch.rdoc b/doc/bsearch.rdoc
index ca8091fc0d..90705853d7 100644
--- a/doc/bsearch.rdoc
+++ b/doc/bsearch.rdoc
@@ -1,4 +1,4 @@
-== Binary Searching
+= Binary Searching
A few Ruby methods support binary searching in a collection:
diff --git a/doc/case_mapping.rdoc b/doc/case_mapping.rdoc
index 3c42154973..57c037b9d8 100644
--- a/doc/case_mapping.rdoc
+++ b/doc/case_mapping.rdoc
@@ -1,4 +1,4 @@
-== Case Mapping
+= Case Mapping
Some string-oriented methods use case mapping.
@@ -24,7 +24,7 @@ In Symbol:
- Symbol#swapcase
- Symbol#upcase
-=== Default Case Mapping
+== Default Case Mapping
By default, all of these methods use full Unicode case mapping,
which is suitable for most languages.
@@ -60,7 +60,7 @@ Case changes may not be reversible:
Case changing methods may not maintain Unicode normalization.
See String#unicode_normalize).
-=== Options for Case Mapping
+== Options for Case Mapping
Except for +casecmp+ and +casecmp?+,
each of the case-mapping methods listed above
diff --git a/doc/character_selectors.rdoc b/doc/character_selectors.rdoc
index e01b0e6a25..47cf242be7 100644
--- a/doc/character_selectors.rdoc
+++ b/doc/character_selectors.rdoc
@@ -1,6 +1,6 @@
-== Character Selectors
+= Character Selectors
-=== Character Selector
+== Character Selector
A _character_ _selector_ is a string argument accepted by certain Ruby methods.
Each of these instance methods accepts one or more character selectors:
@@ -70,7 +70,7 @@ In a character selector, these three characters get special treatment:
"hello\r\nworld".delete("\\r") # => "hello\r\nwold"
"hello\r\nworld".delete("\\\r") # => "hello\nworld"
-=== Multiple Character Selectors
+== Multiple Character Selectors
These instance methods accept multiple character selectors:
diff --git a/doc/command_injection.rdoc b/doc/command_injection.rdoc
index 4408b1839d..ee33d4a04e 100644
--- a/doc/command_injection.rdoc
+++ b/doc/command_injection.rdoc
@@ -1,4 +1,4 @@
-== Command Injection
+= Command Injection
Some Ruby core methods accept string data
that includes text to be executed as a system command.
@@ -7,11 +7,17 @@ They should not be called with unknown or unsanitized commands.
These methods include:
+- Kernel.exec
+- Kernel.spawn
- Kernel.system
-- Kernel.open
- {\`command` (backtick method)}[rdoc-ref:Kernel#`]
(also called by the expression <tt>%x[command]</tt>).
-- IO.popen(command).
+- IO.popen (when called with other than <tt>"-"</tt>).
+
+Some methods execute a system command only if the given path name starts
+with a <tt>|</tt>:
+
+- Kernel.open(command).
- IO.read(command).
- IO.write(command).
- IO.binread(command).
@@ -21,7 +27,7 @@ These methods include:
- URI.open(command).
Note that some of these methods do not execute commands when called
-from subclass \File:
+from subclass +File+:
- File.read(path).
- File.write(path).
diff --git a/doc/command_line/environment.md b/doc/command_line/environment.md
new file mode 100644
index 0000000000..abdfd5cfeb
--- /dev/null
+++ b/doc/command_line/environment.md
@@ -0,0 +1,173 @@
+## Environment
+
+Certain command-line options affect the execution environment
+of the invoked Ruby program.
+
+### About the Examples
+
+The examples here use command-line option `-e`,
+which passes the Ruby code to be executed on the command line itself:
+
+```sh
+$ ruby -e 'puts "Hello, World."'
+```
+
+### Option `-C`
+
+The argument to option `-C` specifies a working directory
+for the invoked Ruby program;
+does not change the working directory for the current process:
+
+```sh
+$ basename `pwd`
+ruby
+$ ruby -C lib -e 'puts File.basename(Dir.pwd)'
+lib
+$ basename `pwd`
+ruby
+```
+
+Whitespace between the option and its argument may be omitted.
+
+### Option `-I`
+
+The argument to option `-I` specifies a directory
+to be added to the array in global variable `$LOAD_PATH`;
+the option may be given more than once:
+
+```sh
+$ pushd /tmp
+$ ruby -e 'p $LOAD_PATH.size'
+8
+$ ruby -I my_lib -I some_lib -e 'p $LOAD_PATH.size'
+10
+$ ruby -I my_lib -I some_lib -e 'p $LOAD_PATH.take(2)'
+["/tmp/my_lib", "/tmp/some_lib"]
+$ popd
+```
+
+Whitespace between the option and its argument may be omitted.
+
+### Option `-r`
+
+The argument to option `-r` specifies a library to be required
+before executing the Ruby program;
+the option may be given more than once:
+
+```sh
+$ ruby -e 'p defined?(JSON); p defined?(CSV)'
+nil
+nil
+$ ruby -r CSV -r JSON -e 'p defined?(JSON); p defined?(CSV)'
+"constant"
+"constant"
+```
+
+Whitespace between the option and its argument may be omitted.
+
+### Option `-0`
+
+Option `-0` defines the input record separator `$/`
+for the invoked Ruby program.
+
+The optional argument to the option must be octal digits,
+each in the range `0..7`;
+these digits are prefixed with digit `0` to form an octal value:
+
+- If no argument is given, the input record separator is `0x00`.
+- If the argument is `0`, the input record separator is `''`;
+ see {Special Line Separator Values}[rdoc-ref:IO@Special+Line+Separator+Values].
+- If the argument is in range `(1..0377)`,
+ it becomes the character value of the input record separator `$/`.
+- Otherwise, the input record separator is `nil`.
+
+Examples:
+
+```sh
+$ ruby -0 -e 'p $/'
+"\x00"
+ruby -00 -e 'p $/'
+""
+$ ruby -012 -e 'p $/'
+"\n"
+$ ruby -015 -e 'p $/'
+"\r"
+$ ruby -0377 -e 'p $/'
+"\xFF"
+$ ruby -0400 -e 'p $/'
+nil
+```
+
+The option may not be separated from its argument by whitespace.
+
+### Option `-d`
+
+Some code in (or called by) the Ruby program may include statements or blocks
+conditioned by the global variable `$DEBUG` (e.g., `if $DEBUG`);
+these commonly write to `$stdout` or `$stderr`.
+
+The default value for `$DEBUG` is `false`;
+option `-d` (or `--debug`) sets it to `true`:
+
+```sh
+$ ruby -e 'p $DEBUG'
+false
+$ ruby -d -e 'p $DEBUG'
+true
+```
+
+### Option '-w'
+
+Option `-w` (lowercase letter) is equivalent to option `-W1` (uppercase letter).
+
+### Option `-W`
+
+Any Ruby code can create a <i>warning message</i> by calling method Kernel#warn;
+methods in the Ruby core and standard libraries can also create warning messages.
+Such a message may be printed on `$stderr`
+(or not, depending on certain settings).
+
+Option `-W` helps determine whether a particular warning message
+will be written,
+by setting the initial value of global variable `$-W`:
+
+- `-W0`: Sets `$-W` to `0` (silent; no warnings).
+- `-W1`: Sets `$-W` to `1` (moderate verbosity).
+- `-W2`: Sets `$-W` to `2` (high verbosity).
+- `-W`: Same as `-W2` (high verbosity).
+- Option not given: Same as `-W1` (moderate verbosity).
+
+The value of `$-W`, in turn, determines which warning messages (if any)
+are to be printed to `$stdout` (see Kernel#warn):
+
+```sh
+$ ruby -W1 -e 'p $foo'
+nil
+$ ruby -W2 -e 'p $foo'
+-e:1: warning: global variable '$foo' not initialized
+nil
+```
+
+Ruby code may also define warnings for certain categories;
+these are the default settings for the defined categories:
+
+```
+Warning[:experimental] # => true
+Warning[:deprecated] # => false
+Warning[:performance] # => false
+```
+
+They may also be set:
+```
+Warning[:experimental] = false
+Warning[:deprecated] = true
+Warning[:performance] = true
+```
+
+You can suppress a category by prefixing `no-` to the category name:
+
+```
+$ ruby -W:no-experimental -e 'p IO::Buffer.new'
+#<IO::Buffer>
+```
+
diff --git a/doc/contributing/building_ruby.md b/doc/contributing/building_ruby.md
index b2a7b007eb..ce844b5026 100644
--- a/doc/contributing/building_ruby.md
+++ b/doc/contributing/building_ruby.md
@@ -8,28 +8,30 @@
For RubyGems, you will also need:
- * OpenSSL 1.1.x or 3.0.x / LibreSSL
- * libyaml 0.1.7 or later
- * zlib
+ * [OpenSSL] 1.1.x or 3.0.x / [LibreSSL]
+ * [libyaml] 0.1.7 or later
+ * [zlib]
If you want to build from the git repository, you will also need:
- * autoconf - 2.67 or later
- * gperf - 3.1 or later
+ * [autoconf] - 2.67 or later
+ * [gperf] - 3.1 or later
* Usually unneeded; only if you edit some source files using gperf
- * ruby - 2.5 or later
- * We can upgrade this version to system ruby version of the latest Ubuntu LTS.
+ * ruby - 3.0 or later
+ * We can upgrade this version to system ruby version of the latest
+ Ubuntu LTS.
2. Install optional, recommended dependencies:
- * libffi (to build fiddle)
- * gmp (if you with to accelerate Bignum operations)
- * libexecinfo (FreeBSD)
- * rustc - 1.58.0 or later, if you wish to build
- [YJIT](https://docs.ruby-lang.org/en/master/RubyVM/YJIT.html).
+ * [libffi] (to build fiddle)
+ * [gmp] (if you with to accelerate Bignum operations)
+ * [rustc] - 1.58.0 or later, if you wish to build
+ [YJIT](rdoc-ref:RubyVM::YJIT).
- If you installed the libraries needed for extensions (openssl, readline, libyaml, zlib) into other than the OS default place,
- typically using Homebrew on macOS, add `--with-EXTLIB-dir` options to `CONFIGURE_ARGS` environment variable.
+ If you installed the libraries needed for extensions (openssl, readline,
+ libyaml, zlib) into other than the OS default place, typically using
+ Homebrew on macOS, add `--with-EXTLIB-dir` options to `CONFIGURE_ARGS`
+ environment variable.
``` shell
export CONFIGURE_ARGS=""
@@ -38,16 +40,26 @@
done
```
+[OpenSSL]: https://www.openssl.org
+[LibreSSL]: https://www.libressl.org
+[libyaml]: https://github.com/yaml/libyaml/
+[zlib]: https://www.zlib.net
+[autoconf]: https://www.gnu.org/software/autoconf/
+[gperf]: https://www.gnu.org/software/gperf/
+[libffi]: https://sourceware.org/libffi/
+[gmp]: https://gmplib.org
+[rustc]: https://www.rust-lang.org
+
## Quick start guide
1. Download ruby source code:
- Select one of the bellow.
+ Select one of the below.
1. Build from the tarball:
- Download the latest tarball from [ruby-lang.org](https://www.ruby-lang.org/en/downloads/) and
- extract it. Example for Ruby 3.0.2:
+ Download the latest tarball from [Download Ruby] page and extract
+ it. Example for Ruby 3.0.2:
``` shell
tar -xzf ruby-3.0.2.tar.gz
@@ -75,7 +87,8 @@
mkdir build && cd build
```
- While it's not necessary to build in a separate directory, it's good practice to do so.
+ While it's not necessary to build in a separate directory, it's good
+ practice to do so.
3. We'll install Ruby in `~/.rubies/ruby-master`, so create the directory:
@@ -89,25 +102,41 @@
../configure --prefix="${HOME}/.rubies/ruby-master"
```
- - If you are frequently building Ruby, add the `--disable-install-doc` flag to not build documentation which will speed up the build process.
-
- - Also `-C` (or `--config-cache`) would reduce time to configure from the next time.
+ - Also `-C` (or `--config-cache`) would reduce time to configure from the
+ next time.
5. Build Ruby:
``` shell
- make install
+ make
```
6. [Run tests](testing_ruby.md) to confirm your build succeeded.
+7. Install Ruby:
+
+ ``` shell
+ make install
+ ```
+
+ - If you need to run `make install` with `sudo` and want to avoid document
+ generation with different permissions, you can use `make SUDO=sudo
+ install`.
+
+[Download Ruby]: https://www.ruby-lang.org/en/downloads/
+
### Unexplainable Build Errors
-If you are having unexplainable build errors, after saving all your work, try running `git clean -xfd` in the source root to remove all git ignored local files. If you are working from a source directory that's been updated several times, you may have temporary build artifacts from previous releases which can cause build failures.
+If you are having unexplainable build errors, after saving all your work, try
+running `git clean -xfd` in the source root to remove all git ignored local
+files. If you are working from a source directory that's been updated several
+times, you may have temporary build artifacts from previous releases which can
+cause build failures.
## Building on Windows
-The documentation for building on Windows can be found [here](../windows.md).
+The documentation for building on Windows can be found in [the separated
+file](../windows.md).
## More details
@@ -116,8 +145,9 @@ about Ruby's build to help out.
### Running make scripts in parallel
-In GNU make and BSD make implementations, to run a specific make script in parallel, pass the flag `-j<number of processes>`. For instance,
-to run tests on 8 processes, use:
+In GNU make[^caution-gmake-3] and BSD make implementations, to run a specific make script in
+parallel, pass the flag `-j<number of processes>`. For instance, to run tests
+on 8 processes, use:
``` shell
make test-all -j8
@@ -125,7 +155,9 @@ make test-all -j8
We can also set `MAKEFLAGS` to run _all_ `make` commands in parallel.
-Having the right `--jobs` flag will ensure all processors are utilized when building software projects. To do this effectively, you can set `MAKEFLAGS` in your shell configuration/profile:
+Having the right `--jobs` flag will ensure all processors are utilized when
+building software projects. To do this effectively, you can set `MAKEFLAGS` in
+your shell configuration/profile:
``` shell
# On macOS with Fish shell:
@@ -141,11 +173,15 @@ export MAKEFLAGS="--jobs "(nproc)
export MAKEFLAGS="--jobs $(nproc)"
```
+[^caution-gmake-3]: **CAUTION**: GNU make 3 is missing some features for parallel execution, we
+recommend to upgrade to GNU make 4 or later.
+
### Miniruby vs Ruby
-Miniruby is a version of Ruby which has no external dependencies and lacks certain features.
-It can be useful in Ruby development because it allows for faster build times. Miniruby is
-built before Ruby. A functional Miniruby is required to build Ruby. To build Miniruby:
+Miniruby is a version of Ruby which has no external dependencies and lacks
+certain features. It can be useful in Ruby development because it allows for
+faster build times. Miniruby is built before Ruby. A functional Miniruby is
+required to build Ruby. To build Miniruby:
``` shell
make miniruby
@@ -153,8 +189,9 @@ make miniruby
## Debugging
-You can use either lldb or gdb for debugging. Before debugging, you need to create a `test.rb`
-with the Ruby script you'd like to run. You can use the following make targets:
+You can use either lldb or gdb for debugging. Before debugging, you need to
+create a `test.rb` with the Ruby script you'd like to run. You can use the
+following make targets:
* `make run`: Runs `test.rb` using Miniruby
* `make lldb`: Runs `test.rb` using Miniruby in lldb
@@ -165,7 +202,8 @@ with the Ruby script you'd like to run. You can use the following make targets:
### Compiling for Debugging
-You should configure Ruby without optimization and other flags that may interfere with debugging:
+You should configure Ruby without optimization and other flags that may
+interfere with debugging:
``` shell
./configure --enable-debug-env optflags="-O0 -fno-omit-frame-pointer"
@@ -173,17 +211,54 @@ You should configure Ruby without optimization and other flags that may interfer
### Building with Address Sanitizer
-Using the address sanitizer is a great way to detect memory issues.
+Using the address sanitizer (ASAN) is a great way to detect memory issues. It
+can detect memory safety issues in Ruby itself, and also in any C extensions
+compiled with and loaded into a Ruby compiled with ASAN.
``` shell
./autogen.sh
mkdir build && cd build
-export ASAN_OPTIONS="halt_on_error=0:use_sigaltstack=0:detect_leaks=0"
-../configure cppflags="-fsanitize=address -fno-omit-frame-pointer" optflags=-O0 LDFLAGS="-fsanitize=address -fno-omit-frame-pointer"
+../configure CC=clang-18 cflags="-fsanitize=address -fno-omit-frame-pointer -DUSE_MN_THREADS=0" # and any other options you might like
make
```
-On Linux it is important to specify `-O0` when debugging. This is especially true for ASAN which sometimes works incorrectly at higher optimisation levels.
+The compiled Ruby will now automatically crash with a report and a backtrace
+if ASAN detects a memory safety issue. To run Ruby's test suite under ASAN,
+issue the following command. Note that this will take quite a long time (over
+two hours on my laptop); the `RUBY_TEST_TIMEOUT_SCALE` and
+`SYNTAX_SUGEST_TIMEOUT` variables are required to make sure tests don't
+spuriously fail with timeouts when in fact they're just slow.
+
+``` shell
+RUBY_TEST_TIMEOUT_SCALE=5 SYNTAX_SUGGEST_TIMEOUT=600 make check
+```
+
+Please note, however, the following caveats!
+
+* ASAN will not work properly on any currently released version of Ruby; the
+ necessary support is currently only present on Ruby's master branch (and the
+ whole test suite passes only as of commit [Revision 9d0a5148]).
+* Due to [Bug #20243], Clang generates code for threadlocal variables which
+ doesn't work with M:N threading. Thus, it's necessary to disable M:N
+ threading support at build time for now (with the `-DUSE_MN_THREADS=0`
+ configure argument).
+* ASAN will only work when using Clang version 18 or later - it requires
+ [llvm/llvm-project#75290] related to multithreaded `fork`.
+* ASAN has only been tested so far with Clang on Linux. It may or may not work
+ with other compilers or on other platforms - please file an issue on
+ [Ruby Issue Tracking System] if you run into problems with such configurations
+ (or, to report that they actually work properly!)
+* In particular, although I have not yet tried it, I have reason to believe
+ ASAN will _not_ work properly on macOS yet - the fix for the multithreaded
+ fork issue was actually reverted for macOS (see [llvm/llvm-project#75659]).
+ Please open an issue on [Ruby Issue Tracking System] if this is a problem for
+ you.
+
+[Revision 9d0a5148]: https://bugs.ruby-lang.org/projects/ruby-master/repository/git/revisions/9d0a5148ae062a0481a4a18fbeb9cfd01dc10428
+[Bug #20243]: https://bugs.ruby-lang.org/issues/20243
+[llvm/llvm-project#75290]: https://github.com/llvm/llvm-project/pull/75290
+[llvm/llvm-project#75659]: https://github.com/llvm/llvm-project/pull/75659#issuecomment-1861584777
+[Ruby Issue Tracking System]: https://bugs.ruby-lang.org
## How to measure coverage of C and Ruby code
@@ -200,11 +275,12 @@ make lcov
open lcov-out/index.html
```
-If you need only C code coverage, you can remove `COVERAGE=true` from the above process.
-You can also use `gcov` command directly to get per-file coverage.
+If you need only C code coverage, you can remove `COVERAGE=true` from the
+above process. You can also use `gcov` command directly to get per-file
+coverage.
-If you need only Ruby code coverage, you can remove `--enable-gcov`.
-Note that `test-coverage.dat` accumulates all runs of `make test-all`.
-Make sure that you remove the file if you want to measure one test run.
+If you need only Ruby code coverage, you can remove `--enable-gcov`. Note
+that `test-coverage.dat` accumulates all runs of `make test-all`. Make sure
+that you remove the file if you want to measure one test run.
You can see the coverage result of CI: https://rubyci.org/coverage
diff --git a/doc/contributing/documentation_guide.md b/doc/contributing/documentation_guide.md
index af91817003..59953d0d52 100644
--- a/doc/contributing/documentation_guide.md
+++ b/doc/contributing/documentation_guide.md
@@ -173,23 +173,17 @@ Code that is a simple string should include the quote marks.
In general, \RDoc's auto-linking should not be suppressed.
For example, we should write `Array`, not `\Array`.
-We might consider whether to suppress when:
+However, suppress when the word in question:
-- The word in question does not refer to a Ruby entity
+- Does not refer to a Ruby entity
(e.g., some uses of _Class_ or _English_).
-- The reference is to the current class document
- (e.g., _Array_ in the documentation for class `Array`).
-- The same reference is repeated many times
- (e.g., _RDoc_ on this page).
-- The reference is to a class or module that users
- usually don't deal with, including these:
-
- - \Class.
- - \Method.
- - \Module.
+- Refers to the current document
+ (e.g., _Array_ in the documentation for class `Array`);
+ in that case, the word should be forced to
+ [monofont](rdoc-ref:RDoc::MarkupReference@Monofont).
Most often, the name of a class, module, or method
-will be autolinked:
+will be auto-linked:
- Array.
- Enumerable.
@@ -199,6 +193,36 @@ will be autolinked:
If not, or if you suppress autolinking, consider forcing
[monofont](rdoc-ref:RDoc::MarkupReference@Monofont).
+### Explicit Links
+
+When writing an explicit link, follow these guidelines.
+
+#### +rdoc-ref+ Scheme
+
+Use the +rdoc-ref+ scheme for:
+
+- A link in core documentation to other core documentation.
+- A link in core documentation to documentation in a standard library package.
+- A link in a standard library package to other documentation in that same
+ standard library package.
+
+See section "+rdoc-ref+ Scheme" in {Links}[rdoc-ref:RDoc::MarkupReference@Links].
+
+#### URL-Based Link
+
+Use a full URL-based link for:
+
+- A link in standard library documentation to documentation in the core.
+- A link in standard library documentation to documentation in a different
+ standard library package.
+
+Doing so ensures that the link will valid even when the package documentation
+is built independently (separately from the core documentation).
+
+The link should lead to a target in https://docs.ruby-lang.org/en/master/.
+
+Also use a full URL-based link for a link to an off-site document.
+
### Variable Names
The name of a variable (as specified in its call-seq) should be marked up as
@@ -264,7 +288,10 @@ Guidelines:
- Consider listing the parent class and any included modules; consider
[links](rdoc-ref:RDoc::MarkupReference@Links)
to their "What's Here" sections if those exist.
-- List methods as a bullet list:
+- All methods mentioned in the left-pane table of contents
+ should be listed (including any methods extended from another class).
+- Attributes (which are not included in the TOC) may also be listed.
+- Display methods as items in one or more bullet lists:
- Begin each item with the method name, followed by a colon
and a short description.
diff --git a/doc/contributing/glossary.md b/doc/contributing/glossary.md
index 0d27d28c96..86c6671fbd 100644
--- a/doc/contributing/glossary.md
+++ b/doc/contributing/glossary.md
@@ -10,7 +10,7 @@ Just a list of acronyms I've run across in the Ruby source code and their meanin
| `cd` | Call Data. A data structure that points at the `ci` and the `cc`. `iseq` objects points at the `cd`, and access call information and call caches via this structure |
| `cfp`| Control Frame Pointer. Represents a Ruby stack frame. Calling a method pushes a new frame (cfp), returning pops a frame. Points at the `pc`, `sp`, `ep`, and the corresponding `iseq`|
| `ci` | Call Information. Refers to an `rb_callinfo` struct. Contains call information about the call site, including number of parameters to be passed, whether it they are keyword arguments or not, etc. Used in conjunction with the `cc` and `cd`. |
-| `cref` | Class reference. A structure pointing to the class reference where `klass_or_self`, visibility scope, and refinements are stored. It also stores a pointer to the next class in the hierachy referenced by `rb_cref_struct * next`. The Class reference is lexically scoped. |
+| `cref` | Class reference. A structure pointing to the class reference where `klass_or_self`, visibility scope, and refinements are stored. It also stores a pointer to the next class in the hierarchy referenced by `rb_cref_struct * next`. The Class reference is lexically scoped. |
| CRuby | Implementation of Ruby written in C |
| `cvar` | Class Variable. Refers to a Ruby class variable like `@@foo` |
| `dvar` | Dynamic Variable. Used by the parser to refer to local variables that are defined outside of the current lexical scope. For example `def foo; bar = 1; -> { p bar }; end` the "bar" inside the block is a `dvar` |
diff --git a/doc/csv/recipes/generating.rdoc b/doc/csv/recipes/generating.rdoc
index a6bd88a714..e61838d31a 100644
--- a/doc/csv/recipes/generating.rdoc
+++ b/doc/csv/recipes/generating.rdoc
@@ -163,7 +163,7 @@ This example defines and uses two custom write converters to strip and upcase ge
=== RFC 4180 Compliance
By default, \CSV generates data that is compliant with
-{RFC 4180}[https://tools.ietf.org/html/rfc4180]
+{RFC 4180}[https://www.rfc-editor.org/rfc/rfc4180]
with respect to:
- Column separator.
- Quote character.
diff --git a/doc/csv/recipes/parsing.rdoc b/doc/csv/recipes/parsing.rdoc
index f3528fbdf1..1b7071e33f 100644
--- a/doc/csv/recipes/parsing.rdoc
+++ b/doc/csv/recipes/parsing.rdoc
@@ -191,7 +191,7 @@ Output:
=== RFC 4180 Compliance
By default, \CSV parses data that is compliant with
-{RFC 4180}[https://tools.ietf.org/html/rfc4180]
+{RFC 4180}[https://www.rfc-editor.org/rfc/rfc4180]
with respect to:
- Row separator.
- Column separator.
diff --git a/doc/encodings.rdoc b/doc/encodings.rdoc
index 914f5d3afa..d85099cdbc 100644
--- a/doc/encodings.rdoc
+++ b/doc/encodings.rdoc
@@ -1,6 +1,6 @@
-== Encodings
+= Encodings
-=== The Basics
+== The Basics
A {character encoding}[https://en.wikipedia.org/wiki/Character_encoding],
often shortened to _encoding_, is a mapping between:
@@ -30,9 +30,9 @@ Other characters, such as the Euro symbol, are multi-byte:
s = "\u20ac" # => "€"
s.bytes # => [226, 130, 172]
-=== The \Encoding \Class
+== The \Encoding \Class
-==== \Encoding Objects
+=== \Encoding Objects
Ruby encodings are defined by constants in class \Encoding.
There can be only one instance of \Encoding for each of these constants.
@@ -43,7 +43,7 @@ There can be only one instance of \Encoding for each of these constants.
Encoding.list.take(3)
# => [#<Encoding:ASCII-8BIT>, #<Encoding:UTF-8>, #<Encoding:US-ASCII>]
-==== Names and Aliases
+=== Names and Aliases
\Method Encoding#name returns the name of an \Encoding:
@@ -78,7 +78,7 @@ because it includes both the names and their aliases.
Encoding.find("US-ASCII") # => #<Encoding:US-ASCII>
Encoding.find("US-ASCII").class # => Encoding
-==== Default Encodings
+=== Default Encodings
\Method Encoding.find, above, also returns a default \Encoding
for each of these special names:
@@ -118,7 +118,7 @@ for each of these special names:
Encoding.default_internal = 'US-ASCII' # => "US-ASCII"
Encoding.default_internal # => #<Encoding:US-ASCII>
-==== Compatible Encodings
+=== Compatible Encodings
\Method Encoding.compatible? returns whether two given objects are encoding-compatible
(that is, whether they can be concatenated);
@@ -132,7 +132,7 @@ returns the \Encoding of the concatenated string, or +nil+ if incompatible:
s1 = "\xa1\xa1".force_encoding('euc-jp') # => "\x{A1A1}"
Encoding.compatible?(s0, s1) # => nil
-=== \String \Encoding
+== \String \Encoding
A Ruby String object has an encoding that is an instance of class \Encoding.
The encoding may be retrieved by method String#encoding.
@@ -183,7 +183,7 @@ Here are a couple of useful query methods:
s = "\xc2".force_encoding("UTF-8") # => "\xC2"
s.valid_encoding? # => false
-=== \Symbol and \Regexp Encodings
+== \Symbol and \Regexp Encodings
The string stored in a Symbol or Regexp object also has an encoding;
the encoding may be retrieved by method Symbol#encoding or Regexp#encoding.
@@ -194,20 +194,20 @@ The default encoding for these, however, is:
- The script encoding, otherwise;
see (Script Encoding)[rdoc-ref:encodings.rdoc@Script+Encoding].
-=== Filesystem \Encoding
+== Filesystem \Encoding
The filesystem encoding is the default \Encoding for a string from the filesystem:
Encoding.find("filesystem") # => #<Encoding:UTF-8>
-=== Locale \Encoding
+== Locale \Encoding
The locale encoding is the default encoding for a string from the environment,
other than from the filesystem:
Encoding.find('locale') # => #<Encoding:IBM437>
-=== Stream Encodings
+== Stream Encodings
Certain stream objects can have two encodings; these objects include instances of:
@@ -222,7 +222,7 @@ The two encodings are:
- An _internal_ _encoding_, which (if not +nil+) specifies the encoding
to be used for the string constructed from the stream.
-==== External \Encoding
+=== External \Encoding
The external encoding, which is an \Encoding object, specifies how bytes read
from the stream are to be interpreted as characters.
@@ -250,7 +250,7 @@ For an \IO, \File, \ARGF, or \StringIO object, the external encoding may be set
- \Methods +set_encoding+ or (except for \ARGF) +set_encoding_by_bom+.
-==== Internal \Encoding
+=== Internal \Encoding
The internal encoding, which is an \Encoding object or +nil+,
specifies how characters read from the stream
@@ -276,7 +276,7 @@ For an \IO, \File, \ARGF, or \StringIO object, the internal encoding may be set
- \Method +set_encoding+.
-=== Script \Encoding
+== Script \Encoding
A Ruby script has a script encoding, which may be retrieved by:
@@ -291,7 +291,7 @@ followed by a colon, space and the Encoding name or alias:
# encoding: ISO-8859-1
__ENCODING__ #=> #<Encoding:ISO-8859-1>
-=== Transcoding
+== Transcoding
_Transcoding_ is the process of changing a sequence of characters
from one encoding to another.
@@ -302,7 +302,7 @@ but the bytes that represent them may change.
The handling for characters that cannot be represented in the destination encoding
may be specified by @Encoding+Options.
-==== Transcoding a \String
+=== Transcoding a \String
Each of these methods transcodes a string:
@@ -317,7 +317,7 @@ Each of these methods transcodes a string:
- String#unicode_normalize!: Like String#unicode_normalize,
but transcodes +self+ in place.
-=== Transcoding a Stream
+== Transcoding a Stream
Each of these methods may transcode a stream;
whether it does so depends on the external and internal encodings:
@@ -352,7 +352,7 @@ Output:
"R\xE9sum\xE9"
"Résumé"
-=== \Encoding Options
+== \Encoding Options
A number of methods in the Ruby core accept keyword arguments as encoding options.
@@ -419,7 +419,7 @@ These keyword-value pairs specify encoding options:
hash = {"\u3042" => 'xyzzy'}
hash.default = 'XYZZY'
- s.encode('ASCII', fallback: h) # => "xyzzyfooXYZZY"
+ s.encode('ASCII', fallback: hash) # => "xyzzyfooXYZZY"
def (fallback = "U+%.4X").escape(x)
self % x.unpack("U")
diff --git a/doc/exceptions.md b/doc/exceptions.md
new file mode 100644
index 0000000000..4db2f26c18
--- /dev/null
+++ b/doc/exceptions.md
@@ -0,0 +1,362 @@
+# Exceptions
+
+Ruby code can raise exceptions.
+
+Most often, a raised exception is meant to alert the running program
+that an unusual (i.e., _exceptional_) situation has arisen,
+and may need to be handled.
+
+Code throughout the Ruby core, Ruby standard library, and Ruby gems generates exceptions
+in certain circumstances:
+
+```
+File.open('nope.txt') # Raises Errno::ENOENT: "No such file or directory"
+```
+
+## Raised Exceptions
+
+A raised exception transfers program execution, one way or another.
+
+### Unrescued Exceptions
+
+If an exception not _rescued_
+(see [Rescued Exceptions](#label-Rescued+Exceptions) below),
+execution transfers to code in the Ruby interpreter
+that prints a message and exits the program (or thread):
+
+```
+$ ruby -e "raise"
+-e:1:in `<main>': unhandled exception
+```
+
+### Rescued Exceptions
+
+An <i>exception handler</i> may determine what is to happen
+when an exception is raised;
+the handler may _rescue_ an exception,
+and may prevent the program from exiting.
+
+A simple example:
+
+```
+begin
+ raise 'Boom!' # Raises an exception, transfers control.
+ puts 'Will not get here.'
+rescue
+ puts 'Rescued an exception.' # Control transferred to here; program does not exit.
+end
+puts 'Got here.'
+```
+
+Output:
+
+```
+Rescued an exception.
+Got here.
+```
+
+An exception handler has several elements:
+
+| Element | Use |
+|-----------------------------|------------------------------------------------------------------------------------------|
+| Begin clause. | Begins the handler and contains the code whose raised exception, if any, may be rescued. |
+| One or more rescue clauses. | Each contains "rescuing" code, which is to be executed for certain exceptions. |
+| Else clause (optional). | Contains code to be executed if no exception is raised. |
+| Ensure clause (optional). | Contains code to be executed whether or not an exception is raised, or is rescued. |
+| <tt>end</tt> statement. | Ends the handler. ` |
+
+#### Begin Clause
+
+The begin clause begins the exception handler:
+
+- May start with a `begin` statement;
+ see also [Begin-Less Exception Handlers](#label-Begin-Less+Exception+Handlers).
+- Contains code whose raised exception (if any) is covered
+ by the handler.
+- Ends with the first following `rescue` statement.
+
+#### Rescue Clauses
+
+A rescue clause:
+
+- Starts with a `rescue` statement.
+- Contains code that is to be executed for certain raised exceptions.
+- Ends with the first following `rescue`,
+ `else`, `ensure`, or `end` statement.
+
+A `rescue` statement may include one or more classes
+that are to be rescued;
+if none is given, StandardError is assumed.
+
+The rescue clause rescues both the specified class
+(or StandardError if none given) or any of its subclasses;
+(see [Built-In Exception Classes](rdoc-ref:Exception@Built-In+Exception+Classes)
+for the hierarchy of Ruby built-in exception classes):
+
+
+```
+begin
+ 1 / 0 # Raises ZeroDivisionError, a subclass of StandardError.
+rescue
+ puts "Rescued #{$!.class}"
+end
+```
+
+Output:
+
+```
+Rescued ZeroDivisionError
+```
+
+If the `rescue` statement specifies an exception class,
+only that class (or one of its subclasses) is rescued;
+this example exits with a ZeroDivisionError,
+which was not rescued because it is not ArgumentError or one of its subclasses:
+
+```
+begin
+ 1 / 0
+rescue ArgumentError
+ puts "Rescued #{$!.class}"
+end
+```
+
+A `rescue` statement may specify multiple classes,
+which means that its code rescues an exception
+of any of the given classes (or their subclasses):
+
+```
+begin
+ 1 / 0
+rescue FloatDomainError, ZeroDivisionError
+ puts "Rescued #{$!.class}"
+end
+```
+
+An exception handler may contain multiple rescue clauses;
+in that case, the first clause that rescues the exception does so,
+and those before and after are ignored:
+
+```
+begin
+ Dir.open('nosuch')
+rescue Errno::ENOTDIR
+ puts "Rescued #{$!.class}"
+rescue Errno::ENOENT
+ puts "Rescued #{$!.class}"
+end
+```
+
+Output:
+
+```
+Rescued Errno::ENOENT
+```
+
+A `rescue` statement may specify a variable
+whose value becomes the rescued exception
+(an instance of Exception or one of its subclasses:
+
+```
+begin
+ 1 / 0
+rescue => x
+ puts x.class
+ puts x.message
+end
+```
+
+Output:
+
+```
+ZeroDivisionError
+divided by 0
+```
+
+In the rescue clause, these global variables are defined:
+
+- `$!`": the current exception instance.
+- `$@`: its backtrace.
+
+#### Else Clause
+
+The `else` clause:
+
+- Starts with an `else` statement.
+- Contains code that is to be executed if no exception is raised in the begin clause.
+- Ends with the first following `ensure` or `end` statement.
+
+```
+begin
+ puts 'Begin.'
+rescue
+ puts 'Rescued an exception!'
+else
+ puts 'No exception raised.'
+end
+```
+
+Output:
+
+```
+Begin.
+No exception raised.
+```
+
+#### Ensure Clause
+
+The ensure clause:
+
+- Starts with an `ensure` statement.
+- Contains code that is to be executed
+ regardless of whether an exception is raised,
+ and regardless of whether a raised exception is handled.
+- Ends with the first following `end` statement.
+
+```
+def foo(boom: false)
+ puts 'Begin.'
+ raise 'Boom!' if boom
+rescue
+ puts 'Rescued an exception!'
+else
+ puts 'No exception raised.'
+ensure
+ puts 'Always do this.'
+end
+
+foo(boom: true)
+foo(boom: false)
+```
+
+Output:
+
+```
+Begin.
+Rescued an exception!
+Always do this.
+Begin.
+No exception raised.
+Always do this.
+```
+
+#### End Statement
+
+The `end` statement ends the handler.
+
+Code following it is reached only if any raised exception is rescued.
+
+#### Begin-Less \Exception Handlers
+
+As seen above, an exception handler may be implemented with `begin` and `end`.
+
+An exception handler may also be implemented as:
+
+- A method body:
+
+ ```
+ def foo(boom: false) # Serves as beginning of exception handler.
+ puts 'Begin.'
+ raise 'Boom!' if boom
+ rescue
+ puts 'Rescued an exception!'
+ else
+ puts 'No exception raised.'
+ end # Serves as end of exception handler.
+ ```
+
+- A block:
+
+ ```
+ Dir.chdir('.') do |dir| # Serves as beginning of exception handler.
+ raise 'Boom!'
+ rescue
+ puts 'Rescued an exception!'
+ end # Serves as end of exception handler.
+ ```
+
+#### Re-Raising an \Exception
+
+It can be useful to rescue an exception, but allow its eventual effect;
+for example, a program can rescue an exception, log data about it,
+and then "reinstate" the exception.
+
+This may be done via the `raise` method, but in a special way;
+a rescuing clause:
+
+ - Captures an exception.
+ - Does whatever is needed concerning the exception (such as logging it).
+ - Calls method `raise` with no argument,
+ which raises the rescued exception:
+
+```
+begin
+ 1 / 0
+rescue ZeroDivisionError
+ # Do needful things (like logging).
+ raise # Raised exception will be ZeroDivisionError, not RuntimeError.
+end
+```
+
+Output:
+
+```
+ruby t.rb
+t.rb:2:in `/': divided by 0 (ZeroDivisionError)
+ from t.rb:2:in `<main>'
+```
+
+#### Retrying
+
+It can be useful to retry a begin clause;
+for example, if it must access a possibly-volatile resource
+(such as a web page),
+it can be useful to try the access more than once
+(in the hope that it may become available):
+
+```
+retries = 0
+begin
+ puts "Try ##{retries}."
+ raise 'Boom'
+rescue
+ puts "Rescued retry ##{retries}."
+ if (retries += 1) < 3
+ puts 'Retrying'
+ retry
+ else
+ puts 'Giving up.'
+ raise
+ end
+end
+```
+
+```
+Try #0.
+Rescued retry #0.
+Retrying
+Try #1.
+Rescued retry #1.
+Retrying
+Try #2.
+Rescued retry #2.
+Giving up.
+# RuntimeError ('Boom') raised.
+```
+
+Note that the retry re-executes the entire begin clause,
+not just the part after the point of failure.
+
+## Raising an \Exception
+
+Raise an exception with method Kernel#raise.
+
+## Custom Exceptions
+
+To provide additional or alternate information,
+you may create custom exception classes;
+each should be a subclass of one of the built-in exception classes:
+
+```
+class MyException < StandardError; end
+```
diff --git a/doc/extension.ja.rdoc b/doc/extension.ja.rdoc
index bde907c916..2f7856f3d4 100644
--- a/doc/extension.ja.rdoc
+++ b/doc/extension.ja.rdoc
@@ -780,9 +780,14 @@ RUBY_TYPED_WB_PROTECTED ::
メソッドã®å®Ÿè£…ã«é©åˆ‡ã«ãƒ©ã‚¤ãƒˆãƒãƒªã‚¢ã‚’挿入ã™ã‚‹è²¬ä»»ãŒã‚ã‚Šã¾ã™ï¼Ž
ã•ã‚‚ãªãã°Rubyã¯å®Ÿè¡Œæ™‚ã«ã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã™ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ï¼Ž
- ライトãƒãƒªã‚¢ã«ã¤ã„ã¦ã¯doc/extension.ja.rdocã®Appendix D
- "世代別GC"ã‚‚å‚ç…§ã—ã¦ãã ã•ã„.
+ ライトãƒãƒªã‚¢ã«ã¤ã„ã¦ã¯{世代別
+ GC}[rdoc-ref:@Appendix+D.+-E4-B8-96-E4-BB-A3-E5-88-A5GC]
+ ã‚‚å‚ç…§ã—ã¦ãã ã•ã„.
+ã“ã®ãƒžã‚¯ãƒ­ã¯ä¾‹å¤–を発生ã•ã›ã‚‹å¯èƒ½æ€§ãŒã‚ã‚‹ã“ã¨ã«æ³¨æ„ã—ã¦ãã ã•
+ã„. ラップã•ã‚Œã‚‹ sval ãŒï¼Œè§£æ”¾ã™ã‚‹å¿…è¦ãŒã‚るリソース (割り
+当ã¦ã‚‰ã‚ŒãŸãƒ¡ãƒ¢ãƒªï¼Œå¤–部ライブラリã‹ã‚‰ã®ãƒãƒ³ãƒ‰ãƒ«ãªã©) ã‚’ä¿æŒã—
+ã¦ã„ã‚‹å ´åˆã¯ï¼Œrb_protect を使用ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ï¼Ž
Cã®æ§‹é€ ä½“ã®å‰²å½“ã¨å¯¾å¿œã™ã‚‹ã‚ªãƒ–ジェクトã®ç”Ÿæˆã‚’åŒæ™‚ã«è¡Œã†ãƒžã‚¯
ロã¨ã—ã¦ä»¥ä¸‹ã®ã‚‚ã®ãŒæä¾›ã•ã‚Œã¦ã„ã¾ã™ï¼Ž
@@ -1731,7 +1736,7 @@ have_func(func, header) ::
ックã™ã‚‹ï¼ŽfuncãŒæ¨™æº–ã§ã¯ãƒªãƒ³ã‚¯ã•ã‚Œãªã„ライブラリ内ã®ã‚‚ã®ã§
ã‚る時ã«ã¯å…ˆã«have_libraryã§ãã®ãƒ©ã‚¤ãƒ–ラリをãƒã‚§ãƒƒã‚¯ã—ã¦ãŠ
ã事.ãƒã‚§ãƒƒã‚¯ã«æˆåŠŸã™ã‚‹ã¨ï¼Œãƒ—リプロセッサマクロ
- `HAVE_{FUNC}` を定義ã—,trueã‚’è¿”ã™ï¼Ž
+ <tt>HAVE_{FUNC}</tt> を定義ã—,trueã‚’è¿”ã™ï¼Ž
have_var(var, header) ::
@@ -1739,44 +1744,44 @@ have_var(var, header) ::
クã™ã‚‹ï¼ŽvarãŒæ¨™æº–ã§ã¯ãƒªãƒ³ã‚¯ã•ã‚Œãªã„ライブラリ内ã®ã‚‚ã®ã§ã‚
る時ã«ã¯å…ˆã«have_libraryã§ãã®ãƒ©ã‚¤ãƒ–ラリをãƒã‚§ãƒƒã‚¯ã—ã¦ãŠã
事.ãƒã‚§ãƒƒã‚¯ã«æˆåŠŸã™ã‚‹ã¨ï¼Œãƒ—リプロセッサマクロ
- `HAVE_{VAR}` を定義ã—,trueã‚’è¿”ã™ï¼Ž
+ <tt>HAVE_{VAR}</tt> を定義ã—,trueã‚’è¿”ã™ï¼Ž
have_header(header) ::
ヘッダファイルã®å­˜åœ¨ã‚’ãƒã‚§ãƒƒã‚¯ã™ã‚‹ï¼Žãƒã‚§ãƒƒã‚¯ã«æˆåŠŸã™ã‚‹ã¨ï¼Œ
- プリプロセッサマクロ `HAVE_{HEADER_H}` を定義ã—,trueã‚’è¿”ã™ï¼Ž
+ プリプロセッサマクロ <tt>HAVE_{HEADER_H}</tt> を定義ã—,trueã‚’è¿”ã™ï¼Ž
(スラッシュやドットã¯ã‚¢ãƒ³ãƒ€ãƒ¼ã‚¹ã‚³ã‚¢ã«ç½®æ›ã•ã‚Œã‚‹)
find_header(header, path...) ::
ヘッダファイルheaderã®å­˜åœ¨ã‚’ -Ipath を追加ã—ãªãŒã‚‰ãƒã‚§ãƒƒã‚¯
ã™ã‚‹ï¼Žãƒã‚§ãƒƒã‚¯ã«æˆåŠŸã™ã‚‹ã¨ï¼Œãƒ—リプロセッサマクロ
- `HAVE_{HEADER_H}` を定義ã—,trueã‚’è¿”ã™ï¼Ž
+ <tt>HAVE_{HEADER_H}</tt> を定義ã—,trueã‚’è¿”ã™ï¼Ž
(スラッシュやドットã¯ã‚¢ãƒ³ãƒ€ãƒ¼ã‚¹ã‚³ã‚¢ã«ç½®æ›ã•ã‚Œã‚‹)
have_struct_member(type, member[, header[, opt]]) ::
ヘッダファイルheaderをインクルードã—ã¦åž‹typeãŒå®šç¾©ã•ã‚Œï¼Œ
ãªãŠã‹ã¤ãƒ¡ãƒ³ãƒmemberãŒå­˜åœ¨ã™ã‚‹ã‹ã‚’ãƒã‚§ãƒƒã‚¯ã™ã‚‹ï¼Žãƒã‚§ãƒƒã‚¯ã«
- æˆåŠŸã™ã‚‹ã¨ï¼Œãƒ—リプロセッサマクロ `HAVE_{TYPE}_{MEMBER}` ã‚’
+ æˆåŠŸã™ã‚‹ã¨ï¼Œãƒ—リプロセッサマクロ <tt>HAVE_{TYPE}_{MEMBER}</tt> ã‚’
定義ã—,trueã‚’è¿”ã™ï¼Ž
have_type(type, header, opt) ::
ヘッダファイルheaderをインクルードã—ã¦åž‹typeãŒå­˜åœ¨ã™ã‚‹ã‹ã‚’
ãƒã‚§ãƒƒã‚¯ã™ã‚‹ï¼Žãƒã‚§ãƒƒã‚¯ã«æˆåŠŸã™ã‚‹ã¨ï¼Œãƒ—リプロセッサマクロ
- `HAVE_TYPE_{TYPE}` を定義ã—,trueã‚’è¿”ã™ï¼Ž
+ <tt>HAVE_TYPE_{TYPE}</tt> を定義ã—,trueã‚’è¿”ã™ï¼Ž
check_sizeof(type, header) ::
ヘッダファイルheaderをインクルードã—ã¦åž‹typeã®charå˜ä½ã‚µã‚¤
ズを調ã¹ã‚‹ï¼Žãƒã‚§ãƒƒã‚¯ã«æˆåŠŸã™ã‚‹ã¨ï¼Œãƒ—リプロセッサマクロ
- `SIZEOF_{TYPE}` を定義ã—,ãã®ã‚µã‚¤ã‚ºã‚’è¿”ã™ï¼Žå®šç¾©ã•ã‚Œã¦ã„ãª
+ <tt>SIZEOF_{TYPE}</tt> を定義ã—,ãã®ã‚µã‚¤ã‚ºã‚’è¿”ã™ï¼Žå®šç¾©ã•ã‚Œã¦ã„ãª
ã„ã¨ãã¯nilã‚’è¿”ã™ï¼Ž
-append_cppflags(array-of-flags[, opt])
-append_cflags(array-of-flags[, opt])
-append_ldflags(array-of-flags[, opt])
+append_cppflags(array-of-flags[, opt]) ::
+append_cflags(array-of-flags[, opt]) ::
+append_ldflags(array-of-flags[, opt]) ::
å„flagãŒä½¿ç”¨å¯èƒ½ã§ã‚ã‚Œã°ï¼Œãã‚Œãžã‚Œ$CPPFLAGS, $CFLAGS,
$LDFLAGSã«è¿½åŠ ã™ã‚‹ï¼Žã‚³ãƒ³ãƒ‘イラã®ãƒ•ãƒ©ã‚°ã«ã¯ç§»æ¤æ€§ãŒãªã„ã®ã§ï¼Œ
@@ -1850,8 +1855,9 @@ RGenGCã¯ï¼ŒéŽåŽ»ã®æ‹¡å¼µãƒ©ã‚¤ãƒ–ラリã«ï¼ˆã»ã¼ï¼‰äº’æ›æ€§ã‚’ä¿ã¤ã‚ˆã
スã™ã‚‹ã‚ˆã†ãªã‚³ãƒ¼ãƒ‰ã¯æ›¸ã‹ãªã„よã†ã«ã—ã¦ä¸‹ã•ã„.代ã‚ã‚Šã«ï¼Œrb_ary_aref(),
rb_ary_store() ãªã©ã®ï¼Œé©åˆ‡ãª API 関数を利用ã™ã‚‹ã‚ˆã†ã«ã—ã¦ä¸‹ã•ã„.
-ãã®ã»ã‹ï¼Œå¯¾å¿œã«ã¤ã„ã¦ã®è©³ç´°ã¯ extension.rdoc ã®ã€ŒAppendix D. Generational
-GCã€ã‚’å‚ç…§ã—ã¦ä¸‹ã•ã„.
+ãã®ã»ã‹ï¼Œå¯¾å¿œã«ã¤ã„ã¦ã®è©³ç´°ã¯ {Appendix D. Generational
+GC}[rdoc-ref:extension.rdoc@Appendix+D.+Generational+GC]ã‚’å‚
+ç…§ã—ã¦ä¸‹ã•ã„.
== Appendix E. Ractor サãƒãƒ¼ãƒˆ
@@ -1860,10 +1866,12 @@ Ruby 3.0 ã‹ã‚‰ã€Ruby プログラムを並列ã«å®Ÿè¡Œã™ã‚‹ãŸã‚ã®ä»•çµ„ã¿
ãªã‚Šã¾ã™ã€‚サãƒãƒ¼ãƒˆã—ã¦ã„ãªã„ライブラリã¯ã€ãƒ¡ã‚¤ãƒ³ Ractor 以外ã§å®Ÿè¡Œã™ã‚‹ã¨
エラーã«ãªã‚Šã¾ã™ï¼ˆRactor::UnsafeError)。
-Ractor をサãƒãƒ¼ãƒˆã™ã‚‹ãŸã‚ã®è©³ç´°ã¯ã€extension.rdoc ã®ã€ŒAppendix F. Ractor
-supportã€ã‚’å‚ç…§ã—ã¦ãã ã•ã„。
+Ractor をサãƒãƒ¼ãƒˆã™ã‚‹ãŸã‚ã®è©³ç´°ã¯ã€{Appendix F. Ractor
+support}[rdoc-ref:extension.rdoc@Appendix+F.+Ractor+support]
+ã‚’å‚ç…§ã—ã¦ãã ã•ã„。
-
-:enddoc: Local variables:
-:enddoc: fill-column: 60
-:enddoc: end:
+--
+Local variables:
+fill-column: 60
+end:
+++
diff --git a/doc/extension.rdoc b/doc/extension.rdoc
index 5089272599..ba59d107ab 100644
--- a/doc/extension.rdoc
+++ b/doc/extension.rdoc
@@ -747,18 +747,24 @@ RUBY_TYPED_WB_PROTECTED ::
barriers in all implementations of methods of that object as
appropriate. Otherwise Ruby might crash while running.
- More about write barriers can be found in "Generational GC" in
- Appendix D.
+ More about write barriers can be found in {Generational
+ GC}[rdoc-ref:@Appendix+D.+Generational+GC].
RUBY_TYPED_FROZEN_SHAREABLE ::
- This flag indicates that the object is shareable object
- if the object is frozen. See Appendix F more details.
+ This flag indicates that the object is shareable object if the object
+ is frozen. See {Ractor support}[rdoc-ref:@Appendix+F.+Ractor+support]
+ more details.
If this flag is not set, the object can not become a shareable
object by Ractor.make_shareable() method.
-You can allocate and wrap the structure in one step.
+Note that this macro can raise an exception. If sval to be wrapped
+holds a resource needs to be released (e.g., allocated memory, handle
+from an external library, and etc), you will have to use rb_protect.
+
+You can allocate and wrap the structure in one step, in more
+preferable manner.
TypedData_Make_Struct(klass, type, data_type, sval)
@@ -767,6 +773,10 @@ the structure, which is also allocated. This macro works like:
(sval = ZALLOC(type), TypedData_Wrap_Struct(klass, data_type, sval))
+However, you should use this macro instead of "allocation then wrap"
+like the above code if it is simply allocated, because the latter can
+raise a NoMemoryError and sval will be memory leaked in that case.
+
Arguments klass and data_type work like their counterparts in
TypedData_Wrap_Struct(). A pointer to the allocated structure will
be assigned to sval, which should be a pointer of the type specified.
@@ -779,26 +789,26 @@ approach to marking and reference updating is provided, by declaring offset
references to the VALUES in your struct.
Doing this allows the Ruby GC to support marking these references and GC
-compaction without the need to define the `dmark` and `dcompact` callbacks.
+compaction without the need to define the +dmark+ and +dcompact+ callbacks.
You must define a static list of VALUE pointers to the offsets within your
struct where the references are located, and set the "data" member to point to
-this reference list. The reference list must end with `END_REFS`
+this reference list. The reference list must end with +RUBY_END_REFS+.
Some Macros have been provided to make edge referencing easier:
-* <code>RUBY_TYPED_DECL_MARKING</code> =A flag that can be set on the `ruby_data_type_t` to indicate that references are being declared as edges.
+* <code>RUBY_TYPED_DECL_MARKING</code> =A flag that can be set on the +ruby_data_type_t+ to indicate that references are being declared as edges.
-* <code>RUBY_REFERENCES_START(ref_list_name)</code> - Define `ref_list_name` as a list of references
+* <code>RUBY_REFERENCES(ref_list_name)</code> - Define _ref_list_name_ as a list of references
-* <code>RUBY_REFERENCES_END</code> - Mark the end of the references list. This will take care of terminating the list correctly
+* <code>RUBY_REF_END</code> - The end mark of the references list.
-* <code>RUBY_REF_EDGE\(struct, member\)</code> - Declare `member` as a VALUE edge from `struct`. Use this after `RUBY_REFERENCES_START`
+* <code>RUBY_REF_EDGE(struct, member)</code> - Declare _member_ as a VALUE edge from _struct_. Use this after +RUBY_REFERENCES_START+
-* +REFS_LIST_PTR+ - Coerce the reference list into a format that can be
- accepted by the existing `dmark` interface.
+* +RUBY_REFS_LIST_PTR+ - Coerce the reference list into a format that can be
+ accepted by the existing +dmark+ interface.
-The example below is from `Dir` (defined in `dir.c`)
+The example below is from Dir (defined in +dir.c+)
// The struct being wrapped. Notice this contains 3 members of which the second
// is a VALUE reference to another ruby object.
@@ -808,18 +818,19 @@ The example below is from `Dir` (defined in `dir.c`)
rb_encoding *enc;
}
- // Define a reference list `dir_refs` containing a single entry to `path`, and
- // terminating with RUBY_REF_END
- RUBY_REFERENCES_START(dir_refs)
- REF_EDGE(dir_data, path),
- RUBY_REFERENCES_END
+ // Define a reference list `dir_refs` containing a single entry to `path`.
+ // Needs terminating with RUBY_REF_END
+ RUBY_REFERENCES(dir_refs) = {
+ RUBY_REF_EDGE(dir_data, path),
+ RUBY_REF_END
+ };
// Override the "dmark" field with the defined reference list now that we
// no longer need a marking callback and add RUBY_TYPED_DECL_MARKING to the
// flags field
static const rb_data_type_t dir_data_type = {
"dir",
- {REFS_LIST_PTR(dir_refs), dir_free, dir_memsize,},
+ {RUBY_REFS_LIST_PTR(dir_refs), dir_free, dir_memsize,},
0, NULL, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_DECL_MARKING
};
@@ -2208,70 +2219,72 @@ Ractor safety around C extensions has the following properties:
To make a "Ractor-safe" C extension, we need to check the following points:
-(1) Do not share unshareable objects between ractors
+1. Do not share unshareable objects between ractors
-For example, C's global variable can lead sharing an unshareable objects
-between ractors.
+ For example, C's global variable can lead sharing an unshareable objects
+ between ractors.
- VALUE g_var;
- VALUE set(VALUE self, VALUE v){ return g_var = v; }
- VALUE get(VALUE self){ return g_var; }
+ VALUE g_var;
+ VALUE set(VALUE self, VALUE v){ return g_var = v; }
+ VALUE get(VALUE self){ return g_var; }
-set() and get() pair can share an unshareable objects using g_var, and
-it is Ractor-unsafe.
+ set() and get() pair can share an unshareable objects using g_var, and
+ it is Ractor-unsafe.
-Not only using global variables directly, some indirect data structure
-such as global st_table can share the objects, so please take care.
+ Not only using global variables directly, some indirect data structure
+ such as global st_table can share the objects, so please take care.
-Note that class and module objects are shareable objects, so you can
-keep the code "cFoo = rb_define_class(...)" with C's global variables.
+ Note that class and module objects are shareable objects, so you can
+ keep the code "cFoo = rb_define_class(...)" with C's global variables.
-(2) Check the thread-safety of the extension
+2. Check the thread-safety of the extension
-An extension should be thread-safe. For example, the following code is
-not thread-safe:
+ An extension should be thread-safe. For example, the following code is
+ not thread-safe:
- bool g_called = false;
- VALUE call(VALUE self) {
- if (g_called) rb_raise("recursive call is not allowed.");
- g_called = true;
- VALUE ret = do_something();
- g_called = false;
- return ret;
- }
+ bool g_called = false;
+ VALUE call(VALUE self) {
+ if (g_called) rb_raise("recursive call is not allowed.");
+ g_called = true;
+ VALUE ret = do_something();
+ g_called = false;
+ return ret;
+ }
-because g_called global variable should be synchronized by other
-ractor's threads. To avoid such data-race, some synchronization should
-be used. Check include/ruby/thread_native.h and include/ruby/atomic.h.
+ because g_called global variable should be synchronized by other
+ ractor's threads. To avoid such data-race, some synchronization should
+ be used. Check include/ruby/thread_native.h and include/ruby/atomic.h.
-With Ractors, all objects given as method parameters and the receiver (self)
-are guaranteed to be from the current Ractor or to be shareable. As a
-consequence, it is easier to make code ractor-safe than to make code generally
-thread-safe. For example, we don't need to lock an array object to access the
-element of it.
+ With Ractors, all objects given as method parameters and the receiver (self)
+ are guaranteed to be from the current Ractor or to be shareable. As a
+ consequence, it is easier to make code ractor-safe than to make code generally
+ thread-safe. For example, we don't need to lock an array object to access the
+ element of it.
-(3) Check the thread-safety of any used library
+3. Check the thread-safety of any used library
-If the extension relies on an external library, such as a function foo() from
-a library libfoo, the function libfoo foo() should be thread safe.
+ If the extension relies on an external library, such as a function foo() from
+ a library libfoo, the function libfoo foo() should be thread safe.
-(4) Make an object shareable
+4. Make an object shareable
-This is not required to make an extension Ractor-safe.
+ This is not required to make an extension Ractor-safe.
-If an extension provides special objects defined by rb_data_type_t,
-consider these objects can become shareable or not.
+ If an extension provides special objects defined by rb_data_type_t,
+ consider these objects can become shareable or not.
-RUBY_TYPED_FROZEN_SHAREABLE flag indicates that these objects can be
-shareable objects if the object is frozen. This means that if the object
-is frozen, the mutation of wrapped data is not allowed.
+ RUBY_TYPED_FROZEN_SHAREABLE flag indicates that these objects can be
+ shareable objects if the object is frozen. This means that if the object
+ is frozen, the mutation of wrapped data is not allowed.
-(5) Others
+5. Others
-There are possibly other points or requirements which must be considered in the
-making of a Ractor-safe extension. This document will be extended as they are
-discovered.
+ There are possibly other points or requirements which must be considered in the
+ making of a Ractor-safe extension. This document will be extended as they are
+ discovered.
-:enddoc: Local variables:
-:enddoc: fill-column: 70
-:enddoc: end:
+--
+Local variables:
+fill-column: 70
+end:
+++
diff --git a/doc/format_specifications.rdoc b/doc/format_specifications.rdoc
index e589524f27..bdfdc24953 100644
--- a/doc/format_specifications.rdoc
+++ b/doc/format_specifications.rdoc
@@ -1,4 +1,4 @@
-== Format Specifications
+= Format Specifications
Several Ruby core classes have instance method +printf+ or +sprintf+:
@@ -37,12 +37,12 @@ It consists of:
Except for the leading percent character,
the only required part is the type specifier, so we begin with that.
-=== Type Specifiers
+== Type Specifiers
This section provides a brief explanation of each type specifier.
The links lead to the details and examples.
-==== \Integer Type Specifiers
+=== \Integer Type Specifiers
- +b+ or +B+: Format +argument+ as a binary integer.
See {Specifiers b and B}[rdoc-ref:format_specifications.rdoc@Specifiers+b+and+B].
@@ -54,7 +54,7 @@ The links lead to the details and examples.
- +x+ or +X+: Format +argument+ as a hexadecimal integer.
See {Specifiers x and X}[rdoc-ref:format_specifications.rdoc@Specifiers+x+and+X].
-==== Floating-Point Type Specifiers
+=== Floating-Point Type Specifiers
- +a+ or +A+: Format +argument+ as hexadecimal floating-point number.
See {Specifiers a and A}[rdoc-ref:format_specifications.rdoc@Specifiers+a+and+A].
@@ -65,7 +65,7 @@ The links lead to the details and examples.
- +g+ or +G+: Format +argument+ in a "general" format.
See {Specifiers g and G}[rdoc-ref:format_specifications.rdoc@Specifiers+g+and+G].
-==== Other Type Specifiers
+=== Other Type Specifiers
- +c+: Format +argument+ as a character.
See {Specifier c}[rdoc-ref:format_specifications.rdoc@Specifier+c].
@@ -76,7 +76,7 @@ The links lead to the details and examples.
- <tt>%</tt>: Format +argument+ (<tt>'%'</tt>) as a single percent character.
See {Specifier %}[rdoc-ref:format_specifications.rdoc@Specifier+-25].
-=== Flags
+== Flags
The effect of a flag may vary greatly among type specifiers.
These remarks are general in nature.
@@ -85,7 +85,7 @@ See {type-specific details}[rdoc-ref:format_specifications.rdoc@Type+Specifier+D
Multiple flags may be given with single type specifier;
order does not matter.
-==== <tt>' '</tt> Flag
+=== <tt>' '</tt> Flag
Insert a space before a non-negative number:
@@ -97,49 +97,49 @@ Insert a minus sign for negative value:
sprintf('%d', -10) # => "-10"
sprintf('% d', -10) # => "-10"
-==== <tt>'#'</tt> Flag
+=== <tt>'#'</tt> Flag
Use an alternate format; varies among types:
sprintf('%x', 100) # => "64"
sprintf('%#x', 100) # => "0x64"
-==== <tt>'+'</tt> Flag
+=== <tt>'+'</tt> Flag
Add a leading plus sign for a non-negative number:
sprintf('%x', 100) # => "64"
sprintf('%+x', 100) # => "+64"
-==== <tt>'-'</tt> Flag
+=== <tt>'-'</tt> Flag
Left justify the value in its field:
sprintf('%6d', 100) # => " 100"
sprintf('%-6d', 100) # => "100 "
-==== <tt>'0'</tt> Flag
+=== <tt>'0'</tt> Flag
Left-pad with zeros instead of spaces:
sprintf('%6d', 100) # => " 100"
sprintf('%06d', 100) # => "000100"
-==== <tt>'*'</tt> Flag
+=== <tt>'*'</tt> Flag
Use the next argument as the field width:
sprintf('%d', 20, 14) # => "20"
sprintf('%*d', 20, 14) # => " 14"
-==== <tt>'n$'</tt> Flag
+=== <tt>'n$'</tt> Flag
Format the (1-based) <tt>n</tt>th argument into this field:
sprintf("%s %s", 'world', 'hello') # => "world hello"
sprintf("%2$s %1$s", 'world', 'hello') # => "hello world"
-=== Width Specifier
+== Width Specifier
In general, a width specifier determines the minimum width (in characters)
of the formatted field:
@@ -152,7 +152,7 @@ of the formatted field:
# Ignore if too small.
sprintf('%1d', 100) # => "100"
-=== Precision Specifier
+== Precision Specifier
A precision specifier is a decimal point followed by zero or more
decimal digits.
@@ -194,9 +194,9 @@ the number of characters to write:
sprintf('%s', Time.now) # => "2022-05-04 11:59:16 -0400"
sprintf('%.10s', Time.now) # => "2022-05-04"
-=== Type Specifier Details and Examples
+== Type Specifier Details and Examples
-==== Specifiers +a+ and +A+
+=== Specifiers +a+ and +A+
Format +argument+ as hexadecimal floating-point number:
@@ -209,7 +209,7 @@ Format +argument+ as hexadecimal floating-point number:
sprintf('%A', 4096) # => "0X1P+12"
sprintf('%A', -4096) # => "-0X1P+12"
-==== Specifiers +b+ and +B+
+=== Specifiers +b+ and +B+
The two specifiers +b+ and +B+ behave identically
except when flag <tt>'#'</tt>+ is used.
@@ -226,14 +226,16 @@ Format +argument+ as a binary integer:
sprintf('%#b', 4) # => "0b100"
sprintf('%#B', 4) # => "0B100"
-==== Specifier +c+
+=== Specifier +c+
Format +argument+ as a single character:
sprintf('%c', 'A') # => "A"
sprintf('%c', 65) # => "A"
-==== Specifier +d+
+This behaves like String#<<, except for raising ArgumentError instead of RangeError.
+
+=== Specifier +d+
Format +argument+ as a decimal integer:
@@ -242,7 +244,7 @@ Format +argument+ as a decimal integer:
Flag <tt>'#'</tt> does not apply.
-==== Specifiers +e+ and +E+
+=== Specifiers +e+ and +E+
Format +argument+ in
{scientific notation}[https://en.wikipedia.org/wiki/Scientific_notation]:
@@ -250,7 +252,7 @@ Format +argument+ in
sprintf('%e', 3.14159) # => "3.141590e+00"
sprintf('%E', -3.14159) # => "-3.141590E+00"
-==== Specifier +f+
+=== Specifier +f+
Format +argument+ as a floating-point number:
@@ -259,7 +261,7 @@ Format +argument+ as a floating-point number:
Flag <tt>'#'</tt> does not apply.
-==== Specifiers +g+ and +G+
+=== Specifiers +g+ and +G+
Format +argument+ using exponential form (+e+/+E+ specifier)
if the exponent is less than -4 or greater than or equal to the precision.
@@ -281,7 +283,7 @@ Otherwise format +argument+ using floating-point form (+f+ specifier):
sprintf('%#G', 100000000000) # => "1.00000E+11"
sprintf('%#G', 0.000000000001) # => "1.00000E-12"
-==== Specifier +o+
+=== Specifier +o+
Format +argument+ as an octal integer.
If +argument+ is negative, it will be formatted as a two's complement
@@ -296,14 +298,14 @@ prefixed with +..7+:
sprintf('%#o', 16) # => "020"
sprintf('%#o', -16) # => "..760"
-==== Specifier +p+
+=== Specifier +p+
Format +argument+ as a string via <tt>argument.inspect</tt>:
t = Time.now
sprintf('%p', t) # => "2022-05-01 13:42:07.1645683 -0500"
-==== Specifier +s+
+=== Specifier +s+
Format +argument+ as a string via <tt>argument.to_s</tt>:
@@ -312,7 +314,7 @@ Format +argument+ as a string via <tt>argument.to_s</tt>:
Flag <tt>'#'</tt> does not apply.
-==== Specifiers +x+ and +X+
+=== Specifiers +x+ and +X+
Format +argument+ as a hexadecimal integer.
If +argument+ is negative, it will be formatted as a two's complement
@@ -329,7 +331,7 @@ prefixed with +..f+:
# Alternate format for negative value.
sprintf('%#x', -100) # => "0x..f9c"
-==== Specifier <tt>%</tt>
+=== Specifier <tt>%</tt>
Format +argument+ (<tt>'%'</tt>) as a single percent character:
@@ -337,7 +339,7 @@ Format +argument+ (<tt>'%'</tt>) as a single percent character:
Flags do not apply.
-=== Reference by Name
+== Reference by Name
For more complex formatting, Ruby supports a reference by name.
%<name>s style uses format style, but %{name} style doesn't.
diff --git a/doc/globals.rdoc b/doc/globals.rdoc
index 2b4f6bd7cf..1b51bb1b36 100644
--- a/doc/globals.rdoc
+++ b/doc/globals.rdoc
@@ -1,16 +1,16 @@
-== Pre-Defined Global Variables
+= Pre-Defined Global Variables
Some of the pre-defined global variables have synonyms
-that are available via module Engish.
+that are available via module English.
For each of those, the \English synonym is given.
To use the module:
require 'English'
-=== Exceptions
+== Exceptions
-==== <tt>$!</tt> (\Exception)
+=== <tt>$!</tt> (\Exception)
Contains the Exception object set by Kernel#raise:
@@ -26,7 +26,7 @@ Output:
English - <tt>$ERROR_INFO</tt>
-==== <tt>$@</tt> (Backtrace)
+=== <tt>$@</tt> (Backtrace)
Same as <tt>$!.backtrace</tt>;
returns an array of backtrace positions:
@@ -46,7 +46,7 @@ Output:
English - <tt>$ERROR_POSITION</tt>.
-=== Pattern Matching
+== Pattern Matching
These global variables store information about the most recent
successful match in the current scope.
@@ -54,46 +54,46 @@ successful match in the current scope.
For details and examples,
see {Regexp Global Variables}[rdoc-ref:Regexp@Global+Variables].
-==== <tt>$~</tt> (\MatchData)
+=== <tt>$~</tt> (\MatchData)
MatchData object created from the match;
thread-local and frame-local.
English - <tt>$LAST_MATCH_INFO</tt>.
-==== <tt>$&</tt> (Matched Substring)
+=== <tt>$&</tt> (Matched Substring)
The matched string.
English - <tt>$MATCH</tt>.
-==== <tt>$`</tt> (Pre-Match Substring)
+=== <tt>$`</tt> (Pre-Match Substring)
The string to the left of the match.
English - <tt>$PREMATCH</tt>.
-==== <tt>$'</tt> (Post-Match Substring)
+=== <tt>$'</tt> (Post-Match Substring)
The string to the right of the match.
English - <tt>$POSTMATCH</tt>.
-==== <tt>$+</tt> (Last Matched Group)
+=== <tt>$+</tt> (Last Matched Group)
The last group matched.
English - <tt>$LAST_PAREN_MATCH</tt>.
-==== <tt>$1</tt>, <tt>$2</tt>, \Etc. (Matched Group)
+=== <tt>$1</tt>, <tt>$2</tt>, \Etc. (Matched Group)
For <tt>$_n_</tt> the _nth_ group of the match.
No \English.
-=== Separators
+== Separators
-==== <tt>$/</tt> (Input Record Separator)
+=== <tt>$/</tt> (Input Record Separator)
An input record separator, initially newline.
@@ -101,7 +101,7 @@ English - <tt>$INPUT_RECORD_SEPARATOR</tt>, <tt>$RS</tt>.
Aliased as <tt>$-0</tt>.
-==== <tt>$;</tt> (Input Field Separator)
+=== <tt>$;</tt> (Input Field Separator)
An input field separator, initially +nil+.
@@ -109,76 +109,76 @@ English - <tt>$FIELD_SEPARATOR</tt>, <tt>$FS</tt>.
Aliased as <tt>$-F</tt>.
-==== <tt>$\\</tt> (Output Record Separator)
+=== <tt>$\\</tt> (Output Record Separator)
An output record separator, initially +nil+.
English - <tt>$OUTPUT_RECORD_SEPARATOR</tt>, <tt>$ORS</tt>.
-=== Streams
+== Streams
-==== <tt>$stdin</tt> (Standard Input)
+=== <tt>$stdin</tt> (Standard Input)
The current standard input stream; initially:
$stdin # => #<IO:<STDIN>>
-==== <tt>$stdout</tt> (Standard Output)
+=== <tt>$stdout</tt> (Standard Output)
The current standard output stream; initially:
$stdout # => #<IO:<STDOUT>>
-==== <tt>$stderr</tt> (Standard Error)
+=== <tt>$stderr</tt> (Standard Error)
The current standard error stream; initially:
$stderr # => #<IO:<STDERR>>
-==== <tt>$<</tt> (\ARGF or $stdin)
+=== <tt>$<</tt> (\ARGF or $stdin)
Points to stream ARGF if not empty, else to stream $stdin; read-only.
English - <tt>$DEFAULT_INPUT</tt>.
-==== <tt>$></tt> (Default Standard Output)
+=== <tt>$></tt> (Default Standard Output)
An output stream, initially <tt>$stdout</tt>.
English - <tt>$DEFAULT_OUTPUT
-==== <tt>$.</tt> (Input Position)
+=== <tt>$.</tt> (Input Position)
The input position (line number) in the most recently read stream.
English - <tt>$INPUT_LINE_NUMBER</tt>, <tt>$NR</tt>
-==== <tt>$_</tt> (Last Read Line)
+=== <tt>$_</tt> (Last Read Line)
The line (string) from the most recently read stream.
English - <tt>$LAST_READ_LINE</tt>.
-=== Processes
+== Processes
-==== <tt>$0</tt>
+=== <tt>$0</tt>
Initially, contains the name of the script being executed;
may be reassigned.
-==== <tt>$*</tt> (\ARGV)
+=== <tt>$*</tt> (\ARGV)
Points to ARGV.
English - <tt>$ARGV</tt>.
-==== <tt>$$</tt> (Process ID)
+=== <tt>$$</tt> (Process ID)
The process ID of the current process. Same as Process.pid.
English - <tt>$PROCESS_ID</tt>, <tt>$PID</tt>.
-==== <tt>$?</tt> (Child Status)
+=== <tt>$?</tt> (Child Status)
Initially +nil+, otherwise the Process::Status object
created for the most-recently exited child process;
@@ -186,7 +186,7 @@ thread-local.
English - <tt>$CHILD_STATUS</tt>.
-==== <tt>$LOAD_PATH</tt> (Load Path)
+=== <tt>$LOAD_PATH</tt> (Load Path)
Contains the array of paths to be searched
by Kernel#load and Kernel#require.
@@ -211,7 +211,7 @@ Examples:
Aliased as <tt>$:</tt> and <tt>$-I</tt>.
-==== <tt>$LOADED_FEATURES</tt>
+=== <tt>$LOADED_FEATURES</tt>
Contains an array of the paths to the loaded files:
@@ -230,13 +230,13 @@ Contains an array of the paths to the loaded files:
Aliased as <tt>$"</tt>.
-=== Debugging
+== Debugging
-==== <tt>$FILENAME</tt>
+=== <tt>$FILENAME</tt>
The value returned by method ARGF.filename.
-==== <tt>$DEBUG</tt>
+=== <tt>$DEBUG</tt>
Initially +true+ if command-line option <tt>-d</tt> or <tt>--debug</tt> is given,
otherwise initially +false+;
@@ -246,7 +246,7 @@ When +true+, prints each raised exception to <tt>$stderr</tt>.
Aliased as <tt>$-d</tt>.
-==== <tt>$VERBOSE</tt>
+=== <tt>$VERBOSE</tt>
Initially +true+ if command-line option <tt>-v</tt> or <tt>-w</tt> is given,
otherwise initially +false+;
@@ -258,58 +258,58 @@ When +nil+, disables warnings, including those from Kernel#warn.
Aliased as <tt>$-v</tt> and <tt>$-w</tt>.
-=== Other Variables
+== Other Variables
-==== <tt>$-a</tt>
+=== <tt>$-a</tt>
Whether command-line option <tt>-a</tt> was given; read-only.
-==== <tt>$-i</tt>
+=== <tt>$-i</tt>
Contains the extension given with command-line option <tt>-i</tt>,
or +nil+ if none.
An alias of ARGF.inplace_mode.
-==== <tt>$-l</tt>
+=== <tt>$-l</tt>
Whether command-line option <tt>-l</tt> was set; read-only.
-==== <tt>$-p</tt>
+=== <tt>$-p</tt>
Whether command-line option <tt>-p</tt> was given; read-only.
-=== Deprecated
+== Deprecated
-==== <tt>$=</tt>
+=== <tt>$=</tt>
-==== <tt>$,</tt>
+=== <tt>$,</tt>
-== Pre-Defined Global Constants
+= Pre-Defined Global Constants
-== Streams
+= Streams
-==== <tt>STDIN</tt>
+=== <tt>STDIN</tt>
The standard input stream (the default value for <tt>$stdin</tt>):
STDIN # => #<IO:<STDIN>>
-==== <tt>STDOUT</tt>
+=== <tt>STDOUT</tt>
The standard output stream (the default value for <tt>$stdout</tt>):
STDOUT # => #<IO:<STDOUT>>
-==== <tt>STDERR</tt>
+=== <tt>STDERR</tt>
The standard error stream (the default value for <tt>$stderr</tt>):
STDERR # => #<IO:<STDERR>>
-=== Enviroment
+== Environment
-==== ENV
+=== ENV
A hash of the contains current environment variables names and values:
@@ -321,41 +321,41 @@ A hash of the contains current environment variables names and values:
["DISPLAY", ":0"],
["GDMSESSION", "ubuntu"]]
-==== ARGF
+=== ARGF
The virtual concatenation of the files given on the command line, or from
<tt>$stdin</tt> if no files were given, <tt>"-"</tt> is given, or after
all files have been read.
-==== <tt>ARGV</tt>
+=== <tt>ARGV</tt>
An array of the given command-line arguments.
-==== <tt>TOPLEVEL_BINDING</tt>
+=== <tt>TOPLEVEL_BINDING</tt>
The Binding of the top level scope:
TOPLEVEL_BINDING # => #<Binding:0x00007f58da0da7c0>
-==== <tt>RUBY_VERSION</tt>
+=== <tt>RUBY_VERSION</tt>
The Ruby version:
RUBY_VERSION # => "3.2.2"
-==== <tt>RUBY_RELEASE_DATE</tt>
+=== <tt>RUBY_RELEASE_DATE</tt>
The release date string:
RUBY_RELEASE_DATE # => "2023-03-30"
-==== <tt>RUBY_PLATFORM</tt>
+=== <tt>RUBY_PLATFORM</tt>
The platform identifier:
RUBY_PLATFORM # => "x86_64-linux"
-==== <tt>RUBY_PATCHLEVEL</tt>
+=== <tt>RUBY_PATCHLEVEL</tt>
The integer patch level for this Ruby:
@@ -363,41 +363,41 @@ The integer patch level for this Ruby:
For a development build the patch level will be -1.
-==== <tt>RUBY_REVISION</tt>
+=== <tt>RUBY_REVISION</tt>
The git commit hash for this Ruby:
RUBY_REVISION # => "e51014f9c05aa65cbf203442d37fef7c12390015"
-==== <tt>RUBY_COPYRIGHT</tt>
+=== <tt>RUBY_COPYRIGHT</tt>
The copyright string:
RUBY_COPYRIGHT
# => "ruby - Copyright (C) 1993-2023 Yukihiro Matsumoto"
-==== <tt>RUBY_ENGINE</tt>
+=== <tt>RUBY_ENGINE</tt>
The name of the Ruby implementation:
RUBY_ENGINE # => "ruby"
-==== <tt>RUBY_ENGINE_VERSION</tt>
+=== <tt>RUBY_ENGINE_VERSION</tt>
The version of the Ruby implementation:
RUBY_ENGINE_VERSION # => "3.2.2"
-==== <tt>RUBY_DESCRIPTION</tt>
+=== <tt>RUBY_DESCRIPTION</tt>
The description of the Ruby implementation:
RUBY_DESCRIPTION
# => "ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-linux]"
-=== Embedded \Data
+== Embedded \Data
-==== <tt>DATA</tt>
+=== <tt>DATA</tt>
Defined if and only if the program has this line:
diff --git a/doc/implicit_conversion.rdoc b/doc/implicit_conversion.rdoc
index ba15fa4bf4..e244096125 100644
--- a/doc/implicit_conversion.rdoc
+++ b/doc/implicit_conversion.rdoc
@@ -1,4 +1,4 @@
-== Implicit Conversions
+= Implicit Conversions
Some Ruby methods accept one or more objects
that can be either:
@@ -15,7 +15,7 @@ a specific conversion method:
* Integer: +to_int+
* String: +to_str+
-=== Array-Convertible Objects
+== Array-Convertible Objects
An <i>Array-convertible object</i> is an object that:
@@ -69,7 +69,7 @@ This class is not Array-convertible (method +to_ary+ returns non-Array):
# Raises TypeError (can't convert NotArrayConvertible to Array (NotArrayConvertible#to_ary gives Symbol))
a.replace(NotArrayConvertible.new)
-=== Hash-Convertible Objects
+== Hash-Convertible Objects
A <i>Hash-convertible object</i> is an object that:
@@ -123,7 +123,7 @@ This class is not Hash-convertible (method +to_hash+ returns non-Hash):
# Raises TypeError (can't convert NotHashConvertible to Hash (ToHashReturnsNonHash#to_hash gives Symbol))
h.merge(NotHashConvertible.new)
-=== Integer-Convertible Objects
+== Integer-Convertible Objects
An <i>Integer-convertible object</i> is an object that:
@@ -171,7 +171,7 @@ This class is not Integer-convertible (method +to_int+ returns non-Integer):
# Raises TypeError (can't convert NotIntegerConvertible to Integer (NotIntegerConvertible#to_int gives Symbol))
Array.new(NotIntegerConvertible.new)
-=== String-Convertible Objects
+== String-Convertible Objects
A <i>String-convertible object</i> is an object that:
* Has instance method +to_str+.
diff --git a/doc/irb/indexes.md b/doc/irb/indexes.md
new file mode 100644
index 0000000000..24a67b9698
--- /dev/null
+++ b/doc/irb/indexes.md
@@ -0,0 +1,189 @@
+## Indexes
+
+### Index of Command-Line Options
+
+These are the \IRB command-line options, with links to explanatory text:
+
+- `-d`: Set `$DEBUG` and {$VERBOSE}[rdoc-ref:IRB@Verbosity]
+ to `true`.
+- `-E _ex_[:_in_]`: Set initial external (ex) and internal (in)
+ {encodings}[rdoc-ref:IRB@Encodings] (same as `ruby -E>`).
+- `-f`: Don't initialize from {configuration file}[rdoc-ref:IRB@Configuration+File].
+- `-I _dirpath_`: Specify {$LOAD_PATH directory}[rdoc-ref:IRB@Load+Modules]
+ (same as `ruby -I`).
+- `-r _load-module_`: Require {load-module}[rdoc-ref:IRB@Load+Modules]
+ (same as `ruby -r`).
+- `-U`: Set external and internal {encodings}[rdoc-ref:IRB@Encodings] to UTF-8.
+- `-w`: Suppress {warnings}[rdoc-ref:IRB@Warnings] (same as `ruby -w`).
+- `-W[_level_]`: Set {warning level}[rdoc-ref:IRB@Warnings];
+ 0=silence, 1=medium, 2=verbose (same as `ruby -W`).
+- `--autocomplete`: Use {auto-completion}[rdoc-ref:IRB@Automatic+Completion].
+- `--back-trace-limit _n_`: Set a {backtrace limit}[rdoc-ref:IRB@Tracer];
+ display at most the top `n` and bottom `n` entries.
+- `--colorize`: Use {color-highlighting}[rdoc-ref:IRB@Color+Highlighting]
+ for input and output.
+- `--context-mode _n_`: Select method to create Binding object
+ for new {workspace}[rdoc-ref:IRB@Commands]; `n` in range `0..4`.
+- `--echo`: Print ({echo}[rdoc-ref:IRB@Return-Value+Printing+-28Echoing-29])
+ return values.
+- `--extra-doc-dir _dirpath_`:
+ Add a {documentation directory}[rdoc-ref:IRB@RI+Documentation+Directories]
+ for the documentation dialog.
+- `--inf-ruby-mode`: Set prompt mode to {:INF_RUBY}[rdoc-ref:IRB@Pre-Defined+Prompts]
+ (appropriate for `inf-ruby-mode` on Emacs);
+ suppresses --multiline and --singleline.
+- `--inspect`: Use method `inspect` for printing ({echoing}[rdoc-ref:IRB@Return-Value+Printing+-28Echoing-29])
+ return values.
+- `--multiline`: Use the multiline editor as the {input method}[rdoc-ref:IRB@Input+Method].
+- `--noautocomplete`: Don't use {auto-completion}[rdoc-ref:IRB@Automatic+Completion].
+- `--nocolorize`: Don't use {color-highlighting}[rdoc-ref:IRB@Color+Highlighting]
+ for input and output.
+- `--noecho`: Don't print ({echo}[rdoc-ref:IRB@Return-Value+Printing+-28Echoing-29])
+ return values.
+- `--noecho-on-assignment`: Don't print ({echo}[rdoc-ref:IRB@Return-Value+Printing+-28Echoing-29])
+ result on assignment.
+- `--noinspect`: Don't se method `inspect` for printing ({echoing}[rdoc-ref:IRB@Return-Value+Printing+-28Echoing-29])
+ return values.
+- `--nomultiline`: Don't use the multiline editor as the {input method}[rdoc-ref:IRB@Input+Method].
+- `--noprompt`: Don't print {prompts}[rdoc-ref:IRB@Prompt+and+Return+Formats].
+- `--noscript`: Treat the first command-line argument as a normal
+ {command-line argument}[rdoc-ref:IRB@Initialization+Script],
+ and include it in `ARGV`.
+- `--nosingleline`: Don't use the singleline editor as the {input method}[rdoc-ref:IRB@Input+Method].
+- `--noverbose`Don't print {verbose}[rdoc-ref:IRB@Verbosity] details.
+- `--prompt _mode_`, `--prompt-mode _mode_`:
+ Set {prompt and return formats}[rdoc-ref:IRB@Prompt+and+Return+Formats];
+ `mode` may be a {pre-defined prompt}[rdoc-ref:IRB@Pre-Defined+Prompts]
+ or the name of a {custom prompt}[rdoc-ref:IRB@Custom+Prompts].
+- `--script`: Treat the first command-line argument as the path to an
+ {initialization script}[rdoc-ref:IRB@Initialization+Script],
+ and omit it from `ARGV`.
+- `--simple-prompt`, `--sample-book-mode`:
+ Set prompt mode to {:SIMPLE}[rdoc-ref:IRB@Pre-Defined+Prompts].
+- `--singleline`: Use the singleline editor as the {input method}[rdoc-ref:IRB@Input+Method].
+- `--tracer`: Use {Tracer}[rdoc-ref:IRB@Tracer] to print a stack trace for each input command.
+- `--truncate-echo-on-assignment`: Print ({echo}[rdoc-ref:IRB@Return-Value+Printing+-28Echoing-29])
+ truncated result on assignment.
+- `--verbose`Print {verbose}[rdoc-ref:IRB@Verbosity] details.
+- `-v`, `--version`: Print the {IRB version}[rdoc-ref:IRB@Version].
+- `-h`, `--help`: Print the {IRB help text}[rdoc-ref:IRB@Help].
+- `--`: Separate options from {arguments}[rdoc-ref:IRB@Command-Line+Arguments]
+ on the command-line.
+
+### Index of \IRB.conf Entries
+
+These are the keys for hash \IRB.conf entries, with links to explanatory text;
+for each entry that is pre-defined, the initial value is given:
+
+- `:AP_NAME`: \IRB {application name}[rdoc-ref:IRB@Application+Name];
+ initial value: `'irb'`.
+- `:AT_EXIT`: Array of hooks to call
+ {at exit}[rdoc-ref:IRB@IRB];
+ initial value: `[]`.
+- `:AUTO_INDENT`: Whether {automatic indentation}[rdoc-ref:IRB@Automatic+Indentation]
+ is enabled; initial value: `true`.
+- `:BACK_TRACE_LIMIT`: Sets the {back trace limit}[rdoc-ref:IRB@Tracer];
+ initial value: `16`.
+- `:COMMAND_ALIASES`: Defines input {command aliases}[rdoc-ref:IRB@Command+Aliases];
+ initial value:
+
+ {
+ "$": :show_source,
+ "@": :whereami,
+ }
+
+- `:CONTEXT_MODE`: Sets the {context mode}[rdoc-ref:IRB@Context+Mode],
+ the type of binding to be used when evaluating statements;
+ initial value: `4`.
+- `:ECHO`: Whether to print ({echo}[rdoc-ref:IRB@Return-Value+Printing+-28Echoing-29])
+ return values;
+ initial value: `nil`, which would set `conf.echo` to `true`.
+- `:ECHO_ON_ASSIGNMENT`: Whether to print ({echo}[rdoc-ref:IRB@Return-Value+Printing+-28Echoing-29])
+ return values on assignment;
+ initial value: `nil`, which would set `conf.echo_on_assignment` to `:truncate`.
+- `:EVAL_HISTORY`: How much {evaluation history}[rdoc-ref:IRB@Evaluation+History]
+ is to be stored; initial value: `nil`.
+- `:EXTRA_DOC_DIRS`: \Array of
+ {RI documentation directories}[rdoc-ref:IRB@RI+Documentation+Directories]
+ to be parsed for the documentation dialog;
+ initial value: `[]`.
+- `:IGNORE_EOF`: Whether to ignore {end-of-file}[rdoc-ref:IRB@End-of-File];
+ initial value: `false`.
+- `:IGNORE_SIGINT`: Whether to ignore {SIGINT}[rdoc-ref:IRB@SIGINT];
+ initial value: `true`.
+- `:INSPECT_MODE`: Whether to use method `inspect` for printing
+ ({echoing}[rdoc-ref:IRB@Return-Value+Printing+-28Echoing-29]) return values;
+ initial value: `true`.
+- `:IRB_LIB_PATH`: The path to the {IRB library directory}[rdoc-ref:IRB@IRB+Library+Directory]; initial value:
+
+ - `"<i>RUBY_DIR</i>/lib/ruby/gems/<i>RUBY_VER_NUM</i>/gems/irb-<i>IRB_VER_NUM</i>/lib/irb"`,
+
+ where:
+
+ - <i>RUBY_DIR</i> is the Ruby installation dirpath.
+ - <i>RUBY_VER_NUM</i> is the Ruby version number.
+ - <i>IRB_VER_NUM</i> is the \IRB version number.
+
+- `:IRB_NAME`: {IRB name}[rdoc-ref:IRB@IRB+Name];
+ initial value: `'irb'`.
+- `:IRB_RC`: {Configuration monitor}[rdoc-ref:IRB@Configuration+Monitor];
+ initial value: `nil`.
+- `:LC_MESSAGES`: {Locale}[rdoc-ref:IRB@Locale];
+ initial value: IRB::Locale object.
+- `:LOAD_MODULES`: deprecated.
+- `:MAIN_CONTEXT`: The {context}[rdoc-ref:IRB@Session+Context] for the main \IRB session;
+ initial value: IRB::Context object.
+- `:MEASURE`: Whether to
+ {measure performance}[rdoc-ref:IRB@Performance+Measurement];
+ initial value: `false`.
+- `:MEASURE_CALLBACKS`: Callback methods for
+ {performance measurement}[rdoc-ref:IRB@Performance+Measurement];
+ initial value: `[]`.
+- `:MEASURE_PROC`: Procs for
+ {performance measurement}[rdoc-ref:IRB@Performance+Measurement];
+ initial value:
+
+ {
+ :TIME=>#<Proc:0x0000556e271c6598 /var/lib/gems/3.0.0/gems/irb-1.8.3/lib/irb/init.rb:106>,
+ :STACKPROF=>#<Proc:0x0000556e271c6548 /var/lib/gems/3.0.0/gems/irb-1.8.3/lib/irb/init.rb:116>
+ }
+
+- `:PROMPT`: \Hash of {defined prompts}[rdoc-ref:IRB@Prompt+and+Return+Formats];
+ initial value:
+
+ {
+ :NULL=>{:PROMPT_I=>nil, :PROMPT_S=>nil, :PROMPT_C=>nil, :RETURN=>"%s\n"},
+ :DEFAULT=>{:PROMPT_I=>"%N(%m):%03n> ", :PROMPT_S=>"%N(%m):%03n%l ", :PROMPT_C=>"%N(%m):%03n* ", :RETURN=>"=> %s\n"},
+ :CLASSIC=>{:PROMPT_I=>"%N(%m):%03n:%i> ", :PROMPT_S=>"%N(%m):%03n:%i%l ", :PROMPT_C=>"%N(%m):%03n:%i* ", :RETURN=>"%s\n"},
+ :SIMPLE=>{:PROMPT_I=>">> ", :PROMPT_S=>"%l> ", :PROMPT_C=>"?> ", :RETURN=>"=> %s\n"},
+ :INF_RUBY=>{:PROMPT_I=>"%N(%m):%03n> ", :PROMPT_S=>nil, :PROMPT_C=>nil, :RETURN=>"%s\n", :AUTO_INDENT=>true},
+ :XMP=>{:PROMPT_I=>nil, :PROMPT_S=>nil, :PROMPT_C=>nil, :RETURN=>" ==>%s\n"}
+ }
+
+- `:PROMPT_MODE`: Name of {current prompt}[rdoc-ref:IRB@Prompt+and+Return+Formats];
+ initial value: `:DEFAULT`.
+- `:RC`: Whether a {configuration file}[rdoc-ref:IRB@Configuration+File]
+ was found and interpreted;
+ initial value: `true` if a configuration file was found, `false` otherwise.
+- `:SAVE_HISTORY`: Number of commands to save in
+ {input command history}[rdoc-ref:IRB@Input+Command+History];
+ initial value: `1000`.
+- `:SINGLE_IRB`: Whether command-line option `--single-irb` was given;
+ initial value: `true` if the option was given, `false` otherwise.
+ See {Single-IRB Mode}[rdoc-ref:IRB@Single-IRB+Mode].
+- `:USE_AUTOCOMPLETE`: Whether to use
+ {automatic completion}[rdoc-ref:IRB@Automatic+Completion];
+ initial value: `true`.
+- `:USE_COLORIZE`: Whether to use
+ {color highlighting}[rdoc-ref:IRB@Color+Highlighting];
+ initial value: `true`.
+- `:USE_LOADER`: Whether to use the
+ {IRB loader}[rdoc-ref:IRB@IRB+Loader] for `require` and `load`;
+ initial value: `false`.
+- `:USE_TRACER`: Whether to use the
+ {IRB tracer}[rdoc-ref:IRB@Tracer];
+ initial value: `false`.
+- `:VERBOSE`: Whether to print {verbose output}[rdoc-ref:IRB@Verbosity];
+ initial value: `nil`.
+- `:__MAIN__`: The main \IRB object;
+ initial value: `main`.
diff --git a/doc/keywords.rdoc b/doc/keywords.rdoc
index cb1cff33f0..7c368205ef 100644
--- a/doc/keywords.rdoc
+++ b/doc/keywords.rdoc
@@ -1,4 +1,4 @@
-== Keywords
+= Keywords
The following keywords are used by Ruby.
diff --git a/doc/maintainers.md b/doc/maintainers.md
index 631371e178..dabbdc0cb6 100644
--- a/doc/maintainers.md
+++ b/doc/maintainers.md
@@ -1,5 +1,12 @@
# Maintainers
-This page describes the current module, library, and extension maintainers of Ruby.
+This page describes the current branch, module, library, and extension maintainers of Ruby.
+
+## Branch Maintainers
+
+A branch maintainer is responsible for backporting commits into stable branches
+and publishing Ruby patch releases.
+
+[The list of current branch maintainers is available in the wiki](https://github.com/ruby/ruby/wiki/Release-Engineering).
## Module Maintainers
A module maintainer is responsible for a certain part of Ruby.
@@ -72,15 +79,6 @@ have commit right, others don't.
## Default gems Maintainers
### Libraries
-#### lib/abbrev.rb
-* Akinori MUSHA (knu)
-* https://github.com/ruby/abbrev
-* https://rubygems.org/gems/abbrev
-
-#### lib/base64.rb
-* Yusuke Endoh (mame)
-* https://github.com/ruby/base64
-* https://rubygems.org/gems/base64
#### lib/benchmark.rb
* *unmaintained*
@@ -97,12 +95,6 @@ have commit right, others don't.
* https://github.com/ruby/cgi
* https://rubygems.org/gems/cgi
-#### lib/csv.rb
-* Kenta Murata (mrkn)
-* Kouhei Sutou (kou)
-* https://github.com/ruby/csv
-* https://rubygems.org/gems/csv
-
#### lib/English.rb
* *unmaintained*
* https://github.com/ruby/English
@@ -123,11 +115,6 @@ have commit right, others don't.
* https://github.com/ruby/digest
* https://rubygems.org/gems/digest
-#### lib/drb.rb, lib/drb/*
-* Masatoshi SEKI (seki)
-* https://github.com/ruby/drb
-* https://rubygems.org/gems/drb
-
#### lib/erb.rb
* Masatoshi SEKI (seki)
* Takashi Kokubun (k0kubun)
@@ -154,11 +141,6 @@ have commit right, others don't.
* https://github.com/ruby/forwardable
* https://rubygems.org/gems/forwardable
-#### lib/getoptlong.rb
-* *unmaintained*
-* https://github.com/ruby/getoptlong
-* https://rubygems.org/gems/getoptlong
-
#### lib/ipaddr.rb
* Akinori MUSHA (knu)
* https://github.com/ruby/ipaddr
@@ -181,11 +163,6 @@ have commit right, others don't.
* https://github.com/ruby/logger
* https://rubygems.org/gems/logger
-#### lib/mutex_m.rb
-* Keiju ISHITSUKA (keiju)
-* https://github.com/ruby/mutex_m
-* https://rubygems.org/gems/mutex_m
-
#### lib/net/http.rb, lib/net/https.rb
* NARUSE, Yui (naruse)
* https://github.com/ruby/net-http
@@ -196,11 +173,6 @@ have commit right, others don't.
* https://github.com/ruby/net-protocol
* https://rubygems.org/gems/net-protocol
-#### lib/observer.rb
-* *unmaintained*
-* https://github.com/ruby/observer
-* https://rubygems.org/gems/observer
-
#### lib/open3.rb
* *unmaintained*
* https://github.com/ruby/open3
@@ -246,11 +218,6 @@ have commit right, others don't.
* https://github.com/ruby/resolv
* https://rubygems.org/gems/resolv
-#### lib/resolv-replace.rb
-* Tanaka Akira (akr)
-* https://github.com/ruby/resolv-replace
-* https://rubygems.org/gems/resolv-replace
-
#### lib/rdoc.rb, lib/rdoc/*
* Eric Hodel (drbrain)
* Hiroshi SHIBATA (hsbt)
@@ -265,11 +232,6 @@ have commit right, others don't.
* https://github.com/ruby/reline
* https://rubygems.org/gems/reline
-#### lib/rinda/*
-* Masatoshi SEKI (seki)
-* https://github.com/ruby/rinda
-* https://rubygems.org/gems/rinda
-
#### lib/securerandom.rb
* Tanaka Akira (akr)
* https://github.com/ruby/securerandom
@@ -342,9 +304,6 @@ have commit right, others don't.
* https://rubygems.org/gems/weakref
### Extensions
-#### ext/bigdecimal
-* Kenta Murata (mrkn) https://github.com/ruby/bigdecimal
-* https://rubygems.org/gems/bigdecimal
#### ext/cgi
* Nobuyoshi Nakada (nobu)
@@ -392,11 +351,6 @@ have commit right, others don't.
* https://github.com/flori/json
* https://rubygems.org/gems/json
-#### ext/nkf
-* NARUSE, Yui (naruse)
-* https://github.com/ruby/nkf
-* https://rubygems.org/gems/nkf
-
#### ext/openssl
* Kazuki Yamaguchi (rhe)
* https://github.com/ruby/openssl
@@ -423,11 +377,6 @@ have commit right, others don't.
* https://github.com/ruby/strscan
* https://rubygems.org/gems/strscan
-#### ext/syslog
-* Akinori MUSHA (knu)
-* https://github.com/ruby/syslog
-* https://rubygems.org/gems/syslog
-
#### ext/win32ole
* Masaki Suketa (suke)
* https://github.com/ruby/win32ole
@@ -440,7 +389,7 @@ have commit right, others don't.
## Bundled gems upstream repositories
### minitest
-* https://github.com/seattlerb/minitest
+* https://github.com/minitest/minitest
### power_assert
* https://github.com/ruby/power_assert
@@ -487,6 +436,41 @@ have commit right, others don't.
### racc
* https://github.com/ruby/racc
+#### mutex_m
+* https://github.com/ruby/mutex_m
+
+#### getoptlong
+* https://github.com/ruby/getoptlong
+
+#### base64
+* https://github.com/ruby/base64
+
+#### bigdecimal
+* https://github.com/ruby/bigdecimal
+
+#### observer
+* https://github.com/ruby/observer
+
+#### abbrev
+* https://github.com/ruby/abbrev
+
+#### resolv-replace
+* https://github.com/ruby/resolv-replace
+
+#### rinda
+* https://github.com/ruby/rinda
+
+#### drb
+* https://github.com/ruby/drb
+
+#### nkf
+* https://github.com/ruby/nkf
+
+#### syslog
+* https://github.com/ruby/syslog
+
+#### csv
+* https://github.com/ruby/csv
## Platform Maintainers
### mswin64 (Microsoft Windows)
diff --git a/doc/optparse/option_params.rdoc b/doc/optparse/option_params.rdoc
index 55f9b53dff..35db8b5a55 100644
--- a/doc/optparse/option_params.rdoc
+++ b/doc/optparse/option_params.rdoc
@@ -31,7 +31,7 @@ Contents:
- {Long Names with Optional Arguments}[#label-Long+Names+with+Optional+Arguments]
- {Long Names with Negation}[#label-Long+Names+with+Negation]
- {Mixed Names}[#label-Mixed+Names]
-- {Argument Styles}[#label-Argument+Styles]
+- {Argument Strings}[#label-Argument+Strings]
- {Argument Values}[#label-Argument+Values]
- {Explicit Argument Values}[#label-Explicit+Argument+Values]
- {Explicit Values in Array}[#label-Explicit+Values+in+Array]
diff --git a/doc/optparse/ruby/argument_abbreviation.rb b/doc/optparse/ruby/argument_abbreviation.rb
new file mode 100644
index 0000000000..49007ebe69
--- /dev/null
+++ b/doc/optparse/ruby/argument_abbreviation.rb
@@ -0,0 +1,9 @@
+require 'optparse'
+parser = OptionParser.new
+parser.on('-x', '--xxx=VALUE', %w[ABC def], 'Argument abbreviations') do |value|
+ p ['--xxx', value]
+end
+parser.on('-y', '--yyy=VALUE', {"abc"=>"XYZ", def: "FOO"}, 'Argument abbreviations') do |value|
+ p ['--yyy', value]
+end
+parser.parse!
diff --git a/doc/optparse/tutorial.rdoc b/doc/optparse/tutorial.rdoc
index b104379cf7..6f56bbf92d 100644
--- a/doc/optparse/tutorial.rdoc
+++ b/doc/optparse/tutorial.rdoc
@@ -351,6 +351,29 @@ Executions:
Omitting an optional argument does not raise an error.
+==== Argument Abbreviations
+
+Specify an argument list as an Array or a Hash.
+
+ :include: ruby/argument_abbreviation.rb
+
+When an argument is abbreviated, the expanded argument yielded.
+
+Executions:
+
+ $ ruby argument_abbreviation.rb --help
+ Usage: argument_abbreviation [options]
+ Usage: argument_abbreviation [options]
+ -x, --xxx=VALUE Argument abbreviations
+ -y, --yyy=VALUE Argument abbreviations
+ $ ruby argument_abbreviation.rb --xxx A
+ ["--xxx", "ABC"]
+ $ ruby argument_abbreviation.rb --xxx c
+ argument_abbreviation.rb:9:in `<main>': invalid argument: --xxx c (OptionParser::InvalidArgument)
+ $ ruby argument_abbreviation.rb --yyy a --yyy d
+ ["--yyy", "XYZ"]
+ ["--yyy", "FOO"]
+
=== Argument Values
Permissible argument values may be restricted
diff --git a/doc/packed_data.rdoc b/doc/packed_data.rdoc
index bd71d13373..17bbf92023 100644
--- a/doc/packed_data.rdoc
+++ b/doc/packed_data.rdoc
@@ -1,4 +1,4 @@
-== Packed \Data
+= Packed \Data
Certain Ruby core methods deal with packing and unpacking data:
@@ -64,7 +64,7 @@ If elements don't fit the provided directive, only least significant bits are en
[257].pack("C").unpack("C") # => [1]
-=== Packing \Method
+== Packing \Method
\Method Array#pack accepts optional keyword argument
+buffer+ that specifies the target string (instead of a new string):
@@ -76,7 +76,7 @@ The method can accept a block:
# Packed string is passed to the block.
[65, 66].pack('C*') {|s| p s } # => "AB"
-=== Unpacking Methods
+== Unpacking Methods
Methods String#unpack and String#unpack1 each accept
an optional keyword argument +offset+ that specifies an offset
@@ -95,12 +95,12 @@ Both methods can accept a block:
# The single unpacked object is passed to the block.
'AB'.unpack1('C*') {|ele| p ele } # => 65
-=== \Integer Directives
+== \Integer Directives
Each integer directive specifies the packing or unpacking
for one element in the input or output array.
-==== 8-Bit \Integer Directives
+=== 8-Bit \Integer Directives
- <tt>'c'</tt> - 8-bit signed integer
(like C <tt>signed char</tt>):
@@ -116,7 +116,7 @@ for one element in the input or output array.
s = [0, 1, -1].pack('C*') # => "\x00\x01\xFF"
s.unpack('C*') # => [0, 1, 255]
-==== 16-Bit \Integer Directives
+=== 16-Bit \Integer Directives
- <tt>'s'</tt> - 16-bit signed integer, native-endian
(like C <tt>int16_t</tt>):
@@ -146,7 +146,7 @@ for one element in the input or output array.
s.unpack('v*')
# => [0, 1, 65535, 32767, 32768, 65535]
-==== 32-Bit \Integer Directives
+=== 32-Bit \Integer Directives
- <tt>'l'</tt> - 32-bit signed integer, native-endian
(like C <tt>int32_t</tt>):
@@ -178,7 +178,7 @@ for one element in the input or output array.
s.unpack('v*')
# => [0, 0, 1, 0, 65535, 65535]
-==== 64-Bit \Integer Directives
+=== 64-Bit \Integer Directives
- <tt>'q'</tt> - 64-bit signed integer, native-endian
(like C <tt>int64_t</tt>):
@@ -196,7 +196,7 @@ for one element in the input or output array.
s.unpack('Q*')
# => [578437695752307201, 17940646550795321087]
-==== Platform-Dependent \Integer Directives
+=== Platform-Dependent \Integer Directives
- <tt>'i'</tt> - Platform-dependent width signed integer,
native-endian (like C <tt>int</tt>):
@@ -230,7 +230,7 @@ for one element in the input or output array.
s.unpack('J*')
# => [67305985, 4244504319]
-==== Other \Integer Directives
+=== Other \Integer Directives
- <tt>'U'</tt> - UTF-8 character:
@@ -240,14 +240,14 @@ for one element in the input or output array.
# => [4194304]
- <tt>'w'</tt> - BER-encoded integer
- (see {BER enocding}[https://en.wikipedia.org/wiki/X.690#BER_encoding]):
+ (see {BER encoding}[https://en.wikipedia.org/wiki/X.690#BER_encoding]):
s = [1073741823].pack('w*')
# => "\x83\xFF\xFF\xFF\x7F"
s.unpack('w*')
# => [1073741823]
-==== Modifiers for \Integer Directives
+=== Modifiers for \Integer Directives
For the following directives, <tt>'!'</tt> or <tt>'_'</tt> modifiers may be
suffixed as underlying platform’s native size.
@@ -265,12 +265,12 @@ The endian modifiers also may be suffixed in the directives above:
- <tt>'>'</tt> - Big-endian.
- <tt>'<'</tt> - Little-endian.
-=== \Float Directives
+== \Float Directives
Each float directive specifies the packing or unpacking
for one element in the input or output array.
-==== Single-Precision \Float Directives
+=== Single-Precision \Float Directives
- <tt>'F'</tt> or <tt>'f'</tt> - Native format:
@@ -287,7 +287,7 @@ for one element in the input or output array.
s = [3.0].pack('g') # => "@@\x00\x00"
s.unpack('g') # => [3.0]
-==== Double-Precision \Float Directives
+=== Double-Precision \Float Directives
- <tt>'D'</tt> or <tt>'d'</tt> - Native format:
@@ -314,12 +314,12 @@ A float directive may be infinity or not-a-number:
[nan].pack('f') # => "\x00\x00\xC0\x7F"
"\x00\x00\xC0\x7F".unpack('f') # => [NaN]
-=== \String Directives
+== \String Directives
Each string directive specifies the packing or unpacking
for one byte in the input or output string.
-==== Binary \String Directives
+=== Binary \String Directives
- <tt>'A'</tt> - Arbitrary binary string (space padded; count is width);
+nil+ is treated as the empty string:
@@ -377,7 +377,7 @@ for one byte in the input or output string.
"foo".unpack('Z*') # => ["foo"]
"foo\0bar".unpack('Z*') # => ["foo"] # Does not read past "\0".
-==== Bit \String Directives
+=== Bit \String Directives
- <tt>'B'</tt> - Bit string (high byte first):
@@ -421,7 +421,7 @@ for one byte in the input or output string.
"\x01".unpack("b2") # => ["10"]
"\x01".unpack("b3") # => ["100"]
-==== Hex \String Directives
+=== Hex \String Directives
- <tt>'H'</tt> - Hex string (high nibble first):
@@ -467,7 +467,7 @@ for one byte in the input or output string.
"\x01\xfe".unpack('h4') # => ["10ef"]
"\x01\xfe".unpack('h5') # => ["10ef"]
-==== Pointer \String Directives
+=== Pointer \String Directives
- <tt>'P'</tt> - Pointer to a structure (fixed-length string):
@@ -485,7 +485,7 @@ for one byte in the input or output string.
("\0" * 8).unpack("p") # => [nil]
[nil].pack("p") # => "\x00\x00\x00\x00\x00\x00\x00\x00"
-==== Other \String Directives
+=== Other \String Directives
- <tt>'M'</tt> - Quoted printable, MIME encoding;
text mode, but input must use LF and output LF;
@@ -554,12 +554,14 @@ for one byte in the input or output string.
- <tt>'u'</tt> - UU-encoded string:
- [0].pack("U") # => "\u0000"
- [0x3fffffff].pack("U") # => "\xFC\xBF\xBF\xBF\xBF\xBF"
- [0x40000000].pack("U") # => "\xFD\x80\x80\x80\x80\x80"
- [0x7fffffff].pack("U") # => "\xFD\xBF\xBF\xBF\xBF\xBF"
+ [""].pack("u") # => ""
+ ["a"].pack("u") # => "!80``\n"
+ ["aaa"].pack("u") # => "#86%A\n"
-=== Offset Directives
+ "".unpack("u") # => [""]
+ "#86)C\n".unpack("u") # => ["abc"]
+
+== Offset Directives
- <tt>'@'</tt> - Begin packing at the given byte offset;
for packing, null fill if necessary:
@@ -577,7 +579,7 @@ for one byte in the input or output string.
[0, 1, 2].pack("CCX2C") # => "\x02"
"\x00\x02".unpack("CCXC") # => [0, 2, 2]
-=== Null Byte Direcive
+== Null Byte Directive
- <tt>'x'</tt> - Null byte:
diff --git a/doc/pty/README.expect.ja b/doc/pty/README.expect.ja
index 7c0456f24f..a4eb6b01df 100644
--- a/doc/pty/README.expect.ja
+++ b/doc/pty/README.expect.ja
@@ -1,21 +1,23 @@
- README for expect
+= README for expect
by A. Ito, 28 October, 1998
- Expectライブラリã¯ï¼Œtcl ã® expect パッケージã¨ä¼¼ãŸã‚ˆã†ãªæ©Ÿèƒ½ã‚’
+Expectライブラリã¯ï¼Œtcl ã® expect パッケージã¨ä¼¼ãŸã‚ˆã†ãªæ©Ÿèƒ½ã‚’
IOクラスã«è¿½åŠ ã—ã¾ã™ï¼Ž
- 追加ã•ã‚Œã‚‹ãƒ¡ã‚½ãƒƒãƒ‰ã®ä½¿ã„æ–¹ã¯æ¬¡ã®é€šã‚Šã§ã™ï¼Ž
+追加ã•ã‚Œã‚‹ãƒ¡ã‚½ãƒƒãƒ‰ã®ä½¿ã„æ–¹ã¯æ¬¡ã®é€šã‚Šã§ã™ï¼Ž
- IO#expect(pattern,timeout=9999999)
+[IO#expect(pattern,timeout=9999999)]
-pattern 㯠String ã‹ Regexp ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ï¼Œtimeout 㯠Fixnum
-ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã§ã™ï¼Žtimeout ã¯çœç•¥ã§ãã¾ã™ï¼Ž
- ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ãŒãƒ–ロックãªã—ã§å‘¼ã°ã‚ŒãŸå ´åˆï¼Œã¾ãšãƒ¬ã‚·ãƒ¼ãƒã§ã‚ã‚‹
-IOオブジェクトã‹ã‚‰ pattern ã«ãƒžãƒƒãƒã™ã‚‹ãƒ‘ターンãŒèª­ã¿ã“ã¾ã‚Œã‚‹
-ã¾ã§å¾…ã¡ã¾ã™ï¼Žãƒ‘ターンãŒå¾—られãŸã‚‰ï¼Œãã®ãƒ‘ターンã«é–¢ã™ã‚‹é…列を
-è¿”ã—ã¾ã™ï¼Žé…列ã®æœ€åˆã®è¦ç´ ã¯ï¼Œpattern ã«ãƒžãƒƒãƒã™ã‚‹ã¾ã§ã«èª­ã¿ã“
-ã¾ã‚ŒãŸå†…容ã®æ–‡å­—列ã§ã™ï¼Ž2番目以é™ã®è¦ç´ ã¯ï¼Œpattern ã®æ­£è¦è¡¨ç¾
-ã®ä¸­ã«ã‚¢ãƒ³ã‚«ãƒ¼ãŒã‚ã£ãŸå ´åˆã«ï¼Œãã®ã‚¢ãƒ³ã‚«ãƒ¼ã«ãƒžãƒƒãƒã™ã‚‹éƒ¨åˆ†ã§ã™ï¼Ž
-ã‚‚ã—タイムアウトãŒèµ·ããŸå ´åˆã¯ï¼Œã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ã¯nilã‚’è¿”ã—ã¾ã™ï¼Ž
- ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ãŒãƒ–ロック付ãã§å‘¼ã°ã‚ŒãŸå ´åˆã«ã¯ï¼Œãƒžãƒƒãƒã—ãŸè¦ç´ ã®
-é…列ãŒãƒ–ロック引数ã¨ã—ã¦æ¸¡ã•ã‚Œï¼Œãƒ–ロックãŒè©•ä¾¡ã•ã‚Œã¾ã™ï¼Ž
+ _pattern_ 㯠String ã‹ Regexp ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ï¼Œ_timeout_ 㯠Fixnum
+ ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã§ã™ï¼Ž_timeout_ ã¯çœç•¥ã§ãã¾ã™ï¼Ž
+
+ ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ãŒãƒ–ロックãªã—ã§å‘¼ã°ã‚ŒãŸå ´åˆï¼Œã¾ãšãƒ¬ã‚·ãƒ¼ãƒã§ã‚ã‚‹
+ IOオブジェクトã‹ã‚‰ _pattern_ ã«ãƒžãƒƒãƒã™ã‚‹ãƒ‘ターンãŒèª­ã¿ã“ã¾ã‚Œã‚‹
+ ã¾ã§å¾…ã¡ã¾ã™ï¼Žãƒ‘ターンãŒå¾—られãŸã‚‰ï¼Œãã®ãƒ‘ターンã«é–¢ã™ã‚‹é…列を
+ è¿”ã—ã¾ã™ï¼Žé…列ã®æœ€åˆã®è¦ç´ ã¯ï¼Œ_pattern_ ã«ãƒžãƒƒãƒã™ã‚‹ã¾ã§ã«èª­ã¿ã“
+ ã¾ã‚ŒãŸå†…容ã®æ–‡å­—列ã§ã™ï¼Ž2番目以é™ã®è¦ç´ ã¯ï¼Œ_pattern_ ã®æ­£è¦è¡¨ç¾
+ ã®ä¸­ã«ã‚¢ãƒ³ã‚«ãƒ¼ãŒã‚ã£ãŸå ´åˆã«ï¼Œãã®ã‚¢ãƒ³ã‚«ãƒ¼ã«ãƒžãƒƒãƒã™ã‚‹éƒ¨åˆ†ã§ã™ï¼Ž
+ ã‚‚ã—タイムアウトãŒèµ·ããŸå ´åˆã¯ï¼Œã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ã¯ +nil+ ã‚’è¿”ã—ã¾ã™ï¼Ž
+
+ ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ãŒãƒ–ロック付ãã§å‘¼ã°ã‚ŒãŸå ´åˆã«ã¯ï¼Œãƒžãƒƒãƒã—ãŸè¦ç´ ã®
+ é…列ãŒãƒ–ロック引数ã¨ã—ã¦æ¸¡ã•ã‚Œï¼Œãƒ–ロックãŒè©•ä¾¡ã•ã‚Œã¾ã™ï¼Ž
diff --git a/doc/pty/README.ja b/doc/pty/README.ja
index 2d83ffa033..a26b4932ff 100644
--- a/doc/pty/README.ja
+++ b/doc/pty/README.ja
@@ -1,27 +1,26 @@
-pty 拡張モジュール version 0.3 by A.ito
+= pty 拡張モジュール version 0.3 by A.ito
1. ã¯ã˜ã‚ã«
-ã“ã®æ‹¡å¼µãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã¯ï¼Œä»®æƒ³tty (pty) を通ã—ã¦é©å½“ãªã‚³ãƒžãƒ³ãƒ‰ã‚’
-実行ã™ã‚‹æ©Ÿèƒ½ã‚’ ruby ã«æä¾›ã—ã¾ã™ï¼Ž
+ ã“ã®æ‹¡å¼µãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã¯ï¼Œä»®æƒ³tty (pty) を通ã—ã¦é©å½“ãªã‚³ãƒžãƒ³ãƒ‰ã‚’
+ 実行ã™ã‚‹æ©Ÿèƒ½ã‚’ ruby ã«æä¾›ã—ã¾ã™ï¼Ž
2. インストール
-次ã®ã‚ˆã†ã«ã—ã¦ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¦ãã ã•ã„.
+ 次ã®ã‚ˆã†ã«ã—ã¦ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¦ãã ã•ã„.
-(1) ruby extconf.rb
+ 1. <tt>ruby extconf.rb</tt>
+ を実行ã™ã‚‹ã¨ Makefile ãŒç”Ÿæˆã•ã‚Œã¾ã™ï¼Ž
- を実行ã™ã‚‹ã¨ Makefile ãŒç”Ÿæˆã•ã‚Œã¾ã™ï¼Ž
-
-(2) make; make install を実行ã—ã¦ãã ã•ã„.
+ 2. <tt>make; make install</tt> を実行ã—ã¦ãã ã•ã„.
3. 何ãŒã§ãã‚‹ã‹
-ã“ã®æ‹¡å¼µãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã¯ï¼ŒPTY ã¨ã„ã†ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‚’定義ã—ã¾ã™ï¼Žãã®ä¸­
-ã«ã¯ï¼Œæ¬¡ã®ã‚ˆã†ãªãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«é–¢æ•°ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ï¼Ž
+ ã“ã®æ‹¡å¼µãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã¯ï¼ŒPTY ã¨ã„ã†ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‚’定義ã—ã¾ã™ï¼Žãã®ä¸­
+ ã«ã¯ï¼Œæ¬¡ã®ã‚ˆã†ãªãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«é–¢æ•°ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ï¼Ž
- getpty(command)
- spawn(command)
+ [PTY.getpty(command)]
+ [PTY.spawn(command)]
ã“ã®é–¢æ•°ã¯ï¼Œä»®æƒ³ttyを確ä¿ã—,指定ã•ã‚ŒãŸã‚³ãƒžãƒ³ãƒ‰ã‚’ãã®ä»®æƒ³tty
ã®å‘ã“ã†ã§å®Ÿè¡Œã—,é…列を返ã—ã¾ã™ï¼Žæˆ»ã‚Šå€¤ã¯3ã¤ã®è¦ç´ ã‹ã‚‰ãªã‚‹
@@ -35,12 +34,7 @@ pty 拡張モジュール version 0.3 by A.ito
ã®ã¿ä¾‹å¤–ãŒç™ºç”Ÿã—ã¾ã™ï¼Žå­ãƒ—ロセスをモニターã—ã¦ã„るスレッドã¯ãƒ–ロッ
クを抜ã‘ã‚‹ã¨ãã«çµ‚了ã—ã¾ã™ï¼Ž
- protect_signal
- reset_signal
-
- 廃止予定ã§ã™ï¼Ž
-
- PTY.open
+ [PTY.open]
仮想ttyを確ä¿ã—,マスターå´ã«å¯¾å¿œã™ã‚‹IOオブジェクトã¨ã‚¹ãƒ¬ãƒ¼ãƒ–å´ã«
対応ã™ã‚‹Fileオブジェクトã®é…列を返ã—ã¾ã™ï¼Žãƒ–ロック付ãã§å‘¼ã³å‡ºã•
@@ -48,7 +42,7 @@ pty 拡張モジュール version 0.3 by A.ito
クã‹ã‚‰è¿”ã•ã‚ŒãŸçµæžœã‚’è¿”ã—ã¾ã™ï¼Žã¾ãŸã€ã“ã®ãƒžã‚¹ã‚¿ãƒ¼IOã¨ã‚¹ãƒ¬ãƒ¼ãƒ–File
ã¯ã€ãƒ–ロックを抜ã‘ã‚‹ã¨ãã«ã‚¯ãƒ­ãƒ¼ã‚ºæ¸ˆã¿ã§ãªã‘ã‚Œã°ã‚¯ãƒ­ãƒ¼ã‚ºã•ã‚Œã¾ã™ï¼Ž
- PTY.check(pid[, raise=false])
+ [PTY.check(pid[, raise=false])]
pidã§æŒ‡å®šã•ã‚ŒãŸå­ãƒ—ロセスã®çŠ¶æ…‹ã‚’ãƒã‚§ãƒƒã‚¯ã—,実行中ã§ã‚ã‚Œã°nilã‚’
è¿”ã—ã¾ã™ï¼Žçµ‚了ã—ã¦ã„ã‚‹ã‹åœæ­¢ã—ã¦ã„ã‚‹å ´åˆã€ç¬¬äºŒå¼•æ•°ãŒå½ã§ã‚ã‚Œã°ã€
@@ -57,20 +51,20 @@ pty 拡張モジュール version 0.3 by A.ito
4. 利用ã«ã¤ã„ã¦
-伊藤彰則ãŒè‘—作権をä¿æœ‰ã—ã¾ã™ï¼Ž
+ 伊藤彰則ãŒè‘—作権をä¿æœ‰ã—ã¾ã™ï¼Ž
-ソースプログラムã¾ãŸã¯ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã«å…ƒã®è‘—作権表示ãŒæ”¹å¤‰ã•ã‚Œãšã«
-表示ã•ã‚Œã¦ã„ã‚‹å ´åˆã«é™ã‚Šï¼Œèª°ã§ã‚‚,ã“ã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã‚’ç„¡å„Ÿã‹ã¤è‘—作
-権者ã«ç„¡æ–­ã§åˆ©ç”¨ãƒ»é…布・改変ã§ãã¾ã™ï¼Žåˆ©ç”¨ç›®çš„ã¯é™å®šã•ã‚Œã¦ã„ã¾ã›
-ん.
+ ソースプログラムã¾ãŸã¯ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã«å…ƒã®è‘—作権表示ãŒæ”¹å¤‰ã•ã‚Œãšã«
+ 表示ã•ã‚Œã¦ã„ã‚‹å ´åˆã«é™ã‚Šï¼Œèª°ã§ã‚‚,ã“ã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã‚’ç„¡å„Ÿã‹ã¤è‘—作
+ 権者ã«ç„¡æ–­ã§åˆ©ç”¨ãƒ»é…布・改変ã§ãã¾ã™ï¼Žåˆ©ç”¨ç›®çš„ã¯é™å®šã•ã‚Œã¦ã„ã¾ã›
+ ん.
-ã“ã®ãƒ—ログラムã®åˆ©ç”¨ãƒ»é…布ãã®ä»–ã“ã®ãƒ—ログラムã«é–¢ä¿‚ã™ã‚‹è¡Œç‚ºã«ã‚ˆ
-ã£ã¦ç”Ÿã˜ãŸã„ã‹ãªã‚‹æ害ã«å¯¾ã—ã¦ã‚‚,作者ã¯ä¸€åˆ‡è²¬ä»»ã‚’è² ã„ã¾ã›ã‚“.
+ ã“ã®ãƒ—ログラムã®åˆ©ç”¨ãƒ»é…布ãã®ä»–ã“ã®ãƒ—ログラムã«é–¢ä¿‚ã™ã‚‹è¡Œç‚ºã«ã‚ˆ
+ ã£ã¦ç”Ÿã˜ãŸã„ã‹ãªã‚‹æ害ã«å¯¾ã—ã¦ã‚‚,作者ã¯ä¸€åˆ‡è²¬ä»»ã‚’è² ã„ã¾ã›ã‚“.
5. ãƒã‚°å ±å‘Šç­‰
-ãƒã‚°ãƒ¬ãƒãƒ¼ãƒˆã¯æ­“è¿Žã—ã¾ã™ï¼Ž
+ ãƒã‚°ãƒ¬ãƒãƒ¼ãƒˆã¯æ­“è¿Žã—ã¾ã™ï¼Ž
aito@ei5sun.yz.yamagata-u.ac.jp
-ã¾ã§é›»å­ãƒ¡ãƒ¼ãƒ«ã§ãƒã‚°ãƒ¬ãƒãƒ¼ãƒˆã‚’ãŠé€ã‚Šãã ã•ã„.
+ ã¾ã§é›»å­ãƒ¡ãƒ¼ãƒ«ã§ãƒã‚°ãƒ¬ãƒãƒ¼ãƒˆã‚’ãŠé€ã‚Šãã ã•ã„.
diff --git a/doc/ractor.md b/doc/ractor.md
index 3ead510501..7a69e839de 100644
--- a/doc/ractor.md
+++ b/doc/ractor.md
@@ -204,8 +204,8 @@ For message sending and receiving, there are two types of APIs: push type and pu
* When a Ractor is terminated, the Ractor's ports are closed.
* There are 3 ways to send an object as a message
* (1) Send a reference: Sending a shareable object, send only a reference to the object (fast)
- * (2) Copy an object: Sending an unshareable object by copying an object deeply (slow). Note that you can not send an object which does not support deep copy. Some `T_DATA` objects are not supported.
- * (3) Move an object: Sending an unshareable object reference with a membership. Sender Ractor can not access moved objects anymore (raise an exception) after moving it. Current implementation makes new object as a moved object for receiver Ractor and copies references of sending object to moved object.
+ * (2) Copy an object: Sending an unshareable object by copying an object deeply (slow). Note that you can not send an object which does not support deep copy. Some `T_DATA` objects (objects whose class is defined in a C extension, such as `StringIO`) are not supported.
+ * (3) Move an object: Sending an unshareable object reference with a membership. Sender Ractor can not access moved objects anymore (raise an exception) after moving it. Current implementation makes new object as a moved object for receiver Ractor and copies references of sending object to moved object. `T_DATA` objects are not supported.
* You can choose "Copy" and "Move" by the `move:` keyword, `Ractor#send(obj, move: true/false)` and `Ractor.yield(obj, move: true/false)` (default is `false` (COPY)).
### Sending/Receiving ports
diff --git a/doc/rdoc/markup_reference.rb b/doc/rdoc/markup_reference.rb
index dac5c84708..bfc84abd5a 100644
--- a/doc/rdoc/markup_reference.rb
+++ b/doc/rdoc/markup_reference.rb
@@ -7,72 +7,61 @@ require 'rdoc'
# attributes, and constants -- are solely for illustrating \RDoc markup,
# and have no other legitimate use.
#
-# = \RDoc Markup Reference
-#
-# Notes:
+# == About the Examples
#
# - Examples in this reference are Ruby code and comments;
# certain differences from other sources
# (such as C code and comments) are noted.
+# - Almost all examples on this page are all RDoc-like;
+# that is, they have no explicit comment markers like Ruby <tt>#</tt>
+# or C <tt>/* ... */</tt>.
# - An example that shows rendered HTML output
# displays that output in a blockquote:
#
-# Rendered HTML:
# >>>
# Some stuff
#
-# \RDoc-generated documentation is derived from and controlled by:
-#
-# - Single-line or multi-line comments that precede certain definitions;
-# see {Markup in Comments}[rdoc-ref:RDoc::MarkupReference@Markup+in+Comments].
-# - \RDoc directives in trailing comments (on the same line as code);
-# see <tt>:nodoc:</tt>, <tt>:doc:</tt>, and <tt>:notnew:</tt>.
-# - \RDoc directives in single-line comments;
-# see other {Directives}[rdoc-ref:RDoc::MarkupReference@Directives].
-# - The Ruby code itself (but not from C code);
-# see {Documentation Derived from Ruby Code}[rdoc-ref:RDoc::MarkupReference@Documentation+Derived+from+Ruby+Code].
-#
-# == Markup in Comments
-#
-# The treatment of markup in comments varies according to the type of file:
-#
-# - <tt>.rb</tt> (Ruby code file): markup is parsed from Ruby comments.
-# - <tt>.c</tt> (C code file): markup is parsed from C comments.
-# - <tt>.rdoc</tt> (RDoc text file): markup is parsed from the entire file.
-#
-# The comment associated with
-# a Ruby class, module, method, alias, constant, or attribute
-# becomes the documentation for that defined object:
-#
-# - In a Ruby file, that comment immediately precedes
-# the definition of the object.
-# - In a C file, that comment immediately precedes
-# the function that implements a method,
-# or otherwise immediately precedes the definition of the object.
+# == \RDoc Sources
#
-# In either a Ruby or a C file,
-# \RDoc ignores comments that do not precede object definitions.
+# The sources of \RDoc documentation vary according to the type of file:
#
-# In an \RDoc file, the text is not associated with any code object,
-# but may (depending on how the documentation is built),
-# become a separate page.
+# - <tt>.rb</tt> (Ruby code file):
#
-# Almost all examples on this page are all RDoc-like;
-# that is, they have no comment markers like Ruby <tt>#</tt>
-# or C <tt>/* ... */</tt>.
+# - Markup may be found in Ruby comments:
+# A comment that immediately precedes the definition
+# of a Ruby class, module, method, alias, constant, or attribute
+# becomes the documentation for that defined object.
+# - An \RDoc directive may be found in:
#
-# === Margins
+# - A trailing comment (on the same line as code);
+# see <tt>:nodoc:</tt>, <tt>:doc:</tt>, and <tt>:notnew:</tt>.
+# - A single-line comment;
+# see other {Directives}[rdoc-ref:RDoc::MarkupReference@Directives].
#
-# In a multi-line comment,
-# \RDoc looks for the comment's natural left margin,
-# which becomes the <em>base margin</em> for the comment
-# and is the initial <em>current margin</em> for the comment.
+# - Documentation may be derived from the Ruby code itself;
+# see {Documentation Derived from Ruby Code}[rdoc-ref:RDoc::MarkupReference@Documentation+Derived+from+Ruby+Code].
#
-# The current margin can change, and does so, for example in a list.
+# - <tt>.c</tt> (C code file): markup is parsed from C comments.
+# A comment that immediately precedes
+# a function that implements a Ruby method,
+# or otherwise immediately precedes the definition of a Ruby object,
+# becomes the documentation for that object.
+# - <tt>.rdoc</tt> (\RDoc markup text file) or <tt>.md</tt> (\RDoc markdown text file):
+# markup is parsed from the entire file.
+# The text is not associated with any code object,
+# but may (depending on how the documentation is built)
+# become a separate page.
+#
+# An <i>RDoc document</i>:
+#
+# - A (possibly multi-line) comment in a Ruby or C file
+# that generates \RDoc documentation (as above).
+# - The entire markup (<tt>.rdoc</tt>) file or markdown (<tt>.md</tt>) file
+# (which is usually multi-line).
#
# === Blocks
#
-# It's convenient to think of \RDoc markup input as a sequence of _blocks_
+# It's convenient to think of an \RDoc document as a sequence of _blocks_
# of various types (details at the links):
#
# - {Paragraph}[rdoc-ref:RDoc::MarkupReference@Paragraphs]:
@@ -88,7 +77,7 @@ require 'rdoc'
# - {List}[rdoc-ref:RDoc::MarkupReference@Lists]: items for
# a bullet list, numbered list, lettered list, or labeled list.
# - {Heading}[rdoc-ref:RDoc::MarkupReference@Headings]:
-# a section heading.
+# a heading.
# - {Horizontal rule}[rdoc-ref:RDoc::MarkupReference@Horizontal+Rules]:
# a line across the rendered page.
# - {Directive}[rdoc-ref:RDoc::MarkupReference@Directives]:
@@ -103,6 +92,10 @@ require 'rdoc'
# - Any block may appear independently
# (that is, not nested in another block);
# some blocks may be nested, as detailed below.
+# - In a multi-line block,
+# \RDoc looks for the block's natural left margin,
+# which becomes the <em>base margin</em> for the block
+# and is the initial <em>current margin</em> for the block.
#
# ==== Paragraphs
#
@@ -467,8 +460,32 @@ require 'rdoc'
#
# - Appended to a line of code
# that defines a class, module, method, alias, constant, or attribute.
+#
# - Specifies that the defined object should not be documented.
#
+# - For a method definition in C code, it the directive must be in the comment line
+# immediately preceding the definition:
+#
+# /* :nodoc: */
+# static VALUE
+# some_method(VALUE self)
+# {
+# return self;
+# }
+#
+# Note that this directive has <em>no effect at all</em>
+# when placed at the method declaration:
+#
+# /* :nodoc: */
+# rb_define_method(cMyClass, "do_something", something_func, 0);
+#
+# The above comment is just a comment and has nothing to do with \RDoc.
+# Therefore, +do_something+ method will be reported as "undocumented"
+# unless that method or function is documented elsewhere.
+#
+# - For a constant definition in C code, this directive <em>can not work</em>
+# because there is no "implementation" place for a constant.
+#
# - <tt># :nodoc: all</tt>:
#
# - Appended to a line of code
@@ -480,7 +497,7 @@ require 'rdoc'
#
# - Appended to a line of code
# that defines a class, module, method, alias, constant, or attribute.
-# - Specifies the defined object should be documented, even if otherwise
+# - Specifies the defined object should be documented, even if it otherwise
# would not be documented.
#
# - <tt># :notnew:</tt> (aliased as <tt>:not_new:</tt> and <tt>:not-new:</tt>):
@@ -502,8 +519,8 @@ require 'rdoc'
# #++
# # Documented.
#
-# For C code, any of directives <tt>:startdoc:</tt>, <tt>:enddoc:</tt>,
-# and <tt>:nodoc:</tt> may appear in a stand-alone comment:
+# For C code, any of directives <tt>:startdoc:</tt>, <tt>:stopdoc:</tt>,
+# and <tt>:enddoc:</tt> may appear in a stand-alone comment:
#
# /* :startdoc: */
# /* :stopdoc: */
@@ -624,9 +641,9 @@ require 'rdoc'
# The file content is shifted to have the same indentation as the colon
# at the start of the directive.
#
-# The file is searched for in the directories
-# given with the <tt>--include</tt> command-line option,
-# or by default in the current directory.
+# The file is searched for in the directory containing the current file,
+# and then in each of the directories given with the <tt>--include</tt>
+# command-line option.
#
# For C code, the directive may appear in a stand-alone comment
#
@@ -1192,13 +1209,26 @@ require 'rdoc'
#
class RDoc::MarkupReference
+ # Example class.
class DummyClass; end
+
+ # Example module.
module DummyModule; end
+
+ # Example singleton method.
def self.dummy_singleton_method(foo, bar); end
+
+ # Example instance method.
def dummy_instance_method(foo, bar); end;
+
alias dummy_instance_alias dummy_instance_method
+
+ # Example attribute.
attr_accessor :dummy_attribute
+
alias dummy_attribute_alias dummy_attribute
+
+ # Example constant.
DUMMY_CONSTANT = ''
# :call-seq:
diff --git a/doc/regexp.rdoc b/doc/regexp.rdoc
deleted file mode 100644
index 309e109afd..0000000000
--- a/doc/regexp.rdoc
+++ /dev/null
@@ -1,1269 +0,0 @@
-A {regular expression}[https://en.wikipedia.org/wiki/Regular_expression]
-(also called a _regexp_) is a <i>match pattern</i> (also simply called a _pattern_).
-
-A common notation for a regexp uses enclosing slash characters:
-
- /foo/
-
-A regexp may be applied to a <i>target string</i>;
-The part of the string (if any) that matches the pattern is called a _match_,
-and may be said <i>to match</i>:
-
- re = /red/
- re.match?('redirect') # => true # Match at beginning of target.
- re.match?('bored') # => true # Match at end of target.
- re.match?('credit') # => true # Match within target.
- re.match?('foo') # => false # No match.
-
-== \Regexp Uses
-
-A regexp may be used:
-
-- To extract substrings based on a given pattern:
-
- re = /foo/ # => /foo/
- re.match('food') # => #<MatchData "foo">
- re.match('good') # => nil
-
- See sections {Method match}[rdoc-ref:regexp.rdoc@Method+match]
- and {Operator =~}[rdoc-ref:regexp.rdoc@Operator+-3D~].
-
-- To determine whether a string matches a given pattern:
-
- re.match?('food') # => true
- re.match?('good') # => false
-
- See section {Method match?}[rdoc-ref:regexp.rdoc@Method+match-3F].
-
-- As an argument for calls to certain methods in other classes and modules;
- most such methods accept an argument that may be either a string
- or the (much more powerful) regexp.
-
- See {Regexp Methods}[./Regexp/methods_rdoc.html].
-
-== \Regexp Objects
-
-A regexp object has:
-
-- A source; see {Sources}[rdoc-ref:regexp.rdoc@Sources].
-
-- Several modes; see {Modes}[rdoc-ref:regexp.rdoc@Modes].
-
-- A timeout; see {Timeouts}[rdoc-ref:regexp.rdoc@Timeouts].
-
-- An encoding; see {Encodings}[rdoc-ref:regexp.rdoc@Encodings].
-
-== Creating a \Regexp
-
-A regular expression may be created with:
-
-- A regexp literal using slash characters
- (see {Regexp Literals}[https://docs.ruby-lang.org/en/master/syntax/literals_rdoc.html#label-Regexp+Literals]):
-
- # This is a very common usage.
- /foo/ # => /foo/
-
-- A <tt>%r</tt> regexp literal
- (see {%r: Regexp Literals}[https://docs.ruby-lang.org/en/master/syntax/literals_rdoc.html#label-25r-3A+Regexp+Literals]):
-
- # Same delimiter character at beginning and end;
- # useful for avoiding escaping characters
- %r/name\/value pair/ # => /name\/value pair/
- %r:name/value pair: # => /name\/value pair/
- %r|name/value pair| # => /name\/value pair/
-
- # Certain "paired" characters can be delimiters.
- %r[foo] # => /foo/
- %r{foo} # => /foo/
- %r(foo) # => /foo/
- %r<foo> # => /foo/
-
-- \Method Regexp.new.
-
-== \Method <tt>match</tt>
-
-Each of the methods Regexp#match, String#match, and Symbol#match
-returns a MatchData object if a match was found, +nil+ otherwise;
-each also sets {global variables}[rdoc-ref:regexp.rdoc@Global+Variables]:
-
- 'food'.match(/foo/) # => #<MatchData "foo">
- 'food'.match(/bar/) # => nil
-
-== Operator <tt>=~</tt>
-
-Each of the operators Regexp#=~, String#=~, and Symbol#=~
-returns an integer offset if a match was found, +nil+ otherwise;
-each also sets {global variables}[rdoc-ref:regexp.rdoc@Global+Variables]:
-
- /bar/ =~ 'foo bar' # => 4
- 'foo bar' =~ /bar/ # => 4
- /baz/ =~ 'foo bar' # => nil
-
-== \Method <tt>match?</tt>
-
-Each of the methods Regexp#match?, String#match?, and Symbol#match?
-returns +true+ if a match was found, +false+ otherwise;
-none sets {global variables}[rdoc-ref:regexp.rdoc@Global+Variables]:
-
- 'food'.match?(/foo/) # => true
- 'food'.match?(/bar/) # => false
-
-== Global Variables
-
-Certain regexp-oriented methods assign values to global variables:
-
-- <tt>#match</tt>: see {Method match}[rdoc-ref:regexp.rdoc@Method+match].
-- <tt>#=~</tt>: see {Operator =~}[rdoc-ref:regexp.rdoc@Operator+-3D~].
-
-The affected global variables are:
-
-- <tt>$~</tt>: Returns a MatchData object, or +nil+.
-- <tt>$&</tt>: Returns the matched part of the string, or +nil+.
-- <tt>$`</tt>: Returns the part of the string to the left of the match, or +nil+.
-- <tt>$'</tt>: Returns the part of the string to the right of the match, or +nil+.
-- <tt>$+</tt>: Returns the last group matched, or +nil+.
-- <tt>$1</tt>, <tt>$2</tt>, etc.: Returns the first, second, etc.,
- matched group, or +nil+.
- Note that <tt>$0</tt> is quite different;
- it returns the name of the currently executing program.
-
-Examples:
-
- # Matched string, but no matched groups.
- 'foo bar bar baz'.match('bar')
- $~ # => #<MatchData "bar">
- $& # => "bar"
- $` # => "foo "
- $' # => " bar baz"
- $+ # => nil
- $1 # => nil
-
- # Matched groups.
- /s(\w{2}).*(c)/.match('haystack')
- $~ # => #<MatchData "stac" 1:"ta" 2:"c">
- $& # => "stac"
- $` # => "hay"
- $' # => "k"
- $+ # => "c"
- $1 # => "ta"
- $2 # => "c"
- $3 # => nil
-
- # No match.
- 'foo'.match('bar')
- $~ # => nil
- $& # => nil
- $` # => nil
- $' # => nil
- $+ # => nil
- $1 # => nil
-
-Note that Regexp#match?, String#match?, and Symbol#match?
-do not set global variables.
-
-== Sources
-
-As seen above, the simplest regexp uses a literal expression as its source:
-
- re = /foo/ # => /foo/
- re.match('food') # => #<MatchData "foo">
- re.match('good') # => nil
-
-A rich collection of available _subexpressions_
-gives the regexp great power and flexibility:
-
-- {Special characters}[rdoc-ref:regexp.rdoc@Special+Characters]
-- {Source literals}[rdoc-ref:regexp.rdoc@Source+Literals]
-- {Character classes}[rdoc-ref:regexp.rdoc@Character+Classes]
-- {Shorthand character classes}[rdoc-ref:regexp.rdoc@Shorthand+Character+Classes]
-- {Anchors}[rdoc-ref:regexp.rdoc@Anchors]
-- {Alternation}[rdoc-ref:regexp.rdoc@Alternation]
-- {Quantifiers}[rdoc-ref:regexp.rdoc@Quantifiers]
-- {Groups and captures}[rdoc-ref:regexp.rdoc@Groups+and+Captures]
-- {Unicode}[rdoc-ref:regexp.rdoc@Unicode]
-- {POSIX Bracket Expressions}[rdoc-ref:regexp.rdoc@POSIX+Bracket+Expressions]
-- {Comments}[rdoc-ref:regexp.rdoc@Comments]
-
-=== Special Characters
-
-\Regexp special characters, called _metacharacters_,
-have special meanings in certain contexts;
-depending on the context, these are sometimes metacharacters:
-
- . ? - + * ^ \ | $ ( ) [ ] { }
-
-To match a metacharacter literally, backslash-escape it:
-
- # Matches one or more 'o' characters.
- /o+/.match('foo') # => #<MatchData "oo">
- # Would match 'o+'.
- /o\+/.match('foo') # => nil
-
-To match a backslash literally, backslash-escape it:
-
- /\./.match('\.') # => #<MatchData ".">
- /\\./.match('\.') # => #<MatchData "\\.">
-
-Method Regexp.escape returns an escaped string:
-
- Regexp.escape('.?-+*^\|$()[]{}')
- # => "\\.\\?\\-\\+\\*\\^\\\\\\|\\$\\(\\)\\[\\]\\{\\}"
-
-=== Source Literals
-
-The source literal largely behaves like a double-quoted string;
-see {String Literals}[rdoc-ref:syntax/literals.rdoc@String+Literals].
-
-In particular, a source literal may contain interpolated expressions:
-
- s = 'foo' # => "foo"
- /#{s}/ # => /foo/
- /#{s.capitalize}/ # => /Foo/
- /#{2 + 2}/ # => /4/
-
-There are differences between an ordinary string literal and a source literal;
-see {Shorthand Character Classes}[rdoc-ref:regexp.rdoc@Shorthand+Character+Classes].
-
-- <tt>\s</tt> in an ordinary string literal is equivalent to a space character;
- in a source literal, it's shorthand for matching a whitespace character.
-- In an ordinary string literal, these are (needlessly) escaped characters;
- in a source literal, they are shorthands for various matching characters:
-
- \w \W \d \D \h \H \S \R
-
-=== Character Classes
-
-A <i>character class</i> is delimited by square brackets;
-it specifies that certain characters match at a given point in the target string:
-
- # This character class will match any vowel.
- re = /B[aeiou]rd/
- re.match('Bird') # => #<MatchData "Bird">
- re.match('Bard') # => #<MatchData "Bard">
- re.match('Byrd') # => nil
-
-A character class may contain hyphen characters to specify ranges of characters:
-
- # These regexps have the same effect.
- /[abcdef]/.match('foo') # => #<MatchData "f">
- /[a-f]/.match('foo') # => #<MatchData "f">
- /[a-cd-f]/.match('foo') # => #<MatchData "f">
-
-When the first character of a character class is a caret (<tt>^</tt>),
-the sense of the class is inverted: it matches any character _except_ those specified.
-
- /[^a-eg-z]/.match('f') # => #<MatchData "f">
-
-A character class may contain another character class.
-By itself this isn't useful because <tt>[a-z[0-9]]</tt>
-describes the same set as <tt>[a-z0-9]</tt>.
-
-However, character classes also support the <tt>&&</tt> operator,
-which performs set intersection on its arguments.
-The two can be combined as follows:
-
- /[a-w&&[^c-g]z]/ # ([a-w] AND ([^c-g] OR z))
-
-This is equivalent to:
-
- /[abh-w]/
-
-=== Shorthand Character Classes
-
-Each of the following metacharacters serves as a shorthand
-for a character class:
-
-- <tt>/./</tt>: Matches any character except a newline:
-
- /./.match('foo') # => #<MatchData "f">
- /./.match("\n") # => nil
-
-- <tt>/./m</tt>: Matches any character, including a newline;
- see {Multiline Mode}[rdoc-ref:regexp.rdoc@Multiline+Mode}:
-
- /./m.match("\n") # => #<MatchData "\n">
-
-- <tt>/\w/</tt>: Matches a word character: equivalent to <tt>[a-zA-Z0-9_]</tt>:
-
- /\w/.match(' foo') # => #<MatchData "f">
- /\w/.match(' _') # => #<MatchData "_">
- /\w/.match(' ') # => nil
-
-- <tt>/\W/</tt>: Matches a non-word character: equivalent to <tt>[^a-zA-Z0-9_]</tt>:
-
- /\W/.match(' ') # => #<MatchData " ">
- /\W/.match('_') # => nil
-
-- <tt>/\d/</tt>: Matches a digit character: equivalent to <tt>[0-9]</tt>:
-
- /\d/.match('THX1138') # => #<MatchData "1">
- /\d/.match('foo') # => nil
-
-- <tt>/\D/</tt>: Matches a non-digit character: equivalent to <tt>[^0-9]</tt>:
-
- /\D/.match('123Jump!') # => #<MatchData "J">
- /\D/.match('123') # => nil
-
-- <tt>/\h/</tt>: Matches a hexdigit character: equivalent to <tt>[0-9a-fA-F]</tt>:
-
- /\h/.match('xyz fedcba9876543210') # => #<MatchData "f">
- /\h/.match('xyz') # => nil
-
-- <tt>/\H/</tt>: Matches a non-hexdigit character: equivalent to <tt>[^0-9a-fA-F]</tt>:
-
- /\H/.match('fedcba9876543210xyz') # => #<MatchData "x">
- /\H/.match('fedcba9876543210') # => nil
-
-- <tt>/\s/</tt>: Matches a whitespace character: equivalent to <tt>/[ \t\r\n\f\v]/</tt>:
-
- /\s/.match('foo bar') # => #<MatchData " ">
- /\s/.match('foo') # => nil
-
-- <tt>/\S/</tt>: Matches a non-whitespace character: equivalent to <tt>/[^ \t\r\n\f\v]/</tt>:
-
- /\S/.match(" \t\r\n\f\v foo") # => #<MatchData "f">
- /\S/.match(" \t\r\n\f\v") # => nil
-
-- <tt>/\R/</tt>: Matches a linebreak, platform-independently:
-
- /\R/.match("\r") # => #<MatchData "\r"> # Carriage return (CR)
- /\R/.match("\n") # => #<MatchData "\n"> # Newline (LF)
- /\R/.match("\f") # => #<MatchData "\f"> # Formfeed (FF)
- /\R/.match("\v") # => #<MatchData "\v"> # Vertical tab (VT)
- /\R/.match("\r\n") # => #<MatchData "\r\n"> # CRLF
- /\R/.match("\u0085") # => #<MatchData "\u0085"> # Next line (NEL)
- /\R/.match("\u2028") # => #<MatchData "\u2028"> # Line separator (LSEP)
- /\R/.match("\u2029") # => #<MatchData "\u2029"> # Paragraph separator (PSEP)
-
-=== Anchors
-
-An anchor is a metasequence that matches a zero-width position between
-characters in the target string.
-
-For a subexpression with no anchor,
-matching may begin anywhere in the target string:
-
- /real/.match('surrealist') # => #<MatchData "real">
-
-For a subexpression with an anchor,
-matching must begin at the matched anchor.
-
-==== Boundary Anchors
-
-Each of these anchors matches a boundary:
-
-- <tt>^</tt>: Matches the beginning of a line:
-
- /^bar/.match("foo\nbar") # => #<MatchData "bar">
- /^ar/.match("foo\nbar") # => nil
-
-- <tt>$</tt>: Matches the end of a line:
-
- /bar$/.match("foo\nbar") # => #<MatchData "bar">
- /ba$/.match("foo\nbar") # => nil
-
-- <tt>\A</tt>: Matches the beginning of the string:
-
- /\Afoo/.match('foo bar') # => #<MatchData "foo">
- /\Afoo/.match(' foo bar') # => nil
-
-- <tt>\Z</tt>: Matches the end of the string;
- if string ends with a single newline,
- it matches just before the ending newline:
-
- /foo\Z/.match('bar foo') # => #<MatchData "foo">
- /foo\Z/.match('foo bar') # => nil
- /foo\Z/.match("bar foo\n") # => #<MatchData "foo">
- /foo\Z/.match("bar foo\n\n") # => nil
-
-- <tt>\z</tt>: Matches the end of the string:
-
- /foo\z/.match('bar foo') # => #<MatchData "foo">
- /foo\z/.match('foo bar') # => nil
- /foo\z/.match("bar foo\n") # => nil
-
-- <tt>\b</tt>: Matches word boundary when not inside brackets;
- matches backspace (<tt>"0x08"</tt>) when inside brackets:
-
- /foo\b/.match('foo bar') # => #<MatchData "foo">
- /foo\b/.match('foobar') # => nil
-
-- <tt>\B</tt>: Matches non-word boundary:
-
- /foo\B/.match('foobar') # => #<MatchData "foo">
- /foo\B/.match('foo bar') # => nil
-
-- <tt>\G</tt>: Matches first matching position:
-
- In methods like String#gsub and String#scan, it changes on each iteration.
- It initially matches the beginning of subject, and in each following iteration it matches where the last match finished.
-
- " a b c".gsub(/ /, '_') # => "____a_b_c"
- " a b c".gsub(/\G /, '_') # => "____a b c"
-
- In methods like Regexp#match and String#match
- that take an optional offset, it matches where the search begins.
-
- "hello, world".match(/,/, 3) # => #<MatchData ",">
- "hello, world".match(/\G,/, 3) # => nil
-
-==== Lookaround Anchors
-
-Lookahead anchors:
-
-- <tt>(?=_pat_)</tt>: Positive lookahead assertion:
- ensures that the following characters match _pat_,
- but doesn't include those characters in the matched substring.
-
-- <tt>(?!_pat_)</tt>: Negative lookahead assertion:
- ensures that the following characters <i>do not</i> match _pat_,
- but doesn't include those characters in the matched substring.
-
-Lookbehind anchors:
-
-- <tt>(?<=_pat_)</tt>: Positive lookbehind assertion:
- ensures that the preceding characters match _pat_, but
- doesn't include those characters in the matched substring.
-
-- <tt>(?<!_pat_)</tt>: Negative lookbehind assertion:
- ensures that the preceding characters do not match
- _pat_, but doesn't include those characters in the matched substring.
-
-The pattern below uses positive lookahead and positive lookbehind to match
-text appearing in <tt><b></tt>...<tt></b></tt> tags
-without including the tags in the match:
-
- /(?<=<b>)\w+(?=<\/b>)/.match("Fortune favors the <b>bold</b>.")
- # => #<MatchData "bold">
-
-==== Match-Reset Anchor
-
-- <tt>\K</tt>: Match reset:
- the matched content preceding <tt>\K</tt> in the regexp is excluded from the result.
- For example, the following two regexps are almost equivalent:
-
- /ab\Kc/.match('abc') # => #<MatchData "c">
- /(?<=ab)c/.match('abc') # => #<MatchData "c">
-
- These match same string and <tt>$&</tt> equals <tt>'c'</tt>,
- while the matched position is different.
-
- As are the following two regexps:
-
- /(a)\K(b)\Kc/
- /(?<=(?<=(a))(b))c/
-
-=== Alternation
-
-The vertical bar metacharacter (<tt>|</tt>) may be used within parentheses
-to express alternation:
-two or more subexpressions any of which may match the target string.
-
-Two alternatives:
-
- re = /(a|b)/
- re.match('foo') # => nil
- re.match('bar') # => #<MatchData "b" 1:"b">
-
-Four alternatives:
-
- re = /(a|b|c|d)/
- re.match('shazam') # => #<MatchData "a" 1:"a">
- re.match('cold') # => #<MatchData "c" 1:"c">
-
-Each alternative is a subexpression, and may be composed of other subexpressions:
-
- re = /([a-c]|[x-z])/
- re.match('bar') # => #<MatchData "b" 1:"b">
- re.match('ooz') # => #<MatchData "z" 1:"z">
-
-\Method Regexp.union provides a convenient way to construct
-a regexp with alternatives.
-
-=== Quantifiers
-
-A simple regexp matches one character:
-
- /\w/.match('Hello') # => #<MatchData "H">
-
-An added _quantifier_ specifies how many matches are required or allowed:
-
-- <tt>*</tt> - Matches zero or more times:
-
- /\w*/.match('')
- # => #<MatchData "">
- /\w*/.match('x')
- # => #<MatchData "x">
- /\w*/.match('xyz')
- # => #<MatchData "yz">
-
-- <tt>+</tt> - Matches one or more times:
-
- /\w+/.match('') # => nil
- /\w+/.match('x') # => #<MatchData "x">
- /\w+/.match('xyz') # => #<MatchData "xyz">
-
-- <tt>?</tt> - Matches zero or one times:
-
- /\w?/.match('') # => #<MatchData "">
- /\w?/.match('x') # => #<MatchData "x">
- /\w?/.match('xyz') # => #<MatchData "x">
-
-- <tt>{</tt>_n_<tt>}</tt> - Matches exactly _n_ times:
-
- /\w{2}/.match('') # => nil
- /\w{2}/.match('x') # => nil
- /\w{2}/.match('xyz') # => #<MatchData "xy">
-
-- <tt>{</tt>_min_<tt>,}</tt> - Matches _min_ or more times:
-
- /\w{2,}/.match('') # => nil
- /\w{2,}/.match('x') # => nil
- /\w{2,}/.match('xy') # => #<MatchData "xy">
- /\w{2,}/.match('xyz') # => #<MatchData "xyz">
-
-- <tt>{,</tt>_max_<tt>}</tt> - Matches _max_ or fewer times:
-
- /\w{,2}/.match('') # => #<MatchData "">
- /\w{,2}/.match('x') # => #<MatchData "x">
- /\w{,2}/.match('xyz') # => #<MatchData "xy">
-
-- <tt>{</tt>_min_<tt>,</tt>_max_<tt>}</tt> -
- Matches at least _min_ times and at most _max_ times:
-
- /\w{1,2}/.match('') # => nil
- /\w{1,2}/.match('x') # => #<MatchData "x">
- /\w{1,2}/.match('xyz') # => #<MatchData "xy">
-
-==== Greedy, Lazy, or Possessive Matching
-
-Quantifier matching may be greedy, lazy, or possessive:
-
-- In _greedy_ matching, as many occurrences as possible are matched
- while still allowing the overall match to succeed.
- Greedy quantifiers: <tt>*</tt>, <tt>+</tt>, <tt>?</tt>,
- <tt>{min, max}</tt> and its variants.
-- In _lazy_ matching, the minimum number of occurrences are matched.
- Lazy quantifiers: <tt>*?</tt>, <tt>+?</tt>, <tt>??</tt>,
- <tt>{min, max}?</tt> and its variants.
-- In _possessive_ matching, once a match is found, there is no backtracking;
- that match is retained, even if it jeopardises the overall match.
- Possessive quantifiers: <tt>*+</tt>, <tt>++</tt>, <tt>?+</tt>.
- Note that <tt>{min, max}</tt> and its variants do _not_ support possessive matching.
-
-More:
-
-- About greedy and lazy matching, see
- {Choosing Minimal or Maximal Repetition}[https://doc.lagout.org/programmation/Regular%20Expressions/Regular%20Expressions%20Cookbook_%20Detailed%20Solutions%20in%20Eight%20Programming%20Languages%20%282nd%20ed.%29%20%5BGoyvaerts%20%26%20Levithan%202012-09-06%5D.pdf#tutorial-backtrack].
-- About possessive matching, see
- {Eliminate Needless Backtracking}[https://doc.lagout.org/programmation/Regular%20Expressions/Regular%20Expressions%20Cookbook_%20Detailed%20Solutions%20in%20Eight%20Programming%20Languages%20%282nd%20ed.%29%20%5BGoyvaerts%20%26%20Levithan%202012-09-06%5D.pdf#tutorial-backtrack].
-
-=== Groups and Captures
-
-A simple regexp has (at most) one match:
-
- re = /\d\d\d\d-\d\d-\d\d/
- re.match('1943-02-04') # => #<MatchData "1943-02-04">
- re.match('1943-02-04').size # => 1
- re.match('foo') # => nil
-
-Adding one or more pairs of parentheses, <tt>(_subexpression_)</tt>,
-defines _groups_, which may result in multiple matched substrings,
-called _captures_:
-
- re = /(\d\d\d\d)-(\d\d)-(\d\d)/
- re.match('1943-02-04') # => #<MatchData "1943-02-04" 1:"1943" 2:"02" 3:"04">
- re.match('1943-02-04').size # => 4
-
-The first capture is the entire matched string;
-the other captures are the matched substrings from the groups.
-
-A group may have a
-{quantifier}[rdoc-ref:regexp.rdoc@Quantifiers]:
-
- re = /July 4(th)?/
- re.match('July 4') # => #<MatchData "July 4" 1:nil>
- re.match('July 4th') # => #<MatchData "July 4th" 1:"th">
-
- re = /(foo)*/
- re.match('') # => #<MatchData "" 1:nil>
- re.match('foo') # => #<MatchData "foo" 1:"foo">
- re.match('foofoo') # => #<MatchData "foofoo" 1:"foo">
-
- re = /(foo)+/
- re.match('') # => nil
- re.match('foo') # => #<MatchData "foo" 1:"foo">
- re.match('foofoo') # => #<MatchData "foofoo" 1:"foo">
-
-The returned \MatchData object gives access to the matched substrings:
-
- re = /(\d\d\d\d)-(\d\d)-(\d\d)/
- md = re.match('1943-02-04')
- # => #<MatchData "1943-02-04" 1:"1943" 2:"02" 3:"04">
- md[0] # => "1943-02-04"
- md[1] # => "1943"
- md[2] # => "02"
- md[3] # => "04"
-
-==== Non-Capturing Groups
-
-A group may be made non-capturing;
-it is still a group (and, for example, can have a quantifier),
-but its matching substring is not included among the captures.
-
-A non-capturing group begins with <tt>?:</tt> (inside the parentheses):
-
- # Don't capture the year.
- re = /(?:\d\d\d\d)-(\d\d)-(\d\d)/
- md = re.match('1943-02-04') # => #<MatchData "1943-02-04" 1:"02" 2:"04">
-
-==== Backreferences
-
-A group match may also be referenced within the regexp itself;
-such a reference is called a +backreference+:
-
- /[csh](..) [csh]\1 in/.match('The cat sat in the hat')
- # => #<MatchData "cat sat in" 1:"at">
-
-This table shows how each subexpression in the regexp above
-matches a substring in the target string:
-
- | Subexpression in Regexp | Matching Substring in Target String |
- |---------------------------|-------------------------------------|
- | First '[csh]' | Character 'c' |
- | '(..)' | First substring 'at' |
- | First space ' ' | First space character ' ' |
- | Second '[csh]' | Character 's' |
- | '\1' (backreference 'at') | Second substring 'at' |
- | ' in' | Substring ' in' |
-
-A regexp may contain any number of groups:
-
-- For a large number of groups:
-
- - The ordinary <tt>\\_n_</tt> notation applies only for _n_ in range (1..9).
- - The <tt>MatchData[_n_]</tt> notation applies for any non-negative _n_.
-
-- <tt>\0</tt> is a special backreference, referring to the entire matched string;
- it may not be used within the regexp itself,
- but may be used outside it (for example, in a substitution method call):
-
- 'The cat sat in the hat'.gsub(/[csh]at/, '\0s')
- # => "The cats sats in the hats"
-
-==== Named Captures
-
-As seen above, a capture can be referred to by its number.
-A capture can also have a name,
-prefixed as <tt>?<_name_></tt> or <tt>?'_name_'</tt>,
-and the name (symbolized) may be used as an index in <tt>MatchData[]</tt>:
-
- md = /\$(?<dollars>\d+)\.(?'cents'\d+)/.match("$3.67")
- # => #<MatchData "$3.67" dollars:"3" cents:"67">
- md[:dollars] # => "3"
- md[:cents] # => "67"
- # The capture numbers are still valid.
- md[2] # => "67"
-
-When a regexp contains a named capture, there are no unnamed captures:
-
- /\$(?<dollars>\d+)\.(\d+)/.match("$3.67")
- # => #<MatchData "$3.67" dollars:"3">
-
-A named group may be backreferenced as <tt>\k<_name_></tt>:
-
- /(?<vowel>[aeiou]).\k<vowel>.\k<vowel>/.match('ototomy')
- # => #<MatchData "ototo" vowel:"o">
-
-When (and only when) a regexp contains named capture groups
-and appears before the <tt>=~</tt> operator,
-the captured substrings are assigned to local variables with corresponding names:
-
- /\$(?<dollars>\d+)\.(?<cents>\d+)/ =~ '$3.67'
- dollars # => "3"
- cents # => "67"
-
-\Method Regexp#named_captures returns a hash of the capture names and substrings;
-method Regexp#names returns an array of the capture names.
-
-==== Atomic Grouping
-
-A group may be made _atomic_ with <tt>(?></tt>_subexpression_<tt>)</tt>.
-
-This causes the subexpression to be matched
-independently of the rest of the expression,
-so that the matched substring becomes fixed for the remainder of the match,
-unless the entire subexpression must be abandoned and subsequently revisited.
-
-In this way _subexpression_ is treated as a non-divisible whole.
-Atomic grouping is typically used to optimise patterns
-to prevent needless backtracking .
-
-Example (without atomic grouping):
-
- /".*"/.match('"Quote"') # => #<MatchData "\"Quote\"">
-
-Analysis:
-
-1. The leading subexpression <tt>"</tt> in the pattern matches the first character
- <tt>"</tt> in the target string.
-2. The next subexpression <tt>.*</tt> matches the next substring <tt>Quote“</tt>
- (including the trailing double-quote).
-3. Now there is nothing left in the target string to match
- the trailing subexpression <tt>"</tt> in the pattern;
- this would cause the overall match to fail.
-4. The matched substring is backtracked by one position: <tt>Quote</tt>.
-5. The final subexpression <tt>"</tt> now matches the final substring <tt>"</tt>,
- and the overall match succeeds.
-
-If subexpression <tt>.*</tt> is grouped atomically,
-the backtracking is disabled, and the overall match fails:
-
- /"(?>.*)"/.match('"Quote"') # => nil
-
-Atomic grouping can affect performance;
-see {Atomic Group}[https://www.regular-expressions.info/atomic.html].
-
-==== Subexpression Calls
-
-As seen above, a backreference number (<tt>\\_n_</tt>) or name (<tt>\k<_name_></tt>)
-gives access to a captured _substring_;
-the corresponding regexp _subexpression_ may also be accessed,
-via the number (<tt>\\g<i>n</i></tt>) or name (<tt>\g<_name_></tt>):
-
- /\A(?<paren>\(\g<paren>*\))*\z/.match('(())')
- # ^1
- # ^2
- # ^3
- # ^4
- # ^5
- # ^6
- # ^7
- # ^8
- # ^9
- # ^10
-
-The pattern:
-
-1. Matches at the beginning of the string, i.e. before the first character.
-2. Enters a named group +paren+.
-3. Matches the first character in the string, <tt>'('</tt>.
-4. Calls the +paren+ group again, i.e. recurses back to the second step.
-5. Re-enters the +paren+ group.
-6. Matches the second character in the string, <tt>'('</tt>.
-7. Attempts to call +paren+ a third time,
- but fails because doing so would prevent an overall successful match.
-8. Matches the third character in the string, <tt>')'</tt>;
- marks the end of the second recursive call
-9. Matches the fourth character in the string, <tt>')'</tt>.
-10. Matches the end of the string.
-
-See {Subexpression calls}[https://learnbyexample.github.io/Ruby_Regexp/groupings-and-backreferences.html?highlight=subexpression#subexpression-calls].
-
-==== Conditionals
-
-The conditional construct takes the form <tt>(?(_cond_)_yes_|_no_)</tt>, where:
-
-- _cond_ may be a capture number or name.
-- The match to be applied is _yes_ if _cond_ is captured;
- otherwise the match to be applied is _no_.
-- If not needed, <tt>|_no_</tt> may be omitted.
-
-Examples:
-
- re = /\A(foo)?(?(1)(T)|(F))\z/
- re.match('fooT') # => #<MatchData "fooT" 1:"foo" 2:"T" 3:nil>
- re.match('F') # => #<MatchData "F" 1:nil 2:nil 3:"F">
- re.match('fooF') # => nil
- re.match('T') # => nil
-
- re = /\A(?<xyzzy>foo)?(?(<xyzzy>)(T)|(F))\z/
- re.match('fooT') # => #<MatchData "fooT" xyzzy:"foo">
- re.match('F') # => #<MatchData "F" xyzzy:nil>
- re.match('fooF') # => nil
- re.match('T') # => nil
-
-
-==== Absence Operator
-
-The absence operator is a special group that matches anything which does _not_ match the contained subexpressions.
-
- /(?~real)/.match('surrealist') # => #<MatchData "surrea">
- /(?~real)ist/.match('surrealist') # => #<MatchData "ealist">
- /sur(?~real)ist/.match('surrealist') # => nil
-
-=== Unicode
-
-==== Unicode Properties
-
-The <tt>/\p{_property_name_}/</tt> construct (with lowercase +p+)
-matches characters using a Unicode property name,
-much like a character class;
-property +Alpha+ specifies alphabetic characters:
-
- /\p{Alpha}/.match('a') # => #<MatchData "a">
- /\p{Alpha}/.match('1') # => nil
-
-A property can be inverted
-by prefixing the name with a caret character (<tt>^</tt>):
-
- /\p{^Alpha}/.match('1') # => #<MatchData "1">
- /\p{^Alpha}/.match('a') # => nil
-
-Or by using <tt>\P</tt> (uppercase +P+):
-
- /\P{Alpha}/.match('1') # => #<MatchData "1">
- /\P{Alpha}/.match('a') # => nil
-
-See {Unicode Properties}[./Regexp/unicode_properties_rdoc.html]
-for regexps based on the numerous properties.
-
-Some commonly-used properties correspond to POSIX bracket expressions:
-
-- <tt>/\p{Alnum}/</tt>: Alphabetic and numeric character
-- <tt>/\p{Alpha}/</tt>: Alphabetic character
-- <tt>/\p{Blank}/</tt>: Space or tab
-- <tt>/\p{Cntrl}/</tt>: Control character
-- <tt>/\p{Digit}/</tt>: Digit
- characters, and similar)
-- <tt>/\p{Lower}/</tt>: Lowercase alphabetical character
-- <tt>/\p{Print}/</tt>: Like <tt>\p{Graph}</tt>, but includes the space character
-- <tt>/\p{Punct}/</tt>: Punctuation character
-- <tt>/\p{Space}/</tt>: Whitespace character (<tt>[:blank:]</tt>, newline,
- carriage return, etc.)
-- <tt>/\p{Upper}/</tt>: Uppercase alphabetical
-- <tt>/\p{XDigit}/</tt>: Digit allowed in a hexadecimal number (i.e., 0-9a-fA-F)
-
-These are also commonly used:
-
-- <tt>/\p{Emoji}/</tt>: Unicode emoji.
-- <tt>/\p{Graph}/</tt>: Non-blank character
- (excludes spaces, control characters, and similar).
-- <tt>/\p{Word}/</tt>: A member of one of the following Unicode character
- categories (see below):
-
- - +Mark+ (+M+).
- - +Letter+ (+L+).
- - +Number+ (+N+)
- - <tt>Connector Punctuation</tt> (+Pc+).
-
-- <tt>/\p{ASCII}/</tt>: A character in the ASCII character set.
-- <tt>/\p{Any}/</tt>: Any Unicode character (including unassigned characters).
-- <tt>/\p{Assigned}/</tt>: An assigned character.
-
-==== Unicode Character Categories
-
-A Unicode character category name:
-
-- May be either its full name or its abbreviated name.
-- Is case-insensitive.
-- Treats a space, a hyphen, and an underscore as equivalent.
-
-Examples:
-
- /\p{lu}/ # => /\p{lu}/
- /\p{LU}/ # => /\p{LU}/
- /\p{Uppercase Letter}/ # => /\p{Uppercase Letter}/
- /\p{Uppercase_Letter}/ # => /\p{Uppercase_Letter}/
- /\p{UPPERCASE-LETTER}/ # => /\p{UPPERCASE-LETTER}/
-
-Below are the Unicode character category abbreviations and names.
-Enumerations of characters in each category are at the links.
-
-Letters:
-
-- +L+, +Letter+: +LC+, +Lm+, or +Lo+.
-- +LC+, +Cased_Letter+: +Ll+, +Lt+, or +Lu+.
-- {Lu, Lowercase_Letter}[https://www.compart.com/en/unicode/category/Ll].
-- {Lu, Modifier_Letter}[https://www.compart.com/en/unicode/category/Lm].
-- {Lu, Other_Letter}[https://www.compart.com/en/unicode/category/Lo].
-- {Lu, Titlecase_Letter}[https://www.compart.com/en/unicode/category/Lt].
-- {Lu, Uppercase_Letter}[https://www.compart.com/en/unicode/category/Lu].
-
-Marks:
-
-- +M+, +Mark+: +Mc+, +Me+, or +Mn+.
-- {Mc, Spacing_Mark}[https://www.compart.com/en/unicode/category/Mc].
-- {Me, Enclosing_Mark}[https://www.compart.com/en/unicode/category/Me].
-- {Mn, Nonapacing_Mark}[https://www.compart.com/en/unicode/category/Mn].
-
-Numbers:
-
-- +N+, +Number+: +Nd+, +Nl+, or +No+.
-- {Nd, Decimal_Number}[https://www.compart.com/en/unicode/category/Nd].
-- {Nl, Letter_Number}[https://www.compart.com/en/unicode/category/Nl].
-- {No, Other_Number}[https://www.compart.com/en/unicode/category/No].
-
-Punctation:
-
-- +P+, +Punctuation+: +Pc+, +Pd+, +Pe+, +Pf+, +Pi+, +Po+, or +Ps+.
-- {Pc, Connector_Punctuation}[https://www.compart.com/en/unicode/category/Pc].
-- {Pd, Dash_Punctuation}[https://www.compart.com/en/unicode/category/Pd].
-- {Pe, Close_Punctuation}[https://www.compart.com/en/unicode/category/Pe].
-- {Pf, Final_Punctuation}[https://www.compart.com/en/unicode/category/Pf].
-- {Pi, Initial_Punctuation}[https://www.compart.com/en/unicode/category/Pi].
-- {Po, Other_Punctuation}[https://www.compart.com/en/unicode/category/Po].
-- {Ps, Open_Punctuation}[https://www.compart.com/en/unicode/category/Ps].
-
-- +S+, +Symbol+: +Sc+, +Sk+, +Sm+, or +So+.
-- {Sc, Currency_Symbol}[https://www.compart.com/en/unicode/category/Sc].
-- {Sk, Modifier_Symbol}[https://www.compart.com/en/unicode/category/Sk].
-- {Sm, Math_Symbol}[https://www.compart.com/en/unicode/category/Sm].
-- {So, Other_Symbol}[https://www.compart.com/en/unicode/category/So].
-
-- +Z+, +Separator+: +Zl+, +Zp+, or +Zs+.
-- {Zl, Line_Separator}[https://www.compart.com/en/unicode/category/Zl].
-- {Zp, Paragraph_Separator}[https://www.compart.com/en/unicode/category/Zp].
-- {Zs, Space_Separator}[https://www.compart.com/en/unicode/category/Zs].
-
-- +C+, +Other+: +Cc+, +Cf+, +Cn+, +Co+, or +Cs+.
-- {Cc, Control}[https://www.compart.com/en/unicode/category/Cc].
-- {Cf, Format}[https://www.compart.com/en/unicode/category/Cf].
-- {Cn, Unassigned}[https://www.compart.com/en/unicode/category/Cn].
-- {Co, Private_Use}[https://www.compart.com/en/unicode/category/Co].
-- {Cs, Surrogate}[https://www.compart.com/en/unicode/category/Cs].
-
-==== Unicode Scripts and Blocks
-
-Among the Unicode properties are:
-
-- {Unicode scripts}[https://en.wikipedia.org/wiki/Script_(Unicode)];
- see {supported scripts}[https://www.unicode.org/standard/supported.html].
-- {Unicode blocks}[https://en.wikipedia.org/wiki/Unicode_block];
- see {supported blocks}[http://www.unicode.org/Public/UNIDATA/Blocks.txt].
-
-=== POSIX Bracket Expressions
-
-A POSIX <i>bracket expression</i> is also similar to a character class.
-These expressions provide a portable alternative to the above,
-with the added benefit of encompassing non-ASCII characters:
-
-- <tt>/\d/</tt> matches only ASCII decimal digits +0+ through +9+.
-- <tt>/[[:digit:]]/</tt> matches any character in the Unicode
- <tt>Decimal Number</tt> (+Nd+) category;
- see below.
-
-The POSIX bracket expressions:
-
-- <tt>/[[:digit:]]/</tt>: Matches a {Unicode digit}[https://www.compart.com/en/unicode/category/Nd]:
-
- /[[:digit:]]/.match('9') # => #<MatchData "9">
- /[[:digit:]]/.match("\u1fbf9") # => #<MatchData "9">
-
-- <tt>/[[:xdigit:]]/</tt>: Matches a digit allowed in a hexadecimal number;
- equivalent to <tt>[0-9a-fA-F]</tt>.
-
-- <tt>/[[:upper:]]/</tt>: Matches a {Unicode uppercase letter}[https://www.compart.com/en/unicode/category/Lu]:
-
- /[[:upper:]]/.match('A') # => #<MatchData "A">
- /[[:upper:]]/.match("\u00c6") # => #<MatchData "Æ">
-
-- <tt>/[[:lower:]]/</tt>: Matches a {Unicode lowercase letter}[https://www.compart.com/en/unicode/category/Ll]:
-
- /[[:lower:]]/.match('a') # => #<MatchData "a">
- /[[:lower:]]/.match("\u01fd") # => #<MatchData "ǽ">
-
-- <tt>/[[:alpha:]]/</tt>: Matches <tt>/[[:upper:]]/</tt> or <tt>/[[:lower:]]/</tt>.
-
-- <tt>/[[:alnum:]]/</tt>: Matches <tt>/[[:alpha:]]/</tt> or <tt>/[[:digit:]]/</tt>.
-
-- <tt>/[[:space:]]/</tt>: Matches {Unicode space character}[https://www.compart.com/en/unicode/category/Zs]:
-
- /[[:space:]]/.match(' ') # => #<MatchData " ">
- /[[:space:]]/.match("\u2005") # => #<MatchData " ">
-
-- <tt>/[[:blank:]]/</tt>: Matches <tt>/[[:space:]]/</tt> or tab character:
-
- /[[:blank:]]/.match(' ') # => #<MatchData " ">
- /[[:blank:]]/.match("\u2005") # => #<MatchData " ">
- /[[:blank:]]/.match("\t") # => #<MatchData "\t">
-
-- <tt>/[[:cntrl:]]/</tt>: Matches {Unicode control character}[https://www.compart.com/en/unicode/category/Cc]:
-
- /[[:cntrl:]]/.match("\u0000") # => #<MatchData "\u0000">
- /[[:cntrl:]]/.match("\u009f") # => #<MatchData "\u009F">
-
-- <tt>/[[:graph:]]/</tt>: Matches any character
- except <tt>/[[:space:]]/</tt> or <tt>/[[:cntrl:]]/</tt>.
-
-- <tt>/[[:print:]]/</tt>: Matches <tt>/[[:graph:]]/</tt> or space character.
-
-- <tt>/[[:punct:]]/</tt>: Matches any (Unicode punctuation character}[https://www.compart.com/en/unicode/category/Po]:
-
-Ruby also supports these (non-POSIX) bracket expressions:
-
-- <tt>/[[:ascii:]]/</tt>: Matches a character in the ASCII character set.
-- <tt>/[[:word:]]/</tt>: Matches a character in one of these Unicode character
- categories (see below):
-
- - +Mark+ (+M+).
- - +Letter+ (+L+).
- - +Number+ (+N+)
- - <tt>Connector Punctuation</tt> (+Pc+).
-
-=== Comments
-
-A comment may be included in a regexp pattern
-using the <tt>(?#</tt>_comment_<tt>)</tt> construct,
-where _comment_ is a substring that is to be ignored.
-arbitrary text ignored by the regexp engine:
-
- /foo(?#Ignore me)bar/.match('foobar') # => #<MatchData "foobar">
-
-The comment may not include an unescaped terminator character.
-
-See also {Extended Mode}[rdoc-ref:regexp.rdoc@Extended+Mode].
-
-== Modes
-
-Each of these modifiers sets a mode for the regexp:
-
-- +i+: <tt>/_pattern_/i</tt> sets
- {Case-Insensitive Mode}[rdoc-ref:regexp.rdoc@Case-Insensitive+Mode].
-- +m+: <tt>/_pattern_/m</tt> sets
- {Multiline Mode}[rdoc-ref:regexp.rdoc@Multiline+Mode].
-- +x+: <tt>/_pattern_/x</tt> sets
- {Extended Mode}[rdoc-ref:regexp.rdoc@Extended+Mode].
-- +o+: <tt>/_pattern_/o</tt> sets
- {Interpolation Mode}[rdoc-ref:regexp.rdoc@Interpolation+Mode].
-
-Any, all, or none of these may be applied.
-
-Modifiers +i+, +m+, and +x+ may be applied to subexpressions:
-
-- <tt>(?_modifier_)</tt> turns the mode "on" for ensuing subexpressions
-- <tt>(?-_modifier_)</tt> turns the mode "off" for ensuing subexpressions
-- <tt>(?_modifier_:_subexp_)</tt> turns the mode "on" for _subexp_ within the group
-- <tt>(?-_modifier_:_subexp_)</tt> turns the mode "off" for _subexp_ within the group
-
-Example:
-
- re = /(?i)te(?-i)st/
- re.match('test') # => #<MatchData "test">
- re.match('TEst') # => #<MatchData "TEst">
- re.match('TEST') # => nil
- re.match('teST') # => nil
-
- re = /t(?i:e)st/
- re.match('test') # => #<MatchData "test">
- re.match('tEst') # => #<MatchData "tEst">
- re.match('tEST') # => nil
-
-\Method Regexp#options returns an integer whose value showing
-the settings for case-insensitivity mode, multiline mode, and extended mode.
-
-=== Case-Insensitive Mode
-
-By default, a regexp is case-sensitive:
-
- /foo/.match('FOO') # => nil
-
-Modifier +i+ enables case-insensitive mode:
-
- /foo/i.match('FOO')
- # => #<MatchData "FOO">
-
-\Method Regexp#casefold? returns whether the mode is case-insensitive.
-
-=== Multiline Mode
-
-The multiline-mode in Ruby is what is commonly called a "dot-all mode":
-
-- Without the +m+ modifier, the subexpression <tt>.</tt> does not match newlines:
-
- /a.c/.match("a\nc") # => nil
-
-- With the modifier, it does match:
-
- /a.c/m.match("a\nc") # => #<MatchData "a\nc">
-
-Unlike other languages, the modifier +m+ does not affect the anchors <tt>^</tt> and <tt>$</tt>.
-These anchors always match at line-boundaries in Ruby.
-
-=== Extended Mode
-
-Modifier +x+ enables extended mode, which means that:
-
-- Literal white space in the pattern is to be ignored.
-- Character <tt>#</tt> marks the remainder of its containing line as a comment,
- which is also to be ignored for matching purposes.
-
-In extended mode, whitespace and comments may be used
-to form a self-documented regexp.
-
-Regexp not in extended mode (matches some Roman numerals):
-
- pattern = '^M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$'
- re = /#{pattern}/
- re.match('MCMXLIII') # => #<MatchData "MCMXLIII" 1:"CM" 2:"XL" 3:"III">
-
-Regexp in extended mode:
-
- pattern = <<-EOT
- ^ # beginning of string
- M{0,3} # thousands - 0 to 3 Ms
- (CM|CD|D?C{0,3}) # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 Cs),
- # or 500-800 (D, followed by 0 to 3 Cs)
- (XC|XL|L?X{0,3}) # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 Xs),
- # or 50-80 (L, followed by 0 to 3 Xs)
- (IX|IV|V?I{0,3}) # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 Is),
- # or 5-8 (V, followed by 0 to 3 Is)
- $ # end of string
- EOT
- re = /#{pattern}/x
- re.match('MCMXLIII') # => #<MatchData "MCMXLIII" 1:"CM" 2:"XL" 3:"III">
-
-=== Interpolation Mode
-
-Modifier +o+ means that the first time a literal regexp with interpolations
-is encountered,
-the generated Regexp object is saved and used for all future evaluations
-of that literal regexp.
-Without modifier +o+, the generated Regexp is not saved,
-so each evaluation of the literal regexp generates a new Regexp object.
-
-Without modifier +o+:
-
- def letters; sleep 5; /[A-Z][a-z]/; end
- words = %w[abc def xyz]
- start = Time.now
- words.each {|word| word.match(/\A[#{letters}]+\z/) }
- Time.now - start # => 15.0174892
-
-With modifier +o+:
-
- start = Time.now
- words.each {|word| word.match(/\A[#{letters}]+\z/o) }
- Time.now - start # => 5.0010866
-
-Note that if the literal regexp does not have interpolations,
-the +o+ behavior is the default.
-
-== Encodings
-
-By default, a regexp with only US-ASCII characters has US-ASCII encoding:
-
- re = /foo/
- re.source.encoding # => #<Encoding:US-ASCII>
- re.encoding # => #<Encoding:US-ASCII>
-
-A regular expression containing non-US-ASCII characters
-is assumed to use the source encoding.
-This can be overridden with one of the following modifiers.
-
-- <tt>/_pat_/n</tt>: US-ASCII if only containing US-ASCII characters,
- otherwise ASCII-8BIT:
-
- /foo/n.encoding # => #<Encoding:US-ASCII>
- /foo\xff/n.encoding # => #<Encoding:ASCII-8BIT>
- /foo\x7f/n.encoding # => #<Encoding:US-ASCII>
-
-- <tt>/_pat_/u</tt>: UTF-8
-
- /foo/u.encoding # => #<Encoding:UTF-8>
-
-- <tt>/_pat_/e</tt>: EUC-JP
-
- /foo/e.encoding # => #<Encoding:EUC-JP>
-
-- <tt>/_pat_/s</tt>: Windows-31J
-
- /foo/s.encoding # => #<Encoding:Windows-31J>
-
-A regexp can be matched against a target string when either:
-
-- They have the same encoding.
-- The regexp's encoding is a fixed encoding and the string
- contains only ASCII characters.
- Method Regexp#fixed_encoding? returns whether the regexp
- has a <i>fixed</i> encoding.
-
-If a match between incompatible encodings is attempted an
-<tt>Encoding::CompatibilityError</tt> exception is raised.
-
-Example:
-
- re = eval("# encoding: ISO-8859-1\n/foo\\xff?/")
- re.encoding # => #<Encoding:ISO-8859-1>
- re =~ "foo".encode("UTF-8") # => 0
- re =~ "foo\u0100" # Raises Encoding::CompatibilityError
-
-The encoding may be explicitly fixed by including Regexp::FIXEDENCODING
-in the second argument for Regexp.new:
-
- # Regexp with encoding ISO-8859-1.
- re = Regexp.new("a".force_encoding('iso-8859-1'), Regexp::FIXEDENCODING)
- re.encoding # => #<Encoding:ISO-8859-1>
- # Target string with encoding UTF-8.
- s = "a\u3042"
- s.encoding # => #<Encoding:UTF-8>
- re.match(s) # Raises Encoding::CompatibilityError.
-
-== Timeouts
-
-When either a regexp source or a target string comes from untrusted input,
-malicious values could become a denial-of-service attack;
-to prevent such an attack, it is wise to set a timeout.
-
-\Regexp has two timeout values:
-
-- A class default timeout, used for a regexp whose instance timeout is +nil+;
- this default is initially +nil+, and may be set by method Regexp.timeout=:
-
- Regexp.timeout # => nil
- Regexp.timeout = 3.0
- Regexp.timeout # => 3.0
-
-- An instance timeout, which defaults to +nil+ and may be set in Regexp.new:
-
- re = Regexp.new('foo', timeout: 5.0)
- re.timeout # => 5.0
-
-When regexp.timeout is +nil+, the timeout "falls through" to Regexp.timeout;
-when regexp.timeout is non-+nil+, that value controls timing out:
-
- | regexp.timeout Value | Regexp.timeout Value | Result |
- |----------------------|----------------------|-----------------------------|
- | nil | nil | Never times out. |
- | nil | Float | Times out in Float seconds. |
- | Float | Any | Times out in Float seconds. |
-
-== Optimization
-
-For certain values of the pattern and target string,
-matching time can grow polynomially or exponentially in relation to the input size;
-the potential vulnerability arising from this is the {regular expression denial-of-service}[https://en.wikipedia.org/wiki/ReDoS] (ReDoS) attack.
-
-\Regexp matching can apply an optimization to prevent ReDoS attacks.
-When the optimization is applied, matching time increases linearly (not polynomially or exponentially)
-in relation to the input size, and a ReDoS attach is not possible.
-
-This optimization is applied if the pattern meets these criteria:
-
-- No backreferences.
-- No subexpression calls.
-- No nested lookaround anchors or atomic groups.
-- No nested quantifiers with counting (i.e. no nested <tt>{n}</tt>,
- <tt>{min,}</tt>, <tt>{,max}</tt>, or <tt>{min,max}</tt> style quantifiers)
-
-You can use method Regexp.linear_time? to determine whether a pattern meets these criteria:
-
- Regexp.linear_time?(/a*/) # => true
- Regexp.linear_time?('a*') # => true
- Regexp.linear_time?(/(a*)\1/) # => false
-
-However, an untrusted source may not be safe even if the method returns +true+,
-because the optimization uses memoization (which may invoke large memory consumption).
-
-== References
-
-Read (online PDF books):
-
-- {Mastering Regular Expressions}[https://ia902508.us.archive.org/10/items/allitebooks-02/Mastering%20Regular%20Expressions%2C%203rd%20Edition.pdf]
- by Jeffrey E.F. Friedl.
-- {Regular Expressions Cookbook}[https://doc.lagout.org/programmation/Regular%20Expressions/Regular%20Expressions%20Cookbook_%20Detailed%20Solutions%20in%20Eight%20Programming%20Languages%20%282nd%20ed.%29%20%5BGoyvaerts%20%26%20Levithan%202012-09-06%5D.pdf]
- by Jan Goyvaerts & Steven Levithan.
-
-Explore, test (interactive online editor):
-
-- {Rubular}[https://rubular.com/].
diff --git a/doc/rjit/README.md b/doc/rjit/README.md
deleted file mode 100644
index e3795e35b8..0000000000
--- a/doc/rjit/README.md
+++ /dev/null
@@ -1,53 +0,0 @@
-# RJIT: Ruby JIT
-
-This document has some tips that might be useful when you work on RJIT.
-
-## Project purpose
-
-This project is for experimental purposes.
-For production deployment, consider using YJIT instead.
-
-## Supported platforms
-
-The following platforms are assumed to work. `linux-x86_64` is tested on CI.
-
-* OS: Linux, macOS, BSD
-* Arch: x86\_64
-
-## configure
-### --enable-rjit
-
-On supported platforms, `--enable-rjit` is set by default. You usually don't need to specify this.
-You may still manually pass `--enable-rjit` to try RJIT on unsupported platforms.
-
-### --enable-rjit=dev
-
-It enables `--rjit-dump-disasm` if libcapstone is available.
-
-It also enables `vm_insns_count` and `ratio_in_rjit` in `--rjit-stats`.
-However, it makes the interpreter a little slower.
-
-### --enable-rjit=disasm
-
-It enables `--rjit-dump-disasm` if libcapstone is available.
-
-## make
-### rjit-bindgen
-
-If you see an "RJIT bindgen" GitHub Actions failure, please commit the `git diff` shown on the failed job.
-
-For doing the same thing locally, run `make rjit-bindgen` after installing libclang.
-macOS seems to have libclang by default. On Ubuntu, you can install it with `apt install libclang1`.
-
-## ruby
-### --rjit-stats
-
-This prints RJIT stats at exit. Some stats are available only with `--enable-rjit=dev` on configure.
-
-### --rjit-dump-disasm
-
-This dumps all JIT code. You need to install libcapstone before configure and use `--enable-rjit=dev`
-or `--enable-rjit=disasm` on configure.
-
-* Ubuntu: `sudo apt-get install -y libcapstone-dev`
-* macOS: `brew install capstone`
diff --git a/doc/rjit/rjit.md b/doc/rjit/rjit.md
new file mode 100644
index 0000000000..9e60e43ce3
--- /dev/null
+++ b/doc/rjit/rjit.md
@@ -0,0 +1,45 @@
+# RJIT: Ruby JIT
+
+This document has some tips that might be useful when you work on RJIT.
+
+## Project purpose
+
+This project is for experimental purposes.
+For production deployment, consider using YJIT instead.
+
+## Supported platforms
+
+The following platforms are assumed to work. `linux-x86_64` is tested on CI.
+
+* OS: Linux, macOS, BSD
+* Arch: x86\_64
+
+## configure
+### --enable-rjit
+
+On supported platforms, `--enable-rjit` is set by default. You usually don't need to specify this.
+You may still manually pass `--enable-rjit` to try RJIT on unsupported platforms.
+
+### --enable-rjit=dev
+
+It enables `--rjit-dump-disasm` if libcapstone is available.
+
+## make
+### rjit-bindgen
+
+If you see an "RJIT bindgen" GitHub Actions failure, please commit the `git diff` shown on the failed job.
+
+For doing the same thing locally, run `make rjit-bindgen` after installing libclang.
+macOS seems to have libclang by default. On Ubuntu, you can install it with `apt install libclang1`.
+
+## ruby
+### --rjit-stats
+
+This prints RJIT stats at exit.
+
+### --rjit-dump-disasm
+
+This dumps all JIT code. You need to install libcapstone before configure and use `--enable-rjit=dev` on configure.
+
+* Ubuntu: `sudo apt-get install -y libcapstone-dev`
+* macOS: `brew install capstone`
diff --git a/doc/ruby/option_dump.md b/doc/ruby/option_dump.md
new file mode 100644
index 0000000000..00d0ec77d5
--- /dev/null
+++ b/doc/ruby/option_dump.md
@@ -0,0 +1,297 @@
+# Option `--dump`
+
+For other argument values,
+see {Option --dump}[options_md.html#label--dump-3A+Dump+Items].
+
+For the examples here, we use this program:
+
+```sh
+$ cat t.rb
+puts 'Foo'
+```
+
+The supported dump items:
+
+- `insns`: Instruction sequences:
+
+ ```sh
+ $ ruby --dump=insns t.rb
+ == disasm: #<ISeq:<main>@t.rb:1 (1,0)-(1,10)> (catch: FALSE)
+ 0000 putself ( 1)[Li]
+ 0001 putstring "Foo"
+ 0003 opt_send_without_block <calldata!mid:puts, argc:1, FCALL|ARGS_SIMPLE>
+ 0005 leave
+ ```
+
+- `parsetree`: {Abstract syntax tree}[https://en.wikipedia.org/wiki/Abstract_syntax_tree]
+ (AST):
+
+ ```sh
+ $ ruby --dump=parsetree t.rb
+ ###########################################################
+ ## Do NOT use this node dump for any purpose other than ##
+ ## debug and research. Compatibility is not guaranteed. ##
+ ###########################################################
+
+ # @ NODE_SCOPE (line: 1, location: (1,0)-(1,10))
+ # +- nd_tbl: (empty)
+ # +- nd_args:
+ # | (null node)
+ # +- nd_body:
+ # @ NODE_FCALL (line: 1, location: (1,0)-(1,10))*
+ # +- nd_mid: :puts
+ # +- nd_args:
+ # @ NODE_LIST (line: 1, location: (1,5)-(1,10))
+ # +- nd_alen: 1
+ # +- nd_head:
+ # | @ NODE_STR (line: 1, location: (1,5)-(1,10))
+ # | +- nd_lit: "Foo"
+ # +- nd_next:
+ # (null node)
+ ```
+
+- `parsetree_with_comment`: AST with comments:
+
+ ```sh
+ $ ruby --dump=parsetree_with_comment t.rb
+ ###########################################################
+ ## Do NOT use this node dump for any purpose other than ##
+ ## debug and research. Compatibility is not guaranteed. ##
+ ###########################################################
+
+ # @ NODE_SCOPE (line: 1, location: (1,0)-(1,10))
+ # | # new scope
+ # | # format: [nd_tbl]: local table, [nd_args]: arguments, [nd_body]: body
+ # +- nd_tbl (local table): (empty)
+ # +- nd_args (arguments):
+ # | (null node)
+ # +- nd_body (body):
+ # @ NODE_FCALL (line: 1, location: (1,0)-(1,10))*
+ # | # function call
+ # | # format: [nd_mid]([nd_args])
+ # | # example: foo(1)
+ # +- nd_mid (method id): :puts
+ # +- nd_args (arguments):
+ # @ NODE_LIST (line: 1, location: (1,5)-(1,10))
+ # | # list constructor
+ # | # format: [ [nd_head], [nd_next].. ] (length: [nd_alen])
+ # | # example: [1, 2, 3]
+ # +- nd_alen (length): 1
+ # +- nd_head (element):
+ # | @ NODE_STR (line: 1, location: (1,5)-(1,10))
+ # | | # string literal
+ # | | # format: [nd_lit]
+ # | | # example: 'foo'
+ # | +- nd_lit (literal): "Foo"
+ # +- nd_next (next element):
+ # (null node)
+ ```
+
+- `yydebug`: Debugging information from yacc parser generator:
+
+ ```sh
+ $ ruby --dump=yydebug t.rb
+ Starting parse
+ Entering state 0
+ Reducing stack by rule 1 (line 1295):
+ lex_state: NONE -> BEG at line 1296
+ vtable_alloc:12392: 0x0000558453df1a00
+ vtable_alloc:12393: 0x0000558453df1a60
+ cmdarg_stack(push): 0 at line 12406
+ cond_stack(push): 0 at line 12407
+ -> $$ = nterm $@1 (1.0-1.0: )
+ Stack now 0
+ Entering state 2
+ Reading a token:
+ lex_state: BEG -> CMDARG at line 9049
+ Next token is token "local variable or method" (1.0-1.4: puts)
+ Shifting token "local variable or method" (1.0-1.4: puts)
+ Entering state 35
+ Reading a token: Next token is token "string literal" (1.5-1.6: )
+ Reducing stack by rule 742 (line 5567):
+ $1 = token "local variable or method" (1.0-1.4: puts)
+ -> $$ = nterm operation (1.0-1.4: )
+ Stack now 0 2
+ Entering state 126
+ Reducing stack by rule 78 (line 1794):
+ $1 = nterm operation (1.0-1.4: )
+ -> $$ = nterm fcall (1.0-1.4: )
+ Stack now 0 2
+ Entering state 80
+ Next token is token "string literal" (1.5-1.6: )
+ Reducing stack by rule 292 (line 2723):
+ cmdarg_stack(push): 1 at line 2737
+ -> $$ = nterm $@16 (1.4-1.4: )
+ Stack now 0 2 80
+ Entering state 235
+ Next token is token "string literal" (1.5-1.6: )
+ Shifting token "string literal" (1.5-1.6: )
+ Entering state 216
+ Reducing stack by rule 607 (line 4706):
+ -> $$ = nterm string_contents (1.6-1.6: )
+ Stack now 0 2 80 235 216
+ Entering state 437
+ Reading a token: Next token is token "literal content" (1.6-1.9: "Foo")
+ Shifting token "literal content" (1.6-1.9: "Foo")
+ Entering state 503
+ Reducing stack by rule 613 (line 4802):
+ $1 = token "literal content" (1.6-1.9: "Foo")
+ -> $$ = nterm string_content (1.6-1.9: )
+ Stack now 0 2 80 235 216 437
+ Entering state 507
+ Reducing stack by rule 608 (line 4716):
+ $1 = nterm string_contents (1.6-1.6: )
+ $2 = nterm string_content (1.6-1.9: )
+ -> $$ = nterm string_contents (1.6-1.9: )
+ Stack now 0 2 80 235 216
+ Entering state 437
+ Reading a token:
+ lex_state: CMDARG -> END at line 7276
+ Next token is token "terminator" (1.9-1.10: )
+ Shifting token "terminator" (1.9-1.10: )
+ Entering state 508
+ Reducing stack by rule 590 (line 4569):
+ $1 = token "string literal" (1.5-1.6: )
+ $2 = nterm string_contents (1.6-1.9: )
+ $3 = token "terminator" (1.9-1.10: )
+ -> $$ = nterm string1 (1.5-1.10: )
+ Stack now 0 2 80 235
+ Entering state 109
+ Reducing stack by rule 588 (line 4559):
+ $1 = nterm string1 (1.5-1.10: )
+ -> $$ = nterm string (1.5-1.10: )
+ Stack now 0 2 80 235
+ Entering state 108
+ Reading a token:
+ lex_state: END -> BEG at line 9200
+ Next token is token '\n' (1.10-1.10: )
+ Reducing stack by rule 586 (line 4541):
+ $1 = nterm string (1.5-1.10: )
+ -> $$ = nterm strings (1.5-1.10: )
+ Stack now 0 2 80 235
+ Entering state 107
+ Reducing stack by rule 307 (line 2837):
+ $1 = nterm strings (1.5-1.10: )
+ -> $$ = nterm primary (1.5-1.10: )
+ Stack now 0 2 80 235
+ Entering state 90
+ Next token is token '\n' (1.10-1.10: )
+ Reducing stack by rule 261 (line 2553):
+ $1 = nterm primary (1.5-1.10: )
+ -> $$ = nterm arg (1.5-1.10: )
+ Stack now 0 2 80 235
+ Entering state 220
+ Next token is token '\n' (1.10-1.10: )
+ Reducing stack by rule 270 (line 2586):
+ $1 = nterm arg (1.5-1.10: )
+ -> $$ = nterm arg_value (1.5-1.10: )
+ Stack now 0 2 80 235
+ Entering state 221
+ Next token is token '\n' (1.10-1.10: )
+ Reducing stack by rule 297 (line 2779):
+ $1 = nterm arg_value (1.5-1.10: )
+ -> $$ = nterm args (1.5-1.10: )
+ Stack now 0 2 80 235
+ Entering state 224
+ Next token is token '\n' (1.10-1.10: )
+ Reducing stack by rule 772 (line 5626):
+ -> $$ = nterm none (1.10-1.10: )
+ Stack now 0 2 80 235 224
+ Entering state 442
+ Reducing stack by rule 296 (line 2773):
+ $1 = nterm none (1.10-1.10: )
+
+ -> $$ = nterm opt_block_arg (1.10-1.10: )
+ Stack now 0 2 80 235 224
+ Entering state 441
+ Reducing stack by rule 288 (line 2696):
+ $1 = nterm args (1.5-1.10: )
+ $2 = nterm opt_block_arg (1.10-1.10: )
+ -> $$ = nterm call_args (1.5-1.10: )
+ Stack now 0 2 80 235
+ Entering state 453
+ Reducing stack by rule 293 (line 2723):
+ $1 = nterm $@16 (1.4-1.4: )
+ $2 = nterm call_args (1.5-1.10: )
+ cmdarg_stack(pop): 0 at line 2754
+ -> $$ = nterm command_args (1.4-1.10: )
+ Stack now 0 2 80
+ Entering state 333
+ Next token is token '\n' (1.10-1.10: )
+ Reducing stack by rule 79 (line 1804):
+ $1 = nterm fcall (1.0-1.4: )
+ $2 = nterm command_args (1.4-1.10: )
+ -> $$ = nterm command (1.0-1.10: )
+ Stack now 0 2
+ Entering state 81
+ Next token is token '\n' (1.10-1.10: )
+ Reducing stack by rule 73 (line 1770):
+ $1 = nterm command (1.0-1.10: )
+ -> $$ = nterm command_call (1.0-1.10: )
+ Stack now 0 2
+ Entering state 78
+ Reducing stack by rule 51 (line 1659):
+ $1 = nterm command_call (1.0-1.10: )
+ -> $$ = nterm expr (1.0-1.10: )
+ Stack now 0 2
+ Entering state 75
+ Next token is token '\n' (1.10-1.10: )
+ Reducing stack by rule 39 (line 1578):
+ $1 = nterm expr (1.0-1.10: )
+ -> $$ = nterm stmt (1.0-1.10: )
+ Stack now 0 2
+ Entering state 73
+ Next token is token '\n' (1.10-1.10: )
+ Reducing stack by rule 8 (line 1354):
+ $1 = nterm stmt (1.0-1.10: )
+ -> $$ = nterm top_stmt (1.0-1.10: )
+ Stack now 0 2
+ Entering state 72
+ Reducing stack by rule 5 (line 1334):
+ $1 = nterm top_stmt (1.0-1.10: )
+ -> $$ = nterm top_stmts (1.0-1.10: )
+ Stack now 0 2
+ Entering state 71
+ Next token is token '\n' (1.10-1.10: )
+ Shifting token '\n' (1.10-1.10: )
+ Entering state 311
+ Reducing stack by rule 769 (line 5618):
+ $1 = token '\n' (1.10-1.10: )
+ -> $$ = nterm term (1.10-1.10: )
+ Stack now 0 2 71
+ Entering state 313
+ Reducing stack by rule 770 (line 5621):
+ $1 = nterm term (1.10-1.10: )
+ -> $$ = nterm terms (1.10-1.10: )
+ Stack now 0 2 71
+ Entering state 314
+ Reading a token: Now at end of input.
+ Reducing stack by rule 759 (line 5596):
+ $1 = nterm terms (1.10-1.10: )
+ -> $$ = nterm opt_terms (1.10-1.10: )
+ Stack now 0 2 71
+ Entering state 312
+ Reducing stack by rule 3 (line 1321):
+ $1 = nterm top_stmts (1.0-1.10: )
+ $2 = nterm opt_terms (1.10-1.10: )
+ -> $$ = nterm top_compstmt (1.0-1.10: )
+ Stack now 0 2
+ Entering state 70
+ Reducing stack by rule 2 (line 1295):
+ $1 = nterm $@1 (1.0-1.0: )
+ $2 = nterm top_compstmt (1.0-1.10: )
+ vtable_free:12426: p->lvtbl->args(0x0000558453df1a00)
+ vtable_free:12427: p->lvtbl->vars(0x0000558453df1a60)
+ cmdarg_stack(pop): 0 at line 12428
+ cond_stack(pop): 0 at line 12429
+ -> $$ = nterm program (1.0-1.10: )
+ Stack now 0
+ Entering state 1
+ Now at end of input.
+ Shifting token "end-of-input" (1.10-1.10: )
+ Entering state 3
+ Stack now 0 1 3
+ Cleanup: popping token "end-of-input" (1.10-1.10: )
+ Cleanup: popping nterm program (1.0-1.10: )
+ ```
+
diff --git a/doc/ruby/options.md b/doc/ruby/options.md
new file mode 100644
index 0000000000..143c8925f1
--- /dev/null
+++ b/doc/ruby/options.md
@@ -0,0 +1,723 @@
+# Ruby Command-Line Options
+
+## About the Examples
+
+Some examples here use command-line option `-e`,
+which passes the Ruby code to be executed on the command line itself:
+
+```sh
+$ ruby -e 'puts "Hello, World."'
+```
+
+Some examples here assume that file `desiderata.txt` exists:
+
+```
+$ cat desiderata.txt
+Go placidly amid the noise and the haste,
+and remember what peace there may be in silence.
+As far as possible, without surrender,
+be on good terms with all persons.
+```
+
+## Options
+
+### `-0`: \Set `$/` (Input Record Separator)
+
+Option `-0` defines the input record separator `$/`
+for the invoked Ruby program.
+
+The optional argument to the option must be octal digits,
+each in the range `0..7`;
+these digits are prefixed with digit `0` to form an octal value.
+
+If no argument is given, the input record separator is `0x00`.
+
+If an argument is given, it must immediately follow the option
+(no intervening whitespace or equal-sign character `'='`);
+argument values:
+
+- `0`: the input record separator is `''`;
+ see {Special Line Separator Values}[rdoc-ref:IO@Special+Line+Separator+Values].
+- In range `(1..0377)`:
+ the input record separator `$/` is set to the character value of the argument.
+- Any other octal value: the input record separator is `nil`.
+
+Examples:
+
+```sh
+$ ruby -0 -e 'p $/'
+"\x00"
+ruby -00 -e 'p $/'
+""
+$ ruby -012 -e 'p $/'
+"\n"
+$ ruby -015 -e 'p $/'
+"\r"
+$ ruby -0377 -e 'p $/'
+"\xFF"
+$ ruby -0400 -e 'p $/'
+nil
+```
+
+See also:
+
+- {Option -a}[rdoc-ref:ruby/options.md@a-3A+Split+Input+Lines+into+Fields]:
+ Split input lines into fields.
+- {Option -F}[rdoc-ref:ruby/options.md@F-3A+Set+Input+Field+Separator]:
+ \Set input field separator.
+- {Option -l}[rdoc-ref:ruby/options.md@l-3A+Set+Output+Record+Separator-3B+Chop+Lines]:
+ \Set output record separator; chop lines.
+- {Option -n}[rdoc-ref:ruby/options.md@n-3A+Run+Program+in+gets+Loop]:
+ Run program in `gets` loop.
+- {Option -p}[rdoc-ref:ruby/options.md@p-3A+-n-2C+with+Printing]:
+ `-n`, with printing.
+
+### `-a`: Split Input Lines into Fields
+
+Option `-a`, when given with either of options `-n` or `-p`,
+splits the string at `$_` into an array of strings at `$F`:
+
+```sh
+$ ruby -an -e 'p $F' desiderata.txt
+["Go", "placidly", "amid", "the", "noise", "and", "the", "haste,"]
+["and", "remember", "what", "peace", "there", "may", "be", "in", "silence."]
+["As", "far", "as", "possible,", "without", "surrender,"]
+["be", "on", "good", "terms", "with", "all", "persons."]
+```
+
+For the splitting,
+the default record separator is `$/`,
+and the default field separator is `$;`.
+
+See also:
+
+- {Option -0}[rdoc-ref:ruby/options.md@0-3A+Set+-24-2F+-28Input+Record+Separator-29]:
+ \Set `$/` (input record separator).
+- {Option -F}[rdoc-ref:ruby/options.md@F-3A+Set+Input+Field+Separator]:
+ \Set input field separator.
+- {Option -l}[rdoc-ref:ruby/options.md@l-3A+Set+Output+Record+Separator-3B+Chop+Lines]:
+ \Set output record separator; chop lines.
+- {Option -n}[rdoc-ref:ruby/options.md@n-3A+Run+Program+in+gets+Loop]:
+ Run program in `gets` loop.
+- {Option -p}[rdoc-ref:ruby/options.md@p-3A+-n-2C+with+Printing]:
+ `-n`, with printing.
+
+### `-c`: Check Syntax
+
+Option `-c` specifies that the specified Ruby program
+should be checked for syntax, but not actually executed:
+
+```
+$ ruby -e 'puts "Foo"'
+Foo
+$ ruby -c -e 'puts "Foo"'
+Syntax OK
+```
+
+### `-C`: \Set Working Directory
+
+The argument to option `-C` specifies a working directory
+for the invoked Ruby program;
+does not change the working directory for the current process:
+
+```sh
+$ basename `pwd`
+ruby
+$ ruby -C lib -e 'puts File.basename(Dir.pwd)'
+lib
+$ basename `pwd`
+ruby
+```
+
+Whitespace between the option and its argument may be omitted.
+
+### `-d`: \Set `$DEBUG` to `true`
+
+Some code in (or called by) the Ruby program may include statements or blocks
+conditioned by the global variable `$DEBUG` (e.g., `if $DEBUG`);
+these commonly write to `$stdout` or `$stderr`.
+
+The default value for `$DEBUG` is `false`;
+option `-d` sets it to `true`:
+
+```sh
+$ ruby -e 'p $DEBUG'
+false
+$ ruby -d -e 'p $DEBUG'
+true
+```
+
+Option `--debug` is an alias for option `-d`.
+
+### `-e`: Execute Given Ruby Code
+
+Option `-e` requires an argument, which is Ruby code to be executed;
+the option may be given more than once:
+
+```
+$ ruby -e 'puts "Foo"' -e 'puts "Bar"'
+Foo
+Bar
+```
+
+Whitespace between the option and its argument may be omitted.
+
+The command may include other options,
+but should not include arguments (which, if given, are ignored).
+
+### `-E`: \Set Default Encodings
+
+Option `-E` requires an argument, which specifies either the default external encoding,
+or both the default external and internal encodings for the invoked Ruby program:
+
+```
+# No option -E.
+$ ruby -e 'p [Encoding::default_external, Encoding::default_internal]'
+[#<Encoding:UTF-8>, nil]
+# Option -E with default external encoding.
+$ ruby -E cesu-8 -e 'p [Encoding::default_external, Encoding::default_internal]'
+[#<Encoding:CESU-8>, nil]
+# Option -E with default external and internal encodings.
+$ ruby -E utf-8:cesu-8 -e 'p [Encoding::default_external, Encoding::default_internal]'
+[#<Encoding:UTF-8>, #<Encoding:CESU-8>]
+```
+
+Whitespace between the option and its argument may be omitted.
+
+See also:
+
+- {Option --external-encoding}[options_md.html#label--external-encoding-3A+Set+Default+External+Encoding]:
+ \Set default external encoding.
+- {Option --internal-encoding}[options_md.html#label--internal-encoding-3A+Set+Default+Internal+Encoding]:
+ \Set default internal encoding.
+
+Option `--encoding` is an alias for option `-E`.
+
+### `-F`: \Set Input Field Separator
+
+Option `-F`, when given with option `-a`,
+specifies that its argument is to be the input field separator to be used for splitting:
+
+```sh
+$ ruby -an -Fs -e 'p $F' desiderata.txt
+["Go placidly amid the noi", "e and the ha", "te,\n"]
+["and remember what peace there may be in ", "ilence.\n"]
+["A", " far a", " po", "", "ible, without ", "urrender,\n"]
+["be on good term", " with all per", "on", ".\n"]
+```
+
+The argument may be a regular expression:
+
+```
+$ ruby -an -F'[.,]\s*' -e 'p $F' desiderata.txt
+["Go placidly amid the noise and the haste"]
+["and remember what peace there may be in silence"]
+["As far as possible", "without surrender"]
+["be on good terms with all persons"]
+```
+
+The argument must immediately follow the option
+(no intervening whitespace or equal-sign character `'='`).
+
+See also:
+
+- {Option -0}[rdoc-ref:ruby/options.md@0-3A+Set+-24-2F+-28Input+Record+Separator-29]:
+ \Set `$/` (input record separator).
+- {Option -a}[rdoc-ref:ruby/options.md@a-3A+Split+Input+Lines+into+Fields]:
+ Split input lines into fields.
+- {Option -l}[rdoc-ref:ruby/options.md@l-3A+Set+Output+Record+Separator-3B+Chop+Lines]:
+ \Set output record separator; chop lines.
+- {Option -n}[rdoc-ref:ruby/options.md@n-3A+Run+Program+in+gets+Loop]:
+ Run program in `gets` loop.
+- {Option -p}[rdoc-ref:ruby/options.md@p-3A+-n-2C+with+Printing]:
+ `-n`, with printing.
+
+### `-h`: Print Short Help Message
+
+Option `-h` prints a short help message
+that includes single-hyphen options (e.g. `-I`),
+and largely omits double-hyphen options (e.g., `--version`).
+
+Arguments and additional options are ignored.
+
+For a longer help message, use option `--help`.
+
+### `-i`: \Set \ARGF In-Place Mode
+
+Option `-i` sets the \ARGF in-place mode for the invoked Ruby program;
+see ARGF#inplace_mode=:
+
+```
+$ ruby -e 'p ARGF.inplace_mode'
+nil
+$ ruby -i -e 'p ARGF.inplace_mode'
+""
+$ ruby -i.bak -e 'p ARGF.inplace_mode'
+".bak"
+```
+
+### `-I`: Add to `$LOAD_PATH`
+
+The argument to option `-I` specifies a directory
+to be added to the array in global variable `$LOAD_PATH`;
+the option may be given more than once:
+
+```sh
+$ pushd /tmp
+$ ruby -e 'p $LOAD_PATH.size'
+8
+$ ruby -I my_lib -I some_lib -e 'p $LOAD_PATH.size'
+10
+$ ruby -I my_lib -I some_lib -e 'p $LOAD_PATH.take(2)'
+["/tmp/my_lib", "/tmp/some_lib"]
+$ popd
+```
+
+Whitespace between the option and its argument may be omitted.
+
+### `-l`: \Set Output Record Separator; Chop Lines
+
+Option `-l`, when given with option `-n` or `-p`,
+modifies line-ending processing by:
+
+- Setting global variable output record separator `$\`
+ to the current value of input record separator `$/`;
+ this affects line-oriented output (such a the output from Kernel#puts).
+- Calling String#chop! on each line read.
+
+Without option `-l` (unchopped):
+
+```sh
+$ ruby -n -e 'p $_' desiderata.txt
+"Go placidly amid the noise and the haste,\n"
+"and remember what peace there may be in silence.\n"
+"As far as possible, without surrender,\n"
+"be on good terms with all persons.\n"
+```
+
+With option `-l' (chopped):
+
+```sh
+$ ruby -ln -e 'p $_' desiderata.txt
+"Go placidly amid the noise and the haste,"
+"and remember what peace there may be in silence."
+"As far as possible, without surrender,"
+"be on good terms with all persons."
+```
+
+See also:
+
+- {Option -0}[rdoc-ref:ruby/options.md@0-3A+Set+-24-2F+-28Input+Record+Separator-29]:
+ \Set `$/` (input record separator).
+- {Option -a}[rdoc-ref:ruby/options.md@a-3A+Split+Input+Lines+into+Fields]:
+ Split input lines into fields.
+- {Option -F}[rdoc-ref:ruby/options.md@F-3A+Set+Input+Field+Separator]:
+ \Set input field separator.
+- {Option -n}[rdoc-ref:ruby/options.md@n-3A+Run+Program+in+gets+Loop]:
+ Run program in `gets` loop.
+- {Option -p}[rdoc-ref:ruby/options.md@p-3A+-n-2C+with+Printing]:
+ `-n`, with printing.
+
+### `-n`: Run Program in `gets` Loop
+
+Option `-n` runs your program in a Kernel#gets loop:
+
+```
+while gets
+ # Your Ruby code.
+end
+```
+
+Note that `gets` reads the next line and sets global variable `$_`
+to the last read line:
+
+```sh
+$ ruby -n -e 'puts $_' desiderata.txt
+Go placidly amid the noise and the haste,
+and remember what peace there may be in silence.
+As far as possible, without surrender,
+be on good terms with all persons.
+```
+
+See also:
+
+- {Option -0}[rdoc-ref:ruby/options.md@0-3A+Set+-24-2F+-28Input+Record+Separator-29]:
+ \Set `$/` (input record separator).
+- {Option -a}[rdoc-ref:ruby/options.md@a-3A+Split+Input+Lines+into+Fields]:
+ Split input lines into fields.
+- {Option -F}[rdoc-ref:ruby/options.md@F-3A+Set+Input+Field+Separator]:
+ \Set input field separator.
+- {Option -l}[rdoc-ref:ruby/options.md@l-3A+Set+Output+Record+Separator-3B+Chop+Lines]:
+ \Set output record separator; chop lines.
+- {Option -p}[rdoc-ref:ruby/options.md@p-3A+-n-2C+with+Printing]:
+ `-n`, with printing.
+
+### `-p`: `-n`, with Printing
+
+Option `-p` is like option `-n`, but also prints each line:
+
+```sh
+$ ruby -p -e 'puts $_.size' desiderata.txt
+42
+Go placidly amid the noise and the haste,
+49
+and remember what peace there may be in silence.
+39
+As far as possible, without surrender,
+35
+be on good terms with all persons.
+```
+
+See also:
+
+- {Option -0}[rdoc-ref:ruby/options.md@0-3A+Set+-24-2F+-28Input+Record+Separator-29]:
+ \Set `$/` (input record separator).
+- {Option -a}[rdoc-ref:ruby/options.md@a-3A+Split+Input+Lines+into+Fields]:
+ Split input lines into fields.
+- {Option -F}[rdoc-ref:ruby/options.md@F-3A+Set+Input+Field+Separator]:
+ \Set input field separator.
+- {Option -l}[rdoc-ref:ruby/options.md@l-3A+Set+Output+Record+Separator-3B+Chop+Lines]:
+ \Set output record separator; chop lines.
+- {Option -n}[rdoc-ref:ruby/options.md@n-3A+Run+Program+in+gets+Loop]:
+ Run program in `gets` loop.
+
+### `-r`: Require Library
+
+The argument to option `-r` specifies a library to be required
+before executing the Ruby program;
+the option may be given more than once:
+
+```sh
+$ ruby -e 'p defined?(JSON); p defined?(CSV)'
+nil
+nil
+$ ruby -r CSV -r JSON -e 'p defined?(JSON); p defined?(CSV)'
+"constant"
+"constant"
+```
+
+Whitespace between the option and its argument may be omitted.
+
+### `-s`: Define Global Variable
+
+Option `-s` specifies that a "custom option" is to define a global variable
+in the invoked Ruby program:
+
+- The custom option must appear _after_ the program name.
+- The custom option must begin with single hyphen (e.g., `-foo`),
+ not two hyphens (e.g., `--foo`).
+- The name of the global variable is based on the option name:
+ global variable `$foo` for custom option`-foo`.
+- The value of the global variable is the string option argument if given,
+ `true` otherwise.
+
+More than one custom option may be given:
+
+```
+$ cat t.rb
+p [$foo, $bar]
+$ ruby t.rb
+[nil, nil]
+$ ruby -s t.rb -foo=baz
+["baz", nil]
+$ ruby -s t.rb -foo
+[true, nil]
+$ ruby -s t.rb -foo=baz -bar=bat
+["baz", "bat"]
+```
+
+The option may not be used with
+{option -e}[rdoc-ref:ruby/options.md@e-3A+Execute+Given+Ruby+Code]
+
+### `-S`: Search Directories in `ENV['PATH']`
+
+Option `-S` specifies that the Ruby interpreter
+is to search (if necessary) the directories whose paths are in the program's
+`PATH` environment variable;
+the program is executed in the shell's current working directory
+(not necessarily in the directory where the program is found).
+
+This example uses adds path `'tmp/'` to the `PATH` environment variable:
+
+```sh
+$ export PATH=/tmp:$PATH
+$ echo "puts File.basename(Dir.pwd)" > /tmp/t.rb
+$ ruby -S t.rb
+ruby
+```
+
+### `-v`: Print Version; \Set `$VERBOSE`
+
+Options `-v` prints the Ruby version and sets global variable `$VERBOSE`:
+
+```
+$ ruby -e 'p $VERBOSE'
+false
+$ ruby -v -e 'p $VERBOSE'
+ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x64-mingw-ucrt]
+true
+```
+
+### `-w`: Synonym for `-W1`
+
+Option `-w` (lowercase letter) is equivalent to option `-W1` (uppercase letter).
+
+### `-W`: \Set \Warning Policy
+
+Any Ruby code can create a <i>warning message</i> by calling method Kernel#warn;
+methods in the Ruby core and standard libraries can also create warning messages.
+Such a message may be printed on `$stderr`
+(or not, depending on certain settings).
+
+Option `-W` helps determine whether a particular warning message
+will be written,
+by setting the initial value of global variable `$-W`:
+
+- `-W0`: Sets `$-W` to `0` (silent; no warnings).
+- `-W1`: Sets `$-W` to `1` (moderate verbosity).
+- `-W2`: Sets `$-W` to `2` (high verbosity).
+- `-W`: Same as `-W2` (high verbosity).
+- Option not given: Same as `-W1` (moderate verbosity).
+
+The value of `$-W`, in turn, determines which warning messages (if any)
+are to be printed to `$stdout` (see Kernel#warn):
+
+```sh
+$ ruby -W1 -e 'p $foo'
+nil
+$ ruby -W2 -e 'p $foo'
+-e:1: warning: global variable '$foo' not initialized
+nil
+```
+
+Ruby code may also define warnings for certain categories;
+these are the default settings for the defined categories:
+
+```
+Warning[:experimental] # => true
+Warning[:deprecated] # => false
+Warning[:performance] # => false
+```
+
+They may also be set:
+```
+Warning[:experimental] = false
+Warning[:deprecated] = true
+Warning[:performance] = true
+```
+
+You can suppress a category by prefixing `no-` to the category name:
+
+```
+$ ruby -W:no-experimental -e 'p IO::Buffer.new'
+#<IO::Buffer>
+```
+
+### `-x`: Execute Ruby Code Found in Text
+
+Option `-x` executes a Ruby program whose code is embedded
+in other, non-code, text:
+
+The ruby code:
+
+- Begins after the first line beginning with `'#!` and containing string `'ruby'`.
+- Ends before any one of:
+
+ - End-of-file.
+ - A line consisting of `'__END__'`,
+ - Character `Ctrl-D` or `Ctrl-Z`.
+
+Example:
+
+```sh
+$ cat t.txt
+Leading garbage.
+#!ruby
+puts File.basename(Dir.pwd)
+__END__
+Trailing garbage.
+
+$ ruby -x t.txt
+ruby
+```
+
+The optional argument specifies the directory where the text file
+is to be found;
+the Ruby code is executed in that directory:
+
+```sh
+$ cp t.txt /tmp/
+$ ruby -x/tmp t.txt
+tmp
+$
+
+```
+
+If an argument is given, it must immediately follow the option
+(no intervening whitespace or equal-sign character `'='`).
+
+### `--backtrace-limit`: \Set Backtrace Limit
+
+Option `--backtrace-limit` sets a limit on the number of entries
+to be displayed in a backtrace.
+
+See Thread::Backtrace.limit.
+
+### `--copyright`: Print Ruby Copyright
+
+Option `--copyright` prints a copyright message:
+
+```sh
+$ ruby --copyright
+ruby - Copyright (C) 1993-2024 Yukihiro Matsumoto
+```
+
+### `--debug`: Alias for `-d`
+
+Option `--debug` is an alias for
+{option -d}[rdoc-ref:ruby/options.md@d-3A+Set+-24DEBUG+to+true].
+
+### `--disable`: Disable Features
+
+Option `--disable` specifies features to be disabled;
+the argument is a comma-separated list of the features to be disabled:
+
+```sh
+ruby --disable=gems,rubyopt t.rb
+```
+
+The supported features:
+
+- `gems`: Rubygems (default: enabled).
+- `did_you_mean`: [`did_you_mean`](https://github.com/ruby/did_you_mean) (default: enabled).
+- `rubyopt`: `RUBYOPT` environment variable (default: enabled).
+- `frozen-string-literal`: Freeze all string literals (default: disabled).
+- `jit`: JIT compiler (default: disabled).
+
+See also {option --enable}[options_md.html#label--enable-3A+Enable+Features].
+
+### `--dump`: Dump Items
+
+Option `--dump` specifies items to be dumped;
+the argument is a comma-separated list of the items.
+
+Some of the argument values cause the command to behave as if a different
+option was given:
+
+- `--dump=copyright`:
+ Same as {option \-\-copyright}[options_md.html#label--copyright-3A+Print+Ruby+Copyright].
+- `--dump=help`:
+ Same as {option \-\-help}[options_md.html#label--help-3A+Print+Help+Message].
+- `--dump=syntax`:
+ Same as {option -c}[rdoc-ref:ruby/options.md@c-3A+Check+Syntax].
+- `--dump=usage`:
+ Same as {option -h}[rdoc-ref:ruby/options.md@h-3A+Print+Short+Help+Message].
+- `--dump=version`:
+ Same as {option \-\-version}[options_md.html#label--version-3A+Print+Ruby+Version].
+
+For other argument values and examples,
+see {Option --dump}[option_dump_md.html].
+
+### `--enable`: Enable Features
+
+Option `--enable` specifies features to be enabled;
+the argument is a comma-separated list of the features to be enabled.
+
+```sh
+ruby --enable=gems,rubyopt t.rb
+```
+
+For the features,
+see {option --disable}[options_md.html#label--disable-3A+Disable+Features].
+
+### `--encoding`: Alias for `-E`.
+
+Option `--encoding` is an alias for
+{option -E}[rdoc-ref:ruby/options.md@E-3A+Set+Default+Encodings].
+
+### `--external-encoding`: \Set Default External \Encoding
+
+Option `--external-encoding`
+sets the default external encoding for the invoked Ruby program;
+for values of +encoding+,
+see {Encoding: Names and Aliases}[rdoc-ref:encodings.rdoc@Names+and+Aliases].
+
+```sh
+$ ruby -e 'puts Encoding::default_external'
+UTF-8
+$ ruby --external-encoding=cesu-8 -e 'puts Encoding::default_external'
+CESU-8
+```
+
+### `--help`: Print Help Message
+
+Option `--help` prints a long help message.
+
+Arguments and additional options are ignored.
+
+For a shorter help message, use option `-h`.
+
+### `--internal-encoding`: \Set Default Internal \Encoding
+
+Option `--internal-encoding`
+sets the default internal encoding for the invoked Ruby program;
+for values of +encoding+,
+see {Encoding: Names and Aliases}[rdoc-ref:encodings.rdoc@Names+and+Aliases].
+
+```sh
+$ ruby -e 'puts Encoding::default_internal.nil?'
+true
+$ ruby --internal-encoding=cesu-8 -e 'puts Encoding::default_internal'
+CESU-8
+```
+
+### `--verbose`: \Set `$VERBOSE`
+
+Option `--verbose` sets global variable `$VERBOSE` to `true`
+and disables input from `$stdin`.
+
+### `--version`: Print Ruby Version
+
+Option `--version` prints the version of the Ruby interpreter, then exits.
+
+## Experimental Options
+
+These options are experimental in the current Ruby release,
+and may be modified or withdrawn in later releases.
+
+### `--jit`
+
+Option `-jit` enables JIT compilation with the default option.
+
+#### `--jit-debug`
+
+Option `--jit-debug` enables JIT debugging (very slow);
+adds compiler flags if given.
+
+#### `--jit-max-cache=num`
+
+Option `--jit-max-cache=num` sets the maximum number of methods
+to be JIT-ed in a cache; default: 100).
+
+#### `--jit-min-calls=num`
+
+Option `jit-min-calls=num` sets the minimum number of calls to trigger JIT
+(for testing); default: 10000).
+
+#### `--jit-save-temps`
+
+Option `--jit-save-temps` saves JIT temporary files in $TMP or /tmp (for testing).
+
+#### `--jit-verbose`
+
+Option `--jit-verbose` prints JIT logs of level `num` or less
+to `$stderr`; default: 0.
+
+#### `--jit-wait`
+
+Option `--jit-wait` waits until JIT compilation finishes every time (for testing).
+
+#### `--jit-warnings`
+
+Option `--jit-warnings` enables printing of JIT warnings.
+
diff --git a/doc/security.rdoc b/doc/security.rdoc
index ae20ed30fa..e428036cf5 100644
--- a/doc/security.rdoc
+++ b/doc/security.rdoc
@@ -37,7 +37,7 @@ programs for configuration and database persistence of Ruby object trees.
Similar to +Marshal+, it is able to deserialize into arbitrary Ruby classes.
For example, the following YAML data will create an +ERB+ object when
-deserialized:
+deserialized, using the `unsafe_load` method:
!ruby/object:ERB
src: puts `uname`
diff --git a/doc/standard_library.rdoc b/doc/standard_library.rdoc
index 2282d7226b..a9fca632f8 100644
--- a/doc/standard_library.rdoc
+++ b/doc/standard_library.rdoc
@@ -33,29 +33,22 @@ Socket:: Access underlying OS socket implementations
== Libraries
-Abbrev:: Calculates a set of unique abbreviations for a given set of strings
-Base64:: Support for encoding and decoding binary data using a Base64 representation
Benchmark:: Provides methods to measure and report the time used to execute code
Bundler:: Manage your Ruby application's gem dependencies
CGI:: Support for the Common Gateway Interface protocol
-CSV:: Provides an interface to read and write CSV files and data
Delegator:: Provides three abilities to delegate method calls to an object
DidYouMean:: "Did you mean?" experience in Ruby
-DRb:: Distributed object system for Ruby
English:: Provides references to special global variables with less cryptic names
ERB:: An easy to use but powerful templating system for Ruby
ErrorHighlight:: Highlight error location in your code
FileUtils:: Several file utility methods for copying, moving, removing, etc
Find:: This module supports top-down traversal of a set of file paths
Forwardable:: Provides delegation of specified methods to a designated object
-GetoptLong:: Parse command line options similar to the GNU C getopt_long()
IPAddr:: Provides methods to manipulate IPv4 and IPv6 IP addresses
IRB:: Interactive Ruby command-line tool for REPL (Read Eval Print Loop)
OptionParser:: Ruby-oriented class for command-line option analysis
Logger:: Provides a simple logging utility for outputting messages
-Mutex_m:: Mixin to extend objects to be handled like a Mutex
Net::HTTP:: HTTP client api for Ruby
-Observable:: Provides a mechanism for publish/subscribe pattern in Ruby
Open3:: Provides access to stdin, stdout and stderr when running other programs
OpenStruct:: Class to build custom data structures, similar to a Hash
OpenURI:: An easy-to-use wrapper for Net::HTTP, Net::HTTPS and Net::FTP
@@ -66,9 +59,7 @@ PStore:: Implements a file based persistence mechanism based on a Hash
Readline:: Wrapper for Readline extencion and Reline
Reline:: GNU Readline and Editline by pure Ruby implementation.
Resolv:: Thread-aware DNS resolver library in Ruby
-resolv-replace.rb:: Replace Socket DNS with Resolv
RDoc:: Produces HTML and command-line documentation for Ruby
-Rinda:: The Linda distributed computing paradigm in Ruby
SecureRandom:: Interface for secure random number generator
Set:: Provides a class to deal with collections of unordered, unique values
Shellwords:: Manipulates strings with word parsing rules of UNIX Bourne shell
@@ -85,7 +76,6 @@ WeakRef:: Allows a referenced object to be garbage-collected
== Extensions
-BigDecimal:: Provides arbitrary-precision floating point decimal arithmetic
Date:: A subclass of Object includes Comparable module for handling dates
DateTime:: Subclass of Date to handling dates, hours, minutes, seconds, offsets
Digest:: Provides a framework for message digest libraries
@@ -94,13 +84,11 @@ Fcntl:: Loads constants defined in the OS fcntl.h C header file
Fiddle:: A libffi wrapper for Ruby
IO:: Extensions for Ruby IO class, including #wait, #nonblock and ::console
JSON:: Implements Javascript Object Notation for Ruby
-NKF:: Ruby extension for Network Kanji Filter
OpenSSL:: Provides SSL, TLS and general purpose cryptography for Ruby
Pathname:: Representation of the name of a file or directory on the filesystem
Psych:: A YAML parser and emitter for Ruby
StringIO:: Pseudo I/O on String objects
StringScanner:: Provides lexical scanning operations on a String
-Syslog:: Ruby interface for the POSIX system logging facility
WIN32OLE:: Provides an interface for OLE Automation in Ruby
Zlib:: Ruby interface for the zlib compression/decompression library
@@ -130,3 +118,15 @@ RBS:: RBS is a language to describe the structure of Ruby programs
TypeProf:: A type analysis tool for Ruby code based on abstract interpretation
DEBUGGER__:: Debugging functionality for Ruby
Racc:: A LALR(1) parser generator written in Ruby.
+Mutex_m:: Mixin to extend objects to be handled like a Mutex
+GetoptLong:: Parse command line options similar to the GNU C getopt_long()
+Base64:: Support for encoding and decoding binary data using a Base64 representation
+BigDecimal:: Provides arbitrary-precision floating point decimal arithmetic
+Observable:: Provides a mechanism for publish/subscribe pattern in Ruby
+Abbrev:: Calculates a set of unique abbreviations for a given set of strings
+resolv-replace.rb:: Replace Socket DNS with Resolv
+Rinda:: The Linda distributed computing paradigm in Ruby
+DRb:: Distributed object system for Ruby
+NKF:: Ruby extension for Network Kanji Filter
+Syslog:: Ruby interface for the POSIX system logging facility
+CSV:: Provides an interface to read and write CSV files and data
diff --git a/doc/strftime_formatting.rdoc b/doc/strftime_formatting.rdoc
index 30a629bf68..5c7b33155d 100644
--- a/doc/strftime_formatting.rdoc
+++ b/doc/strftime_formatting.rdoc
@@ -1,4 +1,4 @@
-== Formats for Dates and Times
+= Formats for Dates and Times
Several Ruby time-related classes have instance method +strftime+,
which returns a formatted string representing all or part of a date or time:
@@ -32,9 +32,9 @@ It consists of:
Except for the leading percent character,
the only required part is the conversion specifier, so we begin with that.
-=== Conversion Specifiers
+== Conversion Specifiers
-==== \Date (Year, Month, Day)
+=== \Date (Year, Month, Day)
- <tt>%Y</tt> - Year including century, zero-padded:
@@ -87,7 +87,7 @@ the only required part is the conversion specifier, so we begin with that.
Time.new(2002, 1, 1).strftime('%j') # => "001"
Time.new(2002, 12, 31).strftime('%j') # => "365"
-==== \Time (Hour, Minute, Second, Subsecond)
+=== \Time (Hour, Minute, Second, Subsecond)
- <tt>%H</tt> - Hour of the day, in range (0..23), zero-padded:
@@ -152,7 +152,7 @@ the only required part is the conversion specifier, so we begin with that.
Time.now.strftime('%s') # => "1656505136"
-==== Timezone
+=== Timezone
- <tt>%z</tt> - Timezone as hour and minute offset from UTC:
@@ -162,7 +162,7 @@ the only required part is the conversion specifier, so we begin with that.
Time.now.strftime('%Z') # => "Central Daylight Time"
-==== Weekday
+=== Weekday
- <tt>%A</tt> - Full weekday name:
@@ -184,7 +184,7 @@ the only required part is the conversion specifier, so we begin with that.
t.strftime('%a') # => "Sun"
t.strftime('%w') # => "0"
-==== Week Number
+=== Week Number
- <tt>%U</tt> - Week number of the year, in range (0..53), zero-padded,
where each week begins on a Sunday:
@@ -200,7 +200,7 @@ the only required part is the conversion specifier, so we begin with that.
t.strftime('%a') # => "Sun"
t.strftime('%W') # => "25"
-==== Week Dates
+=== Week Dates
See {ISO 8601 week dates}[https://en.wikipedia.org/wiki/ISO_8601#Week_dates].
@@ -223,7 +223,7 @@ See {ISO 8601 week dates}[https://en.wikipedia.org/wiki/ISO_8601#Week_dates].
t0.strftime('%V') # => "52"
t1.strftime('%V') # => "01"
-==== Literals
+=== Literals
- <tt>%n</tt> - Newline character "\n":
@@ -237,7 +237,7 @@ See {ISO 8601 week dates}[https://en.wikipedia.org/wiki/ISO_8601#Week_dates].
Time.now.strftime('%%') # => "%"
-==== Shorthand Conversion Specifiers
+=== Shorthand Conversion Specifiers
Each shorthand specifier here is shown with its corresponding
longhand specifier.
@@ -294,14 +294,14 @@ longhand specifier.
DateTime.now.strftime('%a %b %e %H:%M:%S %Z %Y')
# => "Wed Jun 29 08:32:18 -05:00 2022"
-=== Flags
+== Flags
Flags may affect certain formatting specifications.
Multiple flags may be given with a single conversion specified;
order does not matter.
-==== Padding Flags
+=== Padding Flags
- <tt>0</tt> - Pad with zeroes:
@@ -315,7 +315,7 @@ order does not matter.
Time.new(10).strftime('%-Y') # => "10"
-==== Casing Flags
+=== Casing Flags
- <tt>^</tt> - Upcase result:
@@ -328,7 +328,7 @@ order does not matter.
Time.now.strftime('%^p') # => "AM"
Time.now.strftime('%#p') # => "am"
-==== Timezone Flags
+=== Timezone Flags
- <tt>:</tt> - Put timezone as colon-separated hours and minutes:
@@ -338,7 +338,7 @@ order does not matter.
Time.now.strftime('%::z') # => "-05:00:00"
-=== Width Specifiers
+== Width Specifiers
The integer width specifier gives a minimum width for the returned string:
@@ -348,15 +348,15 @@ The integer width specifier gives a minimum width for the returned string:
Time.new(2002, 12).strftime('%10B') # => " December"
Time.new(2002, 12).strftime('%3B') # => "December" # Ignored if too small.
-== Specialized Format Strings
+= Specialized Format Strings
Here are a few specialized format strings,
each based on an external standard.
-=== HTTP Format
+== HTTP Format
The HTTP date format is based on
-{RFC 2616}[https://datatracker.ietf.org/doc/html/rfc2616],
+{RFC 2616}[https://www.rfc-editor.org/rfc/rfc2616],
and treats dates in the format <tt>'%a, %d %b %Y %T GMT'</tt>:
d = Date.new(2001, 2, 3) # => #<Date: 2001-02-03>
@@ -368,10 +368,10 @@ and treats dates in the format <tt>'%a, %d %b %Y %T GMT'</tt>:
Date._httpdate(httpdate)
# => {:wday=>6, :mday=>3, :mon=>2, :year=>2001, :hour=>0, :min=>0, :sec=>0, :zone=>"GMT", :offset=>0}
-=== RFC 3339 Format
+== RFC 3339 Format
The RFC 3339 date format is based on
-{RFC 3339}[https://datatracker.ietf.org/doc/html/rfc3339]:
+{RFC 3339}[https://www.rfc-editor.org/rfc/rfc3339]:
d = Date.new(2001, 2, 3) # => #<Date: 2001-02-03>
# Return 3339-formatted string.
@@ -382,10 +382,10 @@ The RFC 3339 date format is based on
Date._rfc3339(rfc3339)
# => {:year=>2001, :mon=>2, :mday=>3, :hour=>0, :min=>0, :sec=>0, :zone=>"+00:00", :offset=>0}
-=== RFC 2822 Format
+== RFC 2822 Format
The RFC 2822 date format is based on
-{RFC 2822}[https://datatracker.ietf.org/doc/html/rfc2822],
+{RFC 2822}[https://www.rfc-editor.org/rfc/rfc2822],
and treats dates in the format <tt>'%a, %-d %b %Y %T %z'</tt>]:
d = Date.new(2001, 2, 3) # => #<Date: 2001-02-03>
@@ -397,7 +397,7 @@ and treats dates in the format <tt>'%a, %-d %b %Y %T %z'</tt>]:
Date._rfc2822(rfc2822)
# => {:wday=>6, :mday=>3, :mon=>2, :year=>2001, :hour=>0, :min=>0, :sec=>0, :zone=>"+0000", :offset=>0}
-=== JIS X 0301 Format
+== JIS X 0301 Format
The JIS X 0301 format includes the
{Japanese era name}[https://en.wikipedia.org/wiki/Japanese_era_name],
@@ -412,7 +412,7 @@ with the first letter of the romanized era name prefixed:
# Return hash parsed from 0301-formatted string.
Date._jisx0301(jisx0301) # => {:year=>2001, :mon=>2, :mday=>3}
-=== ISO 8601 Format Specifications
+== ISO 8601 Format Specifications
This section shows format specifications that are compatible with
{ISO 8601}[https://en.wikipedia.org/wiki/ISO_8601].
@@ -422,7 +422,7 @@ Examples in this section assume:
t = Time.now # => 2022-06-29 16:49:25.465246 -0500
-==== Dates
+=== Dates
See {ISO 8601 dates}[https://en.wikipedia.org/wiki/ISO_8601#Dates].
@@ -473,7 +473,7 @@ See {ISO 8601 dates}[https://en.wikipedia.org/wiki/ISO_8601#Dates].
t.strftime('%Y-%j') # => "2022-180"
-==== Times
+=== Times
See {ISO 8601 times}[https://en.wikipedia.org/wiki/ISO_8601#Times].
@@ -514,7 +514,7 @@ See {ISO 8601 times}[https://en.wikipedia.org/wiki/ISO_8601#Times].
- {Coordinated Universal Time (UTC)}[https://en.wikipedia.org/wiki/ISO_8601#Coordinated_Universal_Time_(UTC)].
- {Time offsets from UTC}[https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC].
-==== Combined \Date and \Time
+=== Combined \Date and \Time
See {ISO 8601 Combined date and time representations}[https://en.wikipedia.org/wiki/ISO_8601#Combined_date_and_time_representations].
diff --git a/doc/string/split.rdoc b/doc/string/split.rdoc
index 2b5e14ddb6..5ab065093b 100644
--- a/doc/string/split.rdoc
+++ b/doc/string/split.rdoc
@@ -9,7 +9,7 @@ When +field_sep+ is <tt>$;</tt>:
(see below).
- If <tt>$;</tt> is a string,
- the split ocurs just as if +field_sep+ were given as that string
+ the split occurs just as if +field_sep+ were given as that string
(see below).
When +field_sep+ is <tt>' '</tt> and +limit+ is +nil+,
diff --git a/doc/strscan/helper_methods.md b/doc/strscan/helper_methods.md
new file mode 100644
index 0000000000..6555a2ce66
--- /dev/null
+++ b/doc/strscan/helper_methods.md
@@ -0,0 +1,128 @@
+## Helper Methods
+
+These helper methods display values returned by scanner's methods.
+
+### `put_situation(scanner)`
+
+Display scanner's situation:
+
+- Byte position (`#pos`).
+- Character position (`#charpos`)
+- Target string (`#rest`) and size (`#rest_size`).
+
+```
+scanner = StringScanner.new('foobarbaz')
+scanner.scan(/foo/)
+put_situation(scanner)
+# Situation:
+# pos: 3
+# charpos: 3
+# rest: "barbaz"
+# rest_size: 6
+```
+
+### `put_match_values(scanner)`
+
+Display the scanner's match values:
+
+```
+scanner = StringScanner.new('Fri Dec 12 1975 14:39')
+pattern = /(?<wday>\w+) (?<month>\w+) (?<day>\d+) /
+scanner.match?(pattern)
+put_match_values(scanner)
+# Basic match values:
+# matched?: true
+# matched_size: 11
+# pre_match: ""
+# matched : "Fri Dec 12 "
+# post_match: "1975 14:39"
+# Captured match values:
+# size: 4
+# captures: ["Fri", "Dec", "12"]
+# named_captures: {"wday"=>"Fri", "month"=>"Dec", "day"=>"12"}
+# values_at: ["Fri Dec 12 ", "Fri", "Dec", "12", nil]
+# []:
+# [0]: "Fri Dec 12 "
+# [1]: "Fri"
+# [2]: "Dec"
+# [3]: "12"
+# [4]: nil
+```
+
+### `match_values_cleared?(scanner)`
+
+Returns whether the scanner's match values are all properly cleared:
+
+```
+scanner = StringScanner.new('foobarbaz')
+match_values_cleared?(scanner) # => true
+put_match_values(scanner)
+# Basic match values:
+# matched?: false
+# matched_size: nil
+# pre_match: nil
+# matched : nil
+# post_match: nil
+# Captured match values:
+# size: nil
+# captures: nil
+# named_captures: {}
+# values_at: nil
+# [0]: nil
+scanner.scan(/foo/)
+match_values_cleared?(scanner) # => false
+```
+
+## The Code
+
+```
+def put_situation(scanner)
+ puts '# Situation:'
+ puts "# pos: #{scanner.pos}"
+ puts "# charpos: #{scanner.charpos}"
+ puts "# rest: #{scanner.rest.inspect}"
+ puts "# rest_size: #{scanner.rest_size}"
+end
+```
+
+```
+def put_match_values(scanner)
+ puts '# Basic match values:'
+ puts "# matched?: #{scanner.matched?}"
+ value = scanner.matched_size || 'nil'
+ puts "# matched_size: #{value}"
+ puts "# pre_match: #{scanner.pre_match.inspect}"
+ puts "# matched : #{scanner.matched.inspect}"
+ puts "# post_match: #{scanner.post_match.inspect}"
+ puts '# Captured match values:'
+ puts "# size: #{scanner.size}"
+ puts "# captures: #{scanner.captures}"
+ puts "# named_captures: #{scanner.named_captures}"
+ if scanner.size.nil?
+ puts "# values_at: #{scanner.values_at(0)}"
+ puts "# [0]: #{scanner[0]}"
+ else
+ puts "# values_at: #{scanner.values_at(*(0..scanner.size))}"
+ puts "# []:"
+ scanner.size.times do |i|
+ puts "# [#{i}]: #{scanner[i].inspect}"
+ end
+ end
+end
+```
+
+```
+def match_values_cleared?(scanner)
+ scanner.matched? == false &&
+ scanner.matched_size.nil? &&
+ scanner.matched.nil? &&
+ scanner.pre_match.nil? &&
+ scanner.post_match.nil? &&
+ scanner.size.nil? &&
+ scanner[0].nil? &&
+ scanner.captures.nil? &&
+ scanner.values_at(0..1).nil? &&
+ scanner.named_captures == {}
+end
+```
+
diff --git a/doc/strscan/link_refs.txt b/doc/strscan/link_refs.txt
new file mode 100644
index 0000000000..19f6f7ce5c
--- /dev/null
+++ b/doc/strscan/link_refs.txt
@@ -0,0 +1,17 @@
+[1]: rdoc-ref:StringScanner@Stored+String
+[2]: rdoc-ref:StringScanner@Byte+Position+-28Position-29
+[3]: rdoc-ref:StringScanner@Target+Substring
+[4]: rdoc-ref:StringScanner@Setting+the+Target+Substring
+[5]: rdoc-ref:StringScanner@Traversing+the+Target+Substring
+[6]: https://docs.ruby-lang.org/en/master/Regexp.html
+[7]: rdoc-ref:StringScanner@Character+Position
+[8]: https://docs.ruby-lang.org/en/master/String.html#method-i-5B-5D
+[9]: rdoc-ref:StringScanner@Match+Values
+[10]: rdoc-ref:StringScanner@Fixed-Anchor+Property
+[11]: rdoc-ref:StringScanner@Positions
+[13]: rdoc-ref:StringScanner@Captured+Match+Values
+[14]: rdoc-ref:StringScanner@Querying+the+Target+Substring
+[15]: rdoc-ref:StringScanner@Searching+the+Target+Substring
+[16]: https://docs.ruby-lang.org/en/master/Regexp.html#class-Regexp-label-Groups+and+Captures
+[17]: rdoc-ref:StringScanner@Matching
+[18]: rdoc-ref:StringScanner@Basic+Match+Values
diff --git a/doc/strscan/methods/get_byte.md b/doc/strscan/methods/get_byte.md
new file mode 100644
index 0000000000..2f23be1899
--- /dev/null
+++ b/doc/strscan/methods/get_byte.md
@@ -0,0 +1,30 @@
+call-seq:
+ get_byte -> byte_as_character or nil
+
+Returns the next byte, if available:
+
+- If the [position][2]
+ is not at the end of the [stored string][1]:
+
+ - Returns the next byte.
+ - Increments the [byte position][2].
+ - Adjusts the [character position][7].
+
+ ```
+ scanner = StringScanner.new(HIRAGANA_TEXT)
+ # => #<StringScanner 0/15 @ "\xE3\x81\x93\xE3\x82...">
+ scanner.string # => "ã“ã‚“ã«ã¡ã¯"
+ [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\xE3", 1, 1]
+ [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\x81", 2, 2]
+ [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\x93", 3, 1]
+ [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\xE3", 4, 2]
+ [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\x82", 5, 3]
+ [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\x93", 6, 2]
+ ```
+
+- Otherwise, returns `nil`, and does not change the positions.
+
+ ```
+ scanner.terminate
+ [scanner.get_byte, scanner.pos, scanner.charpos] # => [nil, 15, 5]
+ ```
diff --git a/doc/strscan/methods/get_charpos.md b/doc/strscan/methods/get_charpos.md
new file mode 100644
index 0000000000..f77563c860
--- /dev/null
+++ b/doc/strscan/methods/get_charpos.md
@@ -0,0 +1,19 @@
+call-seq:
+ charpos -> character_position
+
+Returns the [character position][7] (initially zero),
+which may be different from the [byte position][2]
+given by method #pos:
+
+```
+scanner = StringScanner.new(HIRAGANA_TEXT)
+scanner.string # => "ã“ã‚“ã«ã¡ã¯"
+scanner.getch # => "ã“" # 3-byte character.
+scanner.getch # => "ã‚“" # 3-byte character.
+put_situation(scanner)
+# Situation:
+# pos: 6
+# charpos: 2
+# rest: "ã«ã¡ã¯"
+# rest_size: 9
+```
diff --git a/doc/strscan/methods/get_pos.md b/doc/strscan/methods/get_pos.md
new file mode 100644
index 0000000000..56bcef3274
--- /dev/null
+++ b/doc/strscan/methods/get_pos.md
@@ -0,0 +1,14 @@
+call-seq:
+ pos -> byte_position
+
+Returns the integer [byte position][2],
+which may be different from the [character position][7]:
+
+```
+scanner = StringScanner.new(HIRAGANA_TEXT)
+scanner.string # => "ã“ã‚“ã«ã¡ã¯"
+scanner.pos # => 0
+scanner.getch # => "ã“" # 3-byte character.
+scanner.charpos # => 1
+scanner.pos # => 3
+```
diff --git a/doc/strscan/methods/getch.md b/doc/strscan/methods/getch.md
new file mode 100644
index 0000000000..b57732ad7c
--- /dev/null
+++ b/doc/strscan/methods/getch.md
@@ -0,0 +1,43 @@
+call-seq:
+ getch -> character or nil
+
+Returns the next (possibly multibyte) character,
+if available:
+
+- If the [position][2]
+ is at the beginning of a character:
+
+ - Returns the character.
+ - Increments the [character position][7] by 1.
+ - Increments the [byte position][2]
+ by the size (in bytes) of the character.
+
+ ```
+ scanner = StringScanner.new(HIRAGANA_TEXT)
+ scanner.string # => "ã“ã‚“ã«ã¡ã¯"
+ [scanner.getch, scanner.pos, scanner.charpos] # => ["ã“", 3, 1]
+ [scanner.getch, scanner.pos, scanner.charpos] # => ["ã‚“", 6, 2]
+ [scanner.getch, scanner.pos, scanner.charpos] # => ["ã«", 9, 3]
+ [scanner.getch, scanner.pos, scanner.charpos] # => ["ã¡", 12, 4]
+ [scanner.getch, scanner.pos, scanner.charpos] # => ["ã¯", 15, 5]
+ [scanner.getch, scanner.pos, scanner.charpos] # => [nil, 15, 5]
+ ```
+
+- If the [position][2] is within a multi-byte character
+ (that is, not at its beginning),
+ behaves like #get_byte (returns a 1-byte character):
+
+ ```
+ scanner.pos = 1
+ [scanner.getch, scanner.pos, scanner.charpos] # => ["\x81", 2, 2]
+ [scanner.getch, scanner.pos, scanner.charpos] # => ["\x93", 3, 1]
+ [scanner.getch, scanner.pos, scanner.charpos] # => ["ã‚“", 6, 2]
+ ```
+
+- If the [position][2] is at the end of the [stored string][1],
+ returns `nil` and does not modify the positions:
+
+ ```
+ scanner.terminate
+ [scanner.getch, scanner.pos, scanner.charpos] # => [nil, 15, 5]
+ ```
diff --git a/doc/strscan/methods/scan.md b/doc/strscan/methods/scan.md
new file mode 100644
index 0000000000..714fa9910a
--- /dev/null
+++ b/doc/strscan/methods/scan.md
@@ -0,0 +1,51 @@
+call-seq:
+ scan(pattern) -> substring or nil
+
+Attempts to [match][17] the given `pattern`
+at the beginning of the [target substring][3].
+
+If the match succeeds:
+
+- Returns the matched substring.
+- Increments the [byte position][2] by <tt>substring.bytesize</tt>,
+ and may increment the [character position][7].
+- Sets [match values][9].
+
+```
+scanner = StringScanner.new(HIRAGANA_TEXT)
+scanner.string # => "ã“ã‚“ã«ã¡ã¯"
+scanner.pos = 6
+scanner.scan(/ã«/) # => "ã«"
+put_match_values(scanner)
+# Basic match values:
+# matched?: true
+# matched_size: 3
+# pre_match: "ã“ã‚“"
+# matched : "ã«"
+# post_match: "ã¡ã¯"
+# Captured match values:
+# size: 1
+# captures: []
+# named_captures: {}
+# values_at: ["ã«", nil]
+# []:
+# [0]: "ã«"
+# [1]: nil
+put_situation(scanner)
+# Situation:
+# pos: 9
+# charpos: 3
+# rest: "ã¡ã¯"
+# rest_size: 6
+```
+
+If the match fails:
+
+- Returns `nil`.
+- Does not increment byte and character positions.
+- Clears match values.
+
+```
+scanner.scan(/nope/) # => nil
+match_values_cleared?(scanner) # => true
+```
diff --git a/doc/strscan/methods/scan_until.md b/doc/strscan/methods/scan_until.md
new file mode 100644
index 0000000000..3b7ff2c3a9
--- /dev/null
+++ b/doc/strscan/methods/scan_until.md
@@ -0,0 +1,52 @@
+call-seq:
+ scan_until(pattern) -> substring or nil
+
+Attempts to [match][17] the given `pattern`
+anywhere (at any [position][2]) in the [target substring][3].
+
+If the match attempt succeeds:
+
+- Sets [match values][9].
+- Sets the [byte position][2] to the end of the matched substring;
+ may adjust the [character position][7].
+- Returns the matched substring.
+
+
+```
+scanner = StringScanner.new(HIRAGANA_TEXT)
+scanner.string # => "ã“ã‚“ã«ã¡ã¯"
+scanner.pos = 6
+scanner.scan_until(/ã¡/) # => "ã«ã¡"
+put_match_values(scanner)
+# Basic match values:
+# matched?: true
+# matched_size: 3
+# pre_match: "ã“ã‚“ã«"
+# matched : "ã¡"
+# post_match: "ã¯"
+# Captured match values:
+# size: 1
+# captures: []
+# named_captures: {}
+# values_at: ["ã¡", nil]
+# []:
+# [0]: "ã¡"
+# [1]: nil
+put_situation(scanner)
+# Situation:
+# pos: 12
+# charpos: 4
+# rest: "ã¯"
+# rest_size: 3
+```
+
+If the match attempt fails:
+
+- Clears match data.
+- Returns `nil`.
+- Does not update positions.
+
+```
+scanner.scan_until(/nope/) # => nil
+match_values_cleared?(scanner) # => true
+```
diff --git a/doc/strscan/methods/set_pos.md b/doc/strscan/methods/set_pos.md
new file mode 100644
index 0000000000..230177109c
--- /dev/null
+++ b/doc/strscan/methods/set_pos.md
@@ -0,0 +1,27 @@
+call-seq:
+ pos = n -> n
+ pointer = n -> n
+
+Sets the [byte position][2] and the [character position][11];
+returns `n`.
+
+Does not affect [match values][9].
+
+For non-negative `n`, sets the position to `n`:
+
+```
+scanner = StringScanner.new(HIRAGANA_TEXT)
+scanner.string # => "ã“ã‚“ã«ã¡ã¯"
+scanner.pos = 3 # => 3
+scanner.rest # => "ã‚“ã«ã¡ã¯"
+scanner.charpos # => 1
+```
+
+For negative `n`, counts from the end of the [stored string][1]:
+
+```
+scanner.pos = -9 # => -9
+scanner.pos # => 6
+scanner.rest # => "ã«ã¡ã¯"
+scanner.charpos # => 2
+```
diff --git a/doc/strscan/methods/skip.md b/doc/strscan/methods/skip.md
new file mode 100644
index 0000000000..656f134c5a
--- /dev/null
+++ b/doc/strscan/methods/skip.md
@@ -0,0 +1,43 @@
+call-seq:
+ skip(pattern) match_size or nil
+
+Attempts to [match][17] the given `pattern`
+at the beginning of the [target substring][3];
+
+If the match succeeds:
+
+- Increments the [byte position][2] by substring.bytesize,
+ and may increment the [character position][7].
+- Sets [match values][9].
+- Returns the size (bytes) of the matched substring.
+
+```
+scanner = StringScanner.new(HIRAGANA_TEXT)
+scanner.string # => "ã“ã‚“ã«ã¡ã¯"
+scanner.pos = 6
+scanner.skip(/ã«/) # => 3
+put_match_values(scanner)
+# Basic match values:
+# matched?: true
+# matched_size: 3
+# pre_match: "ã“ã‚“"
+# matched : "ã«"
+# post_match: "ã¡ã¯"
+# Captured match values:
+# size: 1
+# captures: []
+# named_captures: {}
+# values_at: ["ã«", nil]
+# []:
+# [0]: "ã«"
+# [1]: nil
+put_situation(scanner)
+# Situation:
+# pos: 9
+# charpos: 3
+# rest: "ã¡ã¯"
+# rest_size: 6
+
+scanner.skip(/nope/) # => nil
+match_values_cleared?(scanner) # => true
+```
diff --git a/doc/strscan/methods/skip_until.md b/doc/strscan/methods/skip_until.md
new file mode 100644
index 0000000000..5187a4826f
--- /dev/null
+++ b/doc/strscan/methods/skip_until.md
@@ -0,0 +1,49 @@
+call-seq:
+ skip_until(pattern) -> matched_substring_size or nil
+
+Attempts to [match][17] the given `pattern`
+anywhere (at any [position][2]) in the [target substring][3];
+does not modify the positions.
+
+If the match attempt succeeds:
+
+- Sets [match values][9].
+- Returns the size of the matched substring.
+
+```
+scanner = StringScanner.new(HIRAGANA_TEXT)
+scanner.string # => "ã“ã‚“ã«ã¡ã¯"
+scanner.pos = 6
+scanner.skip_until(/ã¡/) # => 6
+put_match_values(scanner)
+# Basic match values:
+# matched?: true
+# matched_size: 3
+# pre_match: "ã“ã‚“ã«"
+# matched : "ã¡"
+# post_match: "ã¯"
+# Captured match values:
+# size: 1
+# captures: []
+# named_captures: {}
+# values_at: ["ã¡", nil]
+# []:
+# [0]: "ã¡"
+# [1]: nil
+put_situation(scanner)
+# Situation:
+# pos: 12
+# charpos: 4
+# rest: "ã¯"
+# rest_size: 3
+```
+
+If the match attempt fails:
+
+- Clears match values.
+- Returns `nil`.
+
+```
+scanner.skip_until(/nope/) # => nil
+match_values_cleared?(scanner) # => true
+```
diff --git a/doc/strscan/methods/terminate.md b/doc/strscan/methods/terminate.md
new file mode 100644
index 0000000000..fd55727099
--- /dev/null
+++ b/doc/strscan/methods/terminate.md
@@ -0,0 +1,30 @@
+call-seq:
+ terminate -> self
+
+Sets the scanner to end-of-string;
+returns +self+:
+
+- Sets both [positions][11] to end-of-stream.
+- Clears [match values][9].
+
+```
+scanner = StringScanner.new(HIRAGANA_TEXT)
+scanner.string # => "ã“ã‚“ã«ã¡ã¯"
+scanner.scan_until(/ã«/)
+put_situation(scanner)
+# Situation:
+# pos: 9
+# charpos: 3
+# rest: "ã¡ã¯"
+# rest_size: 6
+match_values_cleared?(scanner) # => false
+
+scanner.terminate # => #<StringScanner fin>
+put_situation(scanner)
+# Situation:
+# pos: 15
+# charpos: 5
+# rest: ""
+# rest_size: 0
+match_values_cleared?(scanner) # => true
+```
diff --git a/doc/strscan/strscan.md b/doc/strscan/strscan.md
new file mode 100644
index 0000000000..465cebd4cb
--- /dev/null
+++ b/doc/strscan/strscan.md
@@ -0,0 +1,543 @@
+\Class `StringScanner` supports processing a stored string as a stream;
+this code creates a new `StringScanner` object with string `'foobarbaz'`:
+
+```
+require 'strscan'
+scanner = StringScanner.new('foobarbaz')
+```
+
+## About the Examples
+
+All examples here assume that `StringScanner` has been required:
+
+```
+require 'strscan'
+```
+
+Some examples here assume that these constants are defined:
+
+```
+MULTILINE_TEXT = <<~EOT
+Go placidly amid the noise and haste,
+and remember what peace there may be in silence.
+EOT
+
+HIRAGANA_TEXT = 'ã“ã‚“ã«ã¡ã¯'
+
+ENGLISH_TEXT = 'Hello'
+```
+
+Some examples here assume that certain helper methods are defined:
+
+- `put_situation(scanner)`:
+ Displays the values of the scanner's
+ methods #pos, #charpos, #rest, and #rest_size.
+- `put_match_values(scanner)`:
+ Displays the scanner's [match values][9].
+- `match_values_cleared?(scanner)`:
+ Returns whether the scanner's [match values][9] are cleared.
+
+See examples [here][ext/strscan/helper_methods_md.html].
+
+## The `StringScanner` \Object
+
+This code creates a `StringScanner` object
+(we'll call it simply a _scanner_),
+and shows some of its basic properties:
+
+```
+scanner = StringScanner.new('foobarbaz')
+scanner.string # => "foobarbaz"
+put_situation(scanner)
+# Situation:
+# pos: 0
+# charpos: 0
+# rest: "foobarbaz"
+# rest_size: 9
+```
+
+The scanner has:
+
+* A <i>stored string</i>, which is:
+
+ * Initially set by StringScanner.new(string) to the given `string`
+ (`'foobarbaz'` in the example above).
+ * Modifiable by methods #string=(new_string) and #concat(more_string).
+ * Returned by method #string.
+
+ More at [Stored String][1] below.
+
+* A _position_;
+ a zero-based index into the bytes of the stored string (_not_ into its characters):
+
+ * Initially set by StringScanner.new to `0`.
+ * Returned by method #pos.
+ * Modifiable explicitly by methods #reset, #terminate, and #pos=(new_pos).
+ * Modifiable implicitly (various traversing methods, among others).
+
+ More at [Byte Position][2] below.
+
+* A <i>target substring</i>,
+ which is a trailing substring of the stored string;
+ it extends from the current position to the end of the stored string:
+
+ * Initially set by StringScanner.new(string) to the given `string`
+ (`'foobarbaz'` in the example above).
+ * Returned by method #rest.
+ * Modified by any modification to either the stored string or the position.
+
+ <b>Most importantly</b>:
+ the searching and traversing methods operate on the target substring,
+ which may be (and often is) less than the entire stored string.
+
+ More at [Target Substring][3] below.
+
+## Stored \String
+
+The <i>stored string</i> is the string stored in the `StringScanner` object.
+
+Each of these methods sets, modifies, or returns the stored string:
+
+| Method | Effect |
+|----------------------|-------------------------------------------------|
+| ::new(string) | Creates a new scanner for the given string. |
+| #string=(new_string) | Replaces the existing stored string. |
+| #concat(more_string) | Appends a string to the existing stored string. |
+| #string | Returns the stored string. |
+
+## Positions
+
+A `StringScanner` object maintains a zero-based <i>byte position</i>
+and a zero-based <i>character position</i>.
+
+Each of these methods explicitly sets positions:
+
+| Method | Effect |
+|--------------------------|----------------------------------------------------------|
+| #reset | Sets both positions to zero (begining of stored string). |
+| #terminate | Sets both positions to the end of the stored string. |
+| #pos=(new_byte_position) | Sets byte position; adjusts character position. |
+
+### Byte Position (Position)
+
+The byte position (or simply _position_)
+is a zero-based index into the bytes in the scanner's stored string;
+for a new `StringScanner` object, the byte position is zero.
+
+When the byte position is:
+
+* Zero (at the beginning), the target substring is the entire stored string.
+* Equal to the size of the stored string (at the end),
+ the target substring is the empty string `''`.
+
+To get or set the byte position:
+
+* \#pos: returns the byte position.
+* \#pos=(new_pos): sets the byte position.
+
+Many methods use the byte position as the basis for finding matches;
+many others set, increment, or decrement the byte position:
+
+```
+scanner = StringScanner.new('foobar')
+scanner.pos # => 0
+scanner.scan(/foo/) # => "foo" # Match found.
+scanner.pos # => 3 # Byte position incremented.
+scanner.scan(/foo/) # => nil # Match not found.
+scanner.pos # => 3 # Byte position not changed.
+```
+
+Some methods implicitly modify the byte position;
+see:
+
+* [Setting the Target Substring][4].
+* [Traversing the Target Substring][5].
+
+The values of these methods are derived directly from the values of #pos and #string:
+
+- \#charpos: the [character position][7].
+- \#rest: the [target substring][3].
+- \#rest_size: `rest.size`.
+
+### Character Position
+
+The character position is a zero-based index into the _characters_
+in the stored string;
+for a new `StringScanner` object, the character position is zero.
+
+\Method #charpos returns the character position;
+its value may not be reset explicitly.
+
+Some methods change (increment or reset) the character position;
+see:
+
+* [Setting the Target Substring][4].
+* [Traversing the Target Substring][5].
+
+Example (string includes multi-byte characters):
+
+```
+scanner = StringScanner.new(ENGLISH_TEXT) # Five 1-byte characters.
+scanner.concat(HIRAGANA_TEXT) # Five 3-byte characters
+scanner.string # => "Helloã“ã‚“ã«ã¡ã¯" # Twenty bytes in all.
+put_situation(scanner)
+# Situation:
+# pos: 0
+# charpos: 0
+# rest: "Helloã“ã‚“ã«ã¡ã¯"
+# rest_size: 20
+scanner.scan(/Hello/) # => "Hello" # Five 1-byte characters.
+put_situation(scanner)
+# Situation:
+# pos: 5
+# charpos: 5
+# rest: "ã“ã‚“ã«ã¡ã¯"
+# rest_size: 15
+scanner.getch # => "ã“" # One 3-byte character.
+put_situation(scanner)
+# Situation:
+# pos: 8
+# charpos: 6
+# rest: "ã‚“ã«ã¡ã¯"
+# rest_size: 12```
+
+## Target Substring
+
+The target substring is the the part of the [stored string][1]
+that extends from the current [byte position][2] to the end of the stored string;
+it is always either:
+
+- The entire stored string (byte position is zero).
+- A trailing substring of the stored string (byte position positive).
+
+The target substring is returned by method #rest,
+and its size is returned by method #rest_size.
+
+Examples:
+
+```
+scanner = StringScanner.new('foobarbaz')
+put_situation(scanner)
+# Situation:
+# pos: 0
+# charpos: 0
+# rest: "foobarbaz"
+# rest_size: 9
+scanner.pos = 3
+put_situation(scanner)
+# Situation:
+# pos: 3
+# charpos: 3
+# rest: "barbaz"
+# rest_size: 6
+scanner.pos = 9
+put_situation(scanner)
+# Situation:
+# pos: 9
+# charpos: 9
+# rest: ""
+# rest_size: 0
+```
+
+### Setting the Target Substring
+
+The target substring is set whenever:
+
+* The [stored string][1] is set (position reset to zero; target substring set to stored string).
+* The [byte position][2] is set (target substring adjusted accordingly).
+
+### Querying the Target Substring
+
+This table summarizes (details and examples at the links):
+
+| Method | Returns |
+|------------|-----------------------------------|
+| #rest | Target substring. |
+| #rest_size | Size (bytes) of target substring. |
+
+### Searching the Target Substring
+
+A _search_ method examines the target substring,
+but does not advance the [positions][11]
+or (by implication) shorten the target substring.
+
+This table summarizes (details and examples at the links):
+
+| Method | Returns | Sets Match Values? |
+|-----------------------|-----------------------------------------------|--------------------|
+| #check(pattern) | Matched leading substring or +nil+. | Yes. |
+| #check_until(pattern) | Matched substring (anywhere) or +nil+. | Yes. |
+| #exist?(pattern) | Matched substring (anywhere) end index. | Yes. |
+| #match?(pattern) | Size of matched leading substring or +nil+. | Yes. |
+| #peek(size) | Leading substring of given length (bytes). | No. |
+| #peek_byte | Integer leading byte or +nil+. | No. |
+| #rest | Target substring (from byte position to end). | No. |
+
+### Traversing the Target Substring
+
+A _traversal_ method examines the target substring,
+and, if successful:
+
+- Advances the [positions][11].
+- Shortens the target substring.
+
+
+This table summarizes (details and examples at links):
+
+| Method | Returns | Sets Match Values? |
+|----------------------|------------------------------------------------------|--------------------|
+| #get_byte | Leading byte or +nil+. | No. |
+| #getch | Leading character or +nil+. | No. |
+| #scan(pattern) | Matched leading substring or +nil+. | Yes. |
+| #scan_byte | Integer leading byte or +nil+. | No. |
+| #scan_until(pattern) | Matched substring (anywhere) or +nil+. | Yes. |
+| #skip(pattern) | Matched leading substring size or +nil+. | Yes. |
+| #skip_until(pattern) | Position delta to end-of-matched-substring or +nil+. | Yes. |
+| #unscan | +self+. | No. |
+
+## Querying the Scanner
+
+Each of these methods queries the scanner object
+without modifying it (details and examples at links)
+
+| Method | Returns |
+|---------------------|----------------------------------|
+| #beginning_of_line? | +true+ or +false+. |
+| #charpos | Character position. |
+| #eos? | +true+ or +false+. |
+| #fixed_anchor? | +true+ or +false+. |
+| #inspect | String representation of +self+. |
+| #pos | Byte position. |
+| #rest | Target substring. |
+| #rest_size | Size of target substring. |
+| #string | Stored string. |
+
+## Matching
+
+`StringScanner` implements pattern matching via Ruby class [Regexp][6],
+and its matching behaviors are the same as Ruby's
+except for the [fixed-anchor property][10].
+
+### Matcher Methods
+
+Each <i>matcher method</i> takes a single argument `pattern`,
+and attempts to find a matching substring in the [target substring][3].
+
+| Method | Pattern Type | Matches Target Substring | Success Return | May Update Positions? |
+|--------------|-------------------|--------------------------|--------------------|-----------------------|
+| #check | Regexp or String. | At beginning. | Matched substring. | No. |
+| #check_until | Regexp. | Anywhere. | Substring. | No. |
+| #match? | Regexp or String. | At beginning. | Updated position. | No. |
+| #exist? | Regexp. | Anywhere. | Updated position. | No. |
+| #scan | Regexp or String. | At beginning. | Matched substring. | Yes. |
+| #scan_until | Regexp. | Anywhere. | Substring. | Yes. |
+| #skip | Regexp or String. | At beginning. | Match size. | Yes. |
+| #skip_until | Regexp. | Anywhere. | Position delta. | Yes. |
+
+<br>
+
+Which matcher you choose will depend on:
+
+- Where you want to find a match:
+
+ - Only at the beginning of the target substring:
+ #check, #match?, #scan, #skip.
+ - Anywhere in the target substring:
+ #check_until, #exist?, #scan_until, #skip_until.
+
+- Whether you want to:
+
+ - Traverse, by advancing the positions:
+ #scan, #scan_until, #skip, #skip_until.
+ - Keep the positions unchanged:
+ #check, #check_until, #exist?, #match?.
+
+- What you want for the return value:
+
+ - The matched substring: #check, #check_until, #scan, #scan_until.
+ - The updated position: #exist?, #match?.
+ - The position delta: #skip_until.
+ - The match size: #skip.
+
+### Match Values
+
+The <i>match values</i> in a `StringScanner` object
+generally contain the results of the most recent attempted match.
+
+Each match value may be thought of as:
+
+* _Clear_: Initially, or after an unsuccessful match attempt:
+ usually, `false`, `nil`, or `{}`.
+* _Set_: After a successful match attempt:
+ `true`, string, array, or hash.
+
+Each of these methods clears match values:
+
+- ::new(string).
+- \#reset.
+- \#terminate.
+
+Each of these methods attempts a match based on a pattern,
+and either sets match values (if successful) or clears them (if not);
+
+- \#check(pattern)
+- \#check_until(pattern)
+- \#exist?(pattern)
+- \#match?(pattern)
+- \#scan(pattern)
+- \#scan_until(pattern)
+- \#skip(pattern)
+- \#skip_until(pattern)
+
+#### Basic Match Values
+
+Basic match values are those not related to captures.
+
+Each of these methods returns a basic match value:
+
+| Method | Return After Match | Return After No Match |
+|-----------------|----------------------------------------|-----------------------|
+| #matched? | +true+. | +false+. |
+| #matched_size | Size of matched substring. | +nil+. |
+| #matched | Matched substring. | +nil+. |
+| #pre_match | Substring preceding matched substring. | +nil+. |
+| #post_match | Substring following matched substring. | +nil+. |
+
+<br>
+
+See examples below.
+
+#### Captured Match Values
+
+Captured match values are those related to [captures][16].
+
+Each of these methods returns a captured match value:
+
+| Method | Return After Match | Return After No Match |
+|-----------------|-----------------------------------------|-----------------------|
+| #size | Count of captured substrings. | +nil+. |
+| #[](n) | <tt>n</tt>th captured substring. | +nil+. |
+| #captures | Array of all captured substrings. | +nil+. |
+| #values_at(*n) | Array of specified captured substrings. | +nil+. |
+| #named_captures | Hash of named captures. | <tt>{}</tt>. |
+
+<br>
+
+See examples below.
+
+#### Match Values Examples
+
+Successful basic match attempt (no captures):
+
+```
+scanner = StringScanner.new('foobarbaz')
+scanner.exist?(/bar/)
+put_match_values(scanner)
+# Basic match values:
+# matched?: true
+# matched_size: 3
+# pre_match: "foo"
+# matched : "bar"
+# post_match: "baz"
+# Captured match values:
+# size: 1
+# captures: []
+# named_captures: {}
+# values_at: ["bar", nil]
+# []:
+# [0]: "bar"
+# [1]: nil
+```
+
+Failed basic match attempt (no captures);
+
+```
+scanner = StringScanner.new('foobarbaz')
+scanner.exist?(/nope/)
+match_values_cleared?(scanner) # => true
+```
+
+Successful unnamed capture match attempt:
+
+```
+scanner = StringScanner.new('foobarbazbatbam')
+scanner.exist?(/(foo)bar(baz)bat(bam)/)
+put_match_values(scanner)
+# Basic match values:
+# matched?: true
+# matched_size: 15
+# pre_match: ""
+# matched : "foobarbazbatbam"
+# post_match: ""
+# Captured match values:
+# size: 4
+# captures: ["foo", "baz", "bam"]
+# named_captures: {}
+# values_at: ["foobarbazbatbam", "foo", "baz", "bam", nil]
+# []:
+# [0]: "foobarbazbatbam"
+# [1]: "foo"
+# [2]: "baz"
+# [3]: "bam"
+# [4]: nil
+```
+
+Successful named capture match attempt;
+same as unnamed above, except for #named_captures:
+
+```
+scanner = StringScanner.new('foobarbazbatbam')
+scanner.exist?(/(?<x>foo)bar(?<y>baz)bat(?<z>bam)/)
+scanner.named_captures # => {"x"=>"foo", "y"=>"baz", "z"=>"bam"}
+```
+
+Failed unnamed capture match attempt:
+
+```
+scanner = StringScanner.new('somestring')
+scanner.exist?(/(foo)bar(baz)bat(bam)/)
+match_values_cleared?(scanner) # => true
+```
+
+Failed named capture match attempt;
+same as unnamed above, except for #named_captures:
+
+```
+scanner = StringScanner.new('somestring')
+scanner.exist?(/(?<x>foo)bar(?<y>baz)bat(?<z>bam)/)
+match_values_cleared?(scanner) # => false
+scanner.named_captures # => {"x"=>nil, "y"=>nil, "z"=>nil}
+```
+
+## Fixed-Anchor Property
+
+Pattern matching in `StringScanner` is the same as in Ruby's,
+except for its fixed-anchor property,
+which determines the meaning of `'\A'`:
+
+* `false` (the default): matches the current byte position.
+
+ ```
+ scanner = StringScanner.new('foobar')
+ scanner.scan(/\A./) # => "f"
+ scanner.scan(/\A./) # => "o"
+ scanner.scan(/\A./) # => "o"
+ scanner.scan(/\A./) # => "b"
+ ```
+
+* `true`: matches the beginning of the target substring;
+ never matches unless the byte position is zero:
+
+ ```
+ scanner = StringScanner.new('foobar', fixed_anchor: true)
+ scanner.scan(/\A./) # => "f"
+ scanner.scan(/\A./) # => nil
+ scanner.reset
+ scanner.scan(/\A./) # => "f"
+ ```
+
+The fixed-anchor property is set when the `StringScanner` object is created,
+and may not be modified
+(see StringScanner.new);
+method #fixed_anchor? returns the setting.
+
diff --git a/doc/syntax/assignment.rdoc b/doc/syntax/assignment.rdoc
index e30cb35adf..f45f5bc0ea 100644
--- a/doc/syntax/assignment.rdoc
+++ b/doc/syntax/assignment.rdoc
@@ -162,9 +162,7 @@ Here is an example of instance variable usage:
p object1.value # prints "some value"
p object2.value # prints "other value"
-An uninitialized instance variable has a value of +nil+. If you run Ruby with
-warnings enabled, you will get a warning when accessing an uninitialized
-instance variable.
+An uninitialized instance variable has a value of +nil+.
The +value+ method has access to the value set by the +initialize+ method, but
only for the same object.
diff --git a/doc/syntax/calling_methods.rdoc b/doc/syntax/calling_methods.rdoc
index da061dbfdb..c2c6c61a10 100644
--- a/doc/syntax/calling_methods.rdoc
+++ b/doc/syntax/calling_methods.rdoc
@@ -210,7 +210,7 @@ definition. If a keyword argument is given that the method did not list,
and the method definition does not accept arbitrary keyword arguments, an
ArgumentError will be raised.
-Keyword argument value can be omitted, meaning the value will be be fetched
+Keyword argument value can be omitted, meaning the value will be fetched
from the context by the name of the key
keyword1 = 'some value'
@@ -322,18 +322,6 @@ Both are equivalent to:
my_method(1, 2, 3)
-If the method accepts keyword arguments, the splat operator will convert a
-hash at the end of the array into keyword arguments:
-
- def my_method(a, b, c: 3)
- end
-
- arguments = [1, 2, { c: 4 }]
- my_method(*arguments)
-
-Note that this behavior is currently deprecated and will emit a warning.
-This behavior will be removed in Ruby 3.0.
-
You may also use the <code>**</code> (described next) to convert a Hash into
keyword arguments.
diff --git a/doc/syntax/control_expressions.rdoc b/doc/syntax/control_expressions.rdoc
index 5350585f15..9126289389 100644
--- a/doc/syntax/control_expressions.rdoc
+++ b/doc/syntax/control_expressions.rdoc
@@ -189,7 +189,7 @@ The same is true for +unless+.
The +case+ expression can be used in two ways.
The most common way is to compare an object against multiple patterns. The
-patterns are matched using the +===+ method which is aliased to +==+ on
+patterns are matched using the <tt>===</tt> method which is aliased to <tt>==</tt> on
Object. Other classes must override it to give meaningful behavior. See
Module#=== and Regexp#=== for examples.
diff --git a/doc/syntax/exceptions.rdoc b/doc/syntax/exceptions.rdoc
index 31e2f0175c..ac5ff78a95 100644
--- a/doc/syntax/exceptions.rdoc
+++ b/doc/syntax/exceptions.rdoc
@@ -86,7 +86,7 @@ To always run some code whether an exception was raised or not, use +ensure+:
rescue
# ...
ensure
- # this always runs
+ # this always runs BUT does not implicitly return the last evaluated statement.
end
You may also run some code when an exception is not raised:
@@ -96,7 +96,11 @@ You may also run some code when an exception is not raised:
rescue
# ...
else
- # this runs only when no exception was raised
+ # this runs only when no exception was raised AND return the last evaluated statement
ensure
- # ...
+ # this always runs.
+ # It is evaluated after the evaluation of either the `rescue` or the `else` block.
+ # It will not return implicitly.
end
+
+NB : Without explicit +return+ in the +ensure+ block, +begin+/+end+ block will return the last evaluated statement before entering in the `ensure` block.
diff --git a/doc/syntax/literals.rdoc b/doc/syntax/literals.rdoc
index 0c1e4a434b..6d681419a2 100644
--- a/doc/syntax/literals.rdoc
+++ b/doc/syntax/literals.rdoc
@@ -138,19 +138,18 @@ Also \Rational numbers may be imaginary numbers.
== Strings
-=== \String Literals
-
-The most common way of writing strings is using <tt>"</tt>:
-
- "This is a string."
-
-The string may be many lines long.
-
-Any internal <tt>"</tt> must be escaped:
-
- "This string has a quote: \". As you can see, it is escaped"
-
-Double-quote strings allow escaped characters such as <tt>\n</tt> for
+=== Escape Sequences
+
+Some characters can be represented as escape sequences in
+double-quoted strings,
+character literals,
+here document literals (non-quoted, double-quoted, and with backticks),
+double-quoted symbols,
+double-quoted symbol keys in Hash literals,
+Regexp literals, and
+several percent literals (<tt>%</tt>, <tt>%Q,</tt> <tt>%W</tt>, <tt>%I</tt>, <tt>%r</tt>, <tt>%x</tt>).
+
+They allow escape sequences such as <tt>\n</tt> for
newline, <tt>\t</tt> for tab, etc. The full list of supported escape
sequences are as follows:
@@ -174,11 +173,31 @@ sequences are as follows:
\M-\cx same as above
\c\M-x same as above
\c? or \C-? delete, ASCII 7Fh (DEL)
+ \<newline> continuation line (empty string)
+
+The last one, <tt>\<newline></tt>, represents an empty string instead of a character.
+It is used to fold a line in a string.
+
+=== Double-quoted \String Literals
-Any other character following a backslash is interpreted as the
+The most common way of writing strings is using <tt>"</tt>:
+
+ "This is a string."
+
+The string may be many lines long.
+
+Any internal <tt>"</tt> must be escaped:
+
+ "This string has a quote: \". As you can see, it is escaped"
+
+Double-quoted strings allow escape sequences described in
+{Escape Sequences}[#label-Escape+Sequences].
+
+In a double-quoted string,
+any other character following a backslash is interpreted as the
character itself.
-Double-quote strings allow interpolation of other values using
+Double-quoted strings allow interpolation of other values using
<tt>#{...}</tt>:
"One plus one is two: #{1 + 1}"
@@ -190,8 +209,14 @@ You can also use <tt>#@foo</tt>, <tt>#@@foo</tt> and <tt>#$foo</tt> as a
shorthand for, respectively, <tt>#{ @foo }</tt>, <tt>#{ @@foo }</tt> and
<tt>#{ $foo }</tt>.
+See also:
+
+* {% and %Q: Interpolable String Literals}[#label-25+and+-25Q-3A+Interpolable+String+Literals]
+
+=== Single-quoted \String Literals
+
Interpolation may be disabled by escaping the "#" character or using
-single-quote strings:
+single-quoted strings:
'#{1 + 1}' #=> "\#{1 + 1}"
@@ -199,6 +224,16 @@ In addition to disabling interpolation, single-quoted strings also disable all
escape sequences except for the single-quote (<tt>\'</tt>) and backslash
(<tt>\\\\</tt>).
+In a single-quoted string,
+any other character following a backslash is interpreted as is:
+a backslash and the character itself.
+
+See also:
+
+* {%q: Non-Interpolable String Literals}[#label-25q-3A+Non-Interpolable+String+Literals]
+
+=== Literal String Concatenation
+
Adjacent string literals are automatically concatenated by the interpreter:
"con" "cat" "en" "at" "ion" #=> "concatenation"
@@ -211,10 +246,12 @@ be concatenated as long as a percent-string is not last.
%q{a} 'b' "c" #=> "abc"
"a" 'b' %q{c} #=> NameError: uninitialized constant q
+=== Character Literal
+
There is also a character literal notation to represent single
character strings, which syntax is a question mark (<tt>?</tt>)
-followed by a single character or escape sequence that corresponds to
-a single codepoint in the script encoding:
+followed by a single character or escape sequence (except continuation line)
+that corresponds to a single codepoint in the script encoding:
?a #=> "a"
?abc #=> SyntaxError
@@ -228,11 +265,6 @@ a single codepoint in the script encoding:
?\C-\M-a #=> "\x81", same as above
?ã‚ #=> "ã‚"
-See also:
-
-* {%q: Non-Interpolable String Literals}[#label-25q-3A+Non-Interpolable+String+Literals]
-* {% and %Q: Interpolable String Literals}[#label-25+and+-25Q-3A+Interpolable+String+Literals]
-
=== Here Document Literals
If you are writing a large block of text you may use a "here document" or
@@ -283,9 +315,10 @@ its end is a multiple of eight. The amount to be removed is counted in terms
of the number of spaces. If the boundary appears in the middle of a tab, that
tab is not removed.
-A heredoc allows interpolation and escaped characters. You may disable
-interpolation and escaping by surrounding the opening identifier with single
-quotes:
+A heredoc allows interpolation and the escape sequences described in
+{Escape Sequences}[#label-Escape+Sequences].
+You may disable interpolation and the escaping by surrounding the opening
+identifier with single quotes:
expected_result = <<-'EXPECTED'
One plus one is #{1 + 1}
@@ -326,12 +359,15 @@ details on what symbols are and when ruby creates them internally.
You may reference a symbol using a colon: <tt>:my_symbol</tt>.
-You may also create symbols by interpolation:
+You may also create symbols by interpolation and escape sequences described in
+{Escape Sequences}[#label-Escape+Sequences] with double-quotes:
:"my_symbol1"
:"my_symbol#{1 + 1}"
+ :"foo\sbar"
-Like strings, a single-quote may be used to disable interpolation:
+Like strings, a single-quote may be used to disable interpolation and
+escape sequences:
:'my_symbol#{1 + 1}' #=> :"my_symbol\#{1 + 1}"
@@ -451,7 +487,12 @@ may use these paired delimiters:
* <tt>(</tt> and <tt>)</tt>.
* <tt>{</tt> and <tt>}</tt>.
* <tt><</tt> and <tt>></tt>.
-* Any other character, as both beginning and ending delimiters.
+* Non-alphanumeric ASCII character except above, as both beginning and ending delimiters.
+
+The delimiters can be escaped with a backslash.
+However, the first four pairs (brackets, parenthesis, braces, and
+angle brackets) are allowed without backslash as far as they are correctly
+paired.
These are demonstrated in the next section.
@@ -460,13 +501,20 @@ These are demonstrated in the next section.
You can write a non-interpolable string with <tt>%q</tt>.
The created string is the same as if you created it with single quotes:
- %[foo bar baz] # => "foo bar baz" # Using [].
- %(foo bar baz) # => "foo bar baz" # Using ().
- %{foo bar baz} # => "foo bar baz" # Using {}.
- %<foo bar baz> # => "foo bar baz" # Using <>.
- %|foo bar baz| # => "foo bar baz" # Using two |.
- %:foo bar baz: # => "foo bar baz" # Using two :.
+ %q[foo bar baz] # => "foo bar baz" # Using [].
+ %q(foo bar baz) # => "foo bar baz" # Using ().
+ %q{foo bar baz} # => "foo bar baz" # Using {}.
+ %q<foo bar baz> # => "foo bar baz" # Using <>.
+ %q|foo bar baz| # => "foo bar baz" # Using two |.
+ %q:foo bar baz: # => "foo bar baz" # Using two :.
%q(1 + 1 is #{1 + 1}) # => "1 + 1 is \#{1 + 1}" # No interpolation.
+ %q[foo[bar]baz] # => "foo[bar]baz" # brackets can be nested.
+ %q(foo(bar)baz) # => "foo(bar)baz" # parenthesis can be nested.
+ %q{foo{bar}baz} # => "foo{bar}baz" # braces can be nested.
+ %q<foo<bar>baz> # => "foo<bar>baz" # angle brackets can be nested.
+
+This is similar to single-quoted string but only backslashs and
+the specified delimiters can be escaped with a backslash.
=== <tt>% and %Q</tt>: Interpolable String Literals
@@ -476,30 +524,63 @@ or with its alias <tt>%</tt>:
%[foo bar baz] # => "foo bar baz"
%(1 + 1 is #{1 + 1}) # => "1 + 1 is 2" # Interpolation.
+This is similar to double-quoted string.
+It allow escape sequences described in
+{Escape Sequences}[#label-Escape+Sequences].
+Other escaped characters (a backslash followed by a character) are
+interpreted as the character.
+
=== <tt>%w and %W</tt>: String-Array Literals
-You can write an array of strings with <tt>%w</tt> (non-interpolable)
-or <tt>%W</tt> (interpolable):
+You can write an array of strings as whitespace-separated words
+with <tt>%w</tt> (non-interpolable) or <tt>%W</tt> (interpolable):
%w[foo bar baz] # => ["foo", "bar", "baz"]
%w[1 % *] # => ["1", "%", "*"]
# Use backslash to embed spaces in the strings.
%w[foo\ bar baz\ bat] # => ["foo bar", "baz bat"]
+ %W[foo\ bar baz\ bat] # => ["foo bar", "baz bat"]
%w(#{1 + 1}) # => ["\#{1", "+", "1}"]
%W(#{1 + 1}) # => ["2"]
+ # The nested delimiters evaluated to a flat array of strings
+ # (not nested array).
+ %w[foo[bar baz]qux] # => ["foo[bar", "baz]qux"]
+
+The following characters are considered as white spaces to separate words:
+
+* space, ASCII 20h (SPC)
+* form feed, ASCII 0Ch (FF)
+* newline (line feed), ASCII 0Ah (LF)
+* carriage return, ASCII 0Dh (CR)
+* horizontal tab, ASCII 09h (TAB)
+* vertical tab, ASCII 0Bh (VT)
+
+The white space characters can be escaped with a backslash to make them
+part of a word.
+
+<tt>%W</tt> allow escape sequences described in
+{Escape Sequences}[#label-Escape+Sequences].
+However the continuation line <tt>\<newline></tt> is not usable because
+it is interpreted as the escaped newline described above.
+
=== <tt>%i and %I</tt>: Symbol-Array Literals
-You can write an array of symbols with <tt>%i</tt> (non-interpolable)
-or <tt>%I</tt> (interpolable):
+You can write an array of symbols as whitespace-separated words
+with <tt>%i</tt> (non-interpolable) or <tt>%I</tt> (interpolable):
%i[foo bar baz] # => [:foo, :bar, :baz]
%i[1 % *] # => [:"1", :%, :*]
# Use backslash to embed spaces in the symbols.
%i[foo\ bar baz\ bat] # => [:"foo bar", :"baz bat"]
+ %I[foo\ bar baz\ bat] # => [:"foo bar", :"baz bat"]
%i(#{1 + 1}) # => [:"\#{1", :+, :"1}"]
%I(#{1 + 1}) # => [:"2"]
+The white space characters and its escapes are interpreted as the same as
+string-array literals described in
+{%w and %W: String-Array Literals}[#label-25w+and+-25W-3A+String-Array+Literals].
+
=== <tt>%s</tt>: Symbol Literals
You can write a symbol with <tt>%s</tt>:
@@ -507,6 +588,10 @@ You can write a symbol with <tt>%s</tt>:
%s[foo] # => :foo
%s[foo bar] # => :"foo bar"
+This is non-interpolable.
+No interpolation allowed.
+Only backslashs and the specified delimiters can be escaped with a backslash.
+
=== <tt>%r</tt>: Regexp Literals
You can write a regular expression with <tt>%r</tt>;
@@ -531,4 +616,10 @@ See {Regexp modes}[rdoc-ref:Regexp@Modes] for details.
You can write and execute a shell command with <tt>%x</tt>:
- %x(echo 1) # => "1\n"
+ %x(echo 1) # => "1\n"
+ %x[echo #{1 + 2}] # => "3\n"
+ %x[echo \u0030] # => "0\n"
+
+This is interpolable.
+<tt>%x</tt> allow escape sequences described in
+{Escape Sequences}[#label-Escape+Sequences].
diff --git a/doc/syntax/operators.rdoc b/doc/syntax/operators.rdoc
index f972309412..d3045ac99e 100644
--- a/doc/syntax/operators.rdoc
+++ b/doc/syntax/operators.rdoc
@@ -36,7 +36,7 @@ operation that specifies the behavior.
== Logical Operators
-Logical operators are not methods, and therefor cannot be
+Logical operators are not methods, and therefore cannot be
redefined/overloaded. They are tokenized at a lower level.
Short-circuit logical operators (<code>&&</code>, <code>||</code>,
@@ -47,9 +47,9 @@ of the operation.
=== <code>&&</code>, <code>and</code>
Both <code>&&</code>/<code>and</code> operators provide short-circuiting by executing each
-side of the operator, left to right, and stopping at the first occurence of a
+side of the operator, left to right, and stopping at the first occurrence of a
falsey expression. The expression that defines the result is the last one
-executed, whether it be the final expression, or the first occurence of a falsey
+executed, whether it be the final expression, or the first occurrence of a falsey
expression.
Some examples:
diff --git a/doc/syntax/pattern_matching.rdoc b/doc/syntax/pattern_matching.rdoc
index e49c09a1f8..6a30380f46 100644
--- a/doc/syntax/pattern_matching.rdoc
+++ b/doc/syntax/pattern_matching.rdoc
@@ -422,7 +422,8 @@ These core and library classes implement deconstruction:
== Guard clauses
-+if+ can be used to attach an additional condition (guard clause) when the pattern matches. This condition may use bound variables:
++if+ can be used to attach an additional condition (guard clause) when the pattern matches in +case+/+in+ expressions.
+This condition may use bound variables:
case [1, 2]
in a, b if b == a*2
@@ -450,6 +451,11 @@ These core and library classes implement deconstruction:
end
#=> "matched"
+Note that <code>=></code> and +in+ operator can not have a guard clause.
+The following examples is parsed as a standalone expression with modifier +if+.
+
+ [1, 2] in a, b if b == a*2
+
== Appendix A. Pattern syntax
Approximate syntax is:
diff --git a/doc/timezones.rdoc b/doc/timezones.rdoc
deleted file mode 100644
index 18233b97ae..0000000000
--- a/doc/timezones.rdoc
+++ /dev/null
@@ -1,102 +0,0 @@
-== Timezones
-
-=== Timezone Specifiers
-
-Certain \Time methods accept arguments that specify timezones:
-
-- Time.at: keyword argument +in:+.
-- Time.new: positional argument +zone+ or keyword argument +in:+.
-- Time.now: keyword argument +in:+.
-- Time#getlocal: positional argument +zone+.
-- Time#localtime: positional argument +zone+.
-
-The value given with any of these must be one of the following
-(each detailed below):
-
-- {Hours/minutes offset}[rdoc-ref:timezones.rdoc@Hours-2FMinutes+Offsets].
-- {Single-letter offset}[rdoc-ref:timezones.rdoc@Single-Letter+Offsets].
-- {Integer offset}[rdoc-ref:timezones.rdoc@Integer+Offsets].
-- {Timezone object}[rdoc-ref:timezones.rdoc@Timezone+Objects].
-
-==== Hours/Minutes Offsets
-
-The zone value may be a string offset from UTC
-in the form <tt>'+HH:MM'</tt> or <tt>'-HH:MM'</tt>,
-where:
-
-- +HH+ is the 2-digit hour in the range <tt>0..23</tt>.
-- +MM+ is the 2-digit minute in the range <tt>0..59</tt>.
-
-Examples:
-
- t = Time.utc(2000, 1, 1, 20, 15, 1) # => 2000-01-01 20:15:01 UTC
- Time.at(t, in: '-23:59') # => 1999-12-31 20:16:01 -2359
- Time.at(t, in: '+23:59') # => 2000-01-02 20:14:01 +2359
-
-==== Single-Letter Offsets
-
-The zone value may be a letter in the range <tt>'A'..'I'</tt>
-or <tt>'K'..'Z'</tt>;
-see {List of military time zones}[https://en.wikipedia.org/wiki/List_of_military_time_zones]:
-
- t = Time.utc(2000, 1, 1, 20, 15, 1) # => 2000-01-01 20:15:01 UTC
- Time.at(t, in: 'A') # => 2000-01-01 21:15:01 +0100
- Time.at(t, in: 'I') # => 2000-01-02 05:15:01 +0900
- Time.at(t, in: 'K') # => 2000-01-02 06:15:01 +1000
- Time.at(t, in: 'Y') # => 2000-01-01 08:15:01 -1200
- Time.at(t, in: 'Z') # => 2000-01-01 20:15:01 UTC
-
-==== \Integer Offsets
-
-The zone value may be an integer number of seconds
-in the range <tt>-86399..86399</tt>:
-
- t = Time.utc(2000, 1, 1, 20, 15, 1) # => 2000-01-01 20:15:01 UTC
- Time.at(t, in: -86399) # => 1999-12-31 20:15:02 -235959
- Time.at(t, in: 86399) # => 2000-01-02 20:15:00 +235959
-
-==== Timezone Objects
-
-The zone value may be an object responding to certain timezone methods.
-
-The timezone methods are:
-
-- +local_to_utc+:
-
- - Called when Time.new is invoked with +tz+
- as the value of positional argument +zone+ or keyword argument +in:+.
- - Argument: a <tt>Time::tm</tt> object.
- - Returns: a \Time-like object in the UTC timezone.
-
-- +utc_to_local+:
-
- - Called when Time.at or Time.now is invoked with +tz+
- as the value for keyword argument +in:+,
- and when Time#getlocal or Time#localtime is called with +tz+
- as the value for positional argument +zone+.
- - Argument: a <tt>Time::tm</tt> object.
- - Returns: a \Time-like object in the local timezone.
-
-A custom timezone class may have these instance methods,
-which will be called if defined:
-
-- +abbr+:
-
- - Called when Time#strftime is invoked with a format involving <tt>%Z</tt>.
- - Argument: a <tt>Time::tm</tt> object.
- - Returns: a string abbreviation for the timezone name.
-
-- +dst?+:
-
- - Called when Time.at or Time.now is invoked with +tz+
- as the value for keyword argument +in:+,
- and when Time#getlocal or Time#localtime is called with +tz+
- as the value for positional argument +zone+.
- - Argument: a <tt>Time::tm</tt> object.
- - Returns: whether the time is daylight saving time.
-
-- +name+:
-
- - Called when <tt>Marshal.dump(t)</tt> is invoked
- - Argument: none.
- - Returns: the string name of the timezone.
diff --git a/doc/windows.md b/doc/windows.md
index 65c6b15c45..2020eec9cf 100644
--- a/doc/windows.md
+++ b/doc/windows.md
@@ -59,9 +59,9 @@ make
### Requirement
-1. Windows 7 or later.
+1. Windows 10/Windows Server 2016 or later.
-2. Visual C++ 12.0 (2013) or later.
+2. Visual C++ 14.0 (2015) or later.
**Note** if you want to build x64 version, use native compiler for
x64.
@@ -80,7 +80,7 @@ make
4. If you want to build from GIT source, following commands are required.
* patch
* sed
- * ruby 2.0 or later
+ * ruby 3.0 or later
You can use [scoop](https://scoop.sh/) to install them like:
@@ -88,10 +88,11 @@ make
scoop install git ruby sed patch
```
-5. You need to install required libraries using [vcpkg](https://vcpkg.io/) like:
+5. You need to install required libraries using [vcpkg](https://vcpkg.io/) on
+ directory of ruby repository like:
```
- vcpkg --triplet x64-windows install openssl libffi libyaml zlib
+ vcpkg --triplet x64-windows install
```
6. Enable Command Extension of your command line. It's the default behavior
@@ -117,7 +118,7 @@ make
executable without console window if also you want.
3. You need specify vcpkg directory to use `--with-opt-dir`
- option like `configure --with-opt-dir=C:\vcpkg\installed\x64-windows`
+ option like `win32\configure.bat --with-opt-dir=vcpkg_installed\x64-windows`
4. Run `nmake up` if you are building from GIT source.
diff --git a/doc/yjit/yjit.md b/doc/yjit/yjit.md
index 5e3e7e961b..8ea3409e48 100644
--- a/doc/yjit/yjit.md
+++ b/doc/yjit/yjit.md
@@ -4,22 +4,22 @@
</a>
</p>
-
YJIT - Yet Another Ruby JIT
===========================
YJIT is a lightweight, minimalistic Ruby JIT built inside CRuby.
It lazily compiles code using a Basic Block Versioning (BBV) architecture.
-The target use case is that of servers running Ruby on Rails.
YJIT is currently supported for macOS, Linux and BSD on x86-64 and arm64/aarch64 CPUs.
This project is open source and falls under the same license as CRuby.
<p align="center"><b>
If you're using YJIT in production, please
<a href="mailto:maxime.chevalierboisvert@shopify.com">share your success stories with us!</a>
- </b></p>
+</b></p>
If you wish to learn more about the approach taken, here are some conference talks and publications:
+- RubyKaigi 2023 keynote: [Optimizing YJIT’s Performance, from Inception to Production](https://www.youtube.com/watch?v=X0JRhh8w_4I)
+- RubyKaigi 2023 keynote: [Fitting Rust YJIT into CRuby](https://www.youtube.com/watch?v=GI7vvAgP_Qs)
- RubyKaigi 2022 keynote: [Stories from developing YJIT](https://www.youtube.com/watch?v=EMchdR9C8XM)
- RubyKaigi 2022 talk: [Building a Lightweight IR and Backend for YJIT](https://www.youtube.com/watch?v=BbLGqTxTRp0)
- RubyKaigi 2021 talk: [YJIT: Building a New JIT Compiler Inside CRuby](https://www.youtube.com/watch?v=PBVLf3yfMs8)
@@ -55,8 +55,8 @@ series = {MPLR 2023}
## Current Limitations
-YJIT may not be suitable for certain applications. It currently only supports macOS and Linux on x86-64 and arm64/aarch64 CPUs. YJIT will use more memory than the Ruby interpreter because the JIT compiler needs to generate machine code in memory and maintain additional state information.
-You can change how much executable memory is allocated using [YJIT's command-line options](#command-line-options). There is a slight performance tradeoff because allocating less executable memory could result in the generated machine code being collected more often.
+YJIT may not be suitable for certain applications. It currently only supports macOS, Linux and BSD on x86-64 and arm64/aarch64 CPUs. YJIT will use more memory than the Ruby interpreter because the JIT compiler needs to generate machine code in memory and maintain additional state information.
+You can change how much executable memory is allocated using [YJIT's command-line options](#command-line-options).
## Installation
@@ -165,44 +165,62 @@ The machine code generated for a given method can be printed by adding `puts Rub
YJIT supports all command-line options supported by upstream CRuby, but also adds a few YJIT-specific options:
- `--yjit`: enable YJIT (disabled by default)
-- `--yjit-call-threshold=N`: number of calls after which YJIT begins to compile a function (default 30)
+- `--yjit-exec-mem-size=N`: size of the executable memory block to allocate, in MiB (default 48 MiB)
+- `--yjit-call-threshold=N`: number of calls after which YJIT begins to compile a function.
+ It defaults to 30, and it's then increased to 120 when the number of ISEQs in the process reaches 40,000.
- `--yjit-cold-threshold=N`: number of global calls after which an ISEQ is considered cold and not
-compiled, lower values mean less code is compiled (default 200000)
-- `--yjit-exec-mem-size=N`: size of the executable memory block to allocate, in MiB (default 64 MiB in Ruby 3.2, 128 MiB in Ruby 3.3+)
+ compiled, lower values mean less code is compiled (default 200K)
- `--yjit-stats`: print statistics after the execution of a program (incurs a run-time cost)
- `--yjit-stats=quiet`: gather statistics while running a program but don't print them. Stats are accessible through `RubyVM::YJIT.runtime_stats`. (incurs a run-time cost)
-- `--yjit-trace-exits`: produce a Marshal dump of backtraces from specific exits. Automatically enables `--yjit-stats`
-- `--yjit-max-versions=N`: maximum number of versions to generate per basic block (default 4)
-- `--yjit-perf`: Enable frame pointers and profiling with the `perf` tool
+- `--yjit-disable`: disable YJIT despite other `--yjit*` flags for lazily enabling it with `RubyVM::YJIT.enable`
+- `--yjit-code-gc`: enable code GC (disabled by default as of Ruby 3.3).
+ It will cause all machine code to be discarded when the executable memory size limit is hit, meaning JIT compilation will then start over.
+ This can allow you to use a lower executable memory size limit, but may cause a slight drop in performance when the limit is hit.
+- `--yjit-perf`: enable frame pointers and profiling with the `perf` tool
+- `--yjit-trace-exits`: produce a Marshal dump of backtraces from all exits. Automatically enables `--yjit-stats`
+- `--yjit-trace-exits=COUNTER`: produce a Marshal dump of backtraces from specified exits. Automatically enables `--yjit-stats`
+- `--yjit-trace-exits-sample-rate=N`: trace exit locations only every Nth occurrence. Automatically enables `--yjit-trace-exits`
Note that there is also an environment variable `RUBY_YJIT_ENABLE` which can be used to enable YJIT.
This can be useful for some deployment scripts where specifying an extra command-line option to Ruby is not practical.
-You can verify that YJIT is enabled by checking that `ruby -v --yjit` includes the string `+YJIT`:
+You can also enable YJIT at run-time using `RubyVM::YJIT.enable`. This can allow you to enable YJIT after your application is done
+booting, which makes it possible to avoid compiling any initialization code.
+
+You can verify that YJIT is enabled using `RubyVM::YJIT.enabled?` or by checking that `ruby --yjit -v` includes the string `+YJIT`:
```sh
-ruby -v --yjit
+ruby --yjit -v
ruby 3.3.0dev (2023-01-31T15:11:10Z master 2a0bf269c9) +YJIT dev [x86_64-darwin22]
+
+ruby --yjit -e "p RubyVM::YJIT.enabled?"
+true
+
+ruby -e "RubyVM::YJIT.enable; p RubyVM::YJIT.enabled?"
+true
```
### Benchmarking
-We have collected a set of benchmarks and implemented a simple benchmarking harness in the [yjit-bench](https://github.com/Shopify/yjit-bench) repository. This benchmarking harness is designed to disable CPU frequency scaling, set process affinity and disable address space randomization so that the variance between benchmarking runs will be as small as possible. Please kindly note that we are at an early stage in this project.
+We have collected a set of benchmarks and implemented a simple benchmarking harness in the [yjit-bench](https://github.com/Shopify/yjit-bench) repository. This benchmarking harness is designed to disable CPU frequency scaling, set process affinity and disable address space randomization so that the variance between benchmarking runs will be as small as possible.
## Performance Tips for Production Deployments
While YJIT options default to what we think would work well for most workloads,
they might not necessarily be the best configuration for your application.
-
This section covers tips on improving YJIT performance in case YJIT does not
speed up your application in production.
### Increasing --yjit-exec-mem-size
When JIT code size (`RubyVM::YJIT.runtime_stats[:code_region_size]`) reaches this value,
-YJIT triggers "code GC" that frees all JIT code and starts recompiling everything.
-Compiling code takes some time, so scheduling code GC too frequently slows down your application.
-Increasing `--yjit-exec-mem-size` may speed up your application if `RubyVM::YJIT.runtime_stats[:code_gc_count]` is not 0 or 1.
+YJIT stops compiling new code. Increasing the executable memory size means more code
+can be optimized by YJIT, at the cost of more memory usage.
+
+If you start Ruby with `--yjit-stats`, e.g. using an environment variable `RUBYOPT=--yjit-stats`,
+`RubyVM::YJIT.runtime_stats[:ratio_in_yjit]` shows the ratio of YJIT-executed instructions in %.
+Ideally, `ratio_in_yjit` should be as large as 99%, and increasing `--yjit-exec-mem-size` often
+helps improving `ratio_in_yjit`.
### Running workers as long as possible
@@ -214,30 +232,29 @@ You should monitor the number of requests each process has served.
If you're periodically killing worker processes, e.g. with `unicorn-worker-killer` or `puma_worker_killer`,
you may want to reduce the killing frequency or increase the limit.
-## Saving YJIT Memory Usage
+## Reducing YJIT Memory Usage
YJIT allocates memory for JIT code and metadata. Enabling YJIT generally results in more memory usage.
-
This section goes over tips on minimizing YJIT memory usage in case it uses more than your capacity.
-### Increasing --yjit-call-threshold
-
-As of Ruby 3.2, `--yjit-call-threshold` defaults to 30. With this default, some applications end up
-compiling methods that are used only during the application boot. Increasing this option may help
-you reduce the size of JIT code and metadata. It's worth trying different values like `--yjit-call-threshold=100`.
-
-Note that increasing the value too much may result in compiling code too late.
-You should monitor how many requests each worker processes before it's restarted. For example,
-if each process only handles 1000 requests, `--yjit-call-threshold=1000` might be too large for your application.
-
### Decreasing --yjit-exec-mem-size
-`--yjit-exec-mem-size` specifies the JIT code size, but YJIT also uses memory for its metadata,
+The `--yjit-exec-mem-size` option specifies the JIT code size, but YJIT also uses memory for its metadata,
which often consumes more memory than JIT code. Generally, YJIT adds memory overhead by roughly
-3-4x of `--yjit-exec-mem-size` in production as of Ruby 3.2. You should multiply that by the number
+3-4x of `--yjit-exec-mem-size` in production as of Ruby 3.3. You should multiply that by the number
of worker processes to estimate the worst case memory overhead.
-Running code GC adds overhead, but it could be still faster than recovering from a whole process killed by OOM.
+`--yjit-exec-mem-size=48` is the default since Ruby 3.3.1,
+but smaller values like 32 MiB might make sense for your application.
+While doing so, you may want to monitor `RubyVM::YJIT.runtime_stats[:ratio_in_yjit]` as explained above.
+
+### Enabling YJIT lazily
+
+If you enable YJIT by `--yjit` options or `RUBY_YJIT_ENABLE=1`, YJIT may compile code that is
+used only during the application boot. `RubyVM::YJIT.enable` allows you to enable YJIT from Ruby code,
+and you can call this after your application is initialized, e.g. on Unicorn's `after_fork` hook.
+If you use any YJIT options (`--yjit-*`), YJIT will start at boot by default, but `--yjit-disable`
+allows you to start Ruby with the YJIT-disabled mode while passing YJIT tuning options.
## Code Optimization Tips
@@ -248,21 +265,21 @@ This section contains tips on writing Ruby code that will run as fast as possibl
- Avoid redefining the meaning of `nil`, equality, etc.
- Avoid allocating objects in the hot parts of your code
- Minimize layers of indirection
- - Avoid classes that wrap objects if you can
- - Avoid methods that just call another method, trivial one liner methods
-- Try to write code so that the same variables always have the same type
-- Use `while` loops if you can, instead of C methods like `Array#each`
- - This is not idiomatic Ruby, but could help in hot methods
-- CRuby method calls are costly. Avoid things such as methods that only return a value from a hash or return a constant.
+ - Avoid writing wrapper classes if you can (e.g. a class that only wraps a Ruby hash)
+ - Avoid methods that just call another method
+- Ruby method calls are costly. Avoid things such as methods that only return a value from a hash
+- Try to write code so that the same variables and method arguments always have the same type
+- Avoid using `TracePoint` as it can cause YJIT to deoptimize code
+- Avoid using `Binding` as it can cause YJIT to deoptimize code
You can also use the `--yjit-stats` command-line option to see which bytecodes cause YJIT to exit, and refactor your code to avoid using these instructions in the hottest methods of your code.
### Other Statistics
-If you run `ruby` with `--yjit --yjit-stats`, YJIT will track and return performance statistics in `RubyVM::YJIT.runtime_stats`.
+If you run `ruby` with `--yjit-stats`, YJIT will track and return performance statistics in `RubyVM::YJIT.runtime_stats`.
```rb
-$ RUBYOPT="--yjit --yjit-stats" irb
+$ RUBYOPT="--yjit-stats" irb
irb(main):001:0> RubyVM::YJIT.runtime_stats
=>
{:inline_code_size=>340745,
@@ -289,25 +306,26 @@ Some of the counters include:
* :total_exit_count - number of exits, including side exits, taken at runtime
* :avg_len_in_yjit - avg. number of instructions in compiled blocks before exiting to interpreter
-Counters starting with "exit_" show reasons for YJIT code taking a side exit (return to the interpreter.) See yjit_hacking.md for more details.
+Counters starting with "exit_" show reasons for YJIT code taking a side exit (return to the interpreter.)
-Performance counter names are not guaranteed to remain the same between Ruby versions. If you're curious what one does, it's usually best to search the source code for it &mdash; but it may change in a later Ruby version.
+Performance counter names are not guaranteed to remain the same between Ruby versions. If you're curious what each counter means,
+it's usually best to search the source code for it &mdash; but it may change in a later Ruby version.
-The printed text after a --yjit-stats run includes other information that may be named differently than the information in runtime_stats.
+The printed text after a `--yjit-stats` run includes other information that may be named differently than the information in `RubyVM::YJIT.runtime_stats`.
## Contributing
-We welcome open source contributors. You should feel free to open new issues to report bugs or just to ask questions.
+We welcome open source contributions. You should feel free to open new issues to report bugs or just to ask questions.
Suggestions on how to make this readme file more helpful for new contributors are most welcome.
Bug fixes and bug reports are very valuable to us. If you find a bug in YJIT, it's very possible be that nobody has reported it before,
or that we don't have a good reproduction for it, so please open an issue and provide as much information as you can about your configuration and a description of how you encountered the problem. List the commands you used to run YJIT so that we can easily reproduce the issue on our end and investigate it. If you are able to produce a small program reproducing the error to help us track it down, that is very much appreciated as well.
-If you would like to contribute a large patch to YJIT, we suggest opening an issue or a discussion on this repository so that
+If you would like to contribute a large patch to YJIT, we suggest opening an issue or a discussion on the [Shopify/ruby repository](https://github.com/Shopify/ruby/issues) so that
we can have an active discussion. A common problem is that sometimes people submit large pull requests to open source projects
without prior communication, and we have to reject them because the work they implemented does not fit within the design of the
-project. We want to save you time and frustration, so please reach out and we can have a productive discussion as to how
-you can contribute things we will want to merge into YJIT.
+project. We want to save you time and frustration, so please reach out so we can have a productive discussion as to how
+you can contribute patches we will want to merge into YJIT.
### Source Code Organization
@@ -320,8 +338,8 @@ The YJIT source code is divided between:
- `yjit/src/core.rb`: basic block versioning logic, core structure of YJIT
- `yjit/src/stats.rs`: gathering of run-time statistics
- `yjit/src/options.rs`: handling of command-line options
-- `yjit/bindgen/src/main.rs`: C bindings exposed to the Rust codebase through bindgen
- `yjit/src/cruby.rs`: C bindings manually exposed to the Rust codebase
+- `yjit/bindgen/src/main.rs`: C bindings exposed to the Rust codebase through bindgen
The core of CRuby's interpreter logic is found in:
- `insns.def`: defines Ruby's bytecode instructions (gets compiled into `vm.inc`)
@@ -436,6 +454,8 @@ If you use Fish shell you can [read this link](https://tenderlovemaking.com/2022
When you run Ruby with `perf record`, perf looks up `/tmp/perf-{pid}.map` to resolve symbols in JIT code,
and this option lets YJIT write method symbols into that file as well as enabling frame pointers.
+### Call graph
+
Here's an example way to use this option with [Firefox Profiler](https://profiler.firefox.com)
(See also: [Profiling with Linux perf](https://profiler.firefox.com/docs/#/./guide-perf-profiling)):
@@ -450,9 +470,48 @@ echo -1 | sudo tee /proc/sys/kernel/perf_event_paranoid
# Profile Ruby with --yjit-perf
cd ../yjit-bench
-perf record --call-graph fp -- ruby --yjit-perf -Iharness-perf benchmarks/liquid-render/benchmark.rb
+PERF="record --call-graph fp" ruby --yjit-perf -Iharness-perf benchmarks/liquid-render/benchmark.rb
# View results on Firefox Profiler https://profiler.firefox.com.
# Create /tmp/test.perf as below and upload it using "Load a profile from file".
perf script --fields +pid > /tmp/test.perf
```
+
+### YJIT codegen
+
+You can also profile the number of cycles consumed by code generated by each YJIT function.
+
+```bash
+# Install perf
+apt-get install linux-tools-common linux-tools-generic linux-tools-`uname -r`
+
+# [Optional] Allow running perf without sudo
+echo 0 | sudo tee /proc/sys/kernel/kptr_restrict
+echo -1 | sudo tee /proc/sys/kernel/perf_event_paranoid
+
+# Profile Ruby with --yjit-perf=codegen
+cd ../yjit-bench
+PERF=record ruby --yjit-perf=codegen -Iharness-perf benchmarks/lobsters/benchmark.rb
+
+# Aggregate results
+perf script > /tmp/perf.txt
+../ruby/misc/yjit_perf.py /tmp/perf.txt
+```
+
+#### Building perf with Python support
+
+The above instructions work fine for most people, but you could also use
+a handy `perf script -s` interface if you build perf from source.
+
+```bash
+# Build perf from source for Python support
+sudo apt-get install libpython3-dev python3-pip flex libtraceevent-dev \
+ libelf-dev libunwind-dev libaudit-dev libslang2-dev libdw-dev
+git clone --depth=1 https://github.com/torvalds/linux
+cd linux/tools/perf
+make
+make install
+
+# Aggregate results
+perf script -s ../ruby/misc/yjit_perf.py
+```
diff --git a/enc/Makefile.in b/enc/Makefile.in
index dd8ca1b528..ce93fdd22d 100644
--- a/enc/Makefile.in
+++ b/enc/Makefile.in
@@ -40,6 +40,7 @@ BUILTRUBY = $(topdir)/miniruby$(EXEEXT)
empty =
AR = @AR@
+LD = @LD@
CC = @CC@
ARFLAGS = @ARFLAGS@$(empty)
RANLIB = @RANLIB@
@@ -51,11 +52,12 @@ optflags = @optflags@
debugflags = @debugflags@
warnflags = @warnflags@
CCDLFLAGS = @CCDLFLAGS@
-INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir) -I$(top_srcdir)
+INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir) -I$(top_srcdir) @incflags@
DEFS = @DEFS@
CPPFLAGS = @CPPFLAGS@ -DONIG_ENC_REGISTER=rb_enc_register
LDFLAGS = @LDFLAGS@
LDSHARED = @LDSHARED@
+POSTLINK = @POSTLINK@
ldflags = $(LDFLAGS)
dldflags = @DLDFLAGS@
extdldflags = @EXTDLDFLAGS@
@@ -70,6 +72,7 @@ WORKDIRS = @WORKDIRS@
NULLCMD = @NULLCMD@
RM = @RM@
+RMALL = @RMALL@
RMDIR = @RMDIR@
RMDIRS = @RMDIRS@
MAKEDIRS = @MAKEDIRS@
@@ -81,6 +84,9 @@ all:
make-workdir:
$(Q)$(MAKEDIRS) $(WORKDIRS)
+.PHONY: encs all modencs libencs enc libenc trans libtrans srcs
+.PHONY: clean distclean realclean clean-srcs
+
clean:
distclean: clean
diff --git a/enc/depend b/enc/depend
index 12ddbc223a..2918a90a05 100644
--- a/enc/depend
+++ b/enc/depend
@@ -35,6 +35,7 @@ ENCSOS =<%ENCS.map {|e|%> $(ENCSODIR)/<%=e%>.$(DLEXT) \
<%}%> #
ENCCLEANLIBS = <%=cleanlibs.map {|clean|
clean.gsub(/\$\*(\.\w+)?/) {"$(ENCOBJS#{$1 ? ":.#{CONFIG["OBJEXT"]}=#{$1}" : ""})"}
+ .gsub(/\$\(\KTARGET_SO(?=[:\)])/) {"ENCSOS"}
}.join(" ")%>
ENCCLEANOBJS = <%=cleanobjs.map {|clean|
clean.gsub(/\$\*(\.\w+)?/) {"$(ENCOBJS#{$1 ? ":.#{CONFIG["OBJEXT"]}=#{$1}" : ""})"}
@@ -51,6 +52,7 @@ TRANSSOS =<%TRANS.map {|e|%> $(ENCSODIR)/<%=e%>.$(DLEXT) \
<%}%> #
TRANSCLEANLIBS = <%=cleanlibs.map {|clean|
clean.gsub(/\$\*(\.\w+)?/) {"$(TRANSOBJS#{$1 ? ":.#{CONFIG["OBJEXT"]}=#{$1}" : ""})"}
+ .gsub(/\$\(\KTARGET_SO(?=[:\)])/) {"TRANSSOS"}
}.join(" ")%>
TRANSCLEANOBJS = <%=cleanobjs.map {|clean|
clean.gsub(/\$\*(\.\w+)?/) {"$(TRANSOBJS#{$1 ? ":.#{CONFIG["OBJEXT"]}=#{$1}" : ""})"}
@@ -151,7 +153,7 @@ enc/trans/transdb.$(OBJEXT): transdb.h
clean:
% %w[$(ENCSOS) $(LIBENC) $(ENCOBJS) $(ENCCLEANOBJS) $(ENCCLEANLIBS) $(TRANSSOS) $(LIBTRANS) $(TRANSOBJS) $(TRANSCLEANOBJS) $(TRANSCLEANLIBS) $(ENC_TRANS_D) $(ENC_TRANS_SO_D)].each do |clean|
- $(Q)$(RM) <%=pathrep[clean]%>
+ $(Q)$(RMALL) <%=pathrep[clean]%>
% end
% unless inplace
$(Q)$(RM) enc/unicode/*/casefold.h enc/unicode/*/name2ctype.h
@@ -334,6 +336,7 @@ enc/ascii.$(OBJEXT): internal/special_consts.h
enc/ascii.$(OBJEXT): internal/static_assert.h
enc/ascii.$(OBJEXT): internal/stdalign.h
enc/ascii.$(OBJEXT): internal/stdbool.h
+enc/ascii.$(OBJEXT): internal/stdckdint.h
enc/ascii.$(OBJEXT): internal/symbol.h
enc/ascii.$(OBJEXT): internal/value.h
enc/ascii.$(OBJEXT): internal/value_type.h
@@ -495,6 +498,7 @@ enc/big5.$(OBJEXT): internal/special_consts.h
enc/big5.$(OBJEXT): internal/static_assert.h
enc/big5.$(OBJEXT): internal/stdalign.h
enc/big5.$(OBJEXT): internal/stdbool.h
+enc/big5.$(OBJEXT): internal/stdckdint.h
enc/big5.$(OBJEXT): internal/symbol.h
enc/big5.$(OBJEXT): internal/value.h
enc/big5.$(OBJEXT): internal/value_type.h
@@ -666,6 +670,7 @@ enc/cesu_8.$(OBJEXT): internal/special_consts.h
enc/cesu_8.$(OBJEXT): internal/static_assert.h
enc/cesu_8.$(OBJEXT): internal/stdalign.h
enc/cesu_8.$(OBJEXT): internal/stdbool.h
+enc/cesu_8.$(OBJEXT): internal/stdckdint.h
enc/cesu_8.$(OBJEXT): internal/symbol.h
enc/cesu_8.$(OBJEXT): internal/value.h
enc/cesu_8.$(OBJEXT): internal/value_type.h
@@ -827,6 +832,7 @@ enc/cp949.$(OBJEXT): internal/special_consts.h
enc/cp949.$(OBJEXT): internal/static_assert.h
enc/cp949.$(OBJEXT): internal/stdalign.h
enc/cp949.$(OBJEXT): internal/stdbool.h
+enc/cp949.$(OBJEXT): internal/stdckdint.h
enc/cp949.$(OBJEXT): internal/symbol.h
enc/cp949.$(OBJEXT): internal/value.h
enc/cp949.$(OBJEXT): internal/value_type.h
@@ -987,6 +993,7 @@ enc/emacs_mule.$(OBJEXT): internal/special_consts.h
enc/emacs_mule.$(OBJEXT): internal/static_assert.h
enc/emacs_mule.$(OBJEXT): internal/stdalign.h
enc/emacs_mule.$(OBJEXT): internal/stdbool.h
+enc/emacs_mule.$(OBJEXT): internal/stdckdint.h
enc/emacs_mule.$(OBJEXT): internal/symbol.h
enc/emacs_mule.$(OBJEXT): internal/value.h
enc/emacs_mule.$(OBJEXT): internal/value_type.h
@@ -1157,6 +1164,7 @@ enc/encdb.$(OBJEXT): internal/special_consts.h
enc/encdb.$(OBJEXT): internal/static_assert.h
enc/encdb.$(OBJEXT): internal/stdalign.h
enc/encdb.$(OBJEXT): internal/stdbool.h
+enc/encdb.$(OBJEXT): internal/stdckdint.h
enc/encdb.$(OBJEXT): internal/symbol.h
enc/encdb.$(OBJEXT): internal/value.h
enc/encdb.$(OBJEXT): internal/value_type.h
@@ -1320,6 +1328,7 @@ enc/euc_jp.$(OBJEXT): internal/special_consts.h
enc/euc_jp.$(OBJEXT): internal/static_assert.h
enc/euc_jp.$(OBJEXT): internal/stdalign.h
enc/euc_jp.$(OBJEXT): internal/stdbool.h
+enc/euc_jp.$(OBJEXT): internal/stdckdint.h
enc/euc_jp.$(OBJEXT): internal/symbol.h
enc/euc_jp.$(OBJEXT): internal/value.h
enc/euc_jp.$(OBJEXT): internal/value_type.h
@@ -1480,6 +1489,7 @@ enc/euc_kr.$(OBJEXT): internal/special_consts.h
enc/euc_kr.$(OBJEXT): internal/static_assert.h
enc/euc_kr.$(OBJEXT): internal/stdalign.h
enc/euc_kr.$(OBJEXT): internal/stdbool.h
+enc/euc_kr.$(OBJEXT): internal/stdckdint.h
enc/euc_kr.$(OBJEXT): internal/symbol.h
enc/euc_kr.$(OBJEXT): internal/value.h
enc/euc_kr.$(OBJEXT): internal/value_type.h
@@ -1640,6 +1650,7 @@ enc/euc_tw.$(OBJEXT): internal/special_consts.h
enc/euc_tw.$(OBJEXT): internal/static_assert.h
enc/euc_tw.$(OBJEXT): internal/stdalign.h
enc/euc_tw.$(OBJEXT): internal/stdbool.h
+enc/euc_tw.$(OBJEXT): internal/stdckdint.h
enc/euc_tw.$(OBJEXT): internal/symbol.h
enc/euc_tw.$(OBJEXT): internal/value.h
enc/euc_tw.$(OBJEXT): internal/value_type.h
@@ -1800,6 +1811,7 @@ enc/gb18030.$(OBJEXT): internal/special_consts.h
enc/gb18030.$(OBJEXT): internal/static_assert.h
enc/gb18030.$(OBJEXT): internal/stdalign.h
enc/gb18030.$(OBJEXT): internal/stdbool.h
+enc/gb18030.$(OBJEXT): internal/stdckdint.h
enc/gb18030.$(OBJEXT): internal/symbol.h
enc/gb18030.$(OBJEXT): internal/value.h
enc/gb18030.$(OBJEXT): internal/value_type.h
@@ -1960,6 +1972,7 @@ enc/gb2312.$(OBJEXT): internal/special_consts.h
enc/gb2312.$(OBJEXT): internal/static_assert.h
enc/gb2312.$(OBJEXT): internal/stdalign.h
enc/gb2312.$(OBJEXT): internal/stdbool.h
+enc/gb2312.$(OBJEXT): internal/stdckdint.h
enc/gb2312.$(OBJEXT): internal/symbol.h
enc/gb2312.$(OBJEXT): internal/value.h
enc/gb2312.$(OBJEXT): internal/value_type.h
@@ -2120,6 +2133,7 @@ enc/gbk.$(OBJEXT): internal/special_consts.h
enc/gbk.$(OBJEXT): internal/static_assert.h
enc/gbk.$(OBJEXT): internal/stdalign.h
enc/gbk.$(OBJEXT): internal/stdbool.h
+enc/gbk.$(OBJEXT): internal/stdckdint.h
enc/gbk.$(OBJEXT): internal/symbol.h
enc/gbk.$(OBJEXT): internal/value.h
enc/gbk.$(OBJEXT): internal/value_type.h
@@ -2281,6 +2295,7 @@ enc/iso_8859_1.$(OBJEXT): internal/special_consts.h
enc/iso_8859_1.$(OBJEXT): internal/static_assert.h
enc/iso_8859_1.$(OBJEXT): internal/stdalign.h
enc/iso_8859_1.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_1.$(OBJEXT): internal/stdckdint.h
enc/iso_8859_1.$(OBJEXT): internal/symbol.h
enc/iso_8859_1.$(OBJEXT): internal/value.h
enc/iso_8859_1.$(OBJEXT): internal/value_type.h
@@ -2442,6 +2457,7 @@ enc/iso_8859_10.$(OBJEXT): internal/special_consts.h
enc/iso_8859_10.$(OBJEXT): internal/static_assert.h
enc/iso_8859_10.$(OBJEXT): internal/stdalign.h
enc/iso_8859_10.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_10.$(OBJEXT): internal/stdckdint.h
enc/iso_8859_10.$(OBJEXT): internal/symbol.h
enc/iso_8859_10.$(OBJEXT): internal/value.h
enc/iso_8859_10.$(OBJEXT): internal/value_type.h
@@ -2602,6 +2618,7 @@ enc/iso_8859_11.$(OBJEXT): internal/special_consts.h
enc/iso_8859_11.$(OBJEXT): internal/static_assert.h
enc/iso_8859_11.$(OBJEXT): internal/stdalign.h
enc/iso_8859_11.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_11.$(OBJEXT): internal/stdckdint.h
enc/iso_8859_11.$(OBJEXT): internal/symbol.h
enc/iso_8859_11.$(OBJEXT): internal/value.h
enc/iso_8859_11.$(OBJEXT): internal/value_type.h
@@ -2763,6 +2780,7 @@ enc/iso_8859_13.$(OBJEXT): internal/special_consts.h
enc/iso_8859_13.$(OBJEXT): internal/static_assert.h
enc/iso_8859_13.$(OBJEXT): internal/stdalign.h
enc/iso_8859_13.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_13.$(OBJEXT): internal/stdckdint.h
enc/iso_8859_13.$(OBJEXT): internal/symbol.h
enc/iso_8859_13.$(OBJEXT): internal/value.h
enc/iso_8859_13.$(OBJEXT): internal/value_type.h
@@ -2924,6 +2942,7 @@ enc/iso_8859_14.$(OBJEXT): internal/special_consts.h
enc/iso_8859_14.$(OBJEXT): internal/static_assert.h
enc/iso_8859_14.$(OBJEXT): internal/stdalign.h
enc/iso_8859_14.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_14.$(OBJEXT): internal/stdckdint.h
enc/iso_8859_14.$(OBJEXT): internal/symbol.h
enc/iso_8859_14.$(OBJEXT): internal/value.h
enc/iso_8859_14.$(OBJEXT): internal/value_type.h
@@ -3085,6 +3104,7 @@ enc/iso_8859_15.$(OBJEXT): internal/special_consts.h
enc/iso_8859_15.$(OBJEXT): internal/static_assert.h
enc/iso_8859_15.$(OBJEXT): internal/stdalign.h
enc/iso_8859_15.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_15.$(OBJEXT): internal/stdckdint.h
enc/iso_8859_15.$(OBJEXT): internal/symbol.h
enc/iso_8859_15.$(OBJEXT): internal/value.h
enc/iso_8859_15.$(OBJEXT): internal/value_type.h
@@ -3246,6 +3266,7 @@ enc/iso_8859_16.$(OBJEXT): internal/special_consts.h
enc/iso_8859_16.$(OBJEXT): internal/static_assert.h
enc/iso_8859_16.$(OBJEXT): internal/stdalign.h
enc/iso_8859_16.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_16.$(OBJEXT): internal/stdckdint.h
enc/iso_8859_16.$(OBJEXT): internal/symbol.h
enc/iso_8859_16.$(OBJEXT): internal/value.h
enc/iso_8859_16.$(OBJEXT): internal/value_type.h
@@ -3407,6 +3428,7 @@ enc/iso_8859_2.$(OBJEXT): internal/special_consts.h
enc/iso_8859_2.$(OBJEXT): internal/static_assert.h
enc/iso_8859_2.$(OBJEXT): internal/stdalign.h
enc/iso_8859_2.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_2.$(OBJEXT): internal/stdckdint.h
enc/iso_8859_2.$(OBJEXT): internal/symbol.h
enc/iso_8859_2.$(OBJEXT): internal/value.h
enc/iso_8859_2.$(OBJEXT): internal/value_type.h
@@ -3568,6 +3590,7 @@ enc/iso_8859_3.$(OBJEXT): internal/special_consts.h
enc/iso_8859_3.$(OBJEXT): internal/static_assert.h
enc/iso_8859_3.$(OBJEXT): internal/stdalign.h
enc/iso_8859_3.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_3.$(OBJEXT): internal/stdckdint.h
enc/iso_8859_3.$(OBJEXT): internal/symbol.h
enc/iso_8859_3.$(OBJEXT): internal/value.h
enc/iso_8859_3.$(OBJEXT): internal/value_type.h
@@ -3729,6 +3752,7 @@ enc/iso_8859_4.$(OBJEXT): internal/special_consts.h
enc/iso_8859_4.$(OBJEXT): internal/static_assert.h
enc/iso_8859_4.$(OBJEXT): internal/stdalign.h
enc/iso_8859_4.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_4.$(OBJEXT): internal/stdckdint.h
enc/iso_8859_4.$(OBJEXT): internal/symbol.h
enc/iso_8859_4.$(OBJEXT): internal/value.h
enc/iso_8859_4.$(OBJEXT): internal/value_type.h
@@ -3889,6 +3913,7 @@ enc/iso_8859_5.$(OBJEXT): internal/special_consts.h
enc/iso_8859_5.$(OBJEXT): internal/static_assert.h
enc/iso_8859_5.$(OBJEXT): internal/stdalign.h
enc/iso_8859_5.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_5.$(OBJEXT): internal/stdckdint.h
enc/iso_8859_5.$(OBJEXT): internal/symbol.h
enc/iso_8859_5.$(OBJEXT): internal/value.h
enc/iso_8859_5.$(OBJEXT): internal/value_type.h
@@ -4049,6 +4074,7 @@ enc/iso_8859_6.$(OBJEXT): internal/special_consts.h
enc/iso_8859_6.$(OBJEXT): internal/static_assert.h
enc/iso_8859_6.$(OBJEXT): internal/stdalign.h
enc/iso_8859_6.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_6.$(OBJEXT): internal/stdckdint.h
enc/iso_8859_6.$(OBJEXT): internal/symbol.h
enc/iso_8859_6.$(OBJEXT): internal/value.h
enc/iso_8859_6.$(OBJEXT): internal/value_type.h
@@ -4209,6 +4235,7 @@ enc/iso_8859_7.$(OBJEXT): internal/special_consts.h
enc/iso_8859_7.$(OBJEXT): internal/static_assert.h
enc/iso_8859_7.$(OBJEXT): internal/stdalign.h
enc/iso_8859_7.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_7.$(OBJEXT): internal/stdckdint.h
enc/iso_8859_7.$(OBJEXT): internal/symbol.h
enc/iso_8859_7.$(OBJEXT): internal/value.h
enc/iso_8859_7.$(OBJEXT): internal/value_type.h
@@ -4369,6 +4396,7 @@ enc/iso_8859_8.$(OBJEXT): internal/special_consts.h
enc/iso_8859_8.$(OBJEXT): internal/static_assert.h
enc/iso_8859_8.$(OBJEXT): internal/stdalign.h
enc/iso_8859_8.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_8.$(OBJEXT): internal/stdckdint.h
enc/iso_8859_8.$(OBJEXT): internal/symbol.h
enc/iso_8859_8.$(OBJEXT): internal/value.h
enc/iso_8859_8.$(OBJEXT): internal/value_type.h
@@ -4530,6 +4558,7 @@ enc/iso_8859_9.$(OBJEXT): internal/special_consts.h
enc/iso_8859_9.$(OBJEXT): internal/static_assert.h
enc/iso_8859_9.$(OBJEXT): internal/stdalign.h
enc/iso_8859_9.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_9.$(OBJEXT): internal/stdckdint.h
enc/iso_8859_9.$(OBJEXT): internal/symbol.h
enc/iso_8859_9.$(OBJEXT): internal/value.h
enc/iso_8859_9.$(OBJEXT): internal/value_type.h
@@ -4690,6 +4719,7 @@ enc/koi8_r.$(OBJEXT): internal/special_consts.h
enc/koi8_r.$(OBJEXT): internal/static_assert.h
enc/koi8_r.$(OBJEXT): internal/stdalign.h
enc/koi8_r.$(OBJEXT): internal/stdbool.h
+enc/koi8_r.$(OBJEXT): internal/stdckdint.h
enc/koi8_r.$(OBJEXT): internal/symbol.h
enc/koi8_r.$(OBJEXT): internal/value.h
enc/koi8_r.$(OBJEXT): internal/value_type.h
@@ -4850,6 +4880,7 @@ enc/koi8_u.$(OBJEXT): internal/special_consts.h
enc/koi8_u.$(OBJEXT): internal/static_assert.h
enc/koi8_u.$(OBJEXT): internal/stdalign.h
enc/koi8_u.$(OBJEXT): internal/stdbool.h
+enc/koi8_u.$(OBJEXT): internal/stdckdint.h
enc/koi8_u.$(OBJEXT): internal/symbol.h
enc/koi8_u.$(OBJEXT): internal/value.h
enc/koi8_u.$(OBJEXT): internal/value_type.h
@@ -5013,6 +5044,7 @@ enc/shift_jis.$(OBJEXT): internal/special_consts.h
enc/shift_jis.$(OBJEXT): internal/static_assert.h
enc/shift_jis.$(OBJEXT): internal/stdalign.h
enc/shift_jis.$(OBJEXT): internal/stdbool.h
+enc/shift_jis.$(OBJEXT): internal/stdckdint.h
enc/shift_jis.$(OBJEXT): internal/symbol.h
enc/shift_jis.$(OBJEXT): internal/value.h
enc/shift_jis.$(OBJEXT): internal/value_type.h
@@ -5172,6 +5204,7 @@ enc/trans/big5.$(OBJEXT): internal/special_consts.h
enc/trans/big5.$(OBJEXT): internal/static_assert.h
enc/trans/big5.$(OBJEXT): internal/stdalign.h
enc/trans/big5.$(OBJEXT): internal/stdbool.h
+enc/trans/big5.$(OBJEXT): internal/stdckdint.h
enc/trans/big5.$(OBJEXT): internal/symbol.h
enc/trans/big5.$(OBJEXT): internal/value.h
enc/trans/big5.$(OBJEXT): internal/value_type.h
@@ -5330,6 +5363,7 @@ enc/trans/cesu_8.$(OBJEXT): internal/special_consts.h
enc/trans/cesu_8.$(OBJEXT): internal/static_assert.h
enc/trans/cesu_8.$(OBJEXT): internal/stdalign.h
enc/trans/cesu_8.$(OBJEXT): internal/stdbool.h
+enc/trans/cesu_8.$(OBJEXT): internal/stdckdint.h
enc/trans/cesu_8.$(OBJEXT): internal/symbol.h
enc/trans/cesu_8.$(OBJEXT): internal/value.h
enc/trans/cesu_8.$(OBJEXT): internal/value_type.h
@@ -5488,6 +5522,7 @@ enc/trans/chinese.$(OBJEXT): internal/special_consts.h
enc/trans/chinese.$(OBJEXT): internal/static_assert.h
enc/trans/chinese.$(OBJEXT): internal/stdalign.h
enc/trans/chinese.$(OBJEXT): internal/stdbool.h
+enc/trans/chinese.$(OBJEXT): internal/stdckdint.h
enc/trans/chinese.$(OBJEXT): internal/symbol.h
enc/trans/chinese.$(OBJEXT): internal/value.h
enc/trans/chinese.$(OBJEXT): internal/value_type.h
@@ -5646,6 +5681,7 @@ enc/trans/ebcdic.$(OBJEXT): internal/special_consts.h
enc/trans/ebcdic.$(OBJEXT): internal/static_assert.h
enc/trans/ebcdic.$(OBJEXT): internal/stdalign.h
enc/trans/ebcdic.$(OBJEXT): internal/stdbool.h
+enc/trans/ebcdic.$(OBJEXT): internal/stdckdint.h
enc/trans/ebcdic.$(OBJEXT): internal/symbol.h
enc/trans/ebcdic.$(OBJEXT): internal/value.h
enc/trans/ebcdic.$(OBJEXT): internal/value_type.h
@@ -5804,6 +5840,7 @@ enc/trans/emoji.$(OBJEXT): internal/special_consts.h
enc/trans/emoji.$(OBJEXT): internal/static_assert.h
enc/trans/emoji.$(OBJEXT): internal/stdalign.h
enc/trans/emoji.$(OBJEXT): internal/stdbool.h
+enc/trans/emoji.$(OBJEXT): internal/stdckdint.h
enc/trans/emoji.$(OBJEXT): internal/symbol.h
enc/trans/emoji.$(OBJEXT): internal/value.h
enc/trans/emoji.$(OBJEXT): internal/value_type.h
@@ -5962,6 +5999,7 @@ enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/special_consts.h
enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/static_assert.h
enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/stdalign.h
enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/stdbool.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/stdckdint.h
enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/symbol.h
enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/value.h
enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/value_type.h
@@ -6120,6 +6158,7 @@ enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/special_consts.h
enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/static_assert.h
enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/stdalign.h
enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/stdbool.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/stdckdint.h
enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/symbol.h
enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/value.h
enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/value_type.h
@@ -6278,6 +6317,7 @@ enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/special_consts.h
enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/static_assert.h
enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/stdalign.h
enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/stdbool.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/stdckdint.h
enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/symbol.h
enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/value.h
enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/value_type.h
@@ -6436,6 +6476,7 @@ enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/special_consts.h
enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/static_assert.h
enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/stdalign.h
enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/stdbool.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/stdckdint.h
enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/symbol.h
enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/value.h
enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/value_type.h
@@ -6594,6 +6635,7 @@ enc/trans/escape.$(OBJEXT): internal/special_consts.h
enc/trans/escape.$(OBJEXT): internal/static_assert.h
enc/trans/escape.$(OBJEXT): internal/stdalign.h
enc/trans/escape.$(OBJEXT): internal/stdbool.h
+enc/trans/escape.$(OBJEXT): internal/stdckdint.h
enc/trans/escape.$(OBJEXT): internal/symbol.h
enc/trans/escape.$(OBJEXT): internal/value.h
enc/trans/escape.$(OBJEXT): internal/value_type.h
@@ -6752,6 +6794,7 @@ enc/trans/gb18030.$(OBJEXT): internal/special_consts.h
enc/trans/gb18030.$(OBJEXT): internal/static_assert.h
enc/trans/gb18030.$(OBJEXT): internal/stdalign.h
enc/trans/gb18030.$(OBJEXT): internal/stdbool.h
+enc/trans/gb18030.$(OBJEXT): internal/stdckdint.h
enc/trans/gb18030.$(OBJEXT): internal/symbol.h
enc/trans/gb18030.$(OBJEXT): internal/value.h
enc/trans/gb18030.$(OBJEXT): internal/value_type.h
@@ -6910,6 +6953,7 @@ enc/trans/gbk.$(OBJEXT): internal/special_consts.h
enc/trans/gbk.$(OBJEXT): internal/static_assert.h
enc/trans/gbk.$(OBJEXT): internal/stdalign.h
enc/trans/gbk.$(OBJEXT): internal/stdbool.h
+enc/trans/gbk.$(OBJEXT): internal/stdckdint.h
enc/trans/gbk.$(OBJEXT): internal/symbol.h
enc/trans/gbk.$(OBJEXT): internal/value.h
enc/trans/gbk.$(OBJEXT): internal/value_type.h
@@ -7068,6 +7112,7 @@ enc/trans/iso2022.$(OBJEXT): internal/special_consts.h
enc/trans/iso2022.$(OBJEXT): internal/static_assert.h
enc/trans/iso2022.$(OBJEXT): internal/stdalign.h
enc/trans/iso2022.$(OBJEXT): internal/stdbool.h
+enc/trans/iso2022.$(OBJEXT): internal/stdckdint.h
enc/trans/iso2022.$(OBJEXT): internal/symbol.h
enc/trans/iso2022.$(OBJEXT): internal/value.h
enc/trans/iso2022.$(OBJEXT): internal/value_type.h
@@ -7226,6 +7271,7 @@ enc/trans/japanese.$(OBJEXT): internal/special_consts.h
enc/trans/japanese.$(OBJEXT): internal/static_assert.h
enc/trans/japanese.$(OBJEXT): internal/stdalign.h
enc/trans/japanese.$(OBJEXT): internal/stdbool.h
+enc/trans/japanese.$(OBJEXT): internal/stdckdint.h
enc/trans/japanese.$(OBJEXT): internal/symbol.h
enc/trans/japanese.$(OBJEXT): internal/value.h
enc/trans/japanese.$(OBJEXT): internal/value_type.h
@@ -7384,6 +7430,7 @@ enc/trans/japanese_euc.$(OBJEXT): internal/special_consts.h
enc/trans/japanese_euc.$(OBJEXT): internal/static_assert.h
enc/trans/japanese_euc.$(OBJEXT): internal/stdalign.h
enc/trans/japanese_euc.$(OBJEXT): internal/stdbool.h
+enc/trans/japanese_euc.$(OBJEXT): internal/stdckdint.h
enc/trans/japanese_euc.$(OBJEXT): internal/symbol.h
enc/trans/japanese_euc.$(OBJEXT): internal/value.h
enc/trans/japanese_euc.$(OBJEXT): internal/value_type.h
@@ -7542,6 +7589,7 @@ enc/trans/japanese_sjis.$(OBJEXT): internal/special_consts.h
enc/trans/japanese_sjis.$(OBJEXT): internal/static_assert.h
enc/trans/japanese_sjis.$(OBJEXT): internal/stdalign.h
enc/trans/japanese_sjis.$(OBJEXT): internal/stdbool.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/stdckdint.h
enc/trans/japanese_sjis.$(OBJEXT): internal/symbol.h
enc/trans/japanese_sjis.$(OBJEXT): internal/value.h
enc/trans/japanese_sjis.$(OBJEXT): internal/value_type.h
@@ -7700,6 +7748,7 @@ enc/trans/korean.$(OBJEXT): internal/special_consts.h
enc/trans/korean.$(OBJEXT): internal/static_assert.h
enc/trans/korean.$(OBJEXT): internal/stdalign.h
enc/trans/korean.$(OBJEXT): internal/stdbool.h
+enc/trans/korean.$(OBJEXT): internal/stdckdint.h
enc/trans/korean.$(OBJEXT): internal/symbol.h
enc/trans/korean.$(OBJEXT): internal/value.h
enc/trans/korean.$(OBJEXT): internal/value_type.h
@@ -7857,6 +7906,7 @@ enc/trans/newline.$(OBJEXT): internal/special_consts.h
enc/trans/newline.$(OBJEXT): internal/static_assert.h
enc/trans/newline.$(OBJEXT): internal/stdalign.h
enc/trans/newline.$(OBJEXT): internal/stdbool.h
+enc/trans/newline.$(OBJEXT): internal/stdckdint.h
enc/trans/newline.$(OBJEXT): internal/symbol.h
enc/trans/newline.$(OBJEXT): internal/value.h
enc/trans/newline.$(OBJEXT): internal/value_type.h
@@ -8015,6 +8065,7 @@ enc/trans/single_byte.$(OBJEXT): internal/special_consts.h
enc/trans/single_byte.$(OBJEXT): internal/static_assert.h
enc/trans/single_byte.$(OBJEXT): internal/stdalign.h
enc/trans/single_byte.$(OBJEXT): internal/stdbool.h
+enc/trans/single_byte.$(OBJEXT): internal/stdckdint.h
enc/trans/single_byte.$(OBJEXT): internal/symbol.h
enc/trans/single_byte.$(OBJEXT): internal/value.h
enc/trans/single_byte.$(OBJEXT): internal/value_type.h
@@ -8173,6 +8224,7 @@ enc/trans/transdb.$(OBJEXT): internal/special_consts.h
enc/trans/transdb.$(OBJEXT): internal/static_assert.h
enc/trans/transdb.$(OBJEXT): internal/stdalign.h
enc/trans/transdb.$(OBJEXT): internal/stdbool.h
+enc/trans/transdb.$(OBJEXT): internal/stdckdint.h
enc/trans/transdb.$(OBJEXT): internal/symbol.h
enc/trans/transdb.$(OBJEXT): internal/value.h
enc/trans/transdb.$(OBJEXT): internal/value_type.h
@@ -8332,6 +8384,7 @@ enc/trans/utf8_mac.$(OBJEXT): internal/special_consts.h
enc/trans/utf8_mac.$(OBJEXT): internal/static_assert.h
enc/trans/utf8_mac.$(OBJEXT): internal/stdalign.h
enc/trans/utf8_mac.$(OBJEXT): internal/stdbool.h
+enc/trans/utf8_mac.$(OBJEXT): internal/stdckdint.h
enc/trans/utf8_mac.$(OBJEXT): internal/symbol.h
enc/trans/utf8_mac.$(OBJEXT): internal/value.h
enc/trans/utf8_mac.$(OBJEXT): internal/value_type.h
@@ -8490,6 +8543,7 @@ enc/trans/utf_16_32.$(OBJEXT): internal/special_consts.h
enc/trans/utf_16_32.$(OBJEXT): internal/static_assert.h
enc/trans/utf_16_32.$(OBJEXT): internal/stdalign.h
enc/trans/utf_16_32.$(OBJEXT): internal/stdbool.h
+enc/trans/utf_16_32.$(OBJEXT): internal/stdckdint.h
enc/trans/utf_16_32.$(OBJEXT): internal/symbol.h
enc/trans/utf_16_32.$(OBJEXT): internal/value.h
enc/trans/utf_16_32.$(OBJEXT): internal/value_type.h
@@ -8651,6 +8705,7 @@ enc/unicode.$(OBJEXT): internal/special_consts.h
enc/unicode.$(OBJEXT): internal/static_assert.h
enc/unicode.$(OBJEXT): internal/stdalign.h
enc/unicode.$(OBJEXT): internal/stdbool.h
+enc/unicode.$(OBJEXT): internal/stdckdint.h
enc/unicode.$(OBJEXT): internal/symbol.h
enc/unicode.$(OBJEXT): internal/value.h
enc/unicode.$(OBJEXT): internal/value_type.h
@@ -8821,6 +8876,7 @@ enc/us_ascii.$(OBJEXT): internal/special_consts.h
enc/us_ascii.$(OBJEXT): internal/static_assert.h
enc/us_ascii.$(OBJEXT): internal/stdalign.h
enc/us_ascii.$(OBJEXT): internal/stdbool.h
+enc/us_ascii.$(OBJEXT): internal/stdckdint.h
enc/us_ascii.$(OBJEXT): internal/symbol.h
enc/us_ascii.$(OBJEXT): internal/value.h
enc/us_ascii.$(OBJEXT): internal/value_type.h
@@ -8983,6 +9039,7 @@ enc/utf_16be.$(OBJEXT): internal/special_consts.h
enc/utf_16be.$(OBJEXT): internal/static_assert.h
enc/utf_16be.$(OBJEXT): internal/stdalign.h
enc/utf_16be.$(OBJEXT): internal/stdbool.h
+enc/utf_16be.$(OBJEXT): internal/stdckdint.h
enc/utf_16be.$(OBJEXT): internal/symbol.h
enc/utf_16be.$(OBJEXT): internal/value.h
enc/utf_16be.$(OBJEXT): internal/value_type.h
@@ -9144,6 +9201,7 @@ enc/utf_16le.$(OBJEXT): internal/special_consts.h
enc/utf_16le.$(OBJEXT): internal/static_assert.h
enc/utf_16le.$(OBJEXT): internal/stdalign.h
enc/utf_16le.$(OBJEXT): internal/stdbool.h
+enc/utf_16le.$(OBJEXT): internal/stdckdint.h
enc/utf_16le.$(OBJEXT): internal/symbol.h
enc/utf_16le.$(OBJEXT): internal/value.h
enc/utf_16le.$(OBJEXT): internal/value_type.h
@@ -9305,6 +9363,7 @@ enc/utf_32be.$(OBJEXT): internal/special_consts.h
enc/utf_32be.$(OBJEXT): internal/static_assert.h
enc/utf_32be.$(OBJEXT): internal/stdalign.h
enc/utf_32be.$(OBJEXT): internal/stdbool.h
+enc/utf_32be.$(OBJEXT): internal/stdckdint.h
enc/utf_32be.$(OBJEXT): internal/symbol.h
enc/utf_32be.$(OBJEXT): internal/value.h
enc/utf_32be.$(OBJEXT): internal/value_type.h
@@ -9466,6 +9525,7 @@ enc/utf_32le.$(OBJEXT): internal/special_consts.h
enc/utf_32le.$(OBJEXT): internal/static_assert.h
enc/utf_32le.$(OBJEXT): internal/stdalign.h
enc/utf_32le.$(OBJEXT): internal/stdbool.h
+enc/utf_32le.$(OBJEXT): internal/stdckdint.h
enc/utf_32le.$(OBJEXT): internal/symbol.h
enc/utf_32le.$(OBJEXT): internal/value.h
enc/utf_32le.$(OBJEXT): internal/value_type.h
@@ -9636,6 +9696,7 @@ enc/utf_8.$(OBJEXT): internal/special_consts.h
enc/utf_8.$(OBJEXT): internal/static_assert.h
enc/utf_8.$(OBJEXT): internal/stdalign.h
enc/utf_8.$(OBJEXT): internal/stdbool.h
+enc/utf_8.$(OBJEXT): internal/stdckdint.h
enc/utf_8.$(OBJEXT): internal/symbol.h
enc/utf_8.$(OBJEXT): internal/value.h
enc/utf_8.$(OBJEXT): internal/value_type.h
@@ -9798,6 +9859,7 @@ enc/windows_1250.$(OBJEXT): internal/special_consts.h
enc/windows_1250.$(OBJEXT): internal/static_assert.h
enc/windows_1250.$(OBJEXT): internal/stdalign.h
enc/windows_1250.$(OBJEXT): internal/stdbool.h
+enc/windows_1250.$(OBJEXT): internal/stdckdint.h
enc/windows_1250.$(OBJEXT): internal/symbol.h
enc/windows_1250.$(OBJEXT): internal/value.h
enc/windows_1250.$(OBJEXT): internal/value_type.h
@@ -9958,6 +10020,7 @@ enc/windows_1251.$(OBJEXT): internal/special_consts.h
enc/windows_1251.$(OBJEXT): internal/static_assert.h
enc/windows_1251.$(OBJEXT): internal/stdalign.h
enc/windows_1251.$(OBJEXT): internal/stdbool.h
+enc/windows_1251.$(OBJEXT): internal/stdckdint.h
enc/windows_1251.$(OBJEXT): internal/symbol.h
enc/windows_1251.$(OBJEXT): internal/value.h
enc/windows_1251.$(OBJEXT): internal/value_type.h
@@ -10119,6 +10182,7 @@ enc/windows_1252.$(OBJEXT): internal/special_consts.h
enc/windows_1252.$(OBJEXT): internal/static_assert.h
enc/windows_1252.$(OBJEXT): internal/stdalign.h
enc/windows_1252.$(OBJEXT): internal/stdbool.h
+enc/windows_1252.$(OBJEXT): internal/stdckdint.h
enc/windows_1252.$(OBJEXT): internal/symbol.h
enc/windows_1252.$(OBJEXT): internal/value.h
enc/windows_1252.$(OBJEXT): internal/value_type.h
@@ -10279,6 +10343,7 @@ enc/windows_1253.$(OBJEXT): internal/special_consts.h
enc/windows_1253.$(OBJEXT): internal/static_assert.h
enc/windows_1253.$(OBJEXT): internal/stdalign.h
enc/windows_1253.$(OBJEXT): internal/stdbool.h
+enc/windows_1253.$(OBJEXT): internal/stdckdint.h
enc/windows_1253.$(OBJEXT): internal/symbol.h
enc/windows_1253.$(OBJEXT): internal/value.h
enc/windows_1253.$(OBJEXT): internal/value_type.h
@@ -10440,6 +10505,7 @@ enc/windows_1254.$(OBJEXT): internal/special_consts.h
enc/windows_1254.$(OBJEXT): internal/static_assert.h
enc/windows_1254.$(OBJEXT): internal/stdalign.h
enc/windows_1254.$(OBJEXT): internal/stdbool.h
+enc/windows_1254.$(OBJEXT): internal/stdckdint.h
enc/windows_1254.$(OBJEXT): internal/symbol.h
enc/windows_1254.$(OBJEXT): internal/value.h
enc/windows_1254.$(OBJEXT): internal/value_type.h
@@ -10601,6 +10667,7 @@ enc/windows_1257.$(OBJEXT): internal/special_consts.h
enc/windows_1257.$(OBJEXT): internal/static_assert.h
enc/windows_1257.$(OBJEXT): internal/stdalign.h
enc/windows_1257.$(OBJEXT): internal/stdbool.h
+enc/windows_1257.$(OBJEXT): internal/stdckdint.h
enc/windows_1257.$(OBJEXT): internal/symbol.h
enc/windows_1257.$(OBJEXT): internal/value.h
enc/windows_1257.$(OBJEXT): internal/value_type.h
@@ -10764,6 +10831,7 @@ enc/windows_31j.$(OBJEXT): internal/special_consts.h
enc/windows_31j.$(OBJEXT): internal/static_assert.h
enc/windows_31j.$(OBJEXT): internal/stdalign.h
enc/windows_31j.$(OBJEXT): internal/stdbool.h
+enc/windows_31j.$(OBJEXT): internal/stdckdint.h
enc/windows_31j.$(OBJEXT): internal/symbol.h
enc/windows_31j.$(OBJEXT): internal/value.h
enc/windows_31j.$(OBJEXT): internal/value_type.h
diff --git a/enc/ebcdic.h b/enc/ebcdic.h
index a3b380a327..5109bf7065 100644
--- a/enc/ebcdic.h
+++ b/enc/ebcdic.h
@@ -7,5 +7,5 @@ ENC_ALIAS("ebcdic-cp-us", "IBM037");
* hopefully the most widely used one.
*
* See http://www.iana.org/assignments/character-sets/character-sets.xhtml
- * http://tools.ietf.org/html/rfc1345
+ * https://www.rfc-editor.org/rfc/rfc1345
*/
diff --git a/enc/encinit.c.erb b/enc/encinit.c.erb
index 120408f8e3..3662ba200d 100644
--- a/enc/encinit.c.erb
+++ b/enc/encinit.c.erb
@@ -1,3 +1,6 @@
+/* Automatically generated from <%= erb.filename %>
+ * Do not edit<%# directly%>.
+ */
/* Copyright 2012 Google Inc. Some Rights Reserved.
* Author: yugui@google.com (Yugui Sonoda)
*/
diff --git a/enc/make_encmake.rb b/enc/make_encmake.rb
index fcfc2c9267..96d1944bcb 100755
--- a/enc/make_encmake.rb
+++ b/enc/make_encmake.rb
@@ -121,39 +121,32 @@ ENCS, ENC_DEPS = target_encodings
ATRANS, TRANS = target_transcoders
if File.exist?(depend = File.join($srcdir, "depend"))
- if ERB.instance_method(:initialize).parameters.assoc(:key) # Ruby 2.6+
- erb = ERB.new(File.read(depend), trim_mode: '%')
- else
- erb = ERB.new(File.read(depend), nil, '%')
- end
+ erb = ERB.new(File.read(depend), trim_mode: '%')
erb.filename = depend
tmp = erb.result(binding)
- dep = "\n#### depend ####\n\n" << depend_rules(tmp).join
+ dep = "\n#### depend ####\n\n" + depend_rules(tmp).join
else
dep = ""
end
mkin = File.read(File.join($srcdir, "Makefile.in"))
-mkin.gsub!(/@(#{CONFIG.keys.join('|')})@/) {CONFIG[$1]}
+# Variables that should not be expanded in Makefile.in to allow
+# overriding inherited variables at make-time.
+not_expand_vars = %w(CFLAGS)
+mkin.gsub!(/@(#{RbConfig::CONFIG.keys.join('|')})@/) do
+ not_expand_vars.include?($1) ? CONFIG[$1] : RbConfig::CONFIG[$1]
+end
File.open(ARGV[0], 'wb') {|f|
f.puts mkin, dep
}
if MODULE_TYPE == :static
filename = "encinit.c.erb"
- if ERB.instance_method(:initialize).parameters.assoc(:key) # Ruby 2.6+
- erb = ERB.new(File.read(File.join($srcdir, filename)), trim_mode: '%-')
- else
- erb = ERB.new(File.read(File.join($srcdir, filename)), nil, '%-')
- end
+ erb = ERB.new(File.read(File.join($srcdir, filename)), trim_mode: '%-')
erb.filename = "enc/#{filename}"
tmp = erb.result(binding)
begin
Dir.mkdir 'enc'
rescue Errno::EEXIST
end
- File.open("enc/encinit.c", "w") {|f|
- f.puts "/* Automatically generated from enc/encinit.c.erb"
- f.puts " * Do not edit."
- f.puts " */"
- f.puts tmp
- }
+ require 'tool/lib/output'
+ Output.new(path: "enc/encinit.c", ifchange: true).write(tmp)
end
diff --git a/encoding.c b/encoding.c
index 8bfab73177..480cc8bdc6 100644
--- a/encoding.c
+++ b/encoding.c
@@ -71,6 +71,24 @@ static struct enc_table {
st_table *names;
} global_enc_table;
+static int
+enc_names_free_i(st_data_t name, st_data_t idx, st_data_t args)
+{
+ ruby_xfree((void *)name);
+ return ST_DELETE;
+}
+
+void
+rb_free_global_enc_table(void)
+{
+ for (size_t i = 0; i < ENCODING_LIST_CAPA; i++) {
+ xfree((void *)global_enc_table.list[i].enc);
+ }
+
+ st_foreach(global_enc_table.names, enc_names_free_i, (st_data_t)0);
+ st_free_table(global_enc_table.names);
+}
+
static rb_encoding *global_enc_ascii,
*global_enc_utf_8,
*global_enc_us_ascii;
@@ -997,13 +1015,22 @@ rb_enc_get(VALUE obj)
return rb_enc_from_index(rb_enc_get_index(obj));
}
+const char *
+rb_enc_inspect_name(rb_encoding *enc)
+{
+ if (enc == global_enc_ascii) {
+ return "BINARY (ASCII-8BIT)";
+ }
+ return enc->name;
+}
+
static rb_encoding*
rb_encoding_check(rb_encoding* enc, VALUE str1, VALUE str2)
{
if (!enc)
rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s",
- rb_enc_name(rb_enc_get(str1)),
- rb_enc_name(rb_enc_get(str2)));
+ rb_enc_inspect_name(rb_enc_get(str1)),
+ rb_enc_inspect_name(rb_enc_get(str2)));
return enc;
}
@@ -1245,9 +1272,10 @@ enc_inspect(VALUE self)
if (!(enc = DATA_PTR(self)) || rb_enc_from_index(rb_enc_to_index(enc)) != enc) {
rb_raise(rb_eTypeError, "broken Encoding");
}
+
return rb_enc_sprintf(rb_usascii_encoding(),
"#<%"PRIsVALUE":%s%s%s>", rb_obj_class(self),
- rb_enc_name(enc),
+ rb_enc_inspect_name(enc),
(ENC_DUMMY_P(enc) ? " (dummy)" : ""),
rb_enc_autoload_p(enc) ? " (autoload)" : "");
}
@@ -1525,7 +1553,14 @@ enc_set_default_encoding(struct default_encoding *def, VALUE encoding, const cha
if (NIL_P(encoding)) {
def->index = -1;
def->enc = 0;
- st_insert(enc_table->names, (st_data_t)strdup(name),
+ char *name_dup = strdup(name);
+
+ st_data_t existing_name = (st_data_t)name_dup;
+ if (st_delete(enc_table->names, &existing_name, NULL)) {
+ xfree((void *)existing_name);
+ }
+
+ st_insert(enc_table->names, (st_data_t)name_dup,
(st_data_t)UNSPECIFIED_ENCODING);
}
else {
@@ -1902,7 +1937,7 @@ Init_Encoding(void)
list = rb_encoding_list = rb_ary_new2(ENCODING_LIST_CAPA);
RBASIC_CLEAR_CLASS(list);
- rb_gc_register_mark_object(list);
+ rb_vm_register_global_object(list);
for (i = 0; i < enc_table->count; ++i) {
rb_ary_push(list, enc_new(enc_table->list[i].enc));
diff --git a/enum.c b/enum.c
index 7f15836ba8..dcb374778e 100644
--- a/enum.c
+++ b/enum.c
@@ -870,134 +870,151 @@ ary_inject_op(VALUE ary, VALUE init, VALUE op)
/*
* call-seq:
- * inject(symbol) -> object
- * inject(initial_operand, symbol) -> object
- * inject {|memo, operand| ... } -> object
- * inject(initial_operand) {|memo, operand| ... } -> object
- *
- * Returns an object formed from operands via either:
+ * inject(symbol) -> object
+ * inject(initial_value, symbol) -> object
+ * inject {|memo, value| ... } -> object
+ * inject(initial_value) {|memo, value| ... } -> object
*
- * - A method named by +symbol+.
- * - A block to which each operand is passed.
- *
- * With method-name argument +symbol+,
- * combines operands using the method:
- *
- * # Sum, without initial_operand.
- * (1..4).inject(:+) # => 10
- * # Sum, with initial_operand.
- * (1..4).inject(10, :+) # => 20
+ * Returns the result of applying a reducer to an initial value and
+ * the first element of the Enumerable. It then takes the result and applies the
+ * function to it and the second element of the collection, and so on. The
+ * return value is the result returned by the final call to the function.
*
- * With a block, passes each operand to the block:
- *
- * # Sum of squares, without initial_operand.
- * (1..4).inject {|sum, n| sum + n*n } # => 30
- * # Sum of squares, with initial_operand.
- * (1..4).inject(2) {|sum, n| sum + n*n } # => 32
+ * You can think of
*
- * <b>Operands</b>
+ * [ a, b, c, d ].inject(i) { |r, v| fn(r, v) }
*
- * If argument +initial_operand+ is not given,
- * the operands for +inject+ are simply the elements of +self+.
- * Example calls and their operands:
+ * as being
*
- * - <tt>(1..4).inject(:+)</tt>:: <tt>[1, 2, 3, 4]</tt>.
- * - <tt>(1...4).inject(:+)</tt>:: <tt>[1, 2, 3]</tt>.
- * - <tt>('a'..'d').inject(:+)</tt>:: <tt>['a', 'b', 'c', 'd']</tt>.
- * - <tt>('a'...'d').inject(:+)</tt>:: <tt>['a', 'b', 'c']</tt>.
+ * fn(fn(fn(fn(i, a), b), c), d)
*
- * Examples with first operand (which is <tt>self.first</tt>) of various types:
+ * In a way the +inject+ function _injects_ the function
+ * between the elements of the enumerable.
*
- * # Integer.
- * (1..4).inject(:+) # => 10
- * # Float.
- * [1.0, 2, 3, 4].inject(:+) # => 10.0
- * # Character.
- * ('a'..'d').inject(:+) # => "abcd"
- * # Complex.
- * [Complex(1, 2), 3, 4].inject(:+) # => (8+2i)
+ * +inject+ is aliased as +reduce+. You use it when you want to
+ * _reduce_ a collection to a single value.
*
- * If argument +initial_operand+ is given,
- * the operands for +inject+ are that value plus the elements of +self+.
- * Example calls their operands:
+ * <b>The Calling Sequences</b>
*
- * - <tt>(1..4).inject(10, :+)</tt>:: <tt>[10, 1, 2, 3, 4]</tt>.
- * - <tt>(1...4).inject(10, :+)</tt>:: <tt>[10, 1, 2, 3]</tt>.
- * - <tt>('a'..'d').inject('e', :+)</tt>:: <tt>['e', 'a', 'b', 'c', 'd']</tt>.
- * - <tt>('a'...'d').inject('e', :+)</tt>:: <tt>['e', 'a', 'b', 'c']</tt>.
+ * Let's start with the most verbose:
*
- * Examples with +initial_operand+ of various types:
+ * enum.inject(initial_value) do |result, next_value|
+ * # do something with +result+ and +next_value+
+ * # the value returned by the block becomes the
+ * # value passed in to the next iteration
+ * # as +result+
+ * end
*
- * # Integer.
- * (1..4).inject(2, :+) # => 12
- * # Float.
- * (1..4).inject(2.0, :+) # => 12.0
- * # String.
- * ('a'..'d').inject('foo', :+) # => "fooabcd"
- * # Array.
- * %w[a b c].inject(['x'], :push) # => ["x", "a", "b", "c"]
- * # Complex.
- * (1..4).inject(Complex(2, 2), :+) # => (12+2i)
+ * For example:
*
- * <b>Combination by Given \Method</b>
+ * product = [ 2, 3, 4 ].inject(1) do |result, next_value|
+ * result * next_value
+ * end
+ * product #=> 24
*
- * If the method-name argument +symbol+ is given,
- * the operands are combined by that method:
+ * When this runs, the block is first called with +1+ (the initial value) and
+ * +2+ (the first element of the array). The block returns <tt>1*2</tt>, so on
+ * the next iteration the block is called with +2+ (the previous result) and
+ * +3+. The block returns +6+, and is called one last time with +6+ and +4+.
+ * The result of the block, +24+ becomes the value returned by +inject+. This
+ * code returns the product of the elements in the enumerable.
*
- * - The first and second operands are combined.
- * - That result is combined with the third operand.
- * - That result is combined with the fourth operand.
- * - And so on.
+ * <b>First Shortcut: Default Initial value</b>
*
- * The return value from +inject+ is the result of the last combination.
+ * In the case of the previous example, the initial value, +1+, wasn't really
+ * necessary: the calculation of the product of a list of numbers is self-contained.
*
- * This call to +inject+ computes the sum of the operands:
+ * In these circumstances, you can omit the +initial_value+ parameter. +inject+
+ * will then initially call the block with the first element of the collection
+ * as the +result+ parameter and the second element as the +next_value+.
*
- * (1..4).inject(:+) # => 10
+ * [ 2, 3, 4 ].inject do |result, next_value|
+ * result * next_value
+ * end
*
- * Examples with various methods:
+ * This shortcut is convenient, but can only be used when the block produces a result
+ * which can be passed back to it as a first parameter.
*
- * # Integer addition.
- * (1..4).inject(:+) # => 10
- * # Integer multiplication.
- * (1..4).inject(:*) # => 24
- * # Character range concatenation.
- * ('a'..'d').inject('', :+) # => "abcd"
- * # String array concatenation.
- * %w[foo bar baz].inject('', :+) # => "foobarbaz"
- * # Hash update.
- * h = [{foo: 0, bar: 1}, {baz: 2}, {bat: 3}].inject(:update)
- * h # => {:foo=>0, :bar=>1, :baz=>2, :bat=>3}
- * # Hash conversion to nested arrays.
- * h = {foo: 0, bar: 1}.inject([], :push)
- * h # => [[:foo, 0], [:bar, 1]]
+ * Here's an example where that's not the case: it returns a hash where the keys are words
+ * and the values are the number of occurrences of that word in the enumerable.
*
- * <b>Combination by Given Block</b>
+ * freqs = File.read("README.md")
+ * .scan(/\w{2,}/)
+ * .reduce(Hash.new(0)) do |counts, word|
+ * counts[word] += 1
+ * counts
+ * end
+ * freqs #=> {"Actions"=>4,
+ * "Status"=>5,
+ * "MinGW"=>3,
+ * "https"=>27,
+ * "github"=>10,
+ * "com"=>15, ...
*
- * If a block is given, the operands are passed to the block:
+ * Note that the last line of the block is just the word +counts+. This ensures the
+ * return value of the block is the result that's being calculated.
*
- * - The first call passes the first and second operands.
- * - The second call passes the result of the first call,
- * along with the third operand.
- * - The third call passes the result of the second call,
- * along with the fourth operand.
- * - And so on.
+ * <b>Second Shortcut: a Reducer function</b>
*
- * The return value from +inject+ is the return value from the last block call.
- *
- * This call to +inject+ gives a block
- * that writes the memo and element, and also sums the elements:
+ * A <i>reducer function</i> is a function that takes a partial result and the next value,
+ * returning the next partial result. The block that is given to +inject+ is a reducer.
*
- * (1..4).inject do |memo, element|
- * p "Memo: #{memo}; element: #{element}"
- * memo + element
- * end # => 10
+ * You can also write a reducer as a function and pass the name of that function
+ * (as a symbol) to +inject+. However, for this to work, the function
*
- * Output:
+ * 1. Must be defined on the type of the result value
+ * 2. Must accept a single parameter, the next value in the collection, and
+ * 3. Must return an updated result which will also implement the function.
+ *
+ * Here's an example that adds elements to a string. The two calls invoke the functions
+ * String#concat and String#+ on the result so far, passing it the next value.
+ *
+ * s = [ "cat", " ", "dog" ].inject("", :concat)
+ * s #=> "cat dog"
+ * s = [ "cat", " ", "dog" ].inject("The result is:", :+)
+ * s #=> "The result is: cat dog"
+ *
+ * Here's a more complex example when the result object maintains
+ * state of a different type to the enumerable elements.
+ *
+ * class Turtle
+ *
+ * def initialize
+ * @x = @y = 0
+ * end
+ *
+ * def move(dir)
+ * case dir
+ * when "n" then @y += 1
+ * when "s" then @y -= 1
+ * when "e" then @x += 1
+ * when "w" then @x -= 1
+ * end
+ * self
+ * end
+ * end
+ *
+ * position = "nnneesw".chars.reduce(Turtle.new, :move)
+ * position #=>> #<Turtle:0x00000001052f4698 @y=2, @x=1>
+ *
+ * <b>Third Shortcut: Reducer With no Initial Value</b>
+ *
+ * If your reducer returns a value that it can accept as a parameter, then you
+ * don't have to pass in an initial value. Here <tt>:*</tt> is the name of the
+ * _times_ function:
+ *
+ * product = [ 2, 3, 4 ].inject(:*)
+ * product # => 24
+ *
+ * String concatenation again:
+ *
+ * s = [ "cat", " ", "dog" ].inject(:+)
+ * s #=> "cat dog"
+ *
+ * And an example that converts a hash to an array of two-element subarrays.
*
- * "Memo: 1; element: 2"
- * "Memo: 3; element: 3"
- * "Memo: 6; element: 4"
+ * nested = {foo: 0, bar: 1}.inject([], :push)
+ * nested # => [[:foo, 0], [:bar, 1]]
*
*
*/
@@ -4538,7 +4555,7 @@ struct enum_sum_memo {
static void
sum_iter_normalize_memo(struct enum_sum_memo *memo)
{
- assert(FIXABLE(memo->n));
+ RUBY_ASSERT(FIXABLE(memo->n));
memo->v = rb_fix_plus(LONG2FIX(memo->n), memo->v);
memo->n = 0;
@@ -4640,7 +4657,7 @@ sum_iter_Kahan_Babuska(VALUE i, struct enum_sum_memo *memo)
static void
sum_iter(VALUE i, struct enum_sum_memo *memo)
{
- assert(memo != NULL);
+ RUBY_ASSERT(memo != NULL);
if (memo->block_given) {
i = rb_yield(i);
}
@@ -4691,8 +4708,8 @@ hash_sum_i(VALUE key, VALUE value, VALUE arg)
static void
hash_sum(VALUE hash, struct enum_sum_memo *memo)
{
- assert(RB_TYPE_P(hash, T_HASH));
- assert(memo != NULL);
+ RUBY_ASSERT(RB_TYPE_P(hash, T_HASH));
+ RUBY_ASSERT(memo != NULL);
rb_hash_foreach(hash, hash_sum_i, (VALUE)memo);
}
diff --git a/enumerator.c b/enumerator.c
index 0e010c14c2..193a865dbc 100644
--- a/enumerator.c
+++ b/enumerator.c
@@ -195,17 +195,18 @@ struct enumerator {
int kw_splat;
};
-RUBY_REFERENCES_START(enumerator_refs)
- REF_EDGE(enumerator, obj),
- REF_EDGE(enumerator, args),
- REF_EDGE(enumerator, fib),
- REF_EDGE(enumerator, dst),
- REF_EDGE(enumerator, lookahead),
- REF_EDGE(enumerator, feedvalue),
- REF_EDGE(enumerator, stop_exc),
- REF_EDGE(enumerator, size),
- REF_EDGE(enumerator, procs),
-RUBY_REFERENCES_END
+RUBY_REFERENCES(enumerator_refs) = {
+ RUBY_REF_EDGE(struct enumerator, obj),
+ RUBY_REF_EDGE(struct enumerator, args),
+ RUBY_REF_EDGE(struct enumerator, fib),
+ RUBY_REF_EDGE(struct enumerator, dst),
+ RUBY_REF_EDGE(struct enumerator, lookahead),
+ RUBY_REF_EDGE(struct enumerator, feedvalue),
+ RUBY_REF_EDGE(struct enumerator, stop_exc),
+ RUBY_REF_EDGE(struct enumerator, size),
+ RUBY_REF_EDGE(struct enumerator, procs),
+ RUBY_REF_END
+};
static VALUE rb_cGenerator, rb_cYielder, rb_cEnumProducer;
@@ -256,23 +257,15 @@ struct enum_product {
VALUE rb_cArithSeq;
-#define enumerator_free RUBY_TYPED_DEFAULT_FREE
-
-static size_t
-enumerator_memsize(const void *p)
-{
- return sizeof(struct enumerator);
-}
-
static const rb_data_type_t enumerator_data_type = {
"enumerator",
{
- REFS_LIST_PTR(enumerator_refs),
- enumerator_free,
- enumerator_memsize,
+ RUBY_REFS_LIST_PTR(enumerator_refs),
+ RUBY_TYPED_DEFAULT_FREE,
+ NULL, // Nothing allocated externally, so don't need a memsize function
NULL,
},
- 0, NULL, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_DECL_MARKING
+ 0, NULL, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_DECL_MARKING | RUBY_TYPED_EMBEDDABLE
};
static struct enumerator *
@@ -303,22 +296,15 @@ proc_entry_compact(void *p)
ptr->memo = rb_gc_location(ptr->memo);
}
-#define proc_entry_free RUBY_TYPED_DEFAULT_FREE
-
-static size_t
-proc_entry_memsize(const void *p)
-{
- return p ? sizeof(struct proc_entry) : 0;
-}
-
static const rb_data_type_t proc_entry_data_type = {
"proc_entry",
{
proc_entry_mark,
- proc_entry_free,
- proc_entry_memsize,
+ RUBY_TYPED_DEFAULT_FREE,
+ NULL, // Nothing allocated externally, so don't need a memsize function
proc_entry_compact,
},
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
};
static struct proc_entry *
@@ -403,7 +389,7 @@ obj_to_enum(int argc, VALUE *argv, VALUE obj)
}
enumerator = rb_enumeratorize_with_size(obj, meth, argc, argv, 0);
if (rb_block_given_p()) {
- enumerator_ptr(enumerator)->size = rb_block_proc();
+ RB_OBJ_WRITE(enumerator, &enumerator_ptr(enumerator)->size, rb_block_proc());
}
return enumerator;
}
@@ -432,15 +418,15 @@ enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, const VALUE *ar
rb_raise(rb_eArgError, "unallocated enumerator");
}
- ptr->obj = obj;
+ RB_OBJ_WRITE(enum_obj, &ptr->obj, obj);
ptr->meth = rb_to_id(meth);
- if (argc) ptr->args = rb_ary_new4(argc, argv);
+ if (argc) RB_OBJ_WRITE(enum_obj, &ptr->args, rb_ary_new4(argc, argv));
ptr->fib = 0;
ptr->dst = Qnil;
ptr->lookahead = Qundef;
ptr->feedvalue = Qundef;
ptr->stop_exc = Qfalse;
- ptr->size = size;
+ RB_OBJ_WRITE(enum_obj, &ptr->size, size);
ptr->size_fn = size_fn;
ptr->kw_splat = kw_splat;
@@ -519,13 +505,13 @@ enumerator_init_copy(VALUE obj, VALUE orig)
rb_raise(rb_eArgError, "unallocated enumerator");
}
- ptr1->obj = ptr0->obj;
- ptr1->meth = ptr0->meth;
- ptr1->args = ptr0->args;
+ RB_OBJ_WRITE(obj, &ptr1->obj, ptr0->obj);
+ RB_OBJ_WRITE(obj, &ptr1->meth, ptr0->meth);
+ RB_OBJ_WRITE(obj, &ptr1->args, ptr0->args);
ptr1->fib = 0;
ptr1->lookahead = Qundef;
ptr1->feedvalue = Qundef;
- ptr1->size = ptr0->size;
+ RB_OBJ_WRITE(obj, &ptr1->size, ptr0->size);
ptr1->size_fn = ptr0->size_fn;
return obj;
@@ -573,11 +559,17 @@ enumerator_block_call(VALUE obj, rb_block_call_func *func, VALUE arg)
const struct enumerator *e = enumerator_ptr(obj);
ID meth = e->meth;
- if (e->args) {
- argc = RARRAY_LENINT(e->args);
- argv = RARRAY_CONST_PTR(e->args);
+ VALUE args = e->args;
+ if (args) {
+ argc = RARRAY_LENINT(args);
+ argv = RARRAY_CONST_PTR(args);
}
- return rb_block_call_kw(e->obj, meth, argc, argv, func, arg, e->kw_splat);
+
+ VALUE ret = rb_block_call_kw(e->obj, meth, argc, argv, func, arg, e->kw_splat);
+
+ RB_GC_GUARD(args);
+
+ return ret;
}
/*
@@ -634,7 +626,7 @@ enumerator_each(int argc, VALUE *argv, VALUE obj)
else {
args = rb_ary_new4(argc, argv);
}
- e->args = args;
+ RB_OBJ_WRITE(obj, &e->args, args);
e->size = Qnil;
e->size_fn = 0;
}
@@ -775,7 +767,7 @@ next_i(RB_BLOCK_CALL_FUNC_ARGLIST(_, obj))
VALUE result;
result = rb_block_call(obj, id_each, 0, 0, next_ii, obj);
- e->stop_exc = rb_exc_new2(rb_eStopIteration, "iteration reached an end");
+ RB_OBJ_WRITE(obj, &e->stop_exc, rb_exc_new2(rb_eStopIteration, "iteration reached an end"));
rb_ivar_set(e->stop_exc, id_result, result);
return rb_fiber_yield(1, &nil);
}
@@ -784,8 +776,8 @@ static void
next_init(VALUE obj, struct enumerator *e)
{
VALUE curr = rb_fiber_current();
- e->dst = curr;
- e->fib = rb_fiber_new(next_i, obj);
+ RB_OBJ_WRITE(obj, &e->dst, curr);
+ RB_OBJ_WRITE(obj, &e->fib, rb_fiber_new(next_i, obj));
e->lookahead = Qundef;
}
@@ -939,8 +931,9 @@ enumerator_peek_values(VALUE obj)
rb_check_frozen(obj);
if (UNDEF_P(e->lookahead)) {
- e->lookahead = get_next_values(obj, e);
+ RB_OBJ_WRITE(obj, &e->lookahead, get_next_values(obj, e));
}
+
return e->lookahead;
}
@@ -1067,7 +1060,7 @@ enumerator_feed(VALUE obj, VALUE v)
if (!UNDEF_P(e->feedvalue)) {
rb_raise(rb_eTypeError, "feed value already set");
}
- e->feedvalue = v;
+ RB_OBJ_WRITE(obj, &e->feedvalue, v);
return Qnil;
}
@@ -1301,23 +1294,15 @@ yielder_compact(void *p)
ptr->proc = rb_gc_location(ptr->proc);
}
-#define yielder_free RUBY_TYPED_DEFAULT_FREE
-
-static size_t
-yielder_memsize(const void *p)
-{
- return sizeof(struct yielder);
-}
-
static const rb_data_type_t yielder_data_type = {
"yielder",
{
yielder_mark,
- yielder_free,
- yielder_memsize,
+ RUBY_TYPED_DEFAULT_FREE,
+ NULL,
yielder_compact,
},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
};
static struct yielder *
@@ -1356,7 +1341,7 @@ yielder_init(VALUE obj, VALUE proc)
rb_raise(rb_eArgError, "unallocated yielder");
}
- ptr->proc = proc;
+ RB_OBJ_WRITE(obj, &ptr->proc, proc);
return obj;
}
@@ -1441,23 +1426,15 @@ generator_compact(void *p)
ptr->obj = rb_gc_location(ptr->obj);
}
-#define generator_free RUBY_TYPED_DEFAULT_FREE
-
-static size_t
-generator_memsize(const void *p)
-{
- return sizeof(struct generator);
-}
-
static const rb_data_type_t generator_data_type = {
"generator",
{
generator_mark,
- generator_free,
- generator_memsize,
+ RUBY_TYPED_DEFAULT_FREE,
+ NULL,
generator_compact,
},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
};
static struct generator *
@@ -1497,7 +1474,7 @@ generator_init(VALUE obj, VALUE proc)
rb_raise(rb_eArgError, "unallocated generator");
}
- ptr->proc = proc;
+ RB_OBJ_WRITE(obj, &ptr->proc, proc);
return obj;
}
@@ -1545,7 +1522,7 @@ generator_init_copy(VALUE obj, VALUE orig)
rb_raise(rb_eArgError, "unallocated generator");
}
- ptr1->proc = ptr0->proc;
+ RB_OBJ_WRITE(obj, &ptr1->proc, ptr0->proc);
return obj;
}
@@ -1712,7 +1689,7 @@ lazy_generator_init(VALUE enumerator, VALUE procs)
lazy_init_block, rb_ary_new3(2, obj, procs));
gen_ptr = generator_ptr(generator);
- gen_ptr->obj = obj;
+ RB_OBJ_WRITE(generator, &gen_ptr->obj, obj);
return generator;
}
@@ -1897,10 +1874,10 @@ lazy_add_method(VALUE obj, int argc, VALUE *argv, VALUE args, VALUE memo,
VALUE entry_obj = TypedData_Make_Struct(rb_cObject, struct proc_entry,
&proc_entry_data_type, entry);
if (rb_block_given_p()) {
- entry->proc = rb_block_proc();
+ RB_OBJ_WRITE(entry_obj, &entry->proc, rb_block_proc());
}
entry->fn = fn;
- entry->memo = args;
+ RB_OBJ_WRITE(entry_obj, &entry->memo, args);
lazy_set_args(entry_obj, memo);
@@ -1909,9 +1886,9 @@ lazy_add_method(VALUE obj, int argc, VALUE *argv, VALUE args, VALUE memo,
rb_ary_push(new_procs, entry_obj);
new_obj = enumerator_init_copy(enumerator_allocate(rb_cLazy), obj);
- new_e = DATA_PTR(new_obj);
- new_e->obj = new_generator;
- new_e->procs = new_procs;
+ new_e = RTYPEDDATA_GET_DATA(new_obj);
+ RB_OBJ_WRITE(new_obj, &new_e->obj, new_generator);
+ RB_OBJ_WRITE(new_obj, &new_e->procs, new_procs);
if (argc > 0) {
new_e->meth = rb_to_id(*argv++);
@@ -1920,7 +1897,9 @@ lazy_add_method(VALUE obj, int argc, VALUE *argv, VALUE args, VALUE memo,
else {
new_e->meth = id_each;
}
- new_e->args = rb_ary_new4(argc, argv);
+
+ RB_OBJ_WRITE(new_obj, &new_e->args, rb_ary_new4(argc, argv));
+
return new_obj;
}
@@ -2006,7 +1985,7 @@ lazy_to_enum(int argc, VALUE *argv, VALUE self)
}
lazy = lazy_to_enum_i(self, meth, argc, argv, 0, rb_keyword_given_p());
if (rb_block_given_p()) {
- enumerator_ptr(lazy)->size = rb_block_proc();
+ RB_OBJ_WRITE(lazy, &enumerator_ptr(lazy)->size, rb_block_proc());
}
return lazy;
}
@@ -2966,7 +2945,7 @@ static const rb_data_type_t producer_data_type = {
producer_memsize,
producer_compact,
},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
};
static struct producer *
@@ -3006,8 +2985,8 @@ producer_init(VALUE obj, VALUE init, VALUE proc)
rb_raise(rb_eArgError, "unallocated producer");
}
- ptr->init = init;
- ptr->proc = proc;
+ RB_OBJ_WRITE(obj, &ptr->init, init);
+ RB_OBJ_WRITE(obj, &ptr->proc, proc);
return obj;
}
@@ -3557,10 +3536,19 @@ static VALUE
enum_product_total_size(VALUE enums)
{
VALUE total = INT2FIX(1);
+ VALUE sizes = rb_ary_hidden_new(RARRAY_LEN(enums));
long i;
for (i = 0; i < RARRAY_LEN(enums); i++) {
VALUE size = enum_size(RARRAY_AREF(enums, i));
+ if (size == INT2FIX(0)) {
+ rb_ary_resize(sizes, 0);
+ return size;
+ }
+ rb_ary_push(sizes, size);
+ }
+ for (i = 0; i < RARRAY_LEN(sizes); i++) {
+ VALUE size = RARRAY_AREF(sizes, i);
if (NIL_P(size) || (RB_TYPE_P(size, T_FLOAT) && isinf(NUM2DBL(size)))) {
return size;
@@ -4583,7 +4571,7 @@ InitVM_Enumerator(void)
rb_hash_aset(lazy_use_super_method, sym("uniq"), sym("_enumerable_uniq"));
rb_hash_aset(lazy_use_super_method, sym("with_index"), sym("_enumerable_with_index"));
rb_obj_freeze(lazy_use_super_method);
- rb_gc_register_mark_object(lazy_use_super_method);
+ rb_vm_register_global_object(lazy_use_super_method);
#if 0 /* for RDoc */
rb_define_method(rb_cLazy, "to_a", lazy_to_a, 0);
diff --git a/error.c b/error.c
index 041ab834f3..fae9038ea9 100644
--- a/error.c
+++ b/error.c
@@ -32,6 +32,7 @@
#endif
#include "internal.h"
+#include "internal/class.h"
#include "internal/error.h"
#include "internal/eval.h"
#include "internal/hash.h"
@@ -48,6 +49,7 @@
#include "ruby/util.h"
#include "ruby_assert.h"
#include "vm_core.h"
+#include "yjit.h"
#include "builtin.h"
@@ -252,6 +254,26 @@ rb_warning_s_aset(VALUE mod, VALUE category, VALUE flag)
/*
* call-seq:
+ * categories -> array
+ *
+ * Returns a list of the supported category symbols.
+ */
+
+static VALUE
+rb_warning_s_categories(VALUE mod)
+{
+ st_index_t num = warning_categories.id2enum->num_entries;
+ ID *ids = ALLOCA_N(ID, num);
+ num = st_keys(warning_categories.id2enum, ids, num);
+ VALUE ary = rb_ary_new_capa(num);
+ for (st_index_t i = 0; i < num; ++i) {
+ rb_ary_push(ary, ID2SYM(ids[i]));
+ }
+ return rb_ary_freeze(ary);
+}
+
+/*
+ * call-seq:
* warn(msg, category: nil) -> nil
*
* Writes warning message +msg+ to $stderr. This method is called by
@@ -291,11 +313,11 @@ rb_warning_s_warn(int argc, VALUE *argv, VALUE mod)
*
* Changing the behavior of Warning.warn is useful to customize how warnings are
* handled by Ruby, for instance by filtering some warnings, and/or outputting
- * warnings somewhere other than $stderr.
+ * warnings somewhere other than <tt>$stderr</tt>.
*
* If you want to change the behavior of Warning.warn you should use
- * +Warning.extend(MyNewModuleWithWarnMethod)+ and you can use `super`
- * to get the default behavior of printing the warning to $stderr.
+ * <tt>Warning.extend(MyNewModuleWithWarnMethod)</tt> and you can use +super+
+ * to get the default behavior of printing the warning to <tt>$stderr</tt>.
*
* Example:
* module MyWarningFilter
@@ -312,7 +334,7 @@ rb_warning_s_warn(int argc, VALUE *argv, VALUE mod)
* You should never redefine Warning#warn (the instance method), as that will
* then no longer provide a way to use the default behavior.
*
- * The +warning+ gem provides convenient ways to customize Warning.warn.
+ * The warning[https://rubygems.org/gems/warning] gem provides convenient ways to customize Warning.warn.
*/
static VALUE
@@ -364,18 +386,28 @@ warn_vsprintf(rb_encoding *enc, const char *file, int line, const char *fmt, va_
return rb_str_cat2(str, "\n");
}
-#define with_warn_vsprintf(file, line, fmt) \
+#define with_warn_vsprintf(enc, file, line, fmt) \
VALUE str; \
va_list args; \
va_start(args, fmt); \
- str = warn_vsprintf(NULL, file, line, fmt, args); \
+ str = warn_vsprintf(enc, file, line, fmt, args); \
va_end(args);
void
rb_compile_warn(const char *file, int line, const char *fmt, ...)
{
if (!NIL_P(ruby_verbose)) {
- with_warn_vsprintf(file, line, fmt) {
+ with_warn_vsprintf(NULL, file, line, fmt) {
+ rb_write_warning_str(str);
+ }
+ }
+}
+
+void
+rb_enc_compile_warn(rb_encoding *enc, const char *file, int line, const char *fmt, ...)
+{
+ if (!NIL_P(ruby_verbose)) {
+ with_warn_vsprintf(enc, file, line, fmt) {
rb_write_warning_str(str);
}
}
@@ -386,7 +418,18 @@ void
rb_compile_warning(const char *file, int line, const char *fmt, ...)
{
if (RTEST(ruby_verbose)) {
- with_warn_vsprintf(file, line, fmt) {
+ with_warn_vsprintf(NULL, file, line, fmt) {
+ rb_write_warning_str(str);
+ }
+ }
+}
+
+/* rb_enc_compile_warning() reports only in verbose mode */
+void
+rb_enc_compile_warning(rb_encoding *enc, const char *file, int line, const char *fmt, ...)
+{
+ if (RTEST(ruby_verbose)) {
+ with_warn_vsprintf(enc, file, line, fmt) {
rb_write_warning_str(str);
}
}
@@ -396,7 +439,7 @@ void
rb_category_compile_warn(rb_warning_category_t category, const char *file, int line, const char *fmt, ...)
{
if (!NIL_P(ruby_verbose)) {
- with_warn_vsprintf(file, line, fmt) {
+ with_warn_vsprintf(NULL, file, line, fmt) {
rb_warn_category(str, rb_warning_category_to_name(category));
}
}
@@ -1066,6 +1109,7 @@ rb_bug_for_fatal_signal(ruby_sighandler_t default_sighandler, int sig, const voi
if (default_sighandler) default_sighandler(sig);
+ ruby_default_signal(sig);
die();
}
@@ -1122,10 +1166,25 @@ rb_report_bug_valist(VALUE file, int line, const char *fmt, va_list args)
void
rb_assert_failure(const char *file, int line, const char *name, const char *expr)
{
+ rb_assert_failure_detail(file, line, name, expr, NULL);
+}
+
+void
+rb_assert_failure_detail(const char *file, int line, const char *name, const char *expr,
+ const char *fmt, ...)
+{
FILE *out = stderr;
fprintf(out, "Assertion Failed: %s:%d:", file, line);
if (name) fprintf(out, "%s:", name);
fprintf(out, "%s\n%s\n\n", expr, rb_dynamic_description);
+
+ if (fmt && *fmt) {
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(out, fmt, args);
+ va_end(args);
+ }
+
preface_dump(out);
rb_vm_bugreport(NULL, out);
bug_report_end(out, -1);
@@ -1393,6 +1452,7 @@ rb_exc_new_cstr(VALUE etype, const char *s)
VALUE
rb_exc_new_str(VALUE etype, VALUE str)
{
+ rb_yjit_lazy_push_frame(GET_EC()->cfp->pc);
StringValue(str);
return rb_class_new_instance(1, &str, etype);
}
@@ -1661,7 +1721,7 @@ exc_detailed_message(int argc, VALUE *argv, VALUE exc)
VALUE highlight = check_highlight_keyword(opt, 0);
- extern VALUE rb_decorate_message(const VALUE eclass, const VALUE emesg, int highlight);
+ extern VALUE rb_decorate_message(const VALUE eclass, VALUE emesg, int highlight);
return rb_decorate_message(CLASS_OF(exc), rb_get_message(exc), RTEST(highlight));
}
@@ -1800,7 +1860,7 @@ static VALUE
rb_check_backtrace(VALUE bt)
{
long i;
- static const char err[] = "backtrace must be Array of String";
+ static const char err[] = "backtrace must be an Array of String or an Array of Thread::Backtrace::Location";
if (!NIL_P(bt)) {
if (RB_TYPE_P(bt, T_STRING)) return rb_ary_new3(1, bt);
@@ -1823,15 +1883,23 @@ rb_check_backtrace(VALUE bt)
* exc.set_backtrace(backtrace) -> array
*
* Sets the backtrace information associated with +exc+. The +backtrace+ must
- * be an array of String objects or a single String in the format described
- * in Exception#backtrace.
+ * be an array of Thread::Backtrace::Location objects or an array of String objects
+ * or a single String in the format described in Exception#backtrace.
*
*/
static VALUE
exc_set_backtrace(VALUE exc, VALUE bt)
{
- return rb_ivar_set(exc, id_bt, rb_check_backtrace(bt));
+ VALUE btobj = rb_location_ary_to_backtrace(bt);
+ if (RTEST(btobj)) {
+ rb_ivar_set(exc, id_bt, btobj);
+ rb_ivar_set(exc, id_bt_locations, btobj);
+ return bt;
+ }
+ else {
+ return rb_ivar_set(exc, id_bt, rb_check_backtrace(bt));
+ }
}
VALUE
@@ -2202,50 +2270,50 @@ rb_nomethod_err_new(VALUE mesg, VALUE recv, VALUE method, VALUE args, int priv)
return nometh_err_init_attr(exc, args, priv);
}
-/* :nodoc: */
-enum {
- NAME_ERR_MESG__MESG,
- NAME_ERR_MESG__RECV,
- NAME_ERR_MESG__NAME,
- NAME_ERR_MESG_COUNT
-};
+typedef struct name_error_message_struct {
+ VALUE mesg;
+ VALUE recv;
+ VALUE name;
+} name_error_message_t;
static void
name_err_mesg_mark(void *p)
{
- VALUE *ptr = p;
- rb_gc_mark_locations(ptr, ptr+NAME_ERR_MESG_COUNT);
+ name_error_message_t *ptr = (name_error_message_t *)p;
+ rb_gc_mark_movable(ptr->mesg);
+ rb_gc_mark_movable(ptr->recv);
+ rb_gc_mark_movable(ptr->name);
}
-#define name_err_mesg_free RUBY_TYPED_DEFAULT_FREE
-
-static size_t
-name_err_mesg_memsize(const void *p)
+static void
+name_err_mesg_update(void *p)
{
- return NAME_ERR_MESG_COUNT * sizeof(VALUE);
+ name_error_message_t *ptr = (name_error_message_t *)p;
+ ptr->mesg = rb_gc_location(ptr->mesg);
+ ptr->recv = rb_gc_location(ptr->recv);
+ ptr->name = rb_gc_location(ptr->name);
}
static const rb_data_type_t name_err_mesg_data_type = {
"name_err_mesg",
{
name_err_mesg_mark,
- name_err_mesg_free,
- name_err_mesg_memsize,
+ RUBY_TYPED_DEFAULT_FREE,
+ NULL, // No external memory to report,
+ name_err_mesg_update,
},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
};
/* :nodoc: */
static VALUE
-rb_name_err_mesg_init(VALUE klass, VALUE mesg, VALUE recv, VALUE method)
+rb_name_err_mesg_init(VALUE klass, VALUE mesg, VALUE recv, VALUE name)
{
- VALUE result = TypedData_Wrap_Struct(klass, &name_err_mesg_data_type, 0);
- VALUE *ptr = ALLOC_N(VALUE, NAME_ERR_MESG_COUNT);
-
- ptr[NAME_ERR_MESG__MESG] = mesg;
- ptr[NAME_ERR_MESG__RECV] = recv;
- ptr[NAME_ERR_MESG__NAME] = method;
- RTYPEDDATA_DATA(result) = ptr;
+ name_error_message_t *message;
+ VALUE result = TypedData_Make_Struct(klass, name_error_message_t, &name_err_mesg_data_type, message);
+ RB_OBJ_WRITE(result, &message->mesg, mesg);
+ RB_OBJ_WRITE(result, &message->recv, recv);
+ RB_OBJ_WRITE(result, &message->name, name);
return result;
}
@@ -2267,14 +2335,16 @@ name_err_mesg_alloc(VALUE klass)
static VALUE
name_err_mesg_init_copy(VALUE obj1, VALUE obj2)
{
- VALUE *ptr1, *ptr2;
-
if (obj1 == obj2) return obj1;
rb_obj_init_copy(obj1, obj2);
- TypedData_Get_Struct(obj1, VALUE, &name_err_mesg_data_type, ptr1);
- TypedData_Get_Struct(obj2, VALUE, &name_err_mesg_data_type, ptr2);
- MEMCPY(ptr1, ptr2, VALUE, NAME_ERR_MESG_COUNT);
+ name_error_message_t *ptr1, *ptr2;
+ TypedData_Get_Struct(obj1, name_error_message_t, &name_err_mesg_data_type, ptr1);
+ TypedData_Get_Struct(obj2, name_error_message_t, &name_err_mesg_data_type, ptr2);
+
+ RB_OBJ_WRITE(obj1, &ptr1->mesg, ptr2->mesg);
+ RB_OBJ_WRITE(obj1, &ptr1->recv, ptr2->recv);
+ RB_OBJ_WRITE(obj1, &ptr1->name, ptr2->name);
return obj1;
}
@@ -2282,19 +2352,18 @@ name_err_mesg_init_copy(VALUE obj1, VALUE obj2)
static VALUE
name_err_mesg_equal(VALUE obj1, VALUE obj2)
{
- VALUE *ptr1, *ptr2;
- int i;
-
if (obj1 == obj2) return Qtrue;
+
if (rb_obj_class(obj2) != rb_cNameErrorMesg)
return Qfalse;
- TypedData_Get_Struct(obj1, VALUE, &name_err_mesg_data_type, ptr1);
- TypedData_Get_Struct(obj2, VALUE, &name_err_mesg_data_type, ptr2);
- for (i=0; i<NAME_ERR_MESG_COUNT; i++) {
- if (!rb_equal(ptr1[i], ptr2[i]))
- return Qfalse;
- }
+ name_error_message_t *ptr1, *ptr2;
+ TypedData_Get_Struct(obj1, name_error_message_t, &name_err_mesg_data_type, ptr1);
+ TypedData_Get_Struct(obj2, name_error_message_t, &name_err_mesg_data_type, ptr2);
+
+ if (!rb_equal(ptr1->mesg, ptr2->mesg)) return Qfalse;
+ if (!rb_equal(ptr1->recv, ptr2->recv)) return Qfalse;
+ if (!rb_equal(ptr1->name, ptr2->name)) return Qfalse;
return Qtrue;
}
@@ -2313,10 +2382,10 @@ name_err_mesg_receiver_name(VALUE obj)
static VALUE
name_err_mesg_to_str(VALUE obj)
{
- VALUE *ptr, mesg;
- TypedData_Get_Struct(obj, VALUE, &name_err_mesg_data_type, ptr);
+ name_error_message_t *ptr;
+ TypedData_Get_Struct(obj, name_error_message_t, &name_err_mesg_data_type, ptr);
- mesg = ptr[NAME_ERR_MESG__MESG];
+ VALUE mesg = ptr->mesg;
if (NIL_P(mesg)) return Qnil;
else {
struct RString s_str, c_str, d_str;
@@ -2326,7 +2395,7 @@ name_err_mesg_to_str(VALUE obj)
#define FAKE_CSTR(v, str) rb_setup_fake_str((v), (str), rb_strlen_lit(str), usascii)
c = s = FAKE_CSTR(&s_str, "");
- obj = ptr[NAME_ERR_MESG__RECV];
+ obj = ptr->recv;
switch (obj) {
case Qnil:
c = d = FAKE_CSTR(&d_str, "nil");
@@ -2369,7 +2438,7 @@ name_err_mesg_to_str(VALUE obj)
VALUE klass;
object:
klass = CLASS_OF(obj);
- if (RB_TYPE_P(klass, T_CLASS) && FL_TEST(klass, FL_SINGLETON)) {
+ if (RB_TYPE_P(klass, T_CLASS) && RCLASS_SINGLETON_P(klass)) {
s = FAKE_CSTR(&s_str, "");
if (obj == rb_vm_top_self()) {
c = FAKE_CSTR(&c_str, "main");
@@ -2397,7 +2466,7 @@ name_err_mesg_to_str(VALUE obj)
c = c2;
break;
}
- args[0] = rb_obj_as_string(ptr[NAME_ERR_MESG__NAME]);
+ args[0] = rb_obj_as_string(ptr->name);
args[1] = d;
args[2] = s;
args[3] = c;
@@ -2430,17 +2499,17 @@ name_err_mesg_load(VALUE klass, VALUE str)
static VALUE
name_err_receiver(VALUE self)
{
- VALUE *ptr, recv, mesg;
-
- recv = rb_ivar_lookup(self, id_recv, Qundef);
+ VALUE recv = rb_ivar_lookup(self, id_recv, Qundef);
if (!UNDEF_P(recv)) return recv;
- mesg = rb_attr_get(self, id_mesg);
+ VALUE mesg = rb_attr_get(self, id_mesg);
if (!rb_typeddata_is_kind_of(mesg, &name_err_mesg_data_type)) {
rb_raise(rb_eArgError, "no receiver is available");
}
- ptr = DATA_PTR(mesg);
- return ptr[NAME_ERR_MESG__RECV];
+
+ name_error_message_t *ptr;
+ TypedData_Get_Struct(mesg, name_error_message_t, &name_err_mesg_data_type, ptr);
+ return ptr->recv;
}
/*
@@ -2650,8 +2719,18 @@ syntax_error_with_path(VALUE exc, VALUE path, VALUE *mesg, rb_encoding *enc)
rb_ivar_set(exc, id_i_path, path);
}
else {
- if (rb_attr_get(exc, id_i_path) != path) {
- rb_raise(rb_eArgError, "SyntaxError#path changed");
+ VALUE old_path = rb_attr_get(exc, id_i_path);
+ if (old_path != path) {
+ if (rb_str_equal(path, old_path)) {
+ rb_raise(rb_eArgError, "SyntaxError#path changed: %+"PRIsVALUE" (%p->%p)",
+ old_path, (void *)old_path, (void *)path);
+ }
+ else {
+ rb_raise(rb_eArgError, "SyntaxError#path changed: %+"PRIsVALUE"(%s%s)->%+"PRIsVALUE"(%s)",
+ old_path, rb_enc_name(rb_enc_get(old_path)),
+ (FL_TEST(old_path, RSTRING_FSTR) ? ":FSTR" : ""),
+ path, rb_enc_name(rb_enc_get(path)));
+ }
}
VALUE s = *mesg = rb_attr_get(exc, idMesg);
if (RSTRING_LEN(s) > 0 && *(RSTRING_END(s)-1) != '\n')
@@ -2662,68 +2741,99 @@ syntax_error_with_path(VALUE exc, VALUE path, VALUE *mesg, rb_encoding *enc)
/*
* Document-module: Errno
+
+ * When an operating system encounters an error,
+ * it typically reports the error as an integer error code:
+ *
+ * $ ls nosuch.txt
+ * ls: cannot access 'nosuch.txt': No such file or directory
+ * $ echo $? # Code for last error.
+ * 2
+ *
+ * When the Ruby interpreter interacts with the operating system
+ * and receives such an error code (e.g., +2+),
+ * it maps the code to a particular Ruby exception class (e.g., +Errno::ENOENT+):
*
- * Ruby exception objects are subclasses of Exception. However,
- * operating systems typically report errors using plain
- * integers. Module Errno is created dynamically to map these
- * operating system errors to Ruby classes, with each error number
- * generating its own subclass of SystemCallError. As the subclass
- * is created in module Errno, its name will start
- * <code>Errno::</code>.
+ * File.open('nosuch.txt')
+ * # => No such file or directory @ rb_sysopen - nosuch.txt (Errno::ENOENT)
*
- * The names of the <code>Errno::</code> classes depend on the
- * environment in which Ruby runs. On a typical Unix or Windows
- * platform, there are Errno classes such as Errno::EACCES,
- * Errno::EAGAIN, Errno::EINTR, and so on.
+ * Each such class is:
*
- * The integer operating system error number corresponding to a
- * particular error is available as the class constant
- * <code>Errno::</code><em>error</em><code>::Errno</code>.
+ * - A nested class in this module, +Errno+.
+ * - A subclass of class SystemCallError.
+ * - Associated with an error code.
*
- * Errno::EACCES::Errno #=> 13
- * Errno::EAGAIN::Errno #=> 11
- * Errno::EINTR::Errno #=> 4
+ * Thus:
*
- * The full list of operating system errors on your particular platform
- * are available as the constants of Errno.
+ * Errno::ENOENT.superclass # => SystemCallError
+ * Errno::ENOENT::Errno # => 2
+ *
+ * The names of nested classes are returned by method +Errno.constants+:
+ *
+ * Errno.constants.size # => 158
+ * Errno.constants.sort.take(5) # => [:E2BIG, :EACCES, :EADDRINUSE, :EADDRNOTAVAIL, :EADV]
+ *
+ * As seen above, the error code associated with each class
+ * is available as the value of a constant;
+ * the value for a particular class may vary among operating systems.
+ * If the class is not needed for the particular operating system,
+ * the value is zero:
+ *
+ * Errno::ENOENT::Errno # => 2
+ * Errno::ENOTCAPABLE::Errno # => 0
*
- * Errno.constants #=> :E2BIG, :EACCES, :EADDRINUSE, :EADDRNOTAVAIL, ...
*/
static st_table *syserr_tbl;
-static VALUE
-set_syserr(int n, const char *name)
+void
+rb_free_warning(void)
{
- st_data_t error;
+ st_free_table(warning_categories.id2enum);
+ st_free_table(warning_categories.enum2id);
+ st_free_table(syserr_tbl);
+}
- if (!st_lookup(syserr_tbl, n, &error)) {
- error = rb_define_class_under(rb_mErrno, name, rb_eSystemCallError);
+static VALUE
+setup_syserr(int n, const char *name)
+{
+ VALUE error = rb_define_class_under(rb_mErrno, name, rb_eSystemCallError);
- /* capture nonblock errnos for WaitReadable/WaitWritable subclasses */
- switch (n) {
- case EAGAIN:
- rb_eEAGAIN = error;
+ /* capture nonblock errnos for WaitReadable/WaitWritable subclasses */
+ switch (n) {
+ case EAGAIN:
+ rb_eEAGAIN = error;
#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
- break;
- case EWOULDBLOCK:
+ break;
+ case EWOULDBLOCK:
#endif
- rb_eEWOULDBLOCK = error;
- break;
- case EINPROGRESS:
- rb_eEINPROGRESS = error;
- break;
- }
+ rb_eEWOULDBLOCK = error;
+ break;
+ case EINPROGRESS:
+ rb_eEINPROGRESS = error;
+ break;
+ }
- rb_define_const(error, "Errno", INT2NUM(n));
- st_add_direct(syserr_tbl, n, error);
+ rb_define_const(error, "Errno", INT2NUM(n));
+ st_add_direct(syserr_tbl, n, (st_data_t)error);
+ return error;
+}
+
+static VALUE
+set_syserr(int n, const char *name)
+{
+ st_data_t error;
+
+ if (!st_lookup(syserr_tbl, n, &error)) {
+ return setup_syserr(n, name);
}
else {
- rb_define_const(rb_mErrno, name, error);
+ VALUE errclass = (VALUE)error;
+ rb_define_const(rb_mErrno, name, errclass);
+ return errclass;
}
- return error;
}
static VALUE
@@ -2732,12 +2842,12 @@ get_syserr(int n)
st_data_t error;
if (!st_lookup(syserr_tbl, n, &error)) {
- char name[8]; /* some Windows' errno have 5 digits. */
+ char name[DECIMAL_SIZE_OF(n) + sizeof("E-")];
snprintf(name, sizeof(name), "E%03d", n);
- error = set_syserr(n, name);
+ return setup_syserr(n, name);
}
- return error;
+ return (VALUE)error;
}
/*
@@ -3051,7 +3161,7 @@ syserr_eqq(VALUE self, VALUE exc)
*
* <em>raises the exception:</em>
*
- * NoMethodError: undefined method `to_ary' for "hello":String
+ * NoMethodError: undefined method `to_ary' for an instance of String
*/
/*
@@ -3124,7 +3234,7 @@ syserr_eqq(VALUE self, VALUE exc)
/*
* Document-class: fatal
*
- * fatal is an Exception that is raised when Ruby has encountered a fatal
+ * +fatal+ is an Exception that is raised when Ruby has encountered a fatal
* error and must exit.
*/
@@ -3247,9 +3357,9 @@ exception_dumper(VALUE exc)
}
static int
-ivar_copy_i(st_data_t key, st_data_t val, st_data_t exc)
+ivar_copy_i(ID key, VALUE val, st_data_t exc)
{
- rb_ivar_set((VALUE) exc, (ID) key, (VALUE) val);
+ rb_ivar_set((VALUE)exc, key, val);
return ST_CONTINUE;
}
@@ -3377,6 +3487,7 @@ Init_Exception(void)
rb_mWarning = rb_define_module("Warning");
rb_define_singleton_method(rb_mWarning, "[]", rb_warning_s_aref, 1);
rb_define_singleton_method(rb_mWarning, "[]=", rb_warning_s_aset, 2);
+ rb_define_singleton_method(rb_mWarning, "categories", rb_warning_s_categories, 0);
rb_define_method(rb_mWarning, "warn", rb_warning_s_warn, -1);
rb_extend_object(rb_mWarning, rb_mWarning);
@@ -3794,6 +3905,8 @@ inspect_frozen_obj(VALUE obj, VALUE mesg, int recur)
void
rb_error_frozen_object(VALUE frozen_obj)
{
+ rb_yjit_lazy_push_frame(GET_EC()->cfp->pc);
+
VALUE debug_info;
const ID created_info = id_debug_created_info;
VALUE mesg = rb_sprintf("can't modify frozen %"PRIsVALUE": ",
@@ -3816,23 +3929,33 @@ rb_error_frozen_object(VALUE frozen_obj)
void
rb_check_frozen(VALUE obj)
{
- rb_check_frozen_internal(obj);
+ if (RB_UNLIKELY(RB_OBJ_FROZEN(obj))) {
+ rb_error_frozen_object(obj);
+ }
+
+ if (RB_UNLIKELY(CHILLED_STRING_P(obj))) {
+ rb_str_modify(obj);
+ }
}
void
rb_check_copyable(VALUE obj, VALUE orig)
{
if (!FL_ABLE(obj)) return;
- rb_check_frozen_internal(obj);
+ rb_check_frozen(obj);
if (!FL_ABLE(orig)) return;
}
void
Init_syserr(void)
{
- rb_eNOERROR = set_syserr(0, "NOERROR");
+ rb_eNOERROR = setup_syserr(0, "NOERROR");
+#if 0
+ /* No error */
+ rb_define_const(rb_mErrno, "NOERROR", rb_eNOERROR);
+#endif
#define defined_error(name, num) set_syserr((num), (name));
-#define undefined_error(name) set_syserr(0, (name));
+#define undefined_error(name) rb_define_const(rb_mErrno, (name), rb_eNOERROR);
#include "known_errors.inc"
#undef defined_error
#undef undefined_error
diff --git a/eval.c b/eval.c
index be450a02f5..e8da342ac6 100644
--- a/eval.c
+++ b/eval.c
@@ -70,8 +70,6 @@ ruby_setup(void)
if (GET_VM())
return 0;
- ruby_init_stack((void *)&state);
-
/*
* Disable THP early before mallocs happen because we want this to
* affect as many future pages as possible for CoW-friendliness
@@ -80,7 +78,6 @@ ruby_setup(void)
prctl(PR_SET_THP_DISABLE, 1, 0, 0, 0);
#endif
Init_BareVM();
- Init_heap();
rb_vm_encoded_insn_data_table_init();
Init_vm_objects();
@@ -115,10 +112,9 @@ ruby_options(int argc, char **argv)
enum ruby_tag_type state;
void *volatile iseq = 0;
- ruby_init_stack((void *)&iseq);
EC_PUSH_TAG(ec);
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
- SAVE_ROOT_JMPBUF(GET_THREAD(), iseq = ruby_process_options(argc, argv));
+ iseq = ruby_process_options(argc, argv);
}
else {
rb_ec_clear_current_thread_trace_func(ec);
@@ -200,16 +196,15 @@ rb_ec_cleanup(rb_execution_context_t *ec, enum ruby_tag_type ex)
EC_PUSH_TAG(ec);
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
- SAVE_ROOT_JMPBUF(th, { RUBY_VM_CHECK_INTS(ec); });
+ RUBY_VM_CHECK_INTS(ec);
step_0: step++;
save_error = ec->errinfo;
if (THROW_DATA_P(ec->errinfo)) ec->errinfo = Qnil;
- ruby_init_stack(&message);
/* exits with failure but silently when an exception raised
* here */
- SAVE_ROOT_JMPBUF(th, rb_ec_teardown(ec));
+ rb_ec_teardown(ec);
step_1: step++;
VALUE err = ec->errinfo;
@@ -227,7 +222,7 @@ rb_ec_cleanup(rb_execution_context_t *ec, enum ruby_tag_type ex)
mode1 = exiting_split(err, (mode0 & EXITING_WITH_STATUS) ? NULL : &sysex, &signaled);
if (mode1 & EXITING_WITH_MESSAGE) {
buf = rb_str_new(NULL, 0);
- SAVE_ROOT_JMPBUF(th, rb_ec_error_print_detailed(ec, err, buf, Qundef));
+ rb_ec_error_print_detailed(ec, err, buf, Qundef);
message = buf;
}
}
@@ -236,7 +231,7 @@ rb_ec_cleanup(rb_execution_context_t *ec, enum ruby_tag_type ex)
/* protect from Thread#raise */
th->status = THREAD_KILLED;
- SAVE_ROOT_JMPBUF(th, rb_ractor_terminate_all());
+ rb_ractor_terminate_all();
step_3: step++;
if (!NIL_P(buf = message)) {
@@ -283,10 +278,7 @@ rb_ec_exec_node(rb_execution_context_t *ec, void *n)
EC_PUSH_TAG(ec);
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
- rb_thread_t *const th = rb_ec_thread_ptr(ec);
- SAVE_ROOT_JMPBUF(th, {
- rb_iseq_eval_main(iseq);
- });
+ rb_iseq_eval_main(iseq);
}
EC_POP_TAG();
return state;
@@ -324,14 +316,12 @@ ruby_run_node(void *n)
rb_ec_cleanup(ec, (NIL_P(ec->errinfo) ? TAG_NONE : TAG_RAISE));
return status;
}
- ruby_init_stack((void *)&status);
return rb_ec_cleanup(ec, rb_ec_exec_node(ec, n));
}
int
ruby_exec_node(void *n)
{
- ruby_init_stack((void *)&n);
return rb_ec_exec_node(GET_EC(), n);
}
@@ -419,11 +409,11 @@ rb_mod_s_constants(int argc, VALUE *argv, VALUE mod)
return rb_const_list(data);
}
-/*!
- * Asserts that \a klass is not a frozen class.
- * \param[in] klass a \c Module object
- * \exception RuntimeError if \a klass is not a class or frozen.
- * \ingroup class
+/**
+ * Asserts that `klass` is not a frozen class.
+ * @param[in] klass a `Module` object
+ * @exception RuntimeError if `klass` is not a class or frozen.
+ * @ingroup class
*/
void
rb_class_modify_check(VALUE klass)
@@ -437,7 +427,7 @@ rb_class_modify_check(VALUE klass)
if (OBJ_FROZEN(klass)) {
const char *desc;
- if (FL_TEST(klass, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON_P(klass)) {
desc = "object";
klass = RCLASS_ATTACHED_OBJECT(klass);
if (!SPECIAL_CONST_P(klass)) {
@@ -472,7 +462,7 @@ rb_class_modify_check(VALUE klass)
}
}
-NORETURN(static void rb_longjmp(rb_execution_context_t *, int, volatile VALUE, VALUE));
+NORETURN(static void rb_longjmp(rb_execution_context_t *, enum ruby_tag_type, volatile VALUE, VALUE));
static VALUE get_errinfo(void);
#define get_ec_errinfo(ec) rb_ec_get_errinfo(ec)
@@ -550,7 +540,7 @@ exc_setup_message(const rb_execution_context_t *ec, VALUE mesg, VALUE *cause)
}
static void
-setup_exception(rb_execution_context_t *ec, int tag, volatile VALUE mesg, VALUE cause)
+setup_exception(rb_execution_context_t *ec, enum ruby_tag_type tag, volatile VALUE mesg, VALUE cause)
{
VALUE e;
int line;
@@ -598,15 +588,15 @@ setup_exception(rb_execution_context_t *ec, int tag, volatile VALUE mesg, VALUE
e = rb_obj_as_string(mesg);
ec->errinfo = mesg;
if (file && line) {
- e = rb_sprintf("Exception `%"PRIsVALUE"' at %s:%d - %"PRIsVALUE"\n",
+ e = rb_sprintf("Exception '%"PRIsVALUE"' at %s:%d - %"PRIsVALUE"\n",
rb_obj_class(mesg), file, line, e);
}
else if (file) {
- e = rb_sprintf("Exception `%"PRIsVALUE"' at %s - %"PRIsVALUE"\n",
+ e = rb_sprintf("Exception '%"PRIsVALUE"' at %s - %"PRIsVALUE"\n",
rb_obj_class(mesg), file, e);
}
else {
- e = rb_sprintf("Exception `%"PRIsVALUE"' - %"PRIsVALUE"\n",
+ e = rb_sprintf("Exception '%"PRIsVALUE"' - %"PRIsVALUE"\n",
rb_obj_class(mesg), e);
}
warn_print_str(e);
@@ -654,7 +644,7 @@ rb_ec_setup_exception(const rb_execution_context_t *ec, VALUE mesg, VALUE cause)
}
static void
-rb_longjmp(rb_execution_context_t *ec, int tag, volatile VALUE mesg, VALUE cause)
+rb_longjmp(rb_execution_context_t *ec, enum ruby_tag_type tag, volatile VALUE mesg, VALUE cause)
{
mesg = exc_setup_message(ec, mesg, &cause);
setup_exception(ec, tag, mesg, cause);
@@ -664,10 +654,10 @@ rb_longjmp(rb_execution_context_t *ec, int tag, volatile VALUE mesg, VALUE cause
static VALUE make_exception(int argc, const VALUE *argv, int isstr);
-NORETURN(static void rb_exc_exception(VALUE mesg, int tag, VALUE cause));
+NORETURN(static void rb_exc_exception(VALUE mesg, enum ruby_tag_type tag, VALUE cause));
static void
-rb_exc_exception(VALUE mesg, int tag, VALUE cause)
+rb_exc_exception(VALUE mesg, enum ruby_tag_type tag, VALUE cause)
{
if (!NIL_P(mesg)) {
mesg = make_exception(1, &mesg, FALSE);
@@ -675,12 +665,12 @@ rb_exc_exception(VALUE mesg, int tag, VALUE cause)
rb_longjmp(GET_EC(), tag, mesg, cause);
}
-/*!
+/**
* Raises an exception in the current thread.
- * \param[in] mesg an Exception class or an \c Exception object.
- * \exception always raises an instance of the given exception class or
- * the given \c Exception object.
- * \ingroup exception
+ * @param[in] mesg an Exception class or an `Exception` object.
+ * @exception always raises an instance of the given exception class or
+ * the given `Exception` object.
+ * @ingroup exception
*/
void
rb_exc_raise(VALUE mesg)
@@ -770,7 +760,8 @@ rb_f_raise(int argc, VALUE *argv)
* object that returns an +Exception+ object when sent an +exception+
* message). The optional second parameter sets the message associated with
* the exception (accessible via Exception#message), and the third parameter
- * is an array of callback information (accessible via Exception#backtrace).
+ * is an array of callback information (accessible via
+ * Exception#backtrace_locations or Exception#backtrace).
* The +cause+ of the generated exception (accessible via Exception#cause)
* is automatically set to the "current" exception (<code>$!</code>), if any.
* An alternative value, either an +Exception+ object or +nil+, can be
@@ -780,7 +771,7 @@ rb_f_raise(int argc, VALUE *argv)
* <code>begin...end</code> blocks.
*
* raise "Failed to create socket"
- * raise ArgumentError, "No parameters", caller
+ * raise ArgumentError, "No parameters", caller_locations
*/
static VALUE
@@ -980,7 +971,7 @@ rb_protect(VALUE (* proc) (VALUE), VALUE data, int *pstate)
EC_PUSH_TAG(ec);
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
- SAVE_ROOT_JMPBUF(rb_ec_thread_ptr(ec), result = (*proc) (data));
+ result = (*proc)(data);
}
else {
rb_vm_rewind_cfp(ec, cfp);
@@ -994,7 +985,7 @@ rb_protect(VALUE (* proc) (VALUE), VALUE data, int *pstate)
VALUE
rb_ensure(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2)
{
- int state;
+ enum ruby_tag_type state;
volatile VALUE result = Qnil;
VALUE errinfo;
rb_execution_context_t * volatile ec = GET_EC();
@@ -1285,12 +1276,6 @@ rb_using_refinement(rb_cref_t *cref, VALUE klass, VALUE module)
RCLASS_M_TBL(c) = RCLASS_M_TBL(module);
- module = RCLASS_SUPER(module);
- while (module && module != klass) {
- c = RCLASS_SET_SUPER(c, rb_include_class_new(module, RCLASS_SUPER(c)));
- RB_OBJ_WRITE(c, &RCLASS_REFINED_CLASS(c), klass);
- module = RCLASS_SUPER(module);
- }
rb_hash_aset(CREF_REFINEMENTS(cref), klass, iclass);
}
@@ -1346,9 +1331,16 @@ rb_using_module(const rb_cref_t *cref, VALUE module)
/*
* call-seq:
- * target -> class
+ * target -> class_or_module
*
* Return the class or module refined by the receiver.
+ *
+ * module M
+ * refine String do
+ * end
+ * end
+ *
+ * M.refinements[0].target # => String
*/
VALUE
rb_refinement_module_get_refined_class(VALUE module)
@@ -1363,6 +1355,8 @@ rb_refinement_module_get_refined_class(VALUE module)
* call-seq:
* refined_class -> class
*
+ * Deprecated; prefer #target.
+ *
* Return the class refined by the receiver.
*/
static VALUE
@@ -1788,6 +1782,16 @@ rb_obj_extend(int argc, VALUE *argv, VALUE obj)
return obj;
}
+VALUE
+rb_top_main_class(const char *method)
+{
+ VALUE klass = GET_THREAD()->top_wrapper;
+
+ if (!klass) return rb_cObject;
+ rb_warning("main.%s in the wrapped load is effective only in wrapper module", method);
+ return klass;
+}
+
/*
* call-seq:
* include(module, ...) -> self
@@ -1800,13 +1804,7 @@ rb_obj_extend(int argc, VALUE *argv, VALUE obj)
static VALUE
top_include(int argc, VALUE *argv, VALUE self)
{
- rb_thread_t *th = GET_THREAD();
-
- if (th->top_wrapper) {
- rb_warning("main.include in the wrapped load is effective only in wrapper module");
- return rb_mod_include(argc, argv, th->top_wrapper);
- }
- return rb_mod_include(argc, argv, rb_cObject);
+ return rb_mod_include(argc, argv, rb_top_main_class("include"));
}
/*
@@ -1820,7 +1818,7 @@ top_include(int argc, VALUE *argv, VALUE self)
static VALUE
top_using(VALUE self, VALUE module)
{
- const rb_cref_t *cref = CREF_NEXT(rb_vm_cref());;
+ const rb_cref_t *cref = CREF_NEXT(rb_vm_cref());
rb_control_frame_t *prev_cfp = previous_frame(GET_EC());
rb_thread_t *th = GET_THREAD();
@@ -2013,7 +2011,7 @@ f_global_variables(VALUE _)
* +Proc+ object) or block is executed whenever the variable
* is assigned. The block or +Proc+ object receives the
* variable's new value as a parameter. Also see
- * Kernel::untrace_var.
+ * #untrace_var.
*
* trace_var :$_, proc {|v| puts "$_ is now '#{v}'" }
* $_ = "hello"
diff --git a/eval_error.c b/eval_error.c
index bdce295f6e..f3d05a1043 100644
--- a/eval_error.c
+++ b/eval_error.c
@@ -47,7 +47,7 @@ error_pos_str(void)
return rb_sprintf("%"PRIsVALUE": ", sourcefile);
}
else if ((caller_name = rb_frame_callee()) != 0) {
- return rb_sprintf("%"PRIsVALUE":%d:in `%"PRIsVALUE"': ",
+ return rb_sprintf("%"PRIsVALUE":%d:in '%"PRIsVALUE"': ",
sourcefile, sourceline,
rb_id2str(caller_name));
}
@@ -125,7 +125,7 @@ print_errinfo(const VALUE eclass, const VALUE errat, const VALUE emesg, const VA
}
VALUE
-rb_decorate_message(const VALUE eclass, const VALUE emesg, int highlight)
+rb_decorate_message(const VALUE eclass, VALUE emesg, int highlight)
{
const char *einfo = "";
long elen = 0;
@@ -210,6 +210,8 @@ rb_decorate_message(const VALUE eclass, const VALUE emesg, int highlight)
}
}
+ RB_GC_GUARD(emesg);
+
return str;
}
@@ -390,7 +392,7 @@ rb_ec_error_print(rb_execution_context_t *volatile ec, volatile VALUE errinfo)
rb_ec_error_print_detailed(ec, errinfo, Qnil, Qundef);
}
-#define undef_mesg_for(v, k) rb_fstring_lit("undefined"v" method `%1$s' for "k" `%2$s'")
+#define undef_mesg_for(v, k) rb_fstring_lit("undefined"v" method '%1$s' for "k" '%2$s'")
#define undef_mesg(v) ( \
is_mod ? \
undef_mesg_for(v, "module") : \
@@ -418,7 +420,7 @@ rb_print_undef_str(VALUE klass, VALUE name)
rb_name_err_raise_str(undef_mesg(""), klass, name);
}
-#define inaccessible_mesg_for(v, k) rb_fstring_lit("method `%1$s' for "k" `%2$s' is "v)
+#define inaccessible_mesg_for(v, k) rb_fstring_lit("method '%1$s' for "k" '%2$s' is "v)
#define inaccessible_mesg(v) ( \
is_mod ? \
inaccessible_mesg_for(v, "module") : \
diff --git a/eval_intern.h b/eval_intern.h
index d008b17ca1..9a551120ff 100644
--- a/eval_intern.h
+++ b/eval_intern.h
@@ -95,14 +95,6 @@ extern int select_large_fdset(int, fd_set *, fd_set *, fd_set *, struct timeval
#include <sys/stat.h>
-
-#define SAVE_ROOT_JMPBUF(th, stmt) do \
- if (true) { \
- stmt; \
- } \
- else if (th) { /* suppress unused-variable warning */ \
- } while (0)
-
#define EC_PUSH_TAG(ec) do { \
rb_execution_context_t * const _ec = (ec); \
struct rb_vm_tag _tag; \
@@ -153,7 +145,8 @@ rb_ec_tag_state(const rb_execution_context_t *ec)
enum ruby_tag_type state = tag->state;
tag->state = TAG_NONE;
rb_ec_vm_lock_rec_check(ec, tag->lock_rec);
- RBIMPL_ASSUME(state != TAG_NONE);
+ RBIMPL_ASSUME(state > TAG_NONE);
+ RBIMPL_ASSUME(state <= TAG_FATAL);
return state;
}
@@ -161,7 +154,7 @@ NORETURN(static inline void rb_ec_tag_jump(const rb_execution_context_t *ec, enu
static inline void
rb_ec_tag_jump(const rb_execution_context_t *ec, enum ruby_tag_type st)
{
- RUBY_ASSERT(st != TAG_NONE);
+ RUBY_ASSERT(st > TAG_NONE && st <= TAG_FATAL, ": Invalid tag jump: %d", (int)st);
ec->tag->state = st;
ruby_longjmp(RB_VM_TAG_JMPBUF_GET(ec->tag->buf), 1);
}
@@ -297,9 +290,9 @@ NORETURN(void rb_print_undef(VALUE, ID, rb_method_visibility_t));
NORETURN(void rb_print_undef_str(VALUE, VALUE));
NORETURN(void rb_print_inaccessible(VALUE, ID, rb_method_visibility_t));
NORETURN(void rb_vm_localjump_error(const char *,VALUE, int));
-NORETURN(void rb_vm_jump_tag_but_local_jump(int));
+NORETURN(void rb_vm_jump_tag_but_local_jump(enum ruby_tag_type));
-VALUE rb_vm_make_jump_tag_but_local_jump(int state, VALUE val);
+VALUE rb_vm_make_jump_tag_but_local_jump(enum ruby_tag_type state, VALUE val);
rb_cref_t *rb_vm_cref(void);
rb_cref_t *rb_vm_cref_replace_with_duplicated_cref(void);
VALUE rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, VALUE block_handler, VALUE filename);
@@ -328,16 +321,4 @@ rb_char_next(const char *p)
# endif
#endif
-#if defined DOSISH || defined __CYGWIN__
-static inline void
-translit_char(char *p, int from, int to)
-{
- while (*p) {
- if ((unsigned char)*p == from)
- *p = to;
- p = CharNext(p);
- }
-}
-#endif
-
#endif /* RUBY_EVAL_INTERN_H */
diff --git a/ext/-test-/RUBY_ALIGNOF/depend b/ext/-test-/RUBY_ALIGNOF/depend
index 3011b637e5..25364e55fb 100644
--- a/ext/-test-/RUBY_ALIGNOF/depend
+++ b/ext/-test-/RUBY_ALIGNOF/depend
@@ -147,6 +147,7 @@ c.o: $(hdrdir)/ruby/internal/special_consts.h
c.o: $(hdrdir)/ruby/internal/static_assert.h
c.o: $(hdrdir)/ruby/internal/stdalign.h
c.o: $(hdrdir)/ruby/internal/stdbool.h
+c.o: $(hdrdir)/ruby/internal/stdckdint.h
c.o: $(hdrdir)/ruby/internal/symbol.h
c.o: $(hdrdir)/ruby/internal/value.h
c.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/arith_seq/beg_len_step/depend b/ext/-test-/arith_seq/beg_len_step/depend
index dc807eaa99..702a0037a8 100644
--- a/ext/-test-/arith_seq/beg_len_step/depend
+++ b/ext/-test-/arith_seq/beg_len_step/depend
@@ -146,6 +146,7 @@ beg_len_step.o: $(hdrdir)/ruby/internal/special_consts.h
beg_len_step.o: $(hdrdir)/ruby/internal/static_assert.h
beg_len_step.o: $(hdrdir)/ruby/internal/stdalign.h
beg_len_step.o: $(hdrdir)/ruby/internal/stdbool.h
+beg_len_step.o: $(hdrdir)/ruby/internal/stdckdint.h
beg_len_step.o: $(hdrdir)/ruby/internal/symbol.h
beg_len_step.o: $(hdrdir)/ruby/internal/value.h
beg_len_step.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/arith_seq/extract/depend b/ext/-test-/arith_seq/extract/depend
index 231736b277..fdbd71dfbc 100644
--- a/ext/-test-/arith_seq/extract/depend
+++ b/ext/-test-/arith_seq/extract/depend
@@ -146,6 +146,7 @@ extract.o: $(hdrdir)/ruby/internal/special_consts.h
extract.o: $(hdrdir)/ruby/internal/static_assert.h
extract.o: $(hdrdir)/ruby/internal/stdalign.h
extract.o: $(hdrdir)/ruby/internal/stdbool.h
+extract.o: $(hdrdir)/ruby/internal/stdckdint.h
extract.o: $(hdrdir)/ruby/internal/symbol.h
extract.o: $(hdrdir)/ruby/internal/value.h
extract.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/array/concat/depend b/ext/-test-/array/concat/depend
index d66e7a540f..f2213a42ea 100644
--- a/ext/-test-/array/concat/depend
+++ b/ext/-test-/array/concat/depend
@@ -147,6 +147,7 @@ to_ary_concat.o: $(hdrdir)/ruby/internal/special_consts.h
to_ary_concat.o: $(hdrdir)/ruby/internal/static_assert.h
to_ary_concat.o: $(hdrdir)/ruby/internal/stdalign.h
to_ary_concat.o: $(hdrdir)/ruby/internal/stdbool.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/stdckdint.h
to_ary_concat.o: $(hdrdir)/ruby/internal/symbol.h
to_ary_concat.o: $(hdrdir)/ruby/internal/value.h
to_ary_concat.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/array/resize/depend b/ext/-test-/array/resize/depend
index a9c02b3db2..f88a9d03c1 100644
--- a/ext/-test-/array/resize/depend
+++ b/ext/-test-/array/resize/depend
@@ -146,6 +146,7 @@ resize.o: $(hdrdir)/ruby/internal/special_consts.h
resize.o: $(hdrdir)/ruby/internal/static_assert.h
resize.o: $(hdrdir)/ruby/internal/stdalign.h
resize.o: $(hdrdir)/ruby/internal/stdbool.h
+resize.o: $(hdrdir)/ruby/internal/stdckdint.h
resize.o: $(hdrdir)/ruby/internal/symbol.h
resize.o: $(hdrdir)/ruby/internal/value.h
resize.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/asan/asan.c b/ext/-test-/asan/asan.c
new file mode 100644
index 0000000000..45b6253fda
--- /dev/null
+++ b/ext/-test-/asan/asan.c
@@ -0,0 +1,24 @@
+#include "ruby/ruby.h"
+
+static VALUE
+asan_enabled_p(VALUE self)
+{
+#if defined(__has_feature)
+ /* clang uses __has_feature for determining asan */
+ return __has_feature(address_sanitizer) ? Qtrue : Qfalse;
+#elif defined(__SANITIZE_ADDRESS__)
+ /* GCC sets __SANITIZE_ADDRESS__ for determining asan */
+ return Qtrue;
+#else
+ return Qfalse;
+#endif
+}
+
+void
+Init_asan(void)
+{
+ VALUE m = rb_define_module("Test");
+ VALUE c = rb_define_class_under(m, "ASAN", rb_cObject);
+ rb_define_singleton_method(c, "enabled?", asan_enabled_p, 0);
+}
+
diff --git a/ext/-test-/asan/extconf.rb b/ext/-test-/asan/extconf.rb
new file mode 100644
index 0000000000..ec02742b81
--- /dev/null
+++ b/ext/-test-/asan/extconf.rb
@@ -0,0 +1,2 @@
+require 'mkmf'
+create_makefile('-test-/asan')
diff --git a/ext/-test-/bignum/depend b/ext/-test-/bignum/depend
index d4392bb6a1..078915ab72 100644
--- a/ext/-test-/bignum/depend
+++ b/ext/-test-/bignum/depend
@@ -146,6 +146,7 @@ big2str.o: $(hdrdir)/ruby/internal/special_consts.h
big2str.o: $(hdrdir)/ruby/internal/static_assert.h
big2str.o: $(hdrdir)/ruby/internal/stdalign.h
big2str.o: $(hdrdir)/ruby/internal/stdbool.h
+big2str.o: $(hdrdir)/ruby/internal/stdckdint.h
big2str.o: $(hdrdir)/ruby/internal/symbol.h
big2str.o: $(hdrdir)/ruby/internal/value.h
big2str.o: $(hdrdir)/ruby/internal/value_type.h
@@ -305,6 +306,7 @@ bigzero.o: $(hdrdir)/ruby/internal/special_consts.h
bigzero.o: $(hdrdir)/ruby/internal/static_assert.h
bigzero.o: $(hdrdir)/ruby/internal/stdalign.h
bigzero.o: $(hdrdir)/ruby/internal/stdbool.h
+bigzero.o: $(hdrdir)/ruby/internal/stdckdint.h
bigzero.o: $(hdrdir)/ruby/internal/symbol.h
bigzero.o: $(hdrdir)/ruby/internal/value.h
bigzero.o: $(hdrdir)/ruby/internal/value_type.h
@@ -464,6 +466,7 @@ div.o: $(hdrdir)/ruby/internal/special_consts.h
div.o: $(hdrdir)/ruby/internal/static_assert.h
div.o: $(hdrdir)/ruby/internal/stdalign.h
div.o: $(hdrdir)/ruby/internal/stdbool.h
+div.o: $(hdrdir)/ruby/internal/stdckdint.h
div.o: $(hdrdir)/ruby/internal/symbol.h
div.o: $(hdrdir)/ruby/internal/value.h
div.o: $(hdrdir)/ruby/internal/value_type.h
@@ -624,6 +627,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h
init.o: $(hdrdir)/ruby/internal/static_assert.h
init.o: $(hdrdir)/ruby/internal/stdalign.h
init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
init.o: $(hdrdir)/ruby/internal/symbol.h
init.o: $(hdrdir)/ruby/internal/value.h
init.o: $(hdrdir)/ruby/internal/value_type.h
@@ -782,6 +786,7 @@ intpack.o: $(hdrdir)/ruby/internal/special_consts.h
intpack.o: $(hdrdir)/ruby/internal/static_assert.h
intpack.o: $(hdrdir)/ruby/internal/stdalign.h
intpack.o: $(hdrdir)/ruby/internal/stdbool.h
+intpack.o: $(hdrdir)/ruby/internal/stdckdint.h
intpack.o: $(hdrdir)/ruby/internal/symbol.h
intpack.o: $(hdrdir)/ruby/internal/value.h
intpack.o: $(hdrdir)/ruby/internal/value_type.h
@@ -941,6 +946,7 @@ mul.o: $(hdrdir)/ruby/internal/special_consts.h
mul.o: $(hdrdir)/ruby/internal/static_assert.h
mul.o: $(hdrdir)/ruby/internal/stdalign.h
mul.o: $(hdrdir)/ruby/internal/stdbool.h
+mul.o: $(hdrdir)/ruby/internal/stdckdint.h
mul.o: $(hdrdir)/ruby/internal/symbol.h
mul.o: $(hdrdir)/ruby/internal/value.h
mul.o: $(hdrdir)/ruby/internal/value_type.h
@@ -1100,6 +1106,7 @@ str2big.o: $(hdrdir)/ruby/internal/special_consts.h
str2big.o: $(hdrdir)/ruby/internal/static_assert.h
str2big.o: $(hdrdir)/ruby/internal/stdalign.h
str2big.o: $(hdrdir)/ruby/internal/stdbool.h
+str2big.o: $(hdrdir)/ruby/internal/stdckdint.h
str2big.o: $(hdrdir)/ruby/internal/symbol.h
str2big.o: $(hdrdir)/ruby/internal/value.h
str2big.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/bug-14834/depend b/ext/-test-/bug-14834/depend
index bf26a571aa..695094fa7a 100644
--- a/ext/-test-/bug-14834/depend
+++ b/ext/-test-/bug-14834/depend
@@ -147,6 +147,7 @@ bug-14384.o: $(hdrdir)/ruby/internal/special_consts.h
bug-14384.o: $(hdrdir)/ruby/internal/static_assert.h
bug-14384.o: $(hdrdir)/ruby/internal/stdalign.h
bug-14384.o: $(hdrdir)/ruby/internal/stdbool.h
+bug-14384.o: $(hdrdir)/ruby/internal/stdckdint.h
bug-14384.o: $(hdrdir)/ruby/internal/symbol.h
bug-14384.o: $(hdrdir)/ruby/internal/value.h
bug-14384.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/bug-3571/depend b/ext/-test-/bug-3571/depend
index 9105093b0d..84517a9c15 100644
--- a/ext/-test-/bug-3571/depend
+++ b/ext/-test-/bug-3571/depend
@@ -147,6 +147,7 @@ bug.o: $(hdrdir)/ruby/internal/special_consts.h
bug.o: $(hdrdir)/ruby/internal/static_assert.h
bug.o: $(hdrdir)/ruby/internal/stdalign.h
bug.o: $(hdrdir)/ruby/internal/stdbool.h
+bug.o: $(hdrdir)/ruby/internal/stdckdint.h
bug.o: $(hdrdir)/ruby/internal/symbol.h
bug.o: $(hdrdir)/ruby/internal/value.h
bug.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/bug-5832/depend b/ext/-test-/bug-5832/depend
index 9105093b0d..84517a9c15 100644
--- a/ext/-test-/bug-5832/depend
+++ b/ext/-test-/bug-5832/depend
@@ -147,6 +147,7 @@ bug.o: $(hdrdir)/ruby/internal/special_consts.h
bug.o: $(hdrdir)/ruby/internal/static_assert.h
bug.o: $(hdrdir)/ruby/internal/stdalign.h
bug.o: $(hdrdir)/ruby/internal/stdbool.h
+bug.o: $(hdrdir)/ruby/internal/stdckdint.h
bug.o: $(hdrdir)/ruby/internal/symbol.h
bug.o: $(hdrdir)/ruby/internal/value.h
bug.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/bug_reporter/depend b/ext/-test-/bug_reporter/depend
index 20882708d1..1c73234247 100644
--- a/ext/-test-/bug_reporter/depend
+++ b/ext/-test-/bug_reporter/depend
@@ -147,6 +147,7 @@ bug_reporter.o: $(hdrdir)/ruby/internal/special_consts.h
bug_reporter.o: $(hdrdir)/ruby/internal/static_assert.h
bug_reporter.o: $(hdrdir)/ruby/internal/stdalign.h
bug_reporter.o: $(hdrdir)/ruby/internal/stdbool.h
+bug_reporter.o: $(hdrdir)/ruby/internal/stdckdint.h
bug_reporter.o: $(hdrdir)/ruby/internal/symbol.h
bug_reporter.o: $(hdrdir)/ruby/internal/value.h
bug_reporter.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/class/depend b/ext/-test-/class/depend
index 0a805f815e..b0595fdc46 100644
--- a/ext/-test-/class/depend
+++ b/ext/-test-/class/depend
@@ -146,6 +146,7 @@ class2name.o: $(hdrdir)/ruby/internal/special_consts.h
class2name.o: $(hdrdir)/ruby/internal/static_assert.h
class2name.o: $(hdrdir)/ruby/internal/stdalign.h
class2name.o: $(hdrdir)/ruby/internal/stdbool.h
+class2name.o: $(hdrdir)/ruby/internal/stdckdint.h
class2name.o: $(hdrdir)/ruby/internal/symbol.h
class2name.o: $(hdrdir)/ruby/internal/value.h
class2name.o: $(hdrdir)/ruby/internal/value_type.h
@@ -305,6 +306,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h
init.o: $(hdrdir)/ruby/internal/static_assert.h
init.o: $(hdrdir)/ruby/internal/stdalign.h
init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
init.o: $(hdrdir)/ruby/internal/symbol.h
init.o: $(hdrdir)/ruby/internal/value.h
init.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/debug/depend b/ext/-test-/debug/depend
index 5feeea6d98..67e32c6aa6 100644
--- a/ext/-test-/debug/depend
+++ b/ext/-test-/debug/depend
@@ -147,6 +147,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h
init.o: $(hdrdir)/ruby/internal/static_assert.h
init.o: $(hdrdir)/ruby/internal/stdalign.h
init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
init.o: $(hdrdir)/ruby/internal/symbol.h
init.o: $(hdrdir)/ruby/internal/value.h
init.o: $(hdrdir)/ruby/internal/value_type.h
@@ -306,6 +307,7 @@ inspector.o: $(hdrdir)/ruby/internal/special_consts.h
inspector.o: $(hdrdir)/ruby/internal/static_assert.h
inspector.o: $(hdrdir)/ruby/internal/stdalign.h
inspector.o: $(hdrdir)/ruby/internal/stdbool.h
+inspector.o: $(hdrdir)/ruby/internal/stdckdint.h
inspector.o: $(hdrdir)/ruby/internal/symbol.h
inspector.o: $(hdrdir)/ruby/internal/value.h
inspector.o: $(hdrdir)/ruby/internal/value_type.h
@@ -465,6 +467,7 @@ profile_frames.o: $(hdrdir)/ruby/internal/special_consts.h
profile_frames.o: $(hdrdir)/ruby/internal/static_assert.h
profile_frames.o: $(hdrdir)/ruby/internal/stdalign.h
profile_frames.o: $(hdrdir)/ruby/internal/stdbool.h
+profile_frames.o: $(hdrdir)/ruby/internal/stdckdint.h
profile_frames.o: $(hdrdir)/ruby/internal/symbol.h
profile_frames.o: $(hdrdir)/ruby/internal/value.h
profile_frames.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/dln/empty/depend b/ext/-test-/dln/empty/depend
index a460159087..d3e606df57 100644
--- a/ext/-test-/dln/empty/depend
+++ b/ext/-test-/dln/empty/depend
@@ -147,6 +147,7 @@ empty.o: $(hdrdir)/ruby/internal/special_consts.h
empty.o: $(hdrdir)/ruby/internal/static_assert.h
empty.o: $(hdrdir)/ruby/internal/stdalign.h
empty.o: $(hdrdir)/ruby/internal/stdbool.h
+empty.o: $(hdrdir)/ruby/internal/stdckdint.h
empty.o: $(hdrdir)/ruby/internal/symbol.h
empty.o: $(hdrdir)/ruby/internal/value.h
empty.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/enumerator_kw/depend b/ext/-test-/enumerator_kw/depend
index 49ea495421..85daa55b53 100644
--- a/ext/-test-/enumerator_kw/depend
+++ b/ext/-test-/enumerator_kw/depend
@@ -147,6 +147,7 @@ enumerator_kw.o: $(hdrdir)/ruby/internal/special_consts.h
enumerator_kw.o: $(hdrdir)/ruby/internal/static_assert.h
enumerator_kw.o: $(hdrdir)/ruby/internal/stdalign.h
enumerator_kw.o: $(hdrdir)/ruby/internal/stdbool.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/stdckdint.h
enumerator_kw.o: $(hdrdir)/ruby/internal/symbol.h
enumerator_kw.o: $(hdrdir)/ruby/internal/value.h
enumerator_kw.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/exception/depend b/ext/-test-/exception/depend
index 818b4c79df..7a0544b1e1 100644
--- a/ext/-test-/exception/depend
+++ b/ext/-test-/exception/depend
@@ -146,6 +146,7 @@ dataerror.o: $(hdrdir)/ruby/internal/special_consts.h
dataerror.o: $(hdrdir)/ruby/internal/static_assert.h
dataerror.o: $(hdrdir)/ruby/internal/stdalign.h
dataerror.o: $(hdrdir)/ruby/internal/stdbool.h
+dataerror.o: $(hdrdir)/ruby/internal/stdckdint.h
dataerror.o: $(hdrdir)/ruby/internal/symbol.h
dataerror.o: $(hdrdir)/ruby/internal/value.h
dataerror.o: $(hdrdir)/ruby/internal/value_type.h
@@ -315,6 +316,7 @@ enc_raise.o: $(hdrdir)/ruby/internal/special_consts.h
enc_raise.o: $(hdrdir)/ruby/internal/static_assert.h
enc_raise.o: $(hdrdir)/ruby/internal/stdalign.h
enc_raise.o: $(hdrdir)/ruby/internal/stdbool.h
+enc_raise.o: $(hdrdir)/ruby/internal/stdckdint.h
enc_raise.o: $(hdrdir)/ruby/internal/symbol.h
enc_raise.o: $(hdrdir)/ruby/internal/value.h
enc_raise.o: $(hdrdir)/ruby/internal/value_type.h
@@ -476,6 +478,7 @@ ensured.o: $(hdrdir)/ruby/internal/special_consts.h
ensured.o: $(hdrdir)/ruby/internal/static_assert.h
ensured.o: $(hdrdir)/ruby/internal/stdalign.h
ensured.o: $(hdrdir)/ruby/internal/stdbool.h
+ensured.o: $(hdrdir)/ruby/internal/stdckdint.h
ensured.o: $(hdrdir)/ruby/internal/symbol.h
ensured.o: $(hdrdir)/ruby/internal/value.h
ensured.o: $(hdrdir)/ruby/internal/value_type.h
@@ -635,6 +638,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h
init.o: $(hdrdir)/ruby/internal/static_assert.h
init.o: $(hdrdir)/ruby/internal/stdalign.h
init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
init.o: $(hdrdir)/ruby/internal/symbol.h
init.o: $(hdrdir)/ruby/internal/value.h
init.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/fatal/depend b/ext/-test-/fatal/depend
index 730a72e52a..36b0ad4205 100644
--- a/ext/-test-/fatal/depend
+++ b/ext/-test-/fatal/depend
@@ -1,4 +1,325 @@
# AUTOGENERATED DEPENDENCIES START
+
+init.o: $(RUBY_EXTCONF_H)
+init.o: $(arch_hdrdir)/ruby/config.h
+init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/value.h
+init.o: $(hdrdir)/ruby/internal/value_type.h
+init.o: $(hdrdir)/ruby/internal/variable.h
+init.o: $(hdrdir)/ruby/internal/warning_push.h
+init.o: $(hdrdir)/ruby/internal/xmalloc.h
+init.o: $(hdrdir)/ruby/missing.h
+init.o: $(hdrdir)/ruby/ruby.h
+init.o: $(hdrdir)/ruby/st.h
+init.o: $(hdrdir)/ruby/subst.h
+init.o: init.c
+invalid.o: $(RUBY_EXTCONF_H)
+invalid.o: $(arch_hdrdir)/ruby/config.h
+invalid.o: $(hdrdir)/ruby.h
+invalid.o: $(hdrdir)/ruby/assert.h
+invalid.o: $(hdrdir)/ruby/backward.h
+invalid.o: $(hdrdir)/ruby/backward/2/assume.h
+invalid.o: $(hdrdir)/ruby/backward/2/attributes.h
+invalid.o: $(hdrdir)/ruby/backward/2/bool.h
+invalid.o: $(hdrdir)/ruby/backward/2/inttypes.h
+invalid.o: $(hdrdir)/ruby/backward/2/limits.h
+invalid.o: $(hdrdir)/ruby/backward/2/long_long.h
+invalid.o: $(hdrdir)/ruby/backward/2/stdalign.h
+invalid.o: $(hdrdir)/ruby/backward/2/stdarg.h
+invalid.o: $(hdrdir)/ruby/defines.h
+invalid.o: $(hdrdir)/ruby/intern.h
+invalid.o: $(hdrdir)/ruby/internal/abi.h
+invalid.o: $(hdrdir)/ruby/internal/anyargs.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+invalid.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+invalid.o: $(hdrdir)/ruby/internal/assume.h
+invalid.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+invalid.o: $(hdrdir)/ruby/internal/attr/artificial.h
+invalid.o: $(hdrdir)/ruby/internal/attr/cold.h
+invalid.o: $(hdrdir)/ruby/internal/attr/const.h
+invalid.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+invalid.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+invalid.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+invalid.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+invalid.o: $(hdrdir)/ruby/internal/attr/error.h
+invalid.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+invalid.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+invalid.o: $(hdrdir)/ruby/internal/attr/format.h
+invalid.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+invalid.o: $(hdrdir)/ruby/internal/attr/noalias.h
+invalid.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+invalid.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+invalid.o: $(hdrdir)/ruby/internal/attr/noinline.h
+invalid.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+invalid.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+invalid.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+invalid.o: $(hdrdir)/ruby/internal/attr/pure.h
+invalid.o: $(hdrdir)/ruby/internal/attr/restrict.h
+invalid.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+invalid.o: $(hdrdir)/ruby/internal/attr/warning.h
+invalid.o: $(hdrdir)/ruby/internal/attr/weakref.h
+invalid.o: $(hdrdir)/ruby/internal/cast.h
+invalid.o: $(hdrdir)/ruby/internal/compiler_is.h
+invalid.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+invalid.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+invalid.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+invalid.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+invalid.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+invalid.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+invalid.o: $(hdrdir)/ruby/internal/compiler_since.h
+invalid.o: $(hdrdir)/ruby/internal/config.h
+invalid.o: $(hdrdir)/ruby/internal/constant_p.h
+invalid.o: $(hdrdir)/ruby/internal/core.h
+invalid.o: $(hdrdir)/ruby/internal/core/rarray.h
+invalid.o: $(hdrdir)/ruby/internal/core/rbasic.h
+invalid.o: $(hdrdir)/ruby/internal/core/rbignum.h
+invalid.o: $(hdrdir)/ruby/internal/core/rclass.h
+invalid.o: $(hdrdir)/ruby/internal/core/rdata.h
+invalid.o: $(hdrdir)/ruby/internal/core/rfile.h
+invalid.o: $(hdrdir)/ruby/internal/core/rhash.h
+invalid.o: $(hdrdir)/ruby/internal/core/robject.h
+invalid.o: $(hdrdir)/ruby/internal/core/rregexp.h
+invalid.o: $(hdrdir)/ruby/internal/core/rstring.h
+invalid.o: $(hdrdir)/ruby/internal/core/rstruct.h
+invalid.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+invalid.o: $(hdrdir)/ruby/internal/ctype.h
+invalid.o: $(hdrdir)/ruby/internal/dllexport.h
+invalid.o: $(hdrdir)/ruby/internal/dosish.h
+invalid.o: $(hdrdir)/ruby/internal/error.h
+invalid.o: $(hdrdir)/ruby/internal/eval.h
+invalid.o: $(hdrdir)/ruby/internal/event.h
+invalid.o: $(hdrdir)/ruby/internal/fl_type.h
+invalid.o: $(hdrdir)/ruby/internal/gc.h
+invalid.o: $(hdrdir)/ruby/internal/glob.h
+invalid.o: $(hdrdir)/ruby/internal/globals.h
+invalid.o: $(hdrdir)/ruby/internal/has/attribute.h
+invalid.o: $(hdrdir)/ruby/internal/has/builtin.h
+invalid.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+invalid.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+invalid.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+invalid.o: $(hdrdir)/ruby/internal/has/extension.h
+invalid.o: $(hdrdir)/ruby/internal/has/feature.h
+invalid.o: $(hdrdir)/ruby/internal/has/warning.h
+invalid.o: $(hdrdir)/ruby/internal/intern/array.h
+invalid.o: $(hdrdir)/ruby/internal/intern/bignum.h
+invalid.o: $(hdrdir)/ruby/internal/intern/class.h
+invalid.o: $(hdrdir)/ruby/internal/intern/compar.h
+invalid.o: $(hdrdir)/ruby/internal/intern/complex.h
+invalid.o: $(hdrdir)/ruby/internal/intern/cont.h
+invalid.o: $(hdrdir)/ruby/internal/intern/dir.h
+invalid.o: $(hdrdir)/ruby/internal/intern/enum.h
+invalid.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+invalid.o: $(hdrdir)/ruby/internal/intern/error.h
+invalid.o: $(hdrdir)/ruby/internal/intern/eval.h
+invalid.o: $(hdrdir)/ruby/internal/intern/file.h
+invalid.o: $(hdrdir)/ruby/internal/intern/hash.h
+invalid.o: $(hdrdir)/ruby/internal/intern/io.h
+invalid.o: $(hdrdir)/ruby/internal/intern/load.h
+invalid.o: $(hdrdir)/ruby/internal/intern/marshal.h
+invalid.o: $(hdrdir)/ruby/internal/intern/numeric.h
+invalid.o: $(hdrdir)/ruby/internal/intern/object.h
+invalid.o: $(hdrdir)/ruby/internal/intern/parse.h
+invalid.o: $(hdrdir)/ruby/internal/intern/proc.h
+invalid.o: $(hdrdir)/ruby/internal/intern/process.h
+invalid.o: $(hdrdir)/ruby/internal/intern/random.h
+invalid.o: $(hdrdir)/ruby/internal/intern/range.h
+invalid.o: $(hdrdir)/ruby/internal/intern/rational.h
+invalid.o: $(hdrdir)/ruby/internal/intern/re.h
+invalid.o: $(hdrdir)/ruby/internal/intern/ruby.h
+invalid.o: $(hdrdir)/ruby/internal/intern/select.h
+invalid.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+invalid.o: $(hdrdir)/ruby/internal/intern/signal.h
+invalid.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+invalid.o: $(hdrdir)/ruby/internal/intern/string.h
+invalid.o: $(hdrdir)/ruby/internal/intern/struct.h
+invalid.o: $(hdrdir)/ruby/internal/intern/thread.h
+invalid.o: $(hdrdir)/ruby/internal/intern/time.h
+invalid.o: $(hdrdir)/ruby/internal/intern/variable.h
+invalid.o: $(hdrdir)/ruby/internal/intern/vm.h
+invalid.o: $(hdrdir)/ruby/internal/interpreter.h
+invalid.o: $(hdrdir)/ruby/internal/iterator.h
+invalid.o: $(hdrdir)/ruby/internal/memory.h
+invalid.o: $(hdrdir)/ruby/internal/method.h
+invalid.o: $(hdrdir)/ruby/internal/module.h
+invalid.o: $(hdrdir)/ruby/internal/newobj.h
+invalid.o: $(hdrdir)/ruby/internal/scan_args.h
+invalid.o: $(hdrdir)/ruby/internal/special_consts.h
+invalid.o: $(hdrdir)/ruby/internal/static_assert.h
+invalid.o: $(hdrdir)/ruby/internal/stdalign.h
+invalid.o: $(hdrdir)/ruby/internal/stdbool.h
+invalid.o: $(hdrdir)/ruby/internal/stdckdint.h
+invalid.o: $(hdrdir)/ruby/internal/symbol.h
+invalid.o: $(hdrdir)/ruby/internal/value.h
+invalid.o: $(hdrdir)/ruby/internal/value_type.h
+invalid.o: $(hdrdir)/ruby/internal/variable.h
+invalid.o: $(hdrdir)/ruby/internal/warning_push.h
+invalid.o: $(hdrdir)/ruby/internal/xmalloc.h
+invalid.o: $(hdrdir)/ruby/missing.h
+invalid.o: $(hdrdir)/ruby/ruby.h
+invalid.o: $(hdrdir)/ruby/st.h
+invalid.o: $(hdrdir)/ruby/subst.h
+invalid.o: invalid.c
rb_fatal.o: $(RUBY_EXTCONF_H)
rb_fatal.o: $(arch_hdrdir)/ruby/config.h
rb_fatal.o: $(hdrdir)/ruby.h
@@ -147,6 +468,7 @@ rb_fatal.o: $(hdrdir)/ruby/internal/special_consts.h
rb_fatal.o: $(hdrdir)/ruby/internal/static_assert.h
rb_fatal.o: $(hdrdir)/ruby/internal/stdalign.h
rb_fatal.o: $(hdrdir)/ruby/internal/stdbool.h
+rb_fatal.o: $(hdrdir)/ruby/internal/stdckdint.h
rb_fatal.o: $(hdrdir)/ruby/internal/symbol.h
rb_fatal.o: $(hdrdir)/ruby/internal/value.h
rb_fatal.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/fatal/extconf.rb b/ext/-test-/fatal/extconf.rb
index d5849c0733..ca51178a18 100644
--- a/ext/-test-/fatal/extconf.rb
+++ b/ext/-test-/fatal/extconf.rb
@@ -1,2 +1,3 @@
# frozen_string_literal: false
-create_makefile("-test-/fatal/rb_fatal")
+require_relative "../auto_ext.rb"
+auto_ext
diff --git a/ext/-test-/fatal/init.c b/ext/-test-/fatal/init.c
new file mode 100644
index 0000000000..3b71708789
--- /dev/null
+++ b/ext/-test-/fatal/init.c
@@ -0,0 +1,10 @@
+#include "ruby.h"
+
+#define init(n) {void Init_##n(VALUE klass); Init_##n(klass);}
+
+void
+Init_fatal(void)
+{
+ VALUE klass = rb_define_module("Bug");
+ TEST_INIT_FUNCS(init);
+}
diff --git a/ext/-test-/fatal/invalid.c b/ext/-test-/fatal/invalid.c
new file mode 100644
index 0000000000..f0726edb52
--- /dev/null
+++ b/ext/-test-/fatal/invalid.c
@@ -0,0 +1,28 @@
+#include <ruby.h>
+
+#if SIZEOF_LONG == SIZEOF_VOIDP
+# define NUM2PTR(x) (void *)NUM2ULONG(x)
+#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
+# define NUM2PTR(x) (void *)NUM2ULL(x)
+#endif
+
+static VALUE
+invalid_call(VALUE obj, VALUE address)
+{
+ typedef VALUE (*func_type)(VALUE);
+
+ return (*(func_type)NUM2PTR(address))(obj);
+}
+
+static VALUE
+invalid_access(VALUE obj, VALUE address)
+{
+ return *(VALUE *)NUM2PTR(address) == obj ? Qtrue : Qfalse;
+}
+
+void
+Init_invalid(VALUE mBug)
+{
+ rb_define_singleton_method(mBug, "invalid_call", invalid_call, 1);
+ rb_define_singleton_method(mBug, "invalid_access", invalid_access, 1);
+}
diff --git a/ext/-test-/fatal/rb_fatal.c b/ext/-test-/fatal/rb_fatal.c
index eedbc51f8b..6c7bb89628 100644
--- a/ext/-test-/fatal/rb_fatal.c
+++ b/ext/-test-/fatal/rb_fatal.c
@@ -13,8 +13,7 @@ ruby_fatal(VALUE obj, VALUE msg)
}
void
-Init_rb_fatal(void)
+Init_rb_fatal(VALUE mBug)
{
- VALUE mBug = rb_define_module("Bug");
rb_define_singleton_method(mBug, "rb_fatal", ruby_fatal, 1);
}
diff --git a/ext/-test-/file/depend b/ext/-test-/file/depend
index 662136f1ba..e985f914b2 100644
--- a/ext/-test-/file/depend
+++ b/ext/-test-/file/depend
@@ -156,6 +156,7 @@ fs.o: $(hdrdir)/ruby/internal/special_consts.h
fs.o: $(hdrdir)/ruby/internal/static_assert.h
fs.o: $(hdrdir)/ruby/internal/stdalign.h
fs.o: $(hdrdir)/ruby/internal/stdbool.h
+fs.o: $(hdrdir)/ruby/internal/stdckdint.h
fs.o: $(hdrdir)/ruby/internal/symbol.h
fs.o: $(hdrdir)/ruby/internal/value.h
fs.o: $(hdrdir)/ruby/internal/value_type.h
@@ -318,6 +319,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h
init.o: $(hdrdir)/ruby/internal/static_assert.h
init.o: $(hdrdir)/ruby/internal/stdalign.h
init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
init.o: $(hdrdir)/ruby/internal/symbol.h
init.o: $(hdrdir)/ruby/internal/value.h
init.o: $(hdrdir)/ruby/internal/value_type.h
@@ -329,6 +331,178 @@ init.o: $(hdrdir)/ruby/ruby.h
init.o: $(hdrdir)/ruby/st.h
init.o: $(hdrdir)/ruby/subst.h
init.o: init.c
+newline_conv.o: $(RUBY_EXTCONF_H)
+newline_conv.o: $(arch_hdrdir)/ruby/config.h
+newline_conv.o: $(hdrdir)/ruby/assert.h
+newline_conv.o: $(hdrdir)/ruby/backward.h
+newline_conv.o: $(hdrdir)/ruby/backward/2/assume.h
+newline_conv.o: $(hdrdir)/ruby/backward/2/attributes.h
+newline_conv.o: $(hdrdir)/ruby/backward/2/bool.h
+newline_conv.o: $(hdrdir)/ruby/backward/2/inttypes.h
+newline_conv.o: $(hdrdir)/ruby/backward/2/limits.h
+newline_conv.o: $(hdrdir)/ruby/backward/2/long_long.h
+newline_conv.o: $(hdrdir)/ruby/backward/2/stdalign.h
+newline_conv.o: $(hdrdir)/ruby/backward/2/stdarg.h
+newline_conv.o: $(hdrdir)/ruby/defines.h
+newline_conv.o: $(hdrdir)/ruby/encoding.h
+newline_conv.o: $(hdrdir)/ruby/intern.h
+newline_conv.o: $(hdrdir)/ruby/internal/abi.h
+newline_conv.o: $(hdrdir)/ruby/internal/anyargs.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+newline_conv.o: $(hdrdir)/ruby/internal/assume.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/artificial.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/cold.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/const.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/error.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/format.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/noalias.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/noinline.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/pure.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/restrict.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/warning.h
+newline_conv.o: $(hdrdir)/ruby/internal/attr/weakref.h
+newline_conv.o: $(hdrdir)/ruby/internal/cast.h
+newline_conv.o: $(hdrdir)/ruby/internal/compiler_is.h
+newline_conv.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+newline_conv.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+newline_conv.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+newline_conv.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+newline_conv.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+newline_conv.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+newline_conv.o: $(hdrdir)/ruby/internal/compiler_since.h
+newline_conv.o: $(hdrdir)/ruby/internal/config.h
+newline_conv.o: $(hdrdir)/ruby/internal/constant_p.h
+newline_conv.o: $(hdrdir)/ruby/internal/core.h
+newline_conv.o: $(hdrdir)/ruby/internal/core/rarray.h
+newline_conv.o: $(hdrdir)/ruby/internal/core/rbasic.h
+newline_conv.o: $(hdrdir)/ruby/internal/core/rbignum.h
+newline_conv.o: $(hdrdir)/ruby/internal/core/rclass.h
+newline_conv.o: $(hdrdir)/ruby/internal/core/rdata.h
+newline_conv.o: $(hdrdir)/ruby/internal/core/rfile.h
+newline_conv.o: $(hdrdir)/ruby/internal/core/rhash.h
+newline_conv.o: $(hdrdir)/ruby/internal/core/robject.h
+newline_conv.o: $(hdrdir)/ruby/internal/core/rregexp.h
+newline_conv.o: $(hdrdir)/ruby/internal/core/rstring.h
+newline_conv.o: $(hdrdir)/ruby/internal/core/rstruct.h
+newline_conv.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+newline_conv.o: $(hdrdir)/ruby/internal/ctype.h
+newline_conv.o: $(hdrdir)/ruby/internal/dllexport.h
+newline_conv.o: $(hdrdir)/ruby/internal/dosish.h
+newline_conv.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+newline_conv.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+newline_conv.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+newline_conv.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+newline_conv.o: $(hdrdir)/ruby/internal/encoding/re.h
+newline_conv.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+newline_conv.o: $(hdrdir)/ruby/internal/encoding/string.h
+newline_conv.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+newline_conv.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+newline_conv.o: $(hdrdir)/ruby/internal/error.h
+newline_conv.o: $(hdrdir)/ruby/internal/eval.h
+newline_conv.o: $(hdrdir)/ruby/internal/event.h
+newline_conv.o: $(hdrdir)/ruby/internal/fl_type.h
+newline_conv.o: $(hdrdir)/ruby/internal/gc.h
+newline_conv.o: $(hdrdir)/ruby/internal/glob.h
+newline_conv.o: $(hdrdir)/ruby/internal/globals.h
+newline_conv.o: $(hdrdir)/ruby/internal/has/attribute.h
+newline_conv.o: $(hdrdir)/ruby/internal/has/builtin.h
+newline_conv.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+newline_conv.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+newline_conv.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+newline_conv.o: $(hdrdir)/ruby/internal/has/extension.h
+newline_conv.o: $(hdrdir)/ruby/internal/has/feature.h
+newline_conv.o: $(hdrdir)/ruby/internal/has/warning.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/array.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/bignum.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/class.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/compar.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/complex.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/cont.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/dir.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/enum.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/error.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/eval.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/file.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/hash.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/io.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/load.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/marshal.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/numeric.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/object.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/parse.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/proc.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/process.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/random.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/range.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/rational.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/re.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/ruby.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/select.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/signal.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/string.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/struct.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/thread.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/time.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/variable.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/vm.h
+newline_conv.o: $(hdrdir)/ruby/internal/interpreter.h
+newline_conv.o: $(hdrdir)/ruby/internal/iterator.h
+newline_conv.o: $(hdrdir)/ruby/internal/memory.h
+newline_conv.o: $(hdrdir)/ruby/internal/method.h
+newline_conv.o: $(hdrdir)/ruby/internal/module.h
+newline_conv.o: $(hdrdir)/ruby/internal/newobj.h
+newline_conv.o: $(hdrdir)/ruby/internal/scan_args.h
+newline_conv.o: $(hdrdir)/ruby/internal/special_consts.h
+newline_conv.o: $(hdrdir)/ruby/internal/static_assert.h
+newline_conv.o: $(hdrdir)/ruby/internal/stdalign.h
+newline_conv.o: $(hdrdir)/ruby/internal/stdbool.h
+newline_conv.o: $(hdrdir)/ruby/internal/stdckdint.h
+newline_conv.o: $(hdrdir)/ruby/internal/symbol.h
+newline_conv.o: $(hdrdir)/ruby/internal/value.h
+newline_conv.o: $(hdrdir)/ruby/internal/value_type.h
+newline_conv.o: $(hdrdir)/ruby/internal/variable.h
+newline_conv.o: $(hdrdir)/ruby/internal/warning_push.h
+newline_conv.o: $(hdrdir)/ruby/internal/xmalloc.h
+newline_conv.o: $(hdrdir)/ruby/io.h
+newline_conv.o: $(hdrdir)/ruby/missing.h
+newline_conv.o: $(hdrdir)/ruby/onigmo.h
+newline_conv.o: $(hdrdir)/ruby/oniguruma.h
+newline_conv.o: $(hdrdir)/ruby/ruby.h
+newline_conv.o: $(hdrdir)/ruby/st.h
+newline_conv.o: $(hdrdir)/ruby/subst.h
+newline_conv.o: newline_conv.c
stat.o: $(RUBY_EXTCONF_H)
stat.o: $(arch_hdrdir)/ruby/config.h
stat.o: $(hdrdir)/ruby/assert.h
@@ -486,6 +660,7 @@ stat.o: $(hdrdir)/ruby/internal/special_consts.h
stat.o: $(hdrdir)/ruby/internal/static_assert.h
stat.o: $(hdrdir)/ruby/internal/stdalign.h
stat.o: $(hdrdir)/ruby/internal/stdbool.h
+stat.o: $(hdrdir)/ruby/internal/stdckdint.h
stat.o: $(hdrdir)/ruby/internal/symbol.h
stat.o: $(hdrdir)/ruby/internal/value.h
stat.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/file/newline_conv.c b/ext/-test-/file/newline_conv.c
new file mode 100644
index 0000000000..2ac5aef801
--- /dev/null
+++ b/ext/-test-/file/newline_conv.c
@@ -0,0 +1,73 @@
+#include "ruby/ruby.h"
+#include "ruby/io.h"
+#include <fcntl.h>
+
+static VALUE
+open_with_rb_file_open(VALUE self, VALUE filename, VALUE read_or_write, VALUE binary_or_text)
+{
+ char fmode[3] = { 0 };
+ if (rb_sym2id(read_or_write) == rb_intern("read")) {
+ fmode[0] = 'r';
+ }
+ else if (rb_sym2id(read_or_write) == rb_intern("write")) {
+ fmode[0] = 'w';
+ }
+ else {
+ rb_raise(rb_eArgError, "read_or_write param must be :read or :write");
+ }
+
+ if (rb_sym2id(binary_or_text) == rb_intern("binary")) {
+ fmode[1] = 'b';
+ }
+ else if (rb_sym2id(binary_or_text) == rb_intern("text")) {
+
+ }
+ else {
+ rb_raise(rb_eArgError, "binary_or_text param must be :binary or :text");
+ }
+
+ return rb_file_open(StringValueCStr(filename), fmode);
+}
+
+static VALUE
+open_with_rb_io_fdopen(VALUE self, VALUE filename, VALUE read_or_write, VALUE binary_or_text)
+{
+ int omode = 0;
+ if (rb_sym2id(read_or_write) == rb_intern("read")) {
+ omode |= O_RDONLY;
+ }
+ else if (rb_sym2id(read_or_write) == rb_intern("write")) {
+ omode |= O_WRONLY;
+ }
+ else {
+ rb_raise(rb_eArgError, "read_or_write param must be :read or :write");
+ }
+
+ if (rb_sym2id(binary_or_text) == rb_intern("binary")) {
+#ifdef O_BINARY
+ omode |= O_BINARY;
+#endif
+ }
+ else if (rb_sym2id(binary_or_text) == rb_intern("text")) {
+
+ }
+ else {
+ rb_raise(rb_eArgError, "binary_or_text param must be :binary or :text");
+ }
+
+ int fd = rb_cloexec_open(StringValueCStr(filename), omode, 0);
+ if (fd < 0) {
+ rb_raise(rb_eIOError, "failed to open the file");
+ }
+
+ rb_update_max_fd(fd);
+ return rb_io_fdopen(fd, omode, StringValueCStr(filename));
+}
+
+void
+Init_newline_conv(VALUE module)
+{
+ VALUE newline_conv = rb_define_module_under(module, "NewlineConv");
+ rb_define_module_function(newline_conv, "rb_file_open", open_with_rb_file_open, 3);
+ rb_define_module_function(newline_conv, "rb_io_fdopen", open_with_rb_io_fdopen, 3);
+}
diff --git a/ext/-test-/float/depend b/ext/-test-/float/depend
index 9580a0416c..3e34818d5f 100644
--- a/ext/-test-/float/depend
+++ b/ext/-test-/float/depend
@@ -150,6 +150,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h
init.o: $(hdrdir)/ruby/internal/static_assert.h
init.o: $(hdrdir)/ruby/internal/stdalign.h
init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
init.o: $(hdrdir)/ruby/internal/symbol.h
init.o: $(hdrdir)/ruby/internal/value.h
init.o: $(hdrdir)/ruby/internal/value_type.h
@@ -309,6 +310,7 @@ nextafter.o: $(hdrdir)/ruby/internal/special_consts.h
nextafter.o: $(hdrdir)/ruby/internal/static_assert.h
nextafter.o: $(hdrdir)/ruby/internal/stdalign.h
nextafter.o: $(hdrdir)/ruby/internal/stdbool.h
+nextafter.o: $(hdrdir)/ruby/internal/stdckdint.h
nextafter.o: $(hdrdir)/ruby/internal/symbol.h
nextafter.o: $(hdrdir)/ruby/internal/value.h
nextafter.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/funcall/depend b/ext/-test-/funcall/depend
index 6719e4e676..a5a30873ac 100644
--- a/ext/-test-/funcall/depend
+++ b/ext/-test-/funcall/depend
@@ -147,6 +147,7 @@ funcall.o: $(hdrdir)/ruby/internal/special_consts.h
funcall.o: $(hdrdir)/ruby/internal/static_assert.h
funcall.o: $(hdrdir)/ruby/internal/stdalign.h
funcall.o: $(hdrdir)/ruby/internal/stdbool.h
+funcall.o: $(hdrdir)/ruby/internal/stdckdint.h
funcall.o: $(hdrdir)/ruby/internal/symbol.h
funcall.o: $(hdrdir)/ruby/internal/value.h
funcall.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/gvl/call_without_gvl/depend b/ext/-test-/gvl/call_without_gvl/depend
index a4987a65ca..6463d4527d 100644
--- a/ext/-test-/gvl/call_without_gvl/depend
+++ b/ext/-test-/gvl/call_without_gvl/depend
@@ -146,6 +146,7 @@ call_without_gvl.o: $(hdrdir)/ruby/internal/special_consts.h
call_without_gvl.o: $(hdrdir)/ruby/internal/static_assert.h
call_without_gvl.o: $(hdrdir)/ruby/internal/stdalign.h
call_without_gvl.o: $(hdrdir)/ruby/internal/stdbool.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/stdckdint.h
call_without_gvl.o: $(hdrdir)/ruby/internal/symbol.h
call_without_gvl.o: $(hdrdir)/ruby/internal/value.h
call_without_gvl.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/hash/depend b/ext/-test-/hash/depend
index 58d9a6247e..4bc4bfcdd6 100644
--- a/ext/-test-/hash/depend
+++ b/ext/-test-/hash/depend
@@ -147,6 +147,7 @@ delete.o: $(hdrdir)/ruby/internal/special_consts.h
delete.o: $(hdrdir)/ruby/internal/static_assert.h
delete.o: $(hdrdir)/ruby/internal/stdalign.h
delete.o: $(hdrdir)/ruby/internal/stdbool.h
+delete.o: $(hdrdir)/ruby/internal/stdckdint.h
delete.o: $(hdrdir)/ruby/internal/symbol.h
delete.o: $(hdrdir)/ruby/internal/value.h
delete.o: $(hdrdir)/ruby/internal/value_type.h
@@ -306,6 +307,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h
init.o: $(hdrdir)/ruby/internal/static_assert.h
init.o: $(hdrdir)/ruby/internal/stdalign.h
init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
init.o: $(hdrdir)/ruby/internal/symbol.h
init.o: $(hdrdir)/ruby/internal/value.h
init.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/integer/depend b/ext/-test-/integer/depend
index b68a68ce73..d89965e3d9 100644
--- a/ext/-test-/integer/depend
+++ b/ext/-test-/integer/depend
@@ -147,6 +147,7 @@ core_ext.o: $(hdrdir)/ruby/internal/special_consts.h
core_ext.o: $(hdrdir)/ruby/internal/static_assert.h
core_ext.o: $(hdrdir)/ruby/internal/stdalign.h
core_ext.o: $(hdrdir)/ruby/internal/stdbool.h
+core_ext.o: $(hdrdir)/ruby/internal/stdckdint.h
core_ext.o: $(hdrdir)/ruby/internal/symbol.h
core_ext.o: $(hdrdir)/ruby/internal/value.h
core_ext.o: $(hdrdir)/ruby/internal/value_type.h
@@ -314,6 +315,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h
init.o: $(hdrdir)/ruby/internal/static_assert.h
init.o: $(hdrdir)/ruby/internal/stdalign.h
init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
init.o: $(hdrdir)/ruby/internal/symbol.h
init.o: $(hdrdir)/ruby/internal/value.h
init.o: $(hdrdir)/ruby/internal/value_type.h
@@ -473,6 +475,7 @@ my_integer.o: $(hdrdir)/ruby/internal/special_consts.h
my_integer.o: $(hdrdir)/ruby/internal/static_assert.h
my_integer.o: $(hdrdir)/ruby/internal/stdalign.h
my_integer.o: $(hdrdir)/ruby/internal/stdbool.h
+my_integer.o: $(hdrdir)/ruby/internal/stdckdint.h
my_integer.o: $(hdrdir)/ruby/internal/symbol.h
my_integer.o: $(hdrdir)/ruby/internal/value.h
my_integer.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/integer/my_integer.c b/ext/-test-/integer/my_integer.c
index d86474bd7d..94f14d2765 100644
--- a/ext/-test-/integer/my_integer.c
+++ b/ext/-test-/integer/my_integer.c
@@ -1,9 +1,13 @@
#include "ruby.h"
+static const rb_data_type_t my_integer_type = {
+ "MyInteger", {0}, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+};
+
static VALUE
my_integer_s_new(VALUE klass)
{
- return Data_Wrap_Struct(klass, 0, 0, 0);
+ return TypedData_Wrap_Struct(klass, &my_integer_type, 0);
}
void
diff --git a/ext/-test-/iseq_load/depend b/ext/-test-/iseq_load/depend
index 30deb6e039..fd07b3199c 100644
--- a/ext/-test-/iseq_load/depend
+++ b/ext/-test-/iseq_load/depend
@@ -147,6 +147,7 @@ iseq_load.o: $(hdrdir)/ruby/internal/special_consts.h
iseq_load.o: $(hdrdir)/ruby/internal/static_assert.h
iseq_load.o: $(hdrdir)/ruby/internal/stdalign.h
iseq_load.o: $(hdrdir)/ruby/internal/stdbool.h
+iseq_load.o: $(hdrdir)/ruby/internal/stdckdint.h
iseq_load.o: $(hdrdir)/ruby/internal/symbol.h
iseq_load.o: $(hdrdir)/ruby/internal/value.h
iseq_load.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/iter/depend b/ext/-test-/iter/depend
index 077a283532..cff4b1bb43 100644
--- a/ext/-test-/iter/depend
+++ b/ext/-test-/iter/depend
@@ -147,6 +147,7 @@ break.o: $(hdrdir)/ruby/internal/special_consts.h
break.o: $(hdrdir)/ruby/internal/static_assert.h
break.o: $(hdrdir)/ruby/internal/stdalign.h
break.o: $(hdrdir)/ruby/internal/stdbool.h
+break.o: $(hdrdir)/ruby/internal/stdckdint.h
break.o: $(hdrdir)/ruby/internal/symbol.h
break.o: $(hdrdir)/ruby/internal/value.h
break.o: $(hdrdir)/ruby/internal/value_type.h
@@ -306,6 +307,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h
init.o: $(hdrdir)/ruby/internal/static_assert.h
init.o: $(hdrdir)/ruby/internal/stdalign.h
init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
init.o: $(hdrdir)/ruby/internal/symbol.h
init.o: $(hdrdir)/ruby/internal/value.h
init.o: $(hdrdir)/ruby/internal/value_type.h
@@ -465,6 +467,7 @@ yield.o: $(hdrdir)/ruby/internal/special_consts.h
yield.o: $(hdrdir)/ruby/internal/static_assert.h
yield.o: $(hdrdir)/ruby/internal/stdalign.h
yield.o: $(hdrdir)/ruby/internal/stdbool.h
+yield.o: $(hdrdir)/ruby/internal/stdckdint.h
yield.o: $(hdrdir)/ruby/internal/symbol.h
yield.o: $(hdrdir)/ruby/internal/value.h
yield.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/load/dot.dot/depend b/ext/-test-/load/dot.dot/depend
index be835d3ea5..f9be79e957 100644
--- a/ext/-test-/load/dot.dot/depend
+++ b/ext/-test-/load/dot.dot/depend
@@ -147,6 +147,7 @@ dot.dot.o: $(hdrdir)/ruby/internal/special_consts.h
dot.dot.o: $(hdrdir)/ruby/internal/static_assert.h
dot.dot.o: $(hdrdir)/ruby/internal/stdalign.h
dot.dot.o: $(hdrdir)/ruby/internal/stdbool.h
+dot.dot.o: $(hdrdir)/ruby/internal/stdckdint.h
dot.dot.o: $(hdrdir)/ruby/internal/symbol.h
dot.dot.o: $(hdrdir)/ruby/internal/value.h
dot.dot.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/load/protect/depend b/ext/-test-/load/protect/depend
index 57cf029901..324c17237a 100644
--- a/ext/-test-/load/protect/depend
+++ b/ext/-test-/load/protect/depend
@@ -147,6 +147,7 @@ protect.o: $(hdrdir)/ruby/internal/special_consts.h
protect.o: $(hdrdir)/ruby/internal/static_assert.h
protect.o: $(hdrdir)/ruby/internal/stdalign.h
protect.o: $(hdrdir)/ruby/internal/stdbool.h
+protect.o: $(hdrdir)/ruby/internal/stdckdint.h
protect.o: $(hdrdir)/ruby/internal/symbol.h
protect.o: $(hdrdir)/ruby/internal/value.h
protect.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/load/resolve_symbol_resolver/extconf.rb b/ext/-test-/load/resolve_symbol_resolver/extconf.rb
new file mode 100644
index 0000000000..2299efcfd3
--- /dev/null
+++ b/ext/-test-/load/resolve_symbol_resolver/extconf.rb
@@ -0,0 +1 @@
+create_makefile('-test-/load/resolve_symbol_resolver')
diff --git a/ext/-test-/load/resolve_symbol_resolver/resolve_symbol_resolver.c b/ext/-test-/load/resolve_symbol_resolver/resolve_symbol_resolver.c
new file mode 100644
index 0000000000..a856319cfb
--- /dev/null
+++ b/ext/-test-/load/resolve_symbol_resolver/resolve_symbol_resolver.c
@@ -0,0 +1,55 @@
+#include <ruby.h>
+#include "ruby/internal/intern/load.h"
+
+typedef VALUE(*target_func)(VALUE);
+
+static target_func rst_any_method;
+
+VALUE
+rsr_any_method(VALUE klass)
+{
+ return rst_any_method((VALUE)NULL);
+}
+
+VALUE
+rsr_try_resolve_fname(VALUE klass)
+{
+ target_func rst_something_missing =
+ (target_func) rb_ext_resolve_symbol("-test-/load/resolve_symbol_missing", "rst_any_method");
+ if (rst_something_missing == NULL) {
+ // This should be done in Init_*, so the error is LoadError
+ rb_raise(rb_eLoadError, "symbol not found: missing fname");
+ }
+ return Qtrue;
+}
+
+VALUE
+rsr_try_resolve_sname(VALUE klass)
+{
+ target_func rst_something_missing =
+ (target_func)rb_ext_resolve_symbol("-test-/load/resolve_symbol_target", "rst_something_missing");
+ if (rst_something_missing == NULL) {
+ // This should be done in Init_*, so the error is LoadError
+ rb_raise(rb_eLoadError, "symbol not found: missing sname");
+ }
+ return Qtrue;
+}
+
+void
+Init_resolve_symbol_resolver(void)
+{
+ /*
+ * Resolving symbols at the head of Init_ because it raises LoadError (in cases).
+ * If the module and methods are defined before raising LoadError, retrying `require "this.so"` will
+ * cause re-defining those methods (and will be warned).
+ */
+ rst_any_method = (target_func)rb_ext_resolve_symbol("-test-/load/resolve_symbol_target", "rst_any_method");
+ if (rst_any_method == NULL) {
+ rb_raise(rb_eLoadError, "resolve_symbol_target is not loaded");
+ }
+
+ VALUE mod = rb_define_module("ResolveSymbolResolver");
+ rb_define_singleton_method(mod, "any_method", rsr_any_method, 0);
+ rb_define_singleton_method(mod, "try_resolve_fname", rsr_try_resolve_fname, 0);
+ rb_define_singleton_method(mod, "try_resolve_sname", rsr_try_resolve_sname, 0);
+}
diff --git a/ext/-test-/load/resolve_symbol_target/extconf.rb b/ext/-test-/load/resolve_symbol_target/extconf.rb
new file mode 100644
index 0000000000..b5a99ca7f1
--- /dev/null
+++ b/ext/-test-/load/resolve_symbol_target/extconf.rb
@@ -0,0 +1 @@
+create_makefile('-test-/load/resolve_symbol_target')
diff --git a/ext/-test-/load/resolve_symbol_target/resolve_symbol_target.c b/ext/-test-/load/resolve_symbol_target/resolve_symbol_target.c
new file mode 100644
index 0000000000..b5bc9e8ee0
--- /dev/null
+++ b/ext/-test-/load/resolve_symbol_target/resolve_symbol_target.c
@@ -0,0 +1,15 @@
+#include <ruby.h>
+#include "resolve_symbol_target.h"
+
+VALUE
+rst_any_method(VALUE klass)
+{
+ return rb_str_new_cstr("from target");
+}
+
+void
+Init_resolve_symbol_target(void)
+{
+ VALUE mod = rb_define_module("ResolveSymbolTarget");
+ rb_define_singleton_method(mod, "any_method", rst_any_method, 0);
+}
diff --git a/ext/-test-/load/resolve_symbol_target/resolve_symbol_target.def b/ext/-test-/load/resolve_symbol_target/resolve_symbol_target.def
new file mode 100644
index 0000000000..c2ed3610fe
--- /dev/null
+++ b/ext/-test-/load/resolve_symbol_target/resolve_symbol_target.def
@@ -0,0 +1,4 @@
+LIBRARY resolve_symbol_target
+EXPORTS
+ Init_resolve_symbol_target
+ rst_any_method
diff --git a/ext/-test-/load/resolve_symbol_target/resolve_symbol_target.h b/ext/-test-/load/resolve_symbol_target/resolve_symbol_target.h
new file mode 100644
index 0000000000..847dcb7dd3
--- /dev/null
+++ b/ext/-test-/load/resolve_symbol_target/resolve_symbol_target.h
@@ -0,0 +1,4 @@
+#include <ruby.h>
+#include "ruby/internal/dllexport.h"
+
+RUBY_FUNC_EXPORTED VALUE rst_any_method(VALUE);
diff --git a/ext/-test-/load/stringify_symbols/extconf.rb b/ext/-test-/load/stringify_symbols/extconf.rb
new file mode 100644
index 0000000000..ac39c15f09
--- /dev/null
+++ b/ext/-test-/load/stringify_symbols/extconf.rb
@@ -0,0 +1 @@
+create_makefile('-test-/load/stringify_symbols')
diff --git a/ext/-test-/load/stringify_symbols/stringify_symbols.c b/ext/-test-/load/stringify_symbols/stringify_symbols.c
new file mode 100644
index 0000000000..11a5ee3bc5
--- /dev/null
+++ b/ext/-test-/load/stringify_symbols/stringify_symbols.c
@@ -0,0 +1,29 @@
+#include <ruby.h>
+#include "ruby/internal/intern/load.h"
+#include "ruby/util.h"
+
+#if SIZEOF_INTPTR_T == SIZEOF_LONG_LONG
+# define UINTPTR2NUM ULL2NUM
+#elif SIZEOF_INTPTR_T == SIZEOF_LONG
+# define UINTPTR2NUM ULONG2NUM
+#else
+# define UINTPTR2NUM UINT2NUM
+#endif
+
+static VALUE
+stringify_symbol(VALUE klass, VALUE fname, VALUE sname)
+{
+ void *ptr = rb_ext_resolve_symbol(StringValueCStr(fname), StringValueCStr(sname));
+ if (ptr == NULL) {
+ return Qnil;
+ }
+ uintptr_t uintptr = (uintptr_t)ptr;
+ return UINTPTR2NUM(uintptr);
+}
+
+void
+Init_stringify_symbols(void)
+{
+ VALUE mod = rb_define_module("StringifySymbols");
+ rb_define_singleton_method(mod, "stringify_symbol", stringify_symbol, 2);
+}
diff --git a/ext/-test-/load/stringify_target/extconf.rb b/ext/-test-/load/stringify_target/extconf.rb
new file mode 100644
index 0000000000..4aa201cb09
--- /dev/null
+++ b/ext/-test-/load/stringify_target/extconf.rb
@@ -0,0 +1 @@
+create_makefile('-test-/load/stringify_target')
diff --git a/ext/-test-/load/stringify_target/stringify_target.c b/ext/-test-/load/stringify_target/stringify_target.c
new file mode 100644
index 0000000000..ce09b8fd77
--- /dev/null
+++ b/ext/-test-/load/stringify_target/stringify_target.c
@@ -0,0 +1,15 @@
+#include <ruby.h>
+#include "stringify_target.h"
+
+VALUE
+stt_any_method(VALUE klass)
+{
+ return rb_str_new_cstr("from target");
+}
+
+void
+Init_stringify_target(void)
+{
+ VALUE mod = rb_define_module("StringifyTarget");
+ rb_define_singleton_method(mod, "any_method", stt_any_method, 0);
+}
diff --git a/ext/-test-/load/stringify_target/stringify_target.def b/ext/-test-/load/stringify_target/stringify_target.def
new file mode 100644
index 0000000000..89c2b762de
--- /dev/null
+++ b/ext/-test-/load/stringify_target/stringify_target.def
@@ -0,0 +1,4 @@
+LIBRARY stringify_target
+EXPORTS
+ Init_stringify_target
+ stt_any_method
diff --git a/ext/-test-/load/stringify_target/stringify_target.h b/ext/-test-/load/stringify_target/stringify_target.h
new file mode 100644
index 0000000000..d95fb65d7c
--- /dev/null
+++ b/ext/-test-/load/stringify_target/stringify_target.h
@@ -0,0 +1,4 @@
+#include <ruby.h>
+#include "ruby/internal/dllexport.h"
+
+RUBY_FUNC_EXPORTED VALUE stt_any_method(VALUE);
diff --git a/ext/-test-/marshal/compat/depend b/ext/-test-/marshal/compat/depend
index ff675ccabb..8bcd9f8b5e 100644
--- a/ext/-test-/marshal/compat/depend
+++ b/ext/-test-/marshal/compat/depend
@@ -147,6 +147,7 @@ usrcompat.o: $(hdrdir)/ruby/internal/special_consts.h
usrcompat.o: $(hdrdir)/ruby/internal/static_assert.h
usrcompat.o: $(hdrdir)/ruby/internal/stdalign.h
usrcompat.o: $(hdrdir)/ruby/internal/stdbool.h
+usrcompat.o: $(hdrdir)/ruby/internal/stdckdint.h
usrcompat.o: $(hdrdir)/ruby/internal/symbol.h
usrcompat.o: $(hdrdir)/ruby/internal/value.h
usrcompat.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/marshal/internal_ivar/depend b/ext/-test-/marshal/internal_ivar/depend
index 4fe36834d8..f8be031efc 100644
--- a/ext/-test-/marshal/internal_ivar/depend
+++ b/ext/-test-/marshal/internal_ivar/depend
@@ -147,6 +147,7 @@ internal_ivar.o: $(hdrdir)/ruby/internal/special_consts.h
internal_ivar.o: $(hdrdir)/ruby/internal/static_assert.h
internal_ivar.o: $(hdrdir)/ruby/internal/stdalign.h
internal_ivar.o: $(hdrdir)/ruby/internal/stdbool.h
+internal_ivar.o: $(hdrdir)/ruby/internal/stdckdint.h
internal_ivar.o: $(hdrdir)/ruby/internal/symbol.h
internal_ivar.o: $(hdrdir)/ruby/internal/value.h
internal_ivar.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/marshal/usr/depend b/ext/-test-/marshal/usr/depend
index 1d56cc8202..09e8207d3a 100644
--- a/ext/-test-/marshal/usr/depend
+++ b/ext/-test-/marshal/usr/depend
@@ -147,6 +147,7 @@ usrmarshal.o: $(hdrdir)/ruby/internal/special_consts.h
usrmarshal.o: $(hdrdir)/ruby/internal/static_assert.h
usrmarshal.o: $(hdrdir)/ruby/internal/stdalign.h
usrmarshal.o: $(hdrdir)/ruby/internal/stdbool.h
+usrmarshal.o: $(hdrdir)/ruby/internal/stdckdint.h
usrmarshal.o: $(hdrdir)/ruby/internal/symbol.h
usrmarshal.o: $(hdrdir)/ruby/internal/value.h
usrmarshal.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/memory_view/depend b/ext/-test-/memory_view/depend
index c9ef06a15c..0c92fc1236 100644
--- a/ext/-test-/memory_view/depend
+++ b/ext/-test-/memory_view/depend
@@ -147,6 +147,7 @@ memory_view.o: $(hdrdir)/ruby/internal/special_consts.h
memory_view.o: $(hdrdir)/ruby/internal/static_assert.h
memory_view.o: $(hdrdir)/ruby/internal/stdalign.h
memory_view.o: $(hdrdir)/ruby/internal/stdbool.h
+memory_view.o: $(hdrdir)/ruby/internal/stdckdint.h
memory_view.o: $(hdrdir)/ruby/internal/symbol.h
memory_view.o: $(hdrdir)/ruby/internal/value.h
memory_view.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/memory_view/memory_view.c b/ext/-test-/memory_view/memory_view.c
index c1df0353cf..63f0beb81e 100644
--- a/ext/-test-/memory_view/memory_view.c
+++ b/ext/-test-/memory_view/memory_view.c
@@ -313,8 +313,8 @@ mdview_get_memory_view(VALUE obj, rb_memory_view_t *view, int flags)
static bool
mdview_release_memory_view(VALUE obj, rb_memory_view_t *view)
{
- if (view->shape) xfree((void *)view->shape);
- if (view->strides) xfree((void *)view->strides);
+ xfree((void *)view->shape);
+ xfree((void *)view->strides);
return true;
}
diff --git a/ext/-test-/method/depend b/ext/-test-/method/depend
index dbf513f48f..dce2a815a4 100644
--- a/ext/-test-/method/depend
+++ b/ext/-test-/method/depend
@@ -147,6 +147,7 @@ arity.o: $(hdrdir)/ruby/internal/special_consts.h
arity.o: $(hdrdir)/ruby/internal/static_assert.h
arity.o: $(hdrdir)/ruby/internal/stdalign.h
arity.o: $(hdrdir)/ruby/internal/stdbool.h
+arity.o: $(hdrdir)/ruby/internal/stdckdint.h
arity.o: $(hdrdir)/ruby/internal/symbol.h
arity.o: $(hdrdir)/ruby/internal/value.h
arity.o: $(hdrdir)/ruby/internal/value_type.h
@@ -306,6 +307,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h
init.o: $(hdrdir)/ruby/internal/static_assert.h
init.o: $(hdrdir)/ruby/internal/stdalign.h
init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
init.o: $(hdrdir)/ruby/internal/symbol.h
init.o: $(hdrdir)/ruby/internal/value.h
init.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/notimplement/depend b/ext/-test-/notimplement/depend
index 9105093b0d..84517a9c15 100644
--- a/ext/-test-/notimplement/depend
+++ b/ext/-test-/notimplement/depend
@@ -147,6 +147,7 @@ bug.o: $(hdrdir)/ruby/internal/special_consts.h
bug.o: $(hdrdir)/ruby/internal/static_assert.h
bug.o: $(hdrdir)/ruby/internal/stdalign.h
bug.o: $(hdrdir)/ruby/internal/stdbool.h
+bug.o: $(hdrdir)/ruby/internal/stdckdint.h
bug.o: $(hdrdir)/ruby/internal/symbol.h
bug.o: $(hdrdir)/ruby/internal/value.h
bug.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/num2int/depend b/ext/-test-/num2int/depend
index 4e05d1e8c1..5550033be7 100644
--- a/ext/-test-/num2int/depend
+++ b/ext/-test-/num2int/depend
@@ -147,6 +147,7 @@ num2int.o: $(hdrdir)/ruby/internal/special_consts.h
num2int.o: $(hdrdir)/ruby/internal/static_assert.h
num2int.o: $(hdrdir)/ruby/internal/stdalign.h
num2int.o: $(hdrdir)/ruby/internal/stdbool.h
+num2int.o: $(hdrdir)/ruby/internal/stdckdint.h
num2int.o: $(hdrdir)/ruby/internal/symbol.h
num2int.o: $(hdrdir)/ruby/internal/value.h
num2int.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/path_to_class/depend b/ext/-test-/path_to_class/depend
index 8fe6ee37c2..a1657c9574 100644
--- a/ext/-test-/path_to_class/depend
+++ b/ext/-test-/path_to_class/depend
@@ -147,6 +147,7 @@ path_to_class.o: $(hdrdir)/ruby/internal/special_consts.h
path_to_class.o: $(hdrdir)/ruby/internal/static_assert.h
path_to_class.o: $(hdrdir)/ruby/internal/stdalign.h
path_to_class.o: $(hdrdir)/ruby/internal/stdbool.h
+path_to_class.o: $(hdrdir)/ruby/internal/stdckdint.h
path_to_class.o: $(hdrdir)/ruby/internal/symbol.h
path_to_class.o: $(hdrdir)/ruby/internal/value.h
path_to_class.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/popen_deadlock/depend b/ext/-test-/popen_deadlock/depend
index fb58ca30e9..1904e64e59 100644
--- a/ext/-test-/popen_deadlock/depend
+++ b/ext/-test-/popen_deadlock/depend
@@ -147,6 +147,7 @@ infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/special_consts.h
infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/static_assert.h
infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/stdalign.h
infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/stdbool.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/stdckdint.h
infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/symbol.h
infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/value.h
infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/postponed_job/depend b/ext/-test-/postponed_job/depend
index e44d9d51b7..72250896b0 100644
--- a/ext/-test-/postponed_job/depend
+++ b/ext/-test-/postponed_job/depend
@@ -148,6 +148,7 @@ postponed_job.o: $(hdrdir)/ruby/internal/special_consts.h
postponed_job.o: $(hdrdir)/ruby/internal/static_assert.h
postponed_job.o: $(hdrdir)/ruby/internal/stdalign.h
postponed_job.o: $(hdrdir)/ruby/internal/stdbool.h
+postponed_job.o: $(hdrdir)/ruby/internal/stdckdint.h
postponed_job.o: $(hdrdir)/ruby/internal/symbol.h
postponed_job.o: $(hdrdir)/ruby/internal/value.h
postponed_job.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/postponed_job/postponed_job.c b/ext/-test-/postponed_job/postponed_job.c
index fa57bef6f5..9ac866ae77 100644
--- a/ext/-test-/postponed_job/postponed_job.c
+++ b/ext/-test-/postponed_job/postponed_job.c
@@ -1,6 +1,29 @@
#include "ruby.h"
#include "ruby/debug.h"
+// We're testing deprecated things, don't print the compiler warnings
+#if 0
+
+#elif defined(_MSC_VER)
+#pragma warning(disable : 4996)
+
+#elif defined(__INTEL_COMPILER)
+#pragma warning(disable : 1786)
+
+#elif defined(__clang__)
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+#elif defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
+#elif defined(__SUNPRO_CC)
+#pragma error_messages (off,symdeprecated)
+
+#else
+// :FIXME: improve here for your compiler.
+
+#endif
+
static int counter;
static void
@@ -58,6 +81,22 @@ pjob_call_direct(VALUE self, VALUE obj)
return self;
}
+static void pjob_noop_callback(void *data) { }
+
+static VALUE
+pjob_register_one_same(VALUE self)
+{
+ rb_gc_start();
+ int r1 = rb_postponed_job_register_one(0, pjob_noop_callback, NULL);
+ int r2 = rb_postponed_job_register_one(0, pjob_noop_callback, NULL);
+ int r3 = rb_postponed_job_register_one(0, pjob_noop_callback, NULL);
+ VALUE ary = rb_ary_new();
+ rb_ary_push(ary, INT2FIX(r1));
+ rb_ary_push(ary, INT2FIX(r2));
+ rb_ary_push(ary, INT2FIX(r3));
+ return ary;
+}
+
#ifdef HAVE_PTHREAD_H
#include <pthread.h>
@@ -86,6 +125,93 @@ pjob_register_in_c_thread(VALUE self, VALUE obj)
}
#endif
+static void
+pjob_preregistered_callback(void *data)
+{
+ VALUE ary = (VALUE)data;
+ Check_Type(ary, T_ARRAY);
+ rb_ary_push(ary, INT2FIX(counter));
+}
+
+static VALUE
+pjob_preregister_and_call_with_sleep(VALUE self, VALUE obj)
+{
+ counter = 0;
+ rb_postponed_job_handle_t h = rb_postponed_job_preregister(0, pjob_preregistered_callback, (void *)obj);
+ counter++;
+ rb_postponed_job_trigger(h);
+ rb_thread_sleep(0);
+ counter++;
+ rb_postponed_job_trigger(h);
+ rb_thread_sleep(0);
+ counter++;
+ rb_postponed_job_trigger(h);
+ rb_thread_sleep(0);
+ return self;
+}
+
+static VALUE
+pjob_preregister_and_call_without_sleep(VALUE self, VALUE obj)
+{
+ counter = 0;
+ rb_postponed_job_handle_t h = rb_postponed_job_preregister(0, pjob_preregistered_callback, (void *)obj);
+ counter = 3;
+ rb_postponed_job_trigger(h);
+ rb_postponed_job_trigger(h);
+ rb_postponed_job_trigger(h);
+ return self;
+}
+
+static VALUE
+pjob_preregister_multiple_times(VALUE self)
+{
+ int r1 = rb_postponed_job_preregister(0, pjob_noop_callback, NULL);
+ int r2 = rb_postponed_job_preregister(0, pjob_noop_callback, NULL);
+ int r3 = rb_postponed_job_preregister(0, pjob_noop_callback, NULL);
+ VALUE ary = rb_ary_new();
+ rb_ary_push(ary, INT2FIX(r1));
+ rb_ary_push(ary, INT2FIX(r2));
+ rb_ary_push(ary, INT2FIX(r3));
+ return ary;
+
+}
+
+struct pjob_append_data_args {
+ VALUE ary;
+ VALUE data;
+};
+
+static void
+pjob_append_data_callback(void *vctx) {
+ struct pjob_append_data_args *ctx = (struct pjob_append_data_args *)vctx;
+ Check_Type(ctx->ary, T_ARRAY);
+ rb_ary_push(ctx->ary, ctx->data);
+}
+
+static VALUE
+pjob_preregister_calls_with_last_argument(VALUE self)
+{
+ VALUE ary = rb_ary_new();
+
+ struct pjob_append_data_args arg1 = { .ary = ary, .data = INT2FIX(1) };
+ struct pjob_append_data_args arg2 = { .ary = ary, .data = INT2FIX(2) };
+ struct pjob_append_data_args arg3 = { .ary = ary, .data = INT2FIX(3) };
+ struct pjob_append_data_args arg4 = { .ary = ary, .data = INT2FIX(4) };
+
+ rb_postponed_job_handle_t h;
+ h = rb_postponed_job_preregister(0, pjob_append_data_callback, &arg1);
+ rb_postponed_job_preregister(0, pjob_append_data_callback, &arg2);
+ rb_postponed_job_trigger(h);
+ rb_postponed_job_preregister(0, pjob_append_data_callback, &arg3);
+ rb_thread_sleep(0); // should execute with arg3
+
+ rb_postponed_job_preregister(0, pjob_append_data_callback, &arg4);
+ rb_postponed_job_trigger(h);
+ rb_thread_sleep(0); // should execute with arg4
+
+ return ary;
+}
+
void
Init_postponed_job(VALUE self)
{
@@ -93,8 +219,13 @@ Init_postponed_job(VALUE self)
rb_define_module_function(mBug, "postponed_job_register", pjob_register, 1);
rb_define_module_function(mBug, "postponed_job_register_one", pjob_register_one, 1);
rb_define_module_function(mBug, "postponed_job_call_direct", pjob_call_direct, 1);
+ rb_define_module_function(mBug, "postponed_job_register_one_same", pjob_register_one_same, 0);
#ifdef HAVE_PTHREAD_H
rb_define_module_function(mBug, "postponed_job_register_in_c_thread", pjob_register_in_c_thread, 1);
#endif
+ rb_define_module_function(mBug, "postponed_job_preregister_and_call_with_sleep", pjob_preregister_and_call_with_sleep, 1);
+ rb_define_module_function(mBug, "postponed_job_preregister_and_call_without_sleep", pjob_preregister_and_call_without_sleep, 1);
+ rb_define_module_function(mBug, "postponed_job_preregister_multiple_times", pjob_preregister_multiple_times, 0);
+ rb_define_module_function(mBug, "postponed_job_preregister_calls_with_last_argument", pjob_preregister_calls_with_last_argument, 0);
}
diff --git a/ext/-test-/printf/depend b/ext/-test-/printf/depend
index b397041103..0530df78bf 100644
--- a/ext/-test-/printf/depend
+++ b/ext/-test-/printf/depend
@@ -157,6 +157,7 @@ printf.o: $(hdrdir)/ruby/internal/special_consts.h
printf.o: $(hdrdir)/ruby/internal/static_assert.h
printf.o: $(hdrdir)/ruby/internal/stdalign.h
printf.o: $(hdrdir)/ruby/internal/stdbool.h
+printf.o: $(hdrdir)/ruby/internal/stdckdint.h
printf.o: $(hdrdir)/ruby/internal/symbol.h
printf.o: $(hdrdir)/ruby/internal/value.h
printf.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/proc/depend b/ext/-test-/proc/depend
index 7e78aa6f83..45e12bcd09 100644
--- a/ext/-test-/proc/depend
+++ b/ext/-test-/proc/depend
@@ -147,6 +147,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h
init.o: $(hdrdir)/ruby/internal/static_assert.h
init.o: $(hdrdir)/ruby/internal/stdalign.h
init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
init.o: $(hdrdir)/ruby/internal/symbol.h
init.o: $(hdrdir)/ruby/internal/value.h
init.o: $(hdrdir)/ruby/internal/value_type.h
@@ -306,6 +307,7 @@ receiver.o: $(hdrdir)/ruby/internal/special_consts.h
receiver.o: $(hdrdir)/ruby/internal/static_assert.h
receiver.o: $(hdrdir)/ruby/internal/stdalign.h
receiver.o: $(hdrdir)/ruby/internal/stdbool.h
+receiver.o: $(hdrdir)/ruby/internal/stdckdint.h
receiver.o: $(hdrdir)/ruby/internal/symbol.h
receiver.o: $(hdrdir)/ruby/internal/value.h
receiver.o: $(hdrdir)/ruby/internal/value_type.h
@@ -465,6 +467,7 @@ super.o: $(hdrdir)/ruby/internal/special_consts.h
super.o: $(hdrdir)/ruby/internal/static_assert.h
super.o: $(hdrdir)/ruby/internal/stdalign.h
super.o: $(hdrdir)/ruby/internal/stdbool.h
+super.o: $(hdrdir)/ruby/internal/stdckdint.h
super.o: $(hdrdir)/ruby/internal/symbol.h
super.o: $(hdrdir)/ruby/internal/value.h
super.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/public_header_warnings/extconf.rb b/ext/-test-/public_header_warnings/extconf.rb
new file mode 100644
index 0000000000..f6a8a51f63
--- /dev/null
+++ b/ext/-test-/public_header_warnings/extconf.rb
@@ -0,0 +1,23 @@
+#
+# Under compilers with WERRORFLAG, MakeMakefile.try_compile treats warnings as errors, so we can
+# use append_cflags to test whether the public header files emit warnings with certain flags turned
+# on.
+#
+def check_append_cflags(flag, msg = nil)
+ msg ||= "flag #{flag} is not acceptable"
+ !$CFLAGS.include?(flag) or raise("flag #{flag} already present in $CFLAGS")
+ append_cflags(flag)
+ $CFLAGS.include?(flag) or raise(msg)
+end
+
+if %w[gcc clang].include?(RbConfig::CONFIG['CC'])
+ config_string("WERRORFLAG") or raise("expected WERRORFLAG to be defined")
+
+ # should be acceptable on all modern C compilers
+ check_append_cflags("-D_TEST_OK", "baseline compiler warning test failed")
+
+ # Feature #20507: Allow compilation of C extensions with -Wconversion
+ check_append_cflags("-Wconversion", "-Wconversion raising warnings in public headers")
+end
+
+create_makefile("-test-/public_header_warnings")
diff --git a/ext/-test-/random/depend b/ext/-test-/random/depend
index 3f9a52be44..71f5f6e1e6 100644
--- a/ext/-test-/random/depend
+++ b/ext/-test-/random/depend
@@ -146,6 +146,7 @@ bad_version.o: $(hdrdir)/ruby/internal/special_consts.h
bad_version.o: $(hdrdir)/ruby/internal/static_assert.h
bad_version.o: $(hdrdir)/ruby/internal/stdalign.h
bad_version.o: $(hdrdir)/ruby/internal/stdbool.h
+bad_version.o: $(hdrdir)/ruby/internal/stdckdint.h
bad_version.o: $(hdrdir)/ruby/internal/symbol.h
bad_version.o: $(hdrdir)/ruby/internal/value.h
bad_version.o: $(hdrdir)/ruby/internal/value_type.h
@@ -306,6 +307,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h
init.o: $(hdrdir)/ruby/internal/static_assert.h
init.o: $(hdrdir)/ruby/internal/stdalign.h
init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
init.o: $(hdrdir)/ruby/internal/symbol.h
init.o: $(hdrdir)/ruby/internal/value.h
init.o: $(hdrdir)/ruby/internal/value_type.h
@@ -464,6 +466,7 @@ loop.o: $(hdrdir)/ruby/internal/special_consts.h
loop.o: $(hdrdir)/ruby/internal/static_assert.h
loop.o: $(hdrdir)/ruby/internal/stdalign.h
loop.o: $(hdrdir)/ruby/internal/stdbool.h
+loop.o: $(hdrdir)/ruby/internal/stdckdint.h
loop.o: $(hdrdir)/ruby/internal/symbol.h
loop.o: $(hdrdir)/ruby/internal/value.h
loop.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/rational/depend b/ext/-test-/rational/depend
index cff2eae38d..363d779302 100644
--- a/ext/-test-/rational/depend
+++ b/ext/-test-/rational/depend
@@ -151,6 +151,7 @@ rat.o: $(hdrdir)/ruby/internal/special_consts.h
rat.o: $(hdrdir)/ruby/internal/static_assert.h
rat.o: $(hdrdir)/ruby/internal/stdalign.h
rat.o: $(hdrdir)/ruby/internal/stdbool.h
+rat.o: $(hdrdir)/ruby/internal/stdckdint.h
rat.o: $(hdrdir)/ruby/internal/symbol.h
rat.o: $(hdrdir)/ruby/internal/value.h
rat.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/rb_call_super_kw/depend b/ext/-test-/rb_call_super_kw/depend
index a42ddc85ac..04a0fac12c 100644
--- a/ext/-test-/rb_call_super_kw/depend
+++ b/ext/-test-/rb_call_super_kw/depend
@@ -147,6 +147,7 @@ rb_call_super_kw.o: $(hdrdir)/ruby/internal/special_consts.h
rb_call_super_kw.o: $(hdrdir)/ruby/internal/static_assert.h
rb_call_super_kw.o: $(hdrdir)/ruby/internal/stdalign.h
rb_call_super_kw.o: $(hdrdir)/ruby/internal/stdbool.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/stdckdint.h
rb_call_super_kw.o: $(hdrdir)/ruby/internal/symbol.h
rb_call_super_kw.o: $(hdrdir)/ruby/internal/value.h
rb_call_super_kw.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/recursion/depend b/ext/-test-/recursion/depend
index 49377250ef..2a65c98b09 100644
--- a/ext/-test-/recursion/depend
+++ b/ext/-test-/recursion/depend
@@ -147,6 +147,7 @@ recursion.o: $(hdrdir)/ruby/internal/special_consts.h
recursion.o: $(hdrdir)/ruby/internal/static_assert.h
recursion.o: $(hdrdir)/ruby/internal/stdalign.h
recursion.o: $(hdrdir)/ruby/internal/stdbool.h
+recursion.o: $(hdrdir)/ruby/internal/stdckdint.h
recursion.o: $(hdrdir)/ruby/internal/symbol.h
recursion.o: $(hdrdir)/ruby/internal/value.h
recursion.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/regexp/depend b/ext/-test-/regexp/depend
index 484f0320dd..0127a66a2e 100644
--- a/ext/-test-/regexp/depend
+++ b/ext/-test-/regexp/depend
@@ -147,6 +147,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h
init.o: $(hdrdir)/ruby/internal/static_assert.h
init.o: $(hdrdir)/ruby/internal/stdalign.h
init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
init.o: $(hdrdir)/ruby/internal/symbol.h
init.o: $(hdrdir)/ruby/internal/value.h
init.o: $(hdrdir)/ruby/internal/value_type.h
@@ -306,6 +307,7 @@ parse_depth_limit.o: $(hdrdir)/ruby/internal/special_consts.h
parse_depth_limit.o: $(hdrdir)/ruby/internal/static_assert.h
parse_depth_limit.o: $(hdrdir)/ruby/internal/stdalign.h
parse_depth_limit.o: $(hdrdir)/ruby/internal/stdbool.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/stdckdint.h
parse_depth_limit.o: $(hdrdir)/ruby/internal/symbol.h
parse_depth_limit.o: $(hdrdir)/ruby/internal/value.h
parse_depth_limit.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/scan_args/depend b/ext/-test-/scan_args/depend
index 3bedc6a7cf..922e5bbd5c 100644
--- a/ext/-test-/scan_args/depend
+++ b/ext/-test-/scan_args/depend
@@ -147,6 +147,7 @@ scan_args.o: $(hdrdir)/ruby/internal/special_consts.h
scan_args.o: $(hdrdir)/ruby/internal/static_assert.h
scan_args.o: $(hdrdir)/ruby/internal/stdalign.h
scan_args.o: $(hdrdir)/ruby/internal/stdbool.h
+scan_args.o: $(hdrdir)/ruby/internal/stdckdint.h
scan_args.o: $(hdrdir)/ruby/internal/symbol.h
scan_args.o: $(hdrdir)/ruby/internal/value.h
scan_args.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/st/foreach/depend b/ext/-test-/st/foreach/depend
index fdfe356805..36273f8df8 100644
--- a/ext/-test-/st/foreach/depend
+++ b/ext/-test-/st/foreach/depend
@@ -147,6 +147,7 @@ foreach.o: $(hdrdir)/ruby/internal/special_consts.h
foreach.o: $(hdrdir)/ruby/internal/static_assert.h
foreach.o: $(hdrdir)/ruby/internal/stdalign.h
foreach.o: $(hdrdir)/ruby/internal/stdbool.h
+foreach.o: $(hdrdir)/ruby/internal/stdckdint.h
foreach.o: $(hdrdir)/ruby/internal/symbol.h
foreach.o: $(hdrdir)/ruby/internal/value.h
foreach.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/st/numhash/depend b/ext/-test-/st/numhash/depend
index ef28c892f3..a0916183b6 100644
--- a/ext/-test-/st/numhash/depend
+++ b/ext/-test-/st/numhash/depend
@@ -147,6 +147,7 @@ numhash.o: $(hdrdir)/ruby/internal/special_consts.h
numhash.o: $(hdrdir)/ruby/internal/static_assert.h
numhash.o: $(hdrdir)/ruby/internal/stdalign.h
numhash.o: $(hdrdir)/ruby/internal/stdbool.h
+numhash.o: $(hdrdir)/ruby/internal/stdckdint.h
numhash.o: $(hdrdir)/ruby/internal/symbol.h
numhash.o: $(hdrdir)/ruby/internal/value.h
numhash.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/st/update/depend b/ext/-test-/st/update/depend
index 2d5ff224a2..96ba194df0 100644
--- a/ext/-test-/st/update/depend
+++ b/ext/-test-/st/update/depend
@@ -147,6 +147,7 @@ update.o: $(hdrdir)/ruby/internal/special_consts.h
update.o: $(hdrdir)/ruby/internal/static_assert.h
update.o: $(hdrdir)/ruby/internal/stdalign.h
update.o: $(hdrdir)/ruby/internal/stdbool.h
+update.o: $(hdrdir)/ruby/internal/stdckdint.h
update.o: $(hdrdir)/ruby/internal/symbol.h
update.o: $(hdrdir)/ruby/internal/value.h
update.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/string/depend b/ext/-test-/string/depend
index eeb4914346..044b6109ff 100644
--- a/ext/-test-/string/depend
+++ b/ext/-test-/string/depend
@@ -158,6 +158,7 @@ capacity.o: $(hdrdir)/ruby/internal/special_consts.h
capacity.o: $(hdrdir)/ruby/internal/static_assert.h
capacity.o: $(hdrdir)/ruby/internal/stdalign.h
capacity.o: $(hdrdir)/ruby/internal/stdbool.h
+capacity.o: $(hdrdir)/ruby/internal/stdckdint.h
capacity.o: $(hdrdir)/ruby/internal/symbol.h
capacity.o: $(hdrdir)/ruby/internal/value.h
capacity.o: $(hdrdir)/ruby/internal/value_type.h
@@ -173,6 +174,166 @@ capacity.o: $(hdrdir)/ruby/subst.h
capacity.o: $(top_srcdir)/internal/compilers.h
capacity.o: $(top_srcdir)/internal/string.h
capacity.o: capacity.c
+chilled.o: $(RUBY_EXTCONF_H)
+chilled.o: $(arch_hdrdir)/ruby/config.h
+chilled.o: $(hdrdir)/ruby.h
+chilled.o: $(hdrdir)/ruby/assert.h
+chilled.o: $(hdrdir)/ruby/backward.h
+chilled.o: $(hdrdir)/ruby/backward/2/assume.h
+chilled.o: $(hdrdir)/ruby/backward/2/attributes.h
+chilled.o: $(hdrdir)/ruby/backward/2/bool.h
+chilled.o: $(hdrdir)/ruby/backward/2/inttypes.h
+chilled.o: $(hdrdir)/ruby/backward/2/limits.h
+chilled.o: $(hdrdir)/ruby/backward/2/long_long.h
+chilled.o: $(hdrdir)/ruby/backward/2/stdalign.h
+chilled.o: $(hdrdir)/ruby/backward/2/stdarg.h
+chilled.o: $(hdrdir)/ruby/defines.h
+chilled.o: $(hdrdir)/ruby/intern.h
+chilled.o: $(hdrdir)/ruby/internal/abi.h
+chilled.o: $(hdrdir)/ruby/internal/anyargs.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+chilled.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+chilled.o: $(hdrdir)/ruby/internal/assume.h
+chilled.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+chilled.o: $(hdrdir)/ruby/internal/attr/artificial.h
+chilled.o: $(hdrdir)/ruby/internal/attr/cold.h
+chilled.o: $(hdrdir)/ruby/internal/attr/const.h
+chilled.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+chilled.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+chilled.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+chilled.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+chilled.o: $(hdrdir)/ruby/internal/attr/error.h
+chilled.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+chilled.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+chilled.o: $(hdrdir)/ruby/internal/attr/format.h
+chilled.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+chilled.o: $(hdrdir)/ruby/internal/attr/noalias.h
+chilled.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+chilled.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+chilled.o: $(hdrdir)/ruby/internal/attr/noinline.h
+chilled.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+chilled.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+chilled.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+chilled.o: $(hdrdir)/ruby/internal/attr/pure.h
+chilled.o: $(hdrdir)/ruby/internal/attr/restrict.h
+chilled.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+chilled.o: $(hdrdir)/ruby/internal/attr/warning.h
+chilled.o: $(hdrdir)/ruby/internal/attr/weakref.h
+chilled.o: $(hdrdir)/ruby/internal/cast.h
+chilled.o: $(hdrdir)/ruby/internal/compiler_is.h
+chilled.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+chilled.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+chilled.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+chilled.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+chilled.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+chilled.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+chilled.o: $(hdrdir)/ruby/internal/compiler_since.h
+chilled.o: $(hdrdir)/ruby/internal/config.h
+chilled.o: $(hdrdir)/ruby/internal/constant_p.h
+chilled.o: $(hdrdir)/ruby/internal/core.h
+chilled.o: $(hdrdir)/ruby/internal/core/rarray.h
+chilled.o: $(hdrdir)/ruby/internal/core/rbasic.h
+chilled.o: $(hdrdir)/ruby/internal/core/rbignum.h
+chilled.o: $(hdrdir)/ruby/internal/core/rclass.h
+chilled.o: $(hdrdir)/ruby/internal/core/rdata.h
+chilled.o: $(hdrdir)/ruby/internal/core/rfile.h
+chilled.o: $(hdrdir)/ruby/internal/core/rhash.h
+chilled.o: $(hdrdir)/ruby/internal/core/robject.h
+chilled.o: $(hdrdir)/ruby/internal/core/rregexp.h
+chilled.o: $(hdrdir)/ruby/internal/core/rstring.h
+chilled.o: $(hdrdir)/ruby/internal/core/rstruct.h
+chilled.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+chilled.o: $(hdrdir)/ruby/internal/ctype.h
+chilled.o: $(hdrdir)/ruby/internal/dllexport.h
+chilled.o: $(hdrdir)/ruby/internal/dosish.h
+chilled.o: $(hdrdir)/ruby/internal/error.h
+chilled.o: $(hdrdir)/ruby/internal/eval.h
+chilled.o: $(hdrdir)/ruby/internal/event.h
+chilled.o: $(hdrdir)/ruby/internal/fl_type.h
+chilled.o: $(hdrdir)/ruby/internal/gc.h
+chilled.o: $(hdrdir)/ruby/internal/glob.h
+chilled.o: $(hdrdir)/ruby/internal/globals.h
+chilled.o: $(hdrdir)/ruby/internal/has/attribute.h
+chilled.o: $(hdrdir)/ruby/internal/has/builtin.h
+chilled.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+chilled.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+chilled.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+chilled.o: $(hdrdir)/ruby/internal/has/extension.h
+chilled.o: $(hdrdir)/ruby/internal/has/feature.h
+chilled.o: $(hdrdir)/ruby/internal/has/warning.h
+chilled.o: $(hdrdir)/ruby/internal/intern/array.h
+chilled.o: $(hdrdir)/ruby/internal/intern/bignum.h
+chilled.o: $(hdrdir)/ruby/internal/intern/class.h
+chilled.o: $(hdrdir)/ruby/internal/intern/compar.h
+chilled.o: $(hdrdir)/ruby/internal/intern/complex.h
+chilled.o: $(hdrdir)/ruby/internal/intern/cont.h
+chilled.o: $(hdrdir)/ruby/internal/intern/dir.h
+chilled.o: $(hdrdir)/ruby/internal/intern/enum.h
+chilled.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+chilled.o: $(hdrdir)/ruby/internal/intern/error.h
+chilled.o: $(hdrdir)/ruby/internal/intern/eval.h
+chilled.o: $(hdrdir)/ruby/internal/intern/file.h
+chilled.o: $(hdrdir)/ruby/internal/intern/hash.h
+chilled.o: $(hdrdir)/ruby/internal/intern/io.h
+chilled.o: $(hdrdir)/ruby/internal/intern/load.h
+chilled.o: $(hdrdir)/ruby/internal/intern/marshal.h
+chilled.o: $(hdrdir)/ruby/internal/intern/numeric.h
+chilled.o: $(hdrdir)/ruby/internal/intern/object.h
+chilled.o: $(hdrdir)/ruby/internal/intern/parse.h
+chilled.o: $(hdrdir)/ruby/internal/intern/proc.h
+chilled.o: $(hdrdir)/ruby/internal/intern/process.h
+chilled.o: $(hdrdir)/ruby/internal/intern/random.h
+chilled.o: $(hdrdir)/ruby/internal/intern/range.h
+chilled.o: $(hdrdir)/ruby/internal/intern/rational.h
+chilled.o: $(hdrdir)/ruby/internal/intern/re.h
+chilled.o: $(hdrdir)/ruby/internal/intern/ruby.h
+chilled.o: $(hdrdir)/ruby/internal/intern/select.h
+chilled.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+chilled.o: $(hdrdir)/ruby/internal/intern/signal.h
+chilled.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+chilled.o: $(hdrdir)/ruby/internal/intern/string.h
+chilled.o: $(hdrdir)/ruby/internal/intern/struct.h
+chilled.o: $(hdrdir)/ruby/internal/intern/thread.h
+chilled.o: $(hdrdir)/ruby/internal/intern/time.h
+chilled.o: $(hdrdir)/ruby/internal/intern/variable.h
+chilled.o: $(hdrdir)/ruby/internal/intern/vm.h
+chilled.o: $(hdrdir)/ruby/internal/interpreter.h
+chilled.o: $(hdrdir)/ruby/internal/iterator.h
+chilled.o: $(hdrdir)/ruby/internal/memory.h
+chilled.o: $(hdrdir)/ruby/internal/method.h
+chilled.o: $(hdrdir)/ruby/internal/module.h
+chilled.o: $(hdrdir)/ruby/internal/newobj.h
+chilled.o: $(hdrdir)/ruby/internal/scan_args.h
+chilled.o: $(hdrdir)/ruby/internal/special_consts.h
+chilled.o: $(hdrdir)/ruby/internal/static_assert.h
+chilled.o: $(hdrdir)/ruby/internal/stdalign.h
+chilled.o: $(hdrdir)/ruby/internal/stdbool.h
+chilled.o: $(hdrdir)/ruby/internal/stdckdint.h
+chilled.o: $(hdrdir)/ruby/internal/symbol.h
+chilled.o: $(hdrdir)/ruby/internal/value.h
+chilled.o: $(hdrdir)/ruby/internal/value_type.h
+chilled.o: $(hdrdir)/ruby/internal/variable.h
+chilled.o: $(hdrdir)/ruby/internal/warning_push.h
+chilled.o: $(hdrdir)/ruby/internal/xmalloc.h
+chilled.o: $(hdrdir)/ruby/missing.h
+chilled.o: $(hdrdir)/ruby/ruby.h
+chilled.o: $(hdrdir)/ruby/st.h
+chilled.o: $(hdrdir)/ruby/subst.h
+chilled.o: chilled.c
coderange.o: $(RUBY_EXTCONF_H)
coderange.o: $(arch_hdrdir)/ruby/config.h
coderange.o: $(hdrdir)/ruby/assert.h
@@ -330,6 +491,7 @@ coderange.o: $(hdrdir)/ruby/internal/special_consts.h
coderange.o: $(hdrdir)/ruby/internal/static_assert.h
coderange.o: $(hdrdir)/ruby/internal/stdalign.h
coderange.o: $(hdrdir)/ruby/internal/stdbool.h
+coderange.o: $(hdrdir)/ruby/internal/stdckdint.h
coderange.o: $(hdrdir)/ruby/internal/symbol.h
coderange.o: $(hdrdir)/ruby/internal/value.h
coderange.o: $(hdrdir)/ruby/internal/value_type.h
@@ -501,6 +663,7 @@ cstr.o: $(hdrdir)/ruby/internal/special_consts.h
cstr.o: $(hdrdir)/ruby/internal/static_assert.h
cstr.o: $(hdrdir)/ruby/internal/stdalign.h
cstr.o: $(hdrdir)/ruby/internal/stdbool.h
+cstr.o: $(hdrdir)/ruby/internal/stdckdint.h
cstr.o: $(hdrdir)/ruby/internal/symbol.h
cstr.o: $(hdrdir)/ruby/internal/value.h
cstr.o: $(hdrdir)/ruby/internal/value_type.h
@@ -665,6 +828,7 @@ ellipsize.o: $(hdrdir)/ruby/internal/special_consts.h
ellipsize.o: $(hdrdir)/ruby/internal/static_assert.h
ellipsize.o: $(hdrdir)/ruby/internal/stdalign.h
ellipsize.o: $(hdrdir)/ruby/internal/stdbool.h
+ellipsize.o: $(hdrdir)/ruby/internal/stdckdint.h
ellipsize.o: $(hdrdir)/ruby/internal/symbol.h
ellipsize.o: $(hdrdir)/ruby/internal/value.h
ellipsize.o: $(hdrdir)/ruby/internal/value_type.h
@@ -834,6 +998,7 @@ enc_associate.o: $(hdrdir)/ruby/internal/special_consts.h
enc_associate.o: $(hdrdir)/ruby/internal/static_assert.h
enc_associate.o: $(hdrdir)/ruby/internal/stdalign.h
enc_associate.o: $(hdrdir)/ruby/internal/stdbool.h
+enc_associate.o: $(hdrdir)/ruby/internal/stdckdint.h
enc_associate.o: $(hdrdir)/ruby/internal/symbol.h
enc_associate.o: $(hdrdir)/ruby/internal/value.h
enc_associate.o: $(hdrdir)/ruby/internal/value_type.h
@@ -1005,6 +1170,7 @@ enc_dummy.o: $(hdrdir)/ruby/internal/special_consts.h
enc_dummy.o: $(hdrdir)/ruby/internal/static_assert.h
enc_dummy.o: $(hdrdir)/ruby/internal/stdalign.h
enc_dummy.o: $(hdrdir)/ruby/internal/stdbool.h
+enc_dummy.o: $(hdrdir)/ruby/internal/stdckdint.h
enc_dummy.o: $(hdrdir)/ruby/internal/symbol.h
enc_dummy.o: $(hdrdir)/ruby/internal/value.h
enc_dummy.o: $(hdrdir)/ruby/internal/value_type.h
@@ -1175,6 +1341,7 @@ enc_str_buf_cat.o: $(hdrdir)/ruby/internal/special_consts.h
enc_str_buf_cat.o: $(hdrdir)/ruby/internal/static_assert.h
enc_str_buf_cat.o: $(hdrdir)/ruby/internal/stdalign.h
enc_str_buf_cat.o: $(hdrdir)/ruby/internal/stdbool.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/stdckdint.h
enc_str_buf_cat.o: $(hdrdir)/ruby/internal/symbol.h
enc_str_buf_cat.o: $(hdrdir)/ruby/internal/value.h
enc_str_buf_cat.o: $(hdrdir)/ruby/internal/value_type.h
@@ -1347,6 +1514,7 @@ fstring.o: $(hdrdir)/ruby/internal/special_consts.h
fstring.o: $(hdrdir)/ruby/internal/static_assert.h
fstring.o: $(hdrdir)/ruby/internal/stdalign.h
fstring.o: $(hdrdir)/ruby/internal/stdbool.h
+fstring.o: $(hdrdir)/ruby/internal/stdckdint.h
fstring.o: $(hdrdir)/ruby/internal/symbol.h
fstring.o: $(hdrdir)/ruby/internal/value.h
fstring.o: $(hdrdir)/ruby/internal/value_type.h
@@ -1510,6 +1678,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h
init.o: $(hdrdir)/ruby/internal/static_assert.h
init.o: $(hdrdir)/ruby/internal/stdalign.h
init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
init.o: $(hdrdir)/ruby/internal/symbol.h
init.o: $(hdrdir)/ruby/internal/value.h
init.o: $(hdrdir)/ruby/internal/value_type.h
@@ -1669,6 +1838,7 @@ modify.o: $(hdrdir)/ruby/internal/special_consts.h
modify.o: $(hdrdir)/ruby/internal/static_assert.h
modify.o: $(hdrdir)/ruby/internal/stdalign.h
modify.o: $(hdrdir)/ruby/internal/stdbool.h
+modify.o: $(hdrdir)/ruby/internal/stdckdint.h
modify.o: $(hdrdir)/ruby/internal/symbol.h
modify.o: $(hdrdir)/ruby/internal/value.h
modify.o: $(hdrdir)/ruby/internal/value_type.h
@@ -1838,6 +2008,7 @@ new.o: $(hdrdir)/ruby/internal/special_consts.h
new.o: $(hdrdir)/ruby/internal/static_assert.h
new.o: $(hdrdir)/ruby/internal/stdalign.h
new.o: $(hdrdir)/ruby/internal/stdbool.h
+new.o: $(hdrdir)/ruby/internal/stdckdint.h
new.o: $(hdrdir)/ruby/internal/symbol.h
new.o: $(hdrdir)/ruby/internal/value.h
new.o: $(hdrdir)/ruby/internal/value_type.h
@@ -1999,6 +2170,7 @@ nofree.o: $(hdrdir)/ruby/internal/special_consts.h
nofree.o: $(hdrdir)/ruby/internal/static_assert.h
nofree.o: $(hdrdir)/ruby/internal/stdalign.h
nofree.o: $(hdrdir)/ruby/internal/stdbool.h
+nofree.o: $(hdrdir)/ruby/internal/stdckdint.h
nofree.o: $(hdrdir)/ruby/internal/symbol.h
nofree.o: $(hdrdir)/ruby/internal/value.h
nofree.o: $(hdrdir)/ruby/internal/value_type.h
@@ -2167,6 +2339,7 @@ normalize.o: $(hdrdir)/ruby/internal/special_consts.h
normalize.o: $(hdrdir)/ruby/internal/static_assert.h
normalize.o: $(hdrdir)/ruby/internal/stdalign.h
normalize.o: $(hdrdir)/ruby/internal/stdbool.h
+normalize.o: $(hdrdir)/ruby/internal/stdckdint.h
normalize.o: $(hdrdir)/ruby/internal/symbol.h
normalize.o: $(hdrdir)/ruby/internal/value.h
normalize.o: $(hdrdir)/ruby/internal/value_type.h
@@ -2339,6 +2512,7 @@ qsort.o: $(hdrdir)/ruby/internal/special_consts.h
qsort.o: $(hdrdir)/ruby/internal/static_assert.h
qsort.o: $(hdrdir)/ruby/internal/stdalign.h
qsort.o: $(hdrdir)/ruby/internal/stdbool.h
+qsort.o: $(hdrdir)/ruby/internal/stdckdint.h
qsort.o: $(hdrdir)/ruby/internal/symbol.h
qsort.o: $(hdrdir)/ruby/internal/value.h
qsort.o: $(hdrdir)/ruby/internal/value_type.h
@@ -2501,6 +2675,7 @@ rb_interned_str.o: $(hdrdir)/ruby/internal/special_consts.h
rb_interned_str.o: $(hdrdir)/ruby/internal/static_assert.h
rb_interned_str.o: $(hdrdir)/ruby/internal/stdalign.h
rb_interned_str.o: $(hdrdir)/ruby/internal/stdbool.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/stdckdint.h
rb_interned_str.o: $(hdrdir)/ruby/internal/symbol.h
rb_interned_str.o: $(hdrdir)/ruby/internal/value.h
rb_interned_str.o: $(hdrdir)/ruby/internal/value_type.h
@@ -2660,6 +2835,7 @@ rb_str_dup.o: $(hdrdir)/ruby/internal/special_consts.h
rb_str_dup.o: $(hdrdir)/ruby/internal/static_assert.h
rb_str_dup.o: $(hdrdir)/ruby/internal/stdalign.h
rb_str_dup.o: $(hdrdir)/ruby/internal/stdbool.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/stdckdint.h
rb_str_dup.o: $(hdrdir)/ruby/internal/symbol.h
rb_str_dup.o: $(hdrdir)/ruby/internal/value.h
rb_str_dup.o: $(hdrdir)/ruby/internal/value_type.h
@@ -2819,6 +2995,7 @@ set_len.o: $(hdrdir)/ruby/internal/special_consts.h
set_len.o: $(hdrdir)/ruby/internal/static_assert.h
set_len.o: $(hdrdir)/ruby/internal/stdalign.h
set_len.o: $(hdrdir)/ruby/internal/stdbool.h
+set_len.o: $(hdrdir)/ruby/internal/stdckdint.h
set_len.o: $(hdrdir)/ruby/internal/symbol.h
set_len.o: $(hdrdir)/ruby/internal/value.h
set_len.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/string/fstring.c b/ext/-test-/string/fstring.c
index 7ee14a8570..71c4b7f97e 100644
--- a/ext/-test-/string/fstring.c
+++ b/ext/-test-/string/fstring.c
@@ -2,12 +2,10 @@
#include "ruby/encoding.h"
#include "internal/string.h"
-VALUE rb_fstring(VALUE str);
-
VALUE
bug_s_fstring(VALUE self, VALUE str)
{
- return rb_fstring(str);
+ return rb_str_to_interned_str(str);
}
VALUE
@@ -15,19 +13,19 @@ bug_s_fstring_fake_str(VALUE self)
{
static const char literal[] = "abcdefghijklmnopqrstuvwxyz";
struct RString fake_str;
- return rb_fstring(rb_setup_fake_str(&fake_str, literal, sizeof(literal) - 1, 0));
+ return rb_str_to_interned_str(rb_setup_fake_str(&fake_str, literal, sizeof(literal) - 1, 0));
}
VALUE
bug_s_rb_enc_interned_str(VALUE self, VALUE encoding)
{
- return rb_enc_interned_str("foo", 3, RDATA(encoding)->data);
+ return rb_enc_interned_str("foo", 3, NIL_P(encoding) ? NULL : RDATA(encoding)->data);
}
VALUE
bug_s_rb_enc_str_new(VALUE self, VALUE encoding)
{
- return rb_enc_str_new("foo", 3, RDATA(encoding)->data);
+ return rb_enc_str_new("foo", 3, NIL_P(encoding) ? NULL : RDATA(encoding)->data);
}
void
diff --git a/ext/-test-/struct/depend b/ext/-test-/struct/depend
index 5db943e286..951dddd5dd 100644
--- a/ext/-test-/struct/depend
+++ b/ext/-test-/struct/depend
@@ -147,6 +147,7 @@ data.o: $(hdrdir)/ruby/internal/special_consts.h
data.o: $(hdrdir)/ruby/internal/static_assert.h
data.o: $(hdrdir)/ruby/internal/stdalign.h
data.o: $(hdrdir)/ruby/internal/stdbool.h
+data.o: $(hdrdir)/ruby/internal/stdckdint.h
data.o: $(hdrdir)/ruby/internal/symbol.h
data.o: $(hdrdir)/ruby/internal/value.h
data.o: $(hdrdir)/ruby/internal/value_type.h
@@ -306,6 +307,7 @@ duplicate.o: $(hdrdir)/ruby/internal/special_consts.h
duplicate.o: $(hdrdir)/ruby/internal/static_assert.h
duplicate.o: $(hdrdir)/ruby/internal/stdalign.h
duplicate.o: $(hdrdir)/ruby/internal/stdbool.h
+duplicate.o: $(hdrdir)/ruby/internal/stdckdint.h
duplicate.o: $(hdrdir)/ruby/internal/symbol.h
duplicate.o: $(hdrdir)/ruby/internal/value.h
duplicate.o: $(hdrdir)/ruby/internal/value_type.h
@@ -465,6 +467,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h
init.o: $(hdrdir)/ruby/internal/static_assert.h
init.o: $(hdrdir)/ruby/internal/stdalign.h
init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
init.o: $(hdrdir)/ruby/internal/symbol.h
init.o: $(hdrdir)/ruby/internal/value.h
init.o: $(hdrdir)/ruby/internal/value_type.h
@@ -624,6 +627,7 @@ len.o: $(hdrdir)/ruby/internal/special_consts.h
len.o: $(hdrdir)/ruby/internal/static_assert.h
len.o: $(hdrdir)/ruby/internal/stdalign.h
len.o: $(hdrdir)/ruby/internal/stdbool.h
+len.o: $(hdrdir)/ruby/internal/stdckdint.h
len.o: $(hdrdir)/ruby/internal/symbol.h
len.o: $(hdrdir)/ruby/internal/value.h
len.o: $(hdrdir)/ruby/internal/value_type.h
@@ -783,6 +787,7 @@ member.o: $(hdrdir)/ruby/internal/special_consts.h
member.o: $(hdrdir)/ruby/internal/static_assert.h
member.o: $(hdrdir)/ruby/internal/stdalign.h
member.o: $(hdrdir)/ruby/internal/stdbool.h
+member.o: $(hdrdir)/ruby/internal/stdckdint.h
member.o: $(hdrdir)/ruby/internal/symbol.h
member.o: $(hdrdir)/ruby/internal/value.h
member.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/struct/member.c b/ext/-test-/struct/member.c
index f5400fe477..29ddff93e8 100644
--- a/ext/-test-/struct/member.c
+++ b/ext/-test-/struct/member.c
@@ -6,7 +6,7 @@ bug_struct_get(VALUE obj, VALUE name)
ID id = rb_check_id(&name);
if (!id) {
- rb_name_error_str(name, "`%"PRIsVALUE"' is not a struct member", name);
+ rb_name_error_str(name, "'%"PRIsVALUE"' is not a struct member", name);
}
return rb_struct_getmember(obj, id);
}
diff --git a/ext/-test-/symbol/depend b/ext/-test-/symbol/depend
index dd1b5c305f..7c76596fdf 100644
--- a/ext/-test-/symbol/depend
+++ b/ext/-test-/symbol/depend
@@ -147,6 +147,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h
init.o: $(hdrdir)/ruby/internal/static_assert.h
init.o: $(hdrdir)/ruby/internal/stdalign.h
init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
init.o: $(hdrdir)/ruby/internal/symbol.h
init.o: $(hdrdir)/ruby/internal/value.h
init.o: $(hdrdir)/ruby/internal/value_type.h
@@ -306,6 +307,7 @@ type.o: $(hdrdir)/ruby/internal/special_consts.h
type.o: $(hdrdir)/ruby/internal/static_assert.h
type.o: $(hdrdir)/ruby/internal/stdalign.h
type.o: $(hdrdir)/ruby/internal/stdbool.h
+type.o: $(hdrdir)/ruby/internal/stdckdint.h
type.o: $(hdrdir)/ruby/internal/symbol.h
type.o: $(hdrdir)/ruby/internal/value.h
type.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/thread/id/extconf.rb b/ext/-test-/thread/id/extconf.rb
new file mode 100644
index 0000000000..a0ae0eff15
--- /dev/null
+++ b/ext/-test-/thread/id/extconf.rb
@@ -0,0 +1,3 @@
+if have_func("gettid")
+ create_makefile("-test-/thread/id")
+end
diff --git a/ext/-test-/thread/id/id.c b/ext/-test-/thread/id/id.c
new file mode 100644
index 0000000000..b46a5955e2
--- /dev/null
+++ b/ext/-test-/thread/id/id.c
@@ -0,0 +1,15 @@
+#include <ruby.h>
+
+static VALUE
+bug_gettid(VALUE self)
+{
+ pid_t tid = gettid();
+ return PIDT2NUM(tid);
+}
+
+void
+Init_id(void)
+{
+ VALUE klass = rb_define_module_under(rb_define_module("Bug"), "ThreadID");
+ rb_define_module_function(klass, "gettid", bug_gettid, 0);
+}
diff --git a/ext/-test-/thread/instrumentation/depend b/ext/-test-/thread/instrumentation/depend
index b03f51870f..a37e4d5675 100644
--- a/ext/-test-/thread/instrumentation/depend
+++ b/ext/-test-/thread/instrumentation/depend
@@ -147,6 +147,7 @@ instrumentation.o: $(hdrdir)/ruby/internal/special_consts.h
instrumentation.o: $(hdrdir)/ruby/internal/static_assert.h
instrumentation.o: $(hdrdir)/ruby/internal/stdalign.h
instrumentation.o: $(hdrdir)/ruby/internal/stdbool.h
+instrumentation.o: $(hdrdir)/ruby/internal/stdckdint.h
instrumentation.o: $(hdrdir)/ruby/internal/symbol.h
instrumentation.o: $(hdrdir)/ruby/internal/value.h
instrumentation.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/thread/instrumentation/instrumentation.c b/ext/-test-/thread/instrumentation/instrumentation.c
index 4d76f4cbb3..d81bc0f2a7 100644
--- a/ext/-test-/thread/instrumentation/instrumentation.c
+++ b/ext/-test-/thread/instrumentation/instrumentation.c
@@ -2,88 +2,137 @@
#include "ruby/atomic.h"
#include "ruby/thread.h"
-static rb_atomic_t started_count = 0;
-static rb_atomic_t ready_count = 0;
-static rb_atomic_t resumed_count = 0;
-static rb_atomic_t suspended_count = 0;
-static rb_atomic_t exited_count = 0;
-
#ifndef RB_THREAD_LOCAL_SPECIFIER
# define RB_THREAD_LOCAL_SPECIFIER
#endif
-static RB_THREAD_LOCAL_SPECIFIER unsigned int local_ready_count = 0;
-static RB_THREAD_LOCAL_SPECIFIER unsigned int local_resumed_count = 0;
-static RB_THREAD_LOCAL_SPECIFIER unsigned int local_suspended_count = 0;
-
static VALUE last_thread = Qnil;
+static VALUE timeline_value = Qnil;
+
+struct thread_event {
+ VALUE thread;
+ rb_event_flag_t event;
+};
+
+#define MAX_EVENTS 1024
+static struct thread_event event_timeline[MAX_EVENTS];
+static rb_atomic_t timeline_cursor;
static void
-ex_callback(rb_event_flag_t event, const rb_internal_thread_event_data_t *event_data, void *user_data)
+event_timeline_gc_mark(void *ptr) {
+ rb_atomic_t cursor;
+ for (cursor = 0; cursor < timeline_cursor; cursor++) {
+ rb_gc_mark(event_timeline[cursor].thread);
+ }
+}
+
+static const rb_data_type_t event_timeline_type = {
+ "TestThreadInstrumentation/event_timeline",
+ {event_timeline_gc_mark, NULL, NULL,},
+ 0, 0,
+ RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+static void
+reset_timeline(void)
+{
+ timeline_cursor = 0;
+ memset(event_timeline, 0, sizeof(struct thread_event) * MAX_EVENTS);
+}
+
+static rb_event_flag_t
+find_last_event(VALUE thread)
+{
+ rb_atomic_t cursor = timeline_cursor;
+ if (cursor) {
+ do {
+ if (event_timeline[cursor].thread == thread){
+ return event_timeline[cursor].event;
+ }
+ cursor--;
+ } while (cursor > 0);
+ }
+ return 0;
+}
+
+static const char *
+event_name(rb_event_flag_t event)
{
switch (event) {
case RUBY_INTERNAL_THREAD_EVENT_STARTED:
- last_thread = event_data->thread;
- RUBY_ATOMIC_INC(started_count);
- break;
+ return "started";
case RUBY_INTERNAL_THREAD_EVENT_READY:
- RUBY_ATOMIC_INC(ready_count);
- local_ready_count++;
- break;
+ return "ready";
case RUBY_INTERNAL_THREAD_EVENT_RESUMED:
- RUBY_ATOMIC_INC(resumed_count);
- local_resumed_count++;
- break;
+ return "resumed";
case RUBY_INTERNAL_THREAD_EVENT_SUSPENDED:
- RUBY_ATOMIC_INC(suspended_count);
- local_suspended_count++;
- break;
+ return "suspended";
case RUBY_INTERNAL_THREAD_EVENT_EXITED:
- RUBY_ATOMIC_INC(exited_count);
- break;
+ return "exited";
}
+ return "no-event";
}
-static rb_internal_thread_event_hook_t * single_hook = NULL;
-
-static VALUE
-thread_counters(VALUE thread)
+static void
+unexpected(bool strict, const char *format, VALUE thread, rb_event_flag_t last_event)
{
- VALUE array = rb_ary_new2(5);
- rb_ary_push(array, UINT2NUM(started_count));
- rb_ary_push(array, UINT2NUM(ready_count));
- rb_ary_push(array, UINT2NUM(resumed_count));
- rb_ary_push(array, UINT2NUM(suspended_count));
- rb_ary_push(array, UINT2NUM(exited_count));
- return array;
+ const char *last_event_name = event_name(last_event);
+ if (strict) {
+ rb_bug(format, thread, last_event_name);
+ }
+ else {
+ fprintf(stderr, format, thread, last_event_name);
+ fprintf(stderr, "\n");
+ }
}
-static VALUE
-thread_local_counters(VALUE thread)
+static void
+ex_callback(rb_event_flag_t event, const rb_internal_thread_event_data_t *event_data, void *user_data)
{
- VALUE array = rb_ary_new2(3);
- rb_ary_push(array, UINT2NUM(local_ready_count));
- rb_ary_push(array, UINT2NUM(local_resumed_count));
- rb_ary_push(array, UINT2NUM(local_suspended_count));
- return array;
-}
+ rb_event_flag_t last_event = find_last_event(event_data->thread);
+ bool strict = (bool)user_data;
+
+ if (last_event != 0) {
+ switch (event) {
+ case RUBY_INTERNAL_THREAD_EVENT_STARTED:
+ unexpected(strict, "[thread=%"PRIxVALUE"] `started` event can't be preceded by `%s`", event_data->thread, last_event);
+ break;
+ case RUBY_INTERNAL_THREAD_EVENT_READY:
+ if (last_event != RUBY_INTERNAL_THREAD_EVENT_STARTED && last_event != RUBY_INTERNAL_THREAD_EVENT_SUSPENDED) {
+ unexpected(strict, "[thread=%"PRIxVALUE"] `ready` must be preceded by `started` or `suspended`, got: `%s`", event_data->thread, last_event);
+ }
+ break;
+ case RUBY_INTERNAL_THREAD_EVENT_RESUMED:
+ if (last_event != RUBY_INTERNAL_THREAD_EVENT_READY) {
+ unexpected(strict, "[thread=%"PRIxVALUE"] `resumed` must be preceded by `ready`, got: `%s`", event_data->thread, last_event);
+ }
+ break;
+ case RUBY_INTERNAL_THREAD_EVENT_SUSPENDED:
+ if (last_event != RUBY_INTERNAL_THREAD_EVENT_RESUMED) {
+ unexpected(strict, "[thread=%"PRIxVALUE"] `suspended` must be preceded by `resumed`, got: `%s`", event_data->thread, last_event);
+ }
+ break;
+ case RUBY_INTERNAL_THREAD_EVENT_EXITED:
+ if (last_event != RUBY_INTERNAL_THREAD_EVENT_RESUMED && last_event != RUBY_INTERNAL_THREAD_EVENT_SUSPENDED) {
+ unexpected(strict, "[thread=%"PRIxVALUE"] `exited` must be preceded by `resumed` or `suspended`, got: `%s`", event_data->thread, last_event);
+ }
+ break;
+ }
+ }
-static VALUE
-thread_reset_counters(VALUE thread)
-{
- RUBY_ATOMIC_SET(started_count, 0);
- RUBY_ATOMIC_SET(ready_count, 0);
- RUBY_ATOMIC_SET(resumed_count, 0);
- RUBY_ATOMIC_SET(suspended_count, 0);
- RUBY_ATOMIC_SET(exited_count, 0);
- local_ready_count = 0;
- local_resumed_count = 0;
- local_suspended_count = 0;
- return Qtrue;
+ rb_atomic_t cursor = RUBY_ATOMIC_FETCH_ADD(timeline_cursor, 1);
+ if (cursor >= MAX_EVENTS) {
+ rb_bug("TestThreadInstrumentation: ran out of event_timeline space");
+ }
+
+ event_timeline[cursor].thread = event_data->thread;
+ event_timeline[cursor].event = event;
}
+static rb_internal_thread_event_hook_t * single_hook = NULL;
+
static VALUE
-thread_register_callback(VALUE thread)
+thread_register_callback(VALUE thread, VALUE strict)
{
single_hook = rb_internal_thread_add_event_hook(
ex_callback,
@@ -92,13 +141,33 @@ thread_register_callback(VALUE thread)
RUBY_INTERNAL_THREAD_EVENT_RESUMED |
RUBY_INTERNAL_THREAD_EVENT_SUSPENDED |
RUBY_INTERNAL_THREAD_EVENT_EXITED,
- NULL
+ (void *)RTEST(strict)
);
return Qnil;
}
static VALUE
+event_symbol(rb_event_flag_t event)
+{
+ switch (event) {
+ case RUBY_INTERNAL_THREAD_EVENT_STARTED:
+ return rb_id2sym(rb_intern("started"));
+ case RUBY_INTERNAL_THREAD_EVENT_READY:
+ return rb_id2sym(rb_intern("ready"));
+ case RUBY_INTERNAL_THREAD_EVENT_RESUMED:
+ return rb_id2sym(rb_intern("resumed"));
+ case RUBY_INTERNAL_THREAD_EVENT_SUSPENDED:
+ return rb_id2sym(rb_intern("suspended"));
+ case RUBY_INTERNAL_THREAD_EVENT_EXITED:
+ return rb_id2sym(rb_intern("exited"));
+ default:
+ rb_bug("TestThreadInstrumentation: Unexpected event");
+ break;
+ }
+}
+
+static VALUE
thread_unregister_callback(VALUE thread)
{
if (single_hook) {
@@ -106,7 +175,18 @@ thread_unregister_callback(VALUE thread)
single_hook = NULL;
}
- return Qnil;
+ VALUE events = rb_ary_new_capa(timeline_cursor);
+ rb_atomic_t cursor;
+ for (cursor = 0; cursor < timeline_cursor; cursor++) {
+ VALUE pair = rb_ary_new_capa(2);
+ rb_ary_push(pair, event_timeline[cursor].thread);
+ rb_ary_push(pair, event_symbol(event_timeline[cursor].event));
+ rb_ary_push(events, pair);
+ }
+
+ reset_timeline();
+
+ return events;
}
static VALUE
@@ -125,31 +205,16 @@ thread_register_and_unregister_callback(VALUE thread)
return Qtrue;
}
-static VALUE
-thread_last_spawned(VALUE mod)
-{
- return last_thread;
-}
-
-static VALUE
-thread_set_last_spawned(VALUE mod, VALUE value)
-{
- return last_thread = value;
-}
-
void
Init_instrumentation(void)
{
VALUE mBug = rb_define_module("Bug");
VALUE klass = rb_define_module_under(mBug, "ThreadInstrumentation");
+ rb_global_variable(&timeline_value);
+ timeline_value = TypedData_Wrap_Struct(0, &event_timeline_type, 0);
+
rb_global_variable(&last_thread);
- rb_define_singleton_method(klass, "counters", thread_counters, 0);
- rb_define_singleton_method(klass, "local_counters", thread_local_counters, 0);
- rb_define_singleton_method(klass, "reset_counters", thread_reset_counters, 0);
- rb_define_singleton_method(klass, "register_callback", thread_register_callback, 0);
+ rb_define_singleton_method(klass, "register_callback", thread_register_callback, 1);
rb_define_singleton_method(klass, "unregister_callback", thread_unregister_callback, 0);
rb_define_singleton_method(klass, "register_and_unregister_callbacks", thread_register_and_unregister_callback, 0);
-
- rb_define_singleton_method(klass, "last_spawned_thread", thread_last_spawned, 0);
- rb_define_singleton_method(klass, "last_spawned_thread=", thread_set_last_spawned, 1);
}
diff --git a/ext/-test-/thread/lock_native_thread/extconf.rb b/ext/-test-/thread/lock_native_thread/extconf.rb
new file mode 100644
index 0000000000..832bfde01a
--- /dev/null
+++ b/ext/-test-/thread/lock_native_thread/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/thread/lock_native_thread")
diff --git a/ext/-test-/thread/lock_native_thread/lock_native_thread.c b/ext/-test-/thread/lock_native_thread/lock_native_thread.c
new file mode 100644
index 0000000000..2eb75809a9
--- /dev/null
+++ b/ext/-test-/thread/lock_native_thread/lock_native_thread.c
@@ -0,0 +1,50 @@
+
+#include "ruby/ruby.h"
+#include "ruby/thread.h"
+
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+
+static pthread_key_t tls_key;
+
+static VALUE
+get_tls(VALUE self)
+{
+ return (VALUE)pthread_getspecific(tls_key);
+}
+
+static VALUE
+set_tls(VALUE self, VALUE vn)
+{
+ pthread_setspecific(tls_key, (void *)vn);
+ return Qnil;
+}
+
+static VALUE
+lock_native_thread(VALUE self)
+{
+ return rb_thread_lock_native_thread() ? Qtrue : Qfalse;
+}
+
+void
+Init_lock_native_thread(void)
+{
+ int r;
+
+ if ((r = pthread_key_create(&tls_key, NULL)) != 0) {
+ rb_bug("pthread_key_create() returns %d", r);
+ }
+ pthread_setspecific(tls_key, NULL);
+
+ rb_define_method(rb_cThread, "lock_native_thread", lock_native_thread, 0);
+ rb_define_method(rb_cThread, "get_tls", get_tls, 0);
+ rb_define_method(rb_cThread, "set_tls", set_tls, 1);
+}
+
+#else // HAVE_PTHREAD_H
+void
+Init_lock_native_thread(void)
+{
+ // do nothing
+}
+#endif // HAVE_PTHREAD_H
diff --git a/ext/-test-/thread_fd/depend b/ext/-test-/thread_fd/depend
index d4cc772526..0fda9f6dbf 100644
--- a/ext/-test-/thread_fd/depend
+++ b/ext/-test-/thread_fd/depend
@@ -146,6 +146,7 @@ thread_fd.o: $(hdrdir)/ruby/internal/special_consts.h
thread_fd.o: $(hdrdir)/ruby/internal/static_assert.h
thread_fd.o: $(hdrdir)/ruby/internal/stdalign.h
thread_fd.o: $(hdrdir)/ruby/internal/stdbool.h
+thread_fd.o: $(hdrdir)/ruby/internal/stdckdint.h
thread_fd.o: $(hdrdir)/ruby/internal/symbol.h
thread_fd.o: $(hdrdir)/ruby/internal/value.h
thread_fd.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/time/depend b/ext/-test-/time/depend
index c015588b09..5ed791bcc5 100644
--- a/ext/-test-/time/depend
+++ b/ext/-test-/time/depend
@@ -147,6 +147,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h
init.o: $(hdrdir)/ruby/internal/static_assert.h
init.o: $(hdrdir)/ruby/internal/stdalign.h
init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
init.o: $(hdrdir)/ruby/internal/symbol.h
init.o: $(hdrdir)/ruby/internal/value.h
init.o: $(hdrdir)/ruby/internal/value_type.h
@@ -307,6 +308,7 @@ leap_second.o: $(hdrdir)/ruby/internal/special_consts.h
leap_second.o: $(hdrdir)/ruby/internal/static_assert.h
leap_second.o: $(hdrdir)/ruby/internal/stdalign.h
leap_second.o: $(hdrdir)/ruby/internal/stdbool.h
+leap_second.o: $(hdrdir)/ruby/internal/stdckdint.h
leap_second.o: $(hdrdir)/ruby/internal/symbol.h
leap_second.o: $(hdrdir)/ruby/internal/value.h
leap_second.o: $(hdrdir)/ruby/internal/value_type.h
@@ -470,6 +472,7 @@ new.o: $(hdrdir)/ruby/internal/special_consts.h
new.o: $(hdrdir)/ruby/internal/static_assert.h
new.o: $(hdrdir)/ruby/internal/stdalign.h
new.o: $(hdrdir)/ruby/internal/stdbool.h
+new.o: $(hdrdir)/ruby/internal/stdckdint.h
new.o: $(hdrdir)/ruby/internal/symbol.h
new.o: $(hdrdir)/ruby/internal/value.h
new.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/tracepoint/depend b/ext/-test-/tracepoint/depend
index 396004926e..133663b3bd 100644
--- a/ext/-test-/tracepoint/depend
+++ b/ext/-test-/tracepoint/depend
@@ -147,6 +147,7 @@ gc_hook.o: $(hdrdir)/ruby/internal/special_consts.h
gc_hook.o: $(hdrdir)/ruby/internal/static_assert.h
gc_hook.o: $(hdrdir)/ruby/internal/stdalign.h
gc_hook.o: $(hdrdir)/ruby/internal/stdbool.h
+gc_hook.o: $(hdrdir)/ruby/internal/stdckdint.h
gc_hook.o: $(hdrdir)/ruby/internal/symbol.h
gc_hook.o: $(hdrdir)/ruby/internal/value.h
gc_hook.o: $(hdrdir)/ruby/internal/value_type.h
@@ -306,6 +307,7 @@ tracepoint.o: $(hdrdir)/ruby/internal/special_consts.h
tracepoint.o: $(hdrdir)/ruby/internal/static_assert.h
tracepoint.o: $(hdrdir)/ruby/internal/stdalign.h
tracepoint.o: $(hdrdir)/ruby/internal/stdbool.h
+tracepoint.o: $(hdrdir)/ruby/internal/stdckdint.h
tracepoint.o: $(hdrdir)/ruby/internal/symbol.h
tracepoint.o: $(hdrdir)/ruby/internal/value.h
tracepoint.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/tracepoint/gc_hook.c b/ext/-test-/tracepoint/gc_hook.c
index a3f4e7f68a..54c06c54a5 100644
--- a/ext/-test-/tracepoint/gc_hook.c
+++ b/ext/-test-/tracepoint/gc_hook.c
@@ -33,7 +33,9 @@ gc_start_end_i(VALUE tpval, void *data)
}
if (invoking == 0) {
- rb_postponed_job_register(0, invoke_proc, data);
+ /* will overwrite the existing handle with new data on the second and subsequent call */
+ rb_postponed_job_handle_t h = rb_postponed_job_preregister(0, invoke_proc, data);
+ rb_postponed_job_trigger(h);
}
}
diff --git a/ext/-test-/typeddata/depend b/ext/-test-/typeddata/depend
index cbeafa8000..6c0847c82d 100644
--- a/ext/-test-/typeddata/depend
+++ b/ext/-test-/typeddata/depend
@@ -147,6 +147,7 @@ typeddata.o: $(hdrdir)/ruby/internal/special_consts.h
typeddata.o: $(hdrdir)/ruby/internal/static_assert.h
typeddata.o: $(hdrdir)/ruby/internal/stdalign.h
typeddata.o: $(hdrdir)/ruby/internal/stdbool.h
+typeddata.o: $(hdrdir)/ruby/internal/stdckdint.h
typeddata.o: $(hdrdir)/ruby/internal/symbol.h
typeddata.o: $(hdrdir)/ruby/internal/value.h
typeddata.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/vm/depend b/ext/-test-/vm/depend
index f0b3f3b1f4..422b40a32d 100644
--- a/ext/-test-/vm/depend
+++ b/ext/-test-/vm/depend
@@ -146,6 +146,7 @@ at_exit.o: $(hdrdir)/ruby/internal/special_consts.h
at_exit.o: $(hdrdir)/ruby/internal/static_assert.h
at_exit.o: $(hdrdir)/ruby/internal/stdalign.h
at_exit.o: $(hdrdir)/ruby/internal/stdbool.h
+at_exit.o: $(hdrdir)/ruby/internal/stdckdint.h
at_exit.o: $(hdrdir)/ruby/internal/symbol.h
at_exit.o: $(hdrdir)/ruby/internal/value.h
at_exit.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/wait/depend b/ext/-test-/wait/depend
index 2e4887559c..7997a16709 100644
--- a/ext/-test-/wait/depend
+++ b/ext/-test-/wait/depend
@@ -156,6 +156,7 @@ wait.o: $(hdrdir)/ruby/internal/special_consts.h
wait.o: $(hdrdir)/ruby/internal/static_assert.h
wait.o: $(hdrdir)/ruby/internal/stdalign.h
wait.o: $(hdrdir)/ruby/internal/stdbool.h
+wait.o: $(hdrdir)/ruby/internal/stdckdint.h
wait.o: $(hdrdir)/ruby/internal/symbol.h
wait.o: $(hdrdir)/ruby/internal/value.h
wait.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
deleted file mode 100644
index 07c2bcf0b5..0000000000
--- a/ext/bigdecimal/bigdecimal.c
+++ /dev/null
@@ -1,7725 +0,0 @@
-/*
- *
- * Ruby BigDecimal(Variable decimal precision) extension library.
- *
- * Copyright(C) 2002 by Shigeo Kobayashi(shigeo@tinyforest.gr.jp)
- *
- */
-
-/* #define BIGDECIMAL_DEBUG 1 */
-
-#include "bigdecimal.h"
-#include "ruby/util.h"
-
-#ifndef BIGDECIMAL_DEBUG
-# undef NDEBUG
-# define NDEBUG
-#endif
-#include <assert.h>
-
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <math.h>
-
-#ifdef HAVE_IEEEFP_H
-#include <ieeefp.h>
-#endif
-
-#include "bits.h"
-#include "static_assert.h"
-
-#define BIGDECIMAL_VERSION "3.1.5"
-
-/* #define ENABLE_NUMERIC_STRING */
-
-#define SIGNED_VALUE_MAX INTPTR_MAX
-#define SIGNED_VALUE_MIN INTPTR_MIN
-#define MUL_OVERFLOW_SIGNED_VALUE_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, SIGNED_VALUE_MIN, SIGNED_VALUE_MAX)
-
-VALUE rb_cBigDecimal;
-VALUE rb_mBigMath;
-
-static ID id_BigDecimal_exception_mode;
-static ID id_BigDecimal_rounding_mode;
-static ID id_BigDecimal_precision_limit;
-
-static ID id_up;
-static ID id_down;
-static ID id_truncate;
-static ID id_half_up;
-static ID id_default;
-static ID id_half_down;
-static ID id_half_even;
-static ID id_banker;
-static ID id_ceiling;
-static ID id_ceil;
-static ID id_floor;
-static ID id_to_r;
-static ID id_eq;
-static ID id_half;
-
-#define RBD_NUM_ROUNDING_MODES 11
-
-static struct {
- ID id;
- uint8_t mode;
-} rbd_rounding_modes[RBD_NUM_ROUNDING_MODES];
-
-/* MACRO's to guard objects from GC by keeping them in stack */
-#ifdef RBIMPL_ATTR_MAYBE_UNUSED
-#define ENTER(n) RBIMPL_ATTR_MAYBE_UNUSED() volatile VALUE vStack[n];int iStack=0
-#else
-#define ENTER(n) volatile VALUE RB_UNUSED_VAR(vStack[n]);int iStack=0
-#endif
-#define PUSH(x) (vStack[iStack++] = (VALUE)(x))
-#define SAVE(p) PUSH((p)->obj)
-#define GUARD_OBJ(p,y) ((p)=(y), SAVE(p))
-
-#define BASE_FIG BIGDECIMAL_COMPONENT_FIGURES
-#define BASE BIGDECIMAL_BASE
-
-#define HALF_BASE (BASE/2)
-#define BASE1 (BASE/10)
-
-#define LOG10_2 0.3010299956639812
-
-#ifndef RRATIONAL_ZERO_P
-# define RRATIONAL_ZERO_P(x) (FIXNUM_P(rb_rational_num(x)) && \
- FIX2LONG(rb_rational_num(x)) == 0)
-#endif
-
-#ifndef RRATIONAL_NEGATIVE_P
-# define RRATIONAL_NEGATIVE_P(x) RTEST(rb_funcall((x), '<', 1, INT2FIX(0)))
-#endif
-
-#ifndef DECIMAL_SIZE_OF_BITS
-#define DECIMAL_SIZE_OF_BITS(n) (((n) * 3010 + 9998) / 9999)
-/* an approximation of ceil(n * log10(2)), upto 65536 at least */
-#endif
-
-#ifdef PRIsVALUE
-# define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj)
-# define RB_OBJ_STRING(obj) (obj)
-#else
-# define PRIsVALUE "s"
-# define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj)
-# define RB_OBJ_STRING(obj) StringValueCStr(obj)
-#endif
-
-#ifndef MAYBE_UNUSED
-# define MAYBE_UNUSED(x) x
-#endif
-
-#define BIGDECIMAL_POSITIVE_P(bd) ((bd)->sign > 0)
-#define BIGDECIMAL_NEGATIVE_P(bd) ((bd)->sign < 0)
-
-/*
- * ================== Memory allocation ============================
- */
-
-#ifdef BIGDECIMAL_DEBUG
-static size_t rbd_allocation_count = 0; /* Memory allocation counter */
-static inline void
-atomic_allocation_count_inc(void)
-{
- RUBY_ATOMIC_SIZE_INC(rbd_allocation_count);
-}
-static inline void
-atomic_allocation_count_dec_nounderflow(void)
-{
- if (rbd_allocation_count == 0) return;
- RUBY_ATOMIC_SIZE_DEC(rbd_allocation_count);
-}
-static void
-check_allocation_count_nonzero(void)
-{
- if (rbd_allocation_count != 0) return;
- rb_bug("[bigdecimal][rbd_free_struct] Too many memory free calls");
-}
-#else
-# define atomic_allocation_count_inc() /* nothing */
-# define atomic_allocation_count_dec_nounderflow() /* nothing */
-# define check_allocation_count_nonzero() /* nothing */
-#endif /* BIGDECIMAL_DEBUG */
-
-PUREFUNC(static inline size_t rbd_struct_size(size_t const));
-
-static inline size_t
-rbd_struct_size(size_t const internal_digits)
-{
- size_t const frac_len = (internal_digits == 0) ? 1 : internal_digits;
- return offsetof(Real, frac) + frac_len * sizeof(DECDIG);
-}
-
-static inline Real *
-rbd_allocate_struct(size_t const internal_digits)
-{
- size_t const size = rbd_struct_size(internal_digits);
- Real *real = ruby_xcalloc(1, size);
- atomic_allocation_count_inc();
- real->MaxPrec = internal_digits;
- return real;
-}
-
-static size_t
-rbd_calculate_internal_digits(size_t const digits, bool limit_precision)
-{
- size_t const len = roomof(digits, BASE_FIG);
- if (limit_precision) {
- size_t const prec_limit = VpGetPrecLimit();
- if (prec_limit > 0) {
- /* NOTE: 2 more digits for rounding and division */
- size_t const max_len = roomof(prec_limit, BASE_FIG) + 2;
- if (len > max_len)
- return max_len;
- }
- }
-
- return len;
-}
-
-static inline Real *
-rbd_allocate_struct_decimal_digits(size_t const decimal_digits, bool limit_precision)
-{
- size_t const internal_digits = rbd_calculate_internal_digits(decimal_digits, limit_precision);
- return rbd_allocate_struct(internal_digits);
-}
-
-static VALUE BigDecimal_wrap_struct(VALUE obj, Real *vp);
-
-static Real *
-rbd_reallocate_struct(Real *real, size_t const internal_digits)
-{
- size_t const size = rbd_struct_size(internal_digits);
- VALUE obj = real ? real->obj : 0;
- Real *new_real = (Real *)ruby_xrealloc(real, size);
- new_real->MaxPrec = internal_digits;
- if (obj) {
- new_real->obj = 0;
- BigDecimal_wrap_struct(obj, new_real);
- }
- return new_real;
-}
-
-static void
-rbd_free_struct(Real *real)
-{
- if (real != NULL) {
- check_allocation_count_nonzero();
- ruby_xfree(real);
- atomic_allocation_count_dec_nounderflow();
- }
-}
-
-#define NewZero rbd_allocate_struct_zero
-static Real *
-rbd_allocate_struct_zero(int sign, size_t const digits, bool limit_precision)
-{
- Real *real = rbd_allocate_struct_decimal_digits(digits, limit_precision);
- VpSetZero(real, sign);
- return real;
-}
-
-MAYBE_UNUSED(static inline Real * rbd_allocate_struct_zero_limited(int sign, size_t const digits));
-#define NewZeroLimited rbd_allocate_struct_zero_limited
-static inline Real *
-rbd_allocate_struct_zero_limited(int sign, size_t const digits)
-{
- return rbd_allocate_struct_zero(sign, digits, true);
-}
-
-MAYBE_UNUSED(static inline Real * rbd_allocate_struct_zero_nolimit(int sign, size_t const digits));
-#define NewZeroNolimit rbd_allocate_struct_zero_nolimit
-static inline Real *
-rbd_allocate_struct_zero_nolimit(int sign, size_t const digits)
-{
- return rbd_allocate_struct_zero(sign, digits, false);
-}
-
-#define NewOne rbd_allocate_struct_one
-static Real *
-rbd_allocate_struct_one(int sign, size_t const digits, bool limit_precision)
-{
- Real *real = rbd_allocate_struct_decimal_digits(digits, limit_precision);
- VpSetOne(real);
- if (sign < 0)
- VpSetSign(real, VP_SIGN_NEGATIVE_FINITE);
- return real;
-}
-
-MAYBE_UNUSED(static inline Real * rbd_allocate_struct_one_limited(int sign, size_t const digits));
-#define NewOneLimited rbd_allocate_struct_one_limited
-static inline Real *
-rbd_allocate_struct_one_limited(int sign, size_t const digits)
-{
- return rbd_allocate_struct_one(sign, digits, true);
-}
-
-MAYBE_UNUSED(static inline Real * rbd_allocate_struct_one_nolimit(int sign, size_t const digits));
-#define NewOneNolimit rbd_allocate_struct_one_nolimit
-static inline Real *
-rbd_allocate_struct_one_nolimit(int sign, size_t const digits)
-{
- return rbd_allocate_struct_one(sign, digits, false);
-}
-
-/*
- * ================== Ruby Interface part ==========================
- */
-#define DoSomeOne(x,y,f) rb_num_coerce_bin(x,y,f)
-
-/*
- * VP routines used in BigDecimal part
- */
-static unsigned short VpGetException(void);
-static void VpSetException(unsigned short f);
-static void VpCheckException(Real *p, bool always);
-static VALUE VpCheckGetValue(Real *p);
-static void VpInternalRound(Real *c, size_t ixDigit, DECDIG vPrev, DECDIG v);
-static int VpLimitRound(Real *c, size_t ixDigit);
-static Real *VpCopy(Real *pv, Real const* const x);
-static int VPrint(FILE *fp,const char *cntl_chr,Real *a);
-
-/*
- * **** BigDecimal part ****
- */
-
-static VALUE BigDecimal_nan(void);
-static VALUE BigDecimal_positive_infinity(void);
-static VALUE BigDecimal_negative_infinity(void);
-static VALUE BigDecimal_positive_zero(void);
-static VALUE BigDecimal_negative_zero(void);
-
-static void
-BigDecimal_delete(void *pv)
-{
- rbd_free_struct(pv);
-}
-
-static size_t
-BigDecimal_memsize(const void *ptr)
-{
- const Real *pv = ptr;
- return (sizeof(*pv) + pv->MaxPrec * sizeof(DECDIG));
-}
-
-#ifndef HAVE_RB_EXT_RACTOR_SAFE
-# undef RUBY_TYPED_FROZEN_SHAREABLE
-# define RUBY_TYPED_FROZEN_SHAREABLE 0
-#endif
-
-static const rb_data_type_t BigDecimal_data_type = {
- "BigDecimal",
- { 0, BigDecimal_delete, BigDecimal_memsize, },
-#ifdef RUBY_TYPED_FREE_IMMEDIATELY
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE | RUBY_TYPED_WB_PROTECTED
-#endif
-};
-
-static Real *
-rbd_allocate_struct_zero_wrap_klass(VALUE klass, int sign, size_t const digits, bool limit_precision)
-{
- Real *real = rbd_allocate_struct_zero(sign, digits, limit_precision);
- if (real != NULL) {
- VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
- BigDecimal_wrap_struct(obj, real);
- }
- return real;
-}
-
-MAYBE_UNUSED(static inline Real * rbd_allocate_struct_zero_limited_wrap(int sign, size_t const digits));
-#define NewZeroWrapLimited rbd_allocate_struct_zero_limited_wrap
-static inline Real *
-rbd_allocate_struct_zero_limited_wrap(int sign, size_t const digits)
-{
- return rbd_allocate_struct_zero_wrap_klass(rb_cBigDecimal, sign, digits, true);
-}
-
-MAYBE_UNUSED(static inline Real * rbd_allocate_struct_zero_nolimit_wrap(int sign, size_t const digits));
-#define NewZeroWrapNolimit rbd_allocate_struct_zero_nolimit_wrap
-static inline Real *
-rbd_allocate_struct_zero_nolimit_wrap(int sign, size_t const digits)
-{
- return rbd_allocate_struct_zero_wrap_klass(rb_cBigDecimal, sign, digits, false);
-}
-
-static Real *
-rbd_allocate_struct_one_wrap_klass(VALUE klass, int sign, size_t const digits, bool limit_precision)
-{
- Real *real = rbd_allocate_struct_one(sign, digits, limit_precision);
- if (real != NULL) {
- VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
- BigDecimal_wrap_struct(obj, real);
- }
- return real;
-}
-
-MAYBE_UNUSED(static inline Real * rbd_allocate_struct_one_limited_wrap(int sign, size_t const digits));
-#define NewOneWrapLimited rbd_allocate_struct_one_limited_wrap
-static inline Real *
-rbd_allocate_struct_one_limited_wrap(int sign, size_t const digits)
-{
- return rbd_allocate_struct_one_wrap_klass(rb_cBigDecimal, sign, digits, true);
-}
-
-MAYBE_UNUSED(static inline Real * rbd_allocate_struct_one_nolimit_wrap(int sign, size_t const digits));
-#define NewOneWrapNolimit rbd_allocate_struct_one_nolimit_wrap
-static inline Real *
-rbd_allocate_struct_one_nolimit_wrap(int sign, size_t const digits)
-{
- return rbd_allocate_struct_one_wrap_klass(rb_cBigDecimal, sign, digits, false);
-}
-
-static inline int
-is_kind_of_BigDecimal(VALUE const v)
-{
- return rb_typeddata_is_kind_of(v, &BigDecimal_data_type);
-}
-
-NORETURN(static void cannot_be_coerced_into_BigDecimal(VALUE, VALUE));
-
-static void
-cannot_be_coerced_into_BigDecimal(VALUE exc_class, VALUE v)
-{
- VALUE str;
-
- if (rb_special_const_p(v)) {
- str = rb_inspect(v);
- }
- else {
- str = rb_class_name(rb_obj_class(v));
- }
-
- str = rb_str_cat2(rb_str_dup(str), " can't be coerced into BigDecimal");
- rb_exc_raise(rb_exc_new3(exc_class, str));
-}
-
-static inline VALUE BigDecimal_div2(VALUE, VALUE, VALUE);
-static VALUE rb_inum_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception);
-static VALUE rb_float_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception);
-static VALUE rb_rational_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception);
-static VALUE rb_cstr_convert_to_BigDecimal(const char *c_str, size_t digs, int raise_exception);
-static VALUE rb_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception);
-
-static Real*
-GetVpValueWithPrec(VALUE v, long prec, int must)
-{
- const size_t digs = prec < 0 ? SIZE_MAX : (size_t)prec;
-
- switch(TYPE(v)) {
- case T_FLOAT:
- v = rb_float_convert_to_BigDecimal(v, digs, must);
- break;
-
- case T_RATIONAL:
- v = rb_rational_convert_to_BigDecimal(v, digs, must);
- break;
-
- case T_DATA:
- if (!is_kind_of_BigDecimal(v)) {
- goto SomeOneMayDoIt;
- }
- break;
-
- case T_FIXNUM: {
- char szD[128];
- snprintf(szD, 128, "%ld", FIX2LONG(v));
- v = rb_cstr_convert_to_BigDecimal(szD, VpBaseFig() * 2 + 1, must);
- break;
- }
-
-#ifdef ENABLE_NUMERIC_STRING
- case T_STRING: {
- const char *c_str = StringValueCStr(v);
- v = rb_cstr_convert_to_BigDecimal(c_str, RSTRING_LEN(v) + VpBaseFig() + 1, must);
- break;
- }
-#endif /* ENABLE_NUMERIC_STRING */
-
- case T_BIGNUM: {
- VALUE bg = rb_big2str(v, 10);
- v = rb_cstr_convert_to_BigDecimal(RSTRING_PTR(bg), RSTRING_LEN(bg) + VpBaseFig() + 1, must);
- RB_GC_GUARD(bg);
- break;
- }
-
- default:
- goto SomeOneMayDoIt;
- }
-
- Real *vp;
- TypedData_Get_Struct(v, Real, &BigDecimal_data_type, vp);
- return vp;
-
-SomeOneMayDoIt:
- if (must) {
- cannot_be_coerced_into_BigDecimal(rb_eTypeError, v);
- }
- return NULL; /* NULL means to coerce */
-}
-
-static inline Real*
-GetVpValue(VALUE v, int must)
-{
- return GetVpValueWithPrec(v, -1, must);
-}
-
-/* call-seq:
- * BigDecimal.double_fig -> integer
- *
- * Returns the number of digits a Float object is allowed to have;
- * the result is system-dependent:
- *
- * BigDecimal.double_fig # => 16
- *
- */
-static inline VALUE
-BigDecimal_double_fig(VALUE self)
-{
- return INT2FIX(VpDblFig());
-}
-
-/* call-seq:
- * precs -> array
- *
- * Returns an Array of two Integer values that represent platform-dependent
- * internal storage properties.
- *
- * This method is deprecated and will be removed in the future.
- * Instead, use BigDecimal#n_significant_digits for obtaining the number of
- * significant digits in scientific notation, and BigDecimal#precision for
- * obtaining the number of digits in decimal notation.
- *
- */
-
-static VALUE
-BigDecimal_prec(VALUE self)
-{
- ENTER(1);
- Real *p;
- VALUE obj;
-
- rb_category_warn(RB_WARN_CATEGORY_DEPRECATED,
- "BigDecimal#precs is deprecated and will be removed in the future; "
- "use BigDecimal#precision instead.");
-
- GUARD_OBJ(p, GetVpValue(self, 1));
- obj = rb_assoc_new(SIZET2NUM(p->Prec*VpBaseFig()),
- SIZET2NUM(p->MaxPrec*VpBaseFig()));
- return obj;
-}
-
-static void
-BigDecimal_count_precision_and_scale(VALUE self, ssize_t *out_precision, ssize_t *out_scale)
-{
- ENTER(1);
-
- if (out_precision == NULL && out_scale == NULL)
- return;
-
- Real *p;
- GUARD_OBJ(p, GetVpValue(self, 1));
- if (VpIsZero(p) || !VpIsDef(p)) {
- zero:
- if (out_precision) *out_precision = 0;
- if (out_scale) *out_scale = 0;
- return;
- }
-
- DECDIG x;
-
- ssize_t n = p->Prec; /* The length of frac without zeros. */
- while (n > 0 && p->frac[n-1] == 0) --n;
- if (n == 0) goto zero;
-
- int nlz = BASE_FIG;
- for (x = p->frac[0]; x > 0; x /= 10) --nlz;
-
- int ntz = 0;
- for (x = p->frac[n-1]; x > 0 && x % 10 == 0; x /= 10) ++ntz;
-
- /*
- * Calculate the precision and the scale
- * -------------------------------------
- *
- * The most significant digit is frac[0], and the least significant digit
- * is frac[Prec-1]. When the exponent is zero, the decimal point is
- * located just before frac[0].
- *
- * When the exponent is negative, the decimal point moves to leftward.
- * In this case, the precision can be calculated by
- *
- * precision = BASE_FIG * (-exponent + n) - ntz,
- *
- * and the scale is the same as precision.
- *
- * 0 . 0000 0000 | frac[0] ... frac[n-1] |
- * |<----------| exponent == -2 |
- * |---------------------------------->| precision
- * |---------------------------------->| scale
- *
- *
- * Conversely, when the exponent is positive, the decimal point moves to
- * rightward. In this case, the scale equals to
- *
- * BASE_FIG * (n - exponent) - ntz.
- *
- * the precision equals to
- *
- * scale + BASE_FIG * exponent - nlz.
- *
- * | frac[0] frac[1] . frac[2] ... frac[n-1] |
- * |---------------->| exponent == 2 |
- * | |---------------------->| scale
- * |---------------------------------------->| precision
- */
-
- ssize_t ex = p->exponent;
-
- /* Count the number of decimal digits before frac[1]. */
- ssize_t n_digits_head = BASE_FIG;
- if (ex < 0) {
- n_digits_head += (-ex) * BASE_FIG; /* The number of leading zeros before frac[0]. */
- ex = 0;
- }
- else if (ex > 0) {
- /* Count the number of decimal digits without the leading zeros in
- * the most significant digit in the integral part.
- */
- n_digits_head -= nlz; /* Make the number of digits */
- }
-
- if (out_precision) {
- ssize_t precision = n_digits_head;
-
- /* Count the number of decimal digits after frac[0]. */
- if (ex > (ssize_t)n) {
- /* In this case the number is an integer with some trailing zeros. */
- precision += (ex - 1) * BASE_FIG;
- }
- else if (n > 0) {
- precision += (n - 1) * BASE_FIG;
-
- if (ex < (ssize_t)n) {
- precision -= ntz;
- }
- }
-
- *out_precision = precision;
- }
-
- if (out_scale) {
- ssize_t scale = 0;
-
- if (p->exponent < 0) {
- scale = n_digits_head + (n - 1) * BASE_FIG - ntz;
- }
- else if (n > p->exponent) {
- scale = (n - p->exponent) * BASE_FIG - ntz;
- }
-
- *out_scale = scale;
- }
-}
-
-/*
- * call-seq:
- * precision -> integer
- *
- * Returns the number of decimal digits in +self+:
- *
- * BigDecimal("0").precision # => 0
- * BigDecimal("1").precision # => 1
- * BigDecimal("1.1").precision # => 2
- * BigDecimal("3.1415").precision # => 5
- * BigDecimal("-1e20").precision # => 21
- * BigDecimal("1e-20").precision # => 20
- * BigDecimal("Infinity").precision # => 0
- * BigDecimal("-Infinity").precision # => 0
- * BigDecimal("NaN").precision # => 0
- *
- */
-static VALUE
-BigDecimal_precision(VALUE self)
-{
- ssize_t precision;
- BigDecimal_count_precision_and_scale(self, &precision, NULL);
- return SSIZET2NUM(precision);
-}
-
-/*
- * call-seq:
- * scale -> integer
- *
- * Returns the number of decimal digits following the decimal digits in +self+.
- *
- * BigDecimal("0").scale # => 0
- * BigDecimal("1").scale # => 0
- * BigDecimal("1.1").scale # => 1
- * BigDecimal("3.1415").scale # => 4
- * BigDecimal("-1e20").precision # => 0
- * BigDecimal("1e-20").precision # => 20
- * BigDecimal("Infinity").scale # => 0
- * BigDecimal("-Infinity").scale # => 0
- * BigDecimal("NaN").scale # => 0
- */
-static VALUE
-BigDecimal_scale(VALUE self)
-{
- ssize_t scale;
- BigDecimal_count_precision_and_scale(self, NULL, &scale);
- return SSIZET2NUM(scale);
-}
-
-/*
- * call-seq:
- * precision_scale -> [integer, integer]
- *
- * Returns a 2-length array; the first item is the result of
- * BigDecimal#precision and the second one is of BigDecimal#scale.
- *
- * See BigDecimal#precision.
- * See BigDecimal#scale.
- */
-static VALUE
-BigDecimal_precision_scale(VALUE self)
-{
- ssize_t precision, scale;
- BigDecimal_count_precision_and_scale(self, &precision, &scale);
- return rb_assoc_new(SSIZET2NUM(precision), SSIZET2NUM(scale));
-}
-
-/*
- * call-seq:
- * n_significant_digits -> integer
- *
- * Returns the number of decimal significant digits in +self+.
- *
- * BigDecimal("0").n_significant_digits # => 0
- * BigDecimal("1").n_significant_digits # => 1
- * BigDecimal("1.1").n_significant_digits # => 2
- * BigDecimal("3.1415").n_significant_digits # => 5
- * BigDecimal("-1e20").n_significant_digits # => 1
- * BigDecimal("1e-20").n_significant_digits # => 1
- * BigDecimal("Infinity").n_significant_digits # => 0
- * BigDecimal("-Infinity").n_significant_digits # => 0
- * BigDecimal("NaN").n_significant_digits # => 0
- */
-static VALUE
-BigDecimal_n_significant_digits(VALUE self)
-{
- ENTER(1);
-
- Real *p;
- GUARD_OBJ(p, GetVpValue(self, 1));
- if (VpIsZero(p) || !VpIsDef(p)) {
- return INT2FIX(0);
- }
-
- ssize_t n = p->Prec; /* The length of frac without trailing zeros. */
- for (n = p->Prec; n > 0 && p->frac[n-1] == 0; --n);
- if (n == 0) return INT2FIX(0);
-
- DECDIG x;
- int nlz = BASE_FIG;
- for (x = p->frac[0]; x > 0; x /= 10) --nlz;
-
- int ntz = 0;
- for (x = p->frac[n-1]; x > 0 && x % 10 == 0; x /= 10) ++ntz;
-
- ssize_t n_significant_digits = BASE_FIG*n - nlz - ntz;
- return SSIZET2NUM(n_significant_digits);
-}
-
-/*
- * call-seq:
- * hash -> integer
- *
- * Returns the integer hash value for +self+.
- *
- * Two instances of \BigDecimal have the same hash value if and only if
- * they have equal:
- *
- * - Sign.
- * - Fractional part.
- * - Exponent.
- *
- */
-static VALUE
-BigDecimal_hash(VALUE self)
-{
- ENTER(1);
- Real *p;
- st_index_t hash;
-
- GUARD_OBJ(p, GetVpValue(self, 1));
- hash = (st_index_t)p->sign;
- /* hash!=2: the case for 0(1),NaN(0) or +-Infinity(3) is sign itself */
- if(hash == 2 || hash == (st_index_t)-2) {
- hash ^= rb_memhash(p->frac, sizeof(DECDIG)*p->Prec);
- hash += p->exponent;
- }
- return ST2FIX(hash);
-}
-
-/*
- * call-seq:
- * _dump -> string
- *
- * Returns a string representing the marshalling of +self+.
- * See module Marshal.
- *
- * inf = BigDecimal('Infinity') # => Infinity
- * dumped = inf._dump # => "9:Infinity"
- * BigDecimal._load(dumped) # => Infinity
- *
- */
-static VALUE
-BigDecimal_dump(int argc, VALUE *argv, VALUE self)
-{
- ENTER(5);
- Real *vp;
- char *psz;
- VALUE dummy;
- volatile VALUE dump;
- size_t len;
-
- rb_scan_args(argc, argv, "01", &dummy);
- GUARD_OBJ(vp,GetVpValue(self, 1));
- dump = rb_str_new(0, VpNumOfChars(vp, "E")+50);
- psz = RSTRING_PTR(dump);
- snprintf(psz, RSTRING_LEN(dump), "%"PRIuSIZE":", VpMaxPrec(vp)*VpBaseFig());
- len = strlen(psz);
- VpToString(vp, psz+len, RSTRING_LEN(dump)-len, 0, 0);
- rb_str_resize(dump, strlen(psz));
- return dump;
-}
-
-/*
- * Internal method used to provide marshalling support. See the Marshal module.
- */
-static VALUE
-BigDecimal_load(VALUE self, VALUE str)
-{
- ENTER(2);
- Real *pv;
- unsigned char *pch;
- unsigned char ch;
- unsigned long m=0;
-
- pch = (unsigned char *)StringValueCStr(str);
- /* First get max prec */
- while((*pch) != (unsigned char)'\0' && (ch = *pch++) != (unsigned char)':') {
- if(!ISDIGIT(ch)) {
- rb_raise(rb_eTypeError, "load failed: invalid character in the marshaled string");
- }
- m = m*10 + (unsigned long)(ch-'0');
- }
- if (m > VpBaseFig()) m -= VpBaseFig();
- GUARD_OBJ(pv, VpNewRbClass(m, (char *)pch, self, true, true));
- m /= VpBaseFig();
- if (m && pv->MaxPrec > m) {
- pv->MaxPrec = m+1;
- }
- return VpCheckGetValue(pv);
-}
-
-static unsigned short
-check_rounding_mode_option(VALUE const opts)
-{
- VALUE mode;
- char const *s;
- long l;
-
- assert(RB_TYPE_P(opts, T_HASH));
-
- if (NIL_P(opts))
- goto no_opt;
-
- mode = rb_hash_lookup2(opts, ID2SYM(id_half), Qundef);
- if (mode == Qundef || NIL_P(mode))
- goto no_opt;
-
- if (SYMBOL_P(mode))
- mode = rb_sym2str(mode);
- else if (!RB_TYPE_P(mode, T_STRING)) {
- VALUE str_mode = rb_check_string_type(mode);
- if (NIL_P(str_mode))
- goto invalid;
- mode = str_mode;
- }
- s = RSTRING_PTR(mode);
- l = RSTRING_LEN(mode);
- switch (l) {
- case 2:
- if (strncasecmp(s, "up", 2) == 0)
- return VP_ROUND_HALF_UP;
- break;
- case 4:
- if (strncasecmp(s, "even", 4) == 0)
- return VP_ROUND_HALF_EVEN;
- else if (strncasecmp(s, "down", 4) == 0)
- return VP_ROUND_HALF_DOWN;
- break;
- default:
- break;
- }
-
- invalid:
- rb_raise(rb_eArgError, "invalid rounding mode (%"PRIsVALUE")", mode);
-
- no_opt:
- return VpGetRoundMode();
-}
-
-static unsigned short
-check_rounding_mode(VALUE const v)
-{
- unsigned short sw;
- ID id;
- if (RB_TYPE_P(v, T_SYMBOL)) {
- int i;
- id = SYM2ID(v);
- for (i = 0; i < RBD_NUM_ROUNDING_MODES; ++i) {
- if (rbd_rounding_modes[i].id == id) {
- return rbd_rounding_modes[i].mode;
- }
- }
- rb_raise(rb_eArgError, "invalid rounding mode (%"PRIsVALUE")", v);
- }
- else {
- sw = NUM2USHORT(v);
- if (!VpIsRoundMode(sw)) {
- rb_raise(rb_eArgError, "invalid rounding mode (%"PRIsVALUE")", v);
- }
- return sw;
- }
-}
-
-/* call-seq:
- * BigDecimal.mode(mode, setting = nil) -> integer
- *
- * Returns an integer representing the mode settings
- * for exception handling and rounding.
- *
- * These modes control exception handling:
- *
- * - \BigDecimal::EXCEPTION_NaN.
- * - \BigDecimal::EXCEPTION_INFINITY.
- * - \BigDecimal::EXCEPTION_UNDERFLOW.
- * - \BigDecimal::EXCEPTION_OVERFLOW.
- * - \BigDecimal::EXCEPTION_ZERODIVIDE.
- * - \BigDecimal::EXCEPTION_ALL.
- *
- * Values for +setting+ for exception handling:
- *
- * - +true+: sets the given +mode+ to +true+.
- * - +false+: sets the given +mode+ to +false+.
- * - +nil+: does not modify the mode settings.
- *
- * You can use method BigDecimal.save_exception_mode
- * to temporarily change, and then automatically restore, exception modes.
- *
- * For clarity, some examples below begin by setting all
- * exception modes to +false+.
- *
- * This mode controls the way rounding is to be performed:
- *
- * - \BigDecimal::ROUND_MODE
- *
- * You can use method BigDecimal.save_rounding_mode
- * to temporarily change, and then automatically restore, the rounding mode.
- *
- * <b>NaNs</b>
- *
- * Mode \BigDecimal::EXCEPTION_NaN controls behavior
- * when a \BigDecimal NaN is created.
- *
- * Settings:
- *
- * - +false+ (default): Returns <tt>BigDecimal('NaN')</tt>.
- * - +true+: Raises FloatDomainError.
- *
- * Examples:
- *
- * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0
- * BigDecimal('NaN') # => NaN
- * BigDecimal.mode(BigDecimal::EXCEPTION_NaN, true) # => 2
- * BigDecimal('NaN') # Raises FloatDomainError
- *
- * <b>Infinities</b>
- *
- * Mode \BigDecimal::EXCEPTION_INFINITY controls behavior
- * when a \BigDecimal Infinity or -Infinity is created.
- * Settings:
- *
- * - +false+ (default): Returns <tt>BigDecimal('Infinity')</tt>
- * or <tt>BigDecimal('-Infinity')</tt>.
- * - +true+: Raises FloatDomainError.
- *
- * Examples:
- *
- * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0
- * BigDecimal('Infinity') # => Infinity
- * BigDecimal('-Infinity') # => -Infinity
- * BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, true) # => 1
- * BigDecimal('Infinity') # Raises FloatDomainError
- * BigDecimal('-Infinity') # Raises FloatDomainError
- *
- * <b>Underflow</b>
- *
- * Mode \BigDecimal::EXCEPTION_UNDERFLOW controls behavior
- * when a \BigDecimal underflow occurs.
- * Settings:
- *
- * - +false+ (default): Returns <tt>BigDecimal('0')</tt>
- * or <tt>BigDecimal('-Infinity')</tt>.
- * - +true+: Raises FloatDomainError.
- *
- * Examples:
- *
- * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0
- * def flow_under
- * x = BigDecimal('0.1')
- * 100.times { x *= x }
- * end
- * flow_under # => 100
- * BigDecimal.mode(BigDecimal::EXCEPTION_UNDERFLOW, true) # => 4
- * flow_under # Raises FloatDomainError
- *
- * <b>Overflow</b>
- *
- * Mode \BigDecimal::EXCEPTION_OVERFLOW controls behavior
- * when a \BigDecimal overflow occurs.
- * Settings:
- *
- * - +false+ (default): Returns <tt>BigDecimal('Infinity')</tt>
- * or <tt>BigDecimal('-Infinity')</tt>.
- * - +true+: Raises FloatDomainError.
- *
- * Examples:
- *
- * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0
- * def flow_over
- * x = BigDecimal('10')
- * 100.times { x *= x }
- * end
- * flow_over # => 100
- * BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, true) # => 1
- * flow_over # Raises FloatDomainError
- *
- * <b>Zero Division</b>
- *
- * Mode \BigDecimal::EXCEPTION_ZERODIVIDE controls behavior
- * when a zero-division occurs.
- * Settings:
- *
- * - +false+ (default): Returns <tt>BigDecimal('Infinity')</tt>
- * or <tt>BigDecimal('-Infinity')</tt>.
- * - +true+: Raises FloatDomainError.
- *
- * Examples:
- *
- * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0
- * one = BigDecimal('1')
- * zero = BigDecimal('0')
- * one / zero # => Infinity
- * BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, true) # => 16
- * one / zero # Raises FloatDomainError
- *
- * <b>All Exceptions</b>
- *
- * Mode \BigDecimal::EXCEPTION_ALL controls all of the above:
- *
- * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0
- * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, true) # => 23
- *
- * <b>Rounding</b>
- *
- * Mode \BigDecimal::ROUND_MODE controls the way rounding is to be performed;
- * its +setting+ values are:
- *
- * - +ROUND_UP+: Round away from zero.
- * Aliased as +:up+.
- * - +ROUND_DOWN+: Round toward zero.
- * Aliased as +:down+ and +:truncate+.
- * - +ROUND_HALF_UP+: Round toward the nearest neighbor;
- * if the neighbors are equidistant, round away from zero.
- * Aliased as +:half_up+ and +:default+.
- * - +ROUND_HALF_DOWN+: Round toward the nearest neighbor;
- * if the neighbors are equidistant, round toward zero.
- * Aliased as +:half_down+.
- * - +ROUND_HALF_EVEN+ (Banker's rounding): Round toward the nearest neighbor;
- * if the neighbors are equidistant, round toward the even neighbor.
- * Aliased as +:half_even+ and +:banker+.
- * - +ROUND_CEILING+: Round toward positive infinity.
- * Aliased as +:ceiling+ and +:ceil+.
- * - +ROUND_FLOOR+: Round toward negative infinity.
- * Aliased as +:floor:+.
- *
- */
-static VALUE
-BigDecimal_mode(int argc, VALUE *argv, VALUE self)
-{
- VALUE which;
- VALUE val;
- unsigned long f,fo;
-
- rb_scan_args(argc, argv, "11", &which, &val);
- f = (unsigned long)NUM2INT(which);
-
- if (f & VP_EXCEPTION_ALL) {
- /* Exception mode setting */
- fo = VpGetException();
- if (val == Qnil) return INT2FIX(fo);
- if (val != Qfalse && val!=Qtrue) {
- rb_raise(rb_eArgError, "second argument must be true or false");
- return Qnil; /* Not reached */
- }
- if (f & VP_EXCEPTION_INFINITY) {
- VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_INFINITY) :
- (fo & (~VP_EXCEPTION_INFINITY))));
- }
- fo = VpGetException();
- if (f & VP_EXCEPTION_NaN) {
- VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_NaN) :
- (fo & (~VP_EXCEPTION_NaN))));
- }
- fo = VpGetException();
- if (f & VP_EXCEPTION_UNDERFLOW) {
- VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_UNDERFLOW) :
- (fo & (~VP_EXCEPTION_UNDERFLOW))));
- }
- fo = VpGetException();
- if(f & VP_EXCEPTION_ZERODIVIDE) {
- VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_ZERODIVIDE) :
- (fo & (~VP_EXCEPTION_ZERODIVIDE))));
- }
- fo = VpGetException();
- return INT2FIX(fo);
- }
- if (VP_ROUND_MODE == f) {
- /* Rounding mode setting */
- unsigned short sw;
- fo = VpGetRoundMode();
- if (NIL_P(val)) return INT2FIX(fo);
- sw = check_rounding_mode(val);
- fo = VpSetRoundMode(sw);
- return INT2FIX(fo);
- }
- rb_raise(rb_eTypeError, "first argument for BigDecimal.mode invalid");
- return Qnil;
-}
-
-static size_t
-GetAddSubPrec(Real *a, Real *b)
-{
- size_t mxs;
- size_t mx = a->Prec;
- SIGNED_VALUE d;
-
- if (!VpIsDef(a) || !VpIsDef(b)) return (size_t)-1L;
- if (mx < b->Prec) mx = b->Prec;
- if (a->exponent != b->exponent) {
- mxs = mx;
- d = a->exponent - b->exponent;
- if (d < 0) d = -d;
- mx = mx + (size_t)d;
- if (mx < mxs) {
- return VpException(VP_EXCEPTION_INFINITY, "Exponent overflow", 0);
- }
- }
- return mx;
-}
-
-static inline SIGNED_VALUE
-check_int_precision(VALUE v)
-{
- SIGNED_VALUE n;
-#if SIZEOF_VALUE <= SIZEOF_LONG
- n = (SIGNED_VALUE)NUM2LONG(v);
-#elif SIZEOF_VALUE <= SIZEOF_LONG_LONG
- n = (SIGNED_VALUE)NUM2LL(v);
-#else
-# error SIZEOF_VALUE is too large
-#endif
- if (n < 0) {
- rb_raise(rb_eArgError, "negative precision");
- }
- return n;
-}
-
-static VALUE
-BigDecimal_wrap_struct(VALUE obj, Real *vp)
-{
- assert(is_kind_of_BigDecimal(obj));
- assert(vp != NULL);
-
- if (vp->obj == obj && RTYPEDDATA_DATA(obj) == vp)
- return obj;
-
- assert(RTYPEDDATA_DATA(obj) == NULL);
- assert(vp->obj == 0);
-
- RTYPEDDATA_DATA(obj) = vp;
- vp->obj = obj;
- RB_OBJ_FREEZE(obj);
- return obj;
-}
-
-VP_EXPORT Real *
-VpNewRbClass(size_t mx, const char *str, VALUE klass, bool strict_p, bool raise_exception)
-{
- VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
- Real *pv = VpAlloc(mx, str, strict_p, raise_exception);
- if (!pv)
- return NULL;
- BigDecimal_wrap_struct(obj, pv);
- return pv;
-}
-
-VP_EXPORT Real *
-VpCreateRbObject(size_t mx, const char *str, bool raise_exception)
-{
- return VpNewRbClass(mx, str, rb_cBigDecimal, true, raise_exception);
-}
-
-static Real *
-VpCopy(Real *pv, Real const* const x)
-{
- assert(x != NULL);
-
- pv = rbd_reallocate_struct(pv, x->MaxPrec);
- pv->MaxPrec = x->MaxPrec;
- pv->Prec = x->Prec;
- pv->exponent = x->exponent;
- pv->sign = x->sign;
- pv->flag = x->flag;
- MEMCPY(pv->frac, x->frac, DECDIG, pv->MaxPrec);
-
- return pv;
-}
-
-/* Returns True if the value is Not a Number. */
-static VALUE
-BigDecimal_IsNaN(VALUE self)
-{
- Real *p = GetVpValue(self, 1);
- if (VpIsNaN(p)) return Qtrue;
- return Qfalse;
-}
-
-/* Returns nil, -1, or +1 depending on whether the value is finite,
- * -Infinity, or +Infinity.
- */
-static VALUE
-BigDecimal_IsInfinite(VALUE self)
-{
- Real *p = GetVpValue(self, 1);
- if (VpIsPosInf(p)) return INT2FIX(1);
- if (VpIsNegInf(p)) return INT2FIX(-1);
- return Qnil;
-}
-
-/* Returns True if the value is finite (not NaN or infinite). */
-static VALUE
-BigDecimal_IsFinite(VALUE self)
-{
- Real *p = GetVpValue(self, 1);
- if (VpIsNaN(p)) return Qfalse;
- if (VpIsInf(p)) return Qfalse;
- return Qtrue;
-}
-
-static void
-BigDecimal_check_num(Real *p)
-{
- VpCheckException(p, true);
-}
-
-static VALUE BigDecimal_split(VALUE self);
-
-/* Returns the value as an Integer.
- *
- * If the BigDecimal is infinity or NaN, raises FloatDomainError.
- */
-static VALUE
-BigDecimal_to_i(VALUE self)
-{
- ENTER(5);
- ssize_t e, nf;
- Real *p;
-
- GUARD_OBJ(p, GetVpValue(self, 1));
- BigDecimal_check_num(p);
-
- e = VpExponent10(p);
- if (e <= 0) return INT2FIX(0);
- nf = VpBaseFig();
- if (e <= nf) {
- return LONG2NUM((long)(VpGetSign(p) * (DECDIG_DBL_SIGNED)p->frac[0]));
- }
- else {
- VALUE a = BigDecimal_split(self);
- VALUE digits = RARRAY_AREF(a, 1);
- VALUE numerator = rb_funcall(digits, rb_intern("to_i"), 0);
- VALUE ret;
- ssize_t dpower = e - (ssize_t)RSTRING_LEN(digits);
-
- if (BIGDECIMAL_NEGATIVE_P(p)) {
- numerator = rb_funcall(numerator, '*', 1, INT2FIX(-1));
- }
- if (dpower < 0) {
- ret = rb_funcall(numerator, rb_intern("div"), 1,
- rb_funcall(INT2FIX(10), rb_intern("**"), 1,
- INT2FIX(-dpower)));
- }
- else {
- ret = rb_funcall(numerator, '*', 1,
- rb_funcall(INT2FIX(10), rb_intern("**"), 1,
- INT2FIX(dpower)));
- }
- if (RB_TYPE_P(ret, T_FLOAT)) {
- rb_raise(rb_eFloatDomainError, "Infinity");
- }
- return ret;
- }
-}
-
-/* Returns a new Float object having approximately the same value as the
- * BigDecimal number. Normal accuracy limits and built-in errors of binary
- * Float arithmetic apply.
- */
-static VALUE
-BigDecimal_to_f(VALUE self)
-{
- ENTER(1);
- Real *p;
- double d;
- SIGNED_VALUE e;
- char *buf;
- volatile VALUE str;
-
- GUARD_OBJ(p, GetVpValue(self, 1));
- if (VpVtoD(&d, &e, p) != 1)
- return rb_float_new(d);
- if (e > (SIGNED_VALUE)(DBL_MAX_10_EXP+BASE_FIG))
- goto overflow;
- if (e < (SIGNED_VALUE)(DBL_MIN_10_EXP-BASE_FIG))
- goto underflow;
-
- str = rb_str_new(0, VpNumOfChars(p, "E"));
- buf = RSTRING_PTR(str);
- VpToString(p, buf, RSTRING_LEN(str), 0, 0);
- errno = 0;
- d = strtod(buf, 0);
- if (errno == ERANGE) {
- if (d == 0.0) goto underflow;
- if (fabs(d) >= HUGE_VAL) goto overflow;
- }
- return rb_float_new(d);
-
-overflow:
- VpException(VP_EXCEPTION_OVERFLOW, "BigDecimal to Float conversion", 0);
- if (BIGDECIMAL_NEGATIVE_P(p))
- return rb_float_new(VpGetDoubleNegInf());
- else
- return rb_float_new(VpGetDoublePosInf());
-
-underflow:
- VpException(VP_EXCEPTION_UNDERFLOW, "BigDecimal to Float conversion", 0);
- if (BIGDECIMAL_NEGATIVE_P(p))
- return rb_float_new(-0.0);
- else
- return rb_float_new(0.0);
-}
-
-
-/* Converts a BigDecimal to a Rational.
- */
-static VALUE
-BigDecimal_to_r(VALUE self)
-{
- Real *p;
- ssize_t sign, power, denomi_power;
- VALUE a, digits, numerator;
-
- p = GetVpValue(self, 1);
- BigDecimal_check_num(p);
-
- sign = VpGetSign(p);
- power = VpExponent10(p);
- a = BigDecimal_split(self);
- digits = RARRAY_AREF(a, 1);
- denomi_power = power - RSTRING_LEN(digits);
- numerator = rb_funcall(digits, rb_intern("to_i"), 0);
-
- if (sign < 0) {
- numerator = rb_funcall(numerator, '*', 1, INT2FIX(-1));
- }
- if (denomi_power < 0) {
- return rb_Rational(numerator,
- rb_funcall(INT2FIX(10), rb_intern("**"), 1,
- INT2FIX(-denomi_power)));
- }
- else {
- return rb_Rational1(rb_funcall(numerator, '*', 1,
- rb_funcall(INT2FIX(10), rb_intern("**"), 1,
- INT2FIX(denomi_power))));
- }
-}
-
-/* The coerce method provides support for Ruby type coercion. It is not
- * enabled by default.
- *
- * This means that binary operations like + * / or - can often be performed
- * on a BigDecimal and an object of another type, if the other object can
- * be coerced into a BigDecimal value.
- *
- * e.g.
- * a = BigDecimal("1.0")
- * b = a / 2.0 #=> 0.5
- *
- * Note that coercing a String to a BigDecimal is not supported by default;
- * it requires a special compile-time option when building Ruby.
- */
-static VALUE
-BigDecimal_coerce(VALUE self, VALUE other)
-{
- ENTER(2);
- VALUE obj;
- Real *b;
-
- if (RB_TYPE_P(other, T_FLOAT)) {
- GUARD_OBJ(b, GetVpValueWithPrec(other, 0, 1));
- obj = rb_assoc_new(VpCheckGetValue(b), self);
- }
- else {
- if (RB_TYPE_P(other, T_RATIONAL)) {
- Real* pv = DATA_PTR(self);
- GUARD_OBJ(b, GetVpValueWithPrec(other, pv->Prec*VpBaseFig(), 1));
- }
- else {
- GUARD_OBJ(b, GetVpValue(other, 1));
- }
- obj = rb_assoc_new(b->obj, self);
- }
-
- return obj;
-}
-
-/*
- * call-seq:
- * +big_decimal -> self
- *
- * Returns +self+:
- *
- * +BigDecimal(5) # => 0.5e1
- * +BigDecimal(-5) # => -0.5e1
- *
- */
-
-static VALUE
-BigDecimal_uplus(VALUE self)
-{
- return self;
-}
-
- /*
- * call-seq:
- * self + value -> bigdecimal
- *
- * Returns the \BigDecimal sum of +self+ and +value+:
- *
- * b = BigDecimal('111111.111') # => 0.111111111e6
- * b + 2 # => 0.111113111e6
- * b + 2.0 # => 0.111113111e6
- * b + Rational(2, 1) # => 0.111113111e6
- * b + Complex(2, 0) # => (0.111113111e6+0i)
- *
- * See the {Note About Precision}[BigDecimal.html#class-BigDecimal-label-A+Note+About+Precision].
- *
- */
-
-static VALUE
-BigDecimal_add(VALUE self, VALUE r)
-{
- ENTER(5);
- Real *c, *a, *b;
- size_t mx;
-
- GUARD_OBJ(a, GetVpValue(self, 1));
- if (RB_TYPE_P(r, T_FLOAT)) {
- b = GetVpValueWithPrec(r, 0, 1);
- }
- else if (RB_TYPE_P(r, T_RATIONAL)) {
- b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
- }
- else {
- b = GetVpValue(r, 0);
- }
-
- if (!b) return DoSomeOne(self,r,'+');
- SAVE(b);
-
- if (VpIsNaN(b)) return b->obj;
- if (VpIsNaN(a)) return a->obj;
-
- mx = GetAddSubPrec(a, b);
- if (mx == (size_t)-1L) {
- GUARD_OBJ(c, NewZeroWrapLimited(1, VpBaseFig() + 1));
- VpAddSub(c, a, b, 1);
- }
- else {
- GUARD_OBJ(c, NewZeroWrapLimited(1, mx * (VpBaseFig() + 1)));
- if (!mx) {
- VpSetInf(c, VpGetSign(a));
- }
- else {
- VpAddSub(c, a, b, 1);
- }
- }
- return VpCheckGetValue(c);
-}
-
- /* call-seq:
- * self - value -> bigdecimal
- *
- * Returns the \BigDecimal difference of +self+ and +value+:
- *
- * b = BigDecimal('333333.333') # => 0.333333333e6
- * b - 2 # => 0.333331333e6
- * b - 2.0 # => 0.333331333e6
- * b - Rational(2, 1) # => 0.333331333e6
- * b - Complex(2, 0) # => (0.333331333e6+0i)
- *
- * See the {Note About Precision}[BigDecimal.html#class-BigDecimal-label-A+Note+About+Precision].
- *
- */
-static VALUE
-BigDecimal_sub(VALUE self, VALUE r)
-{
- ENTER(5);
- Real *c, *a, *b;
- size_t mx;
-
- GUARD_OBJ(a, GetVpValue(self,1));
- if (RB_TYPE_P(r, T_FLOAT)) {
- b = GetVpValueWithPrec(r, 0, 1);
- }
- else if (RB_TYPE_P(r, T_RATIONAL)) {
- b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
- }
- else {
- b = GetVpValue(r,0);
- }
-
- if (!b) return DoSomeOne(self,r,'-');
- SAVE(b);
-
- if (VpIsNaN(b)) return b->obj;
- if (VpIsNaN(a)) return a->obj;
-
- mx = GetAddSubPrec(a,b);
- if (mx == (size_t)-1L) {
- GUARD_OBJ(c, NewZeroWrapLimited(1, VpBaseFig() + 1));
- VpAddSub(c, a, b, -1);
- }
- else {
- GUARD_OBJ(c, NewZeroWrapLimited(1, mx *(VpBaseFig() + 1)));
- if (!mx) {
- VpSetInf(c,VpGetSign(a));
- }
- else {
- VpAddSub(c, a, b, -1);
- }
- }
- return VpCheckGetValue(c);
-}
-
-static VALUE
-BigDecimalCmp(VALUE self, VALUE r,char op)
-{
- ENTER(5);
- SIGNED_VALUE e;
- Real *a, *b=0;
- GUARD_OBJ(a, GetVpValue(self, 1));
- switch (TYPE(r)) {
- case T_DATA:
- if (!is_kind_of_BigDecimal(r)) break;
- /* fall through */
- case T_FIXNUM:
- /* fall through */
- case T_BIGNUM:
- GUARD_OBJ(b, GetVpValue(r, 0));
- break;
-
- case T_FLOAT:
- GUARD_OBJ(b, GetVpValueWithPrec(r, 0, 0));
- break;
-
- case T_RATIONAL:
- GUARD_OBJ(b, GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 0));
- break;
-
- default:
- break;
- }
- if (b == NULL) {
- ID f = 0;
-
- switch (op) {
- case '*':
- return rb_num_coerce_cmp(self, r, rb_intern("<=>"));
-
- case '=':
- return RTEST(rb_num_coerce_cmp(self, r, rb_intern("=="))) ? Qtrue : Qfalse;
-
- case 'G':
- f = rb_intern(">=");
- break;
-
- case 'L':
- f = rb_intern("<=");
- break;
-
- case '>':
- /* fall through */
- case '<':
- f = (ID)op;
- break;
-
- default:
- break;
- }
- return rb_num_coerce_relop(self, r, f);
- }
- SAVE(b);
- e = VpComp(a, b);
- if (e == 999)
- return (op == '*') ? Qnil : Qfalse;
- switch (op) {
- case '*':
- return INT2FIX(e); /* any op */
-
- case '=':
- if (e == 0) return Qtrue;
- return Qfalse;
-
- case 'G':
- if (e >= 0) return Qtrue;
- return Qfalse;
-
- case '>':
- if (e > 0) return Qtrue;
- return Qfalse;
-
- case 'L':
- if (e <= 0) return Qtrue;
- return Qfalse;
-
- case '<':
- if (e < 0) return Qtrue;
- return Qfalse;
-
- default:
- break;
- }
-
- rb_bug("Undefined operation in BigDecimalCmp()");
-
- UNREACHABLE;
-}
-
-/* Returns True if the value is zero. */
-static VALUE
-BigDecimal_zero(VALUE self)
-{
- Real *a = GetVpValue(self, 1);
- return VpIsZero(a) ? Qtrue : Qfalse;
-}
-
-/* Returns self if the value is non-zero, nil otherwise. */
-static VALUE
-BigDecimal_nonzero(VALUE self)
-{
- Real *a = GetVpValue(self, 1);
- return VpIsZero(a) ? Qnil : self;
-}
-
-/* The comparison operator.
- * a <=> b is 0 if a == b, 1 if a > b, -1 if a < b.
- */
-static VALUE
-BigDecimal_comp(VALUE self, VALUE r)
-{
- return BigDecimalCmp(self, r, '*');
-}
-
-/*
- * Tests for value equality; returns true if the values are equal.
- *
- * The == and === operators and the eql? method have the same implementation
- * for BigDecimal.
- *
- * Values may be coerced to perform the comparison:
- *
- * BigDecimal('1.0') == 1.0 #=> true
- */
-static VALUE
-BigDecimal_eq(VALUE self, VALUE r)
-{
- return BigDecimalCmp(self, r, '=');
-}
-
-/* call-seq:
- * self < other -> true or false
- *
- * Returns +true+ if +self+ is less than +other+, +false+ otherwise:
- *
- * b = BigDecimal('1.5') # => 0.15e1
- * b < 2 # => true
- * b < 2.0 # => true
- * b < Rational(2, 1) # => true
- * b < 1.5 # => false
- *
- * Raises an exception if the comparison cannot be made.
- *
- */
-static VALUE
-BigDecimal_lt(VALUE self, VALUE r)
-{
- return BigDecimalCmp(self, r, '<');
-}
-
-/* call-seq:
- * self <= other -> true or false
- *
- * Returns +true+ if +self+ is less or equal to than +other+, +false+ otherwise:
- *
- * b = BigDecimal('1.5') # => 0.15e1
- * b <= 2 # => true
- * b <= 2.0 # => true
- * b <= Rational(2, 1) # => true
- * b <= 1.5 # => true
- * b < 1 # => false
- *
- * Raises an exception if the comparison cannot be made.
- *
- */
-static VALUE
-BigDecimal_le(VALUE self, VALUE r)
-{
- return BigDecimalCmp(self, r, 'L');
-}
-
-/* call-seq:
- * self > other -> true or false
- *
- * Returns +true+ if +self+ is greater than +other+, +false+ otherwise:
- *
- * b = BigDecimal('1.5')
- * b > 1 # => true
- * b > 1.0 # => true
- * b > Rational(1, 1) # => true
- * b > 2 # => false
- *
- * Raises an exception if the comparison cannot be made.
- *
- */
-static VALUE
-BigDecimal_gt(VALUE self, VALUE r)
-{
- return BigDecimalCmp(self, r, '>');
-}
-
-/* call-seq:
- * self >= other -> true or false
- *
- * Returns +true+ if +self+ is greater than or equal to +other+, +false+ otherwise:
- *
- * b = BigDecimal('1.5')
- * b >= 1 # => true
- * b >= 1.0 # => true
- * b >= Rational(1, 1) # => true
- * b >= 1.5 # => true
- * b > 2 # => false
- *
- * Raises an exception if the comparison cannot be made.
- *
- */
-static VALUE
-BigDecimal_ge(VALUE self, VALUE r)
-{
- return BigDecimalCmp(self, r, 'G');
-}
-
-/*
- * call-seq:
- * -self -> bigdecimal
- *
- * Returns the \BigDecimal negation of self:
- *
- * b0 = BigDecimal('1.5')
- * b1 = -b0 # => -0.15e1
- * b2 = -b1 # => 0.15e1
- *
- */
-
-static VALUE
-BigDecimal_neg(VALUE self)
-{
- ENTER(5);
- Real *c, *a;
- GUARD_OBJ(a, GetVpValue(self, 1));
- GUARD_OBJ(c, NewZeroWrapLimited(1, a->Prec *(VpBaseFig() + 1)));
- VpAsgn(c, a, -1);
- return VpCheckGetValue(c);
-}
-
-static VALUE
-BigDecimal_mult(VALUE self, VALUE r)
-{
- ENTER(5);
- Real *c, *a, *b;
- size_t mx;
-
- GUARD_OBJ(a, GetVpValue(self, 1));
- if (RB_TYPE_P(r, T_FLOAT)) {
- b = GetVpValueWithPrec(r, 0, 1);
- }
- else if (RB_TYPE_P(r, T_RATIONAL)) {
- b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
- }
- else {
- b = GetVpValue(r,0);
- }
-
- if (!b) return DoSomeOne(self, r, '*');
- SAVE(b);
-
- mx = a->Prec + b->Prec;
- GUARD_OBJ(c, NewZeroWrapLimited(1, mx * (VpBaseFig() + 1)));
- VpMult(c, a, b);
- return VpCheckGetValue(c);
-}
-
-static VALUE
-BigDecimal_divide(VALUE self, VALUE r, Real **c, Real **res, Real **div)
-/* For c = self.div(r): with round operation */
-{
- ENTER(5);
- Real *a, *b;
- ssize_t a_prec, b_prec;
- size_t mx;
-
- TypedData_Get_Struct(self, Real, &BigDecimal_data_type, a);
- SAVE(a);
-
- VALUE rr = r;
- if (is_kind_of_BigDecimal(rr)) {
- /* do nothing */
- }
- else if (RB_INTEGER_TYPE_P(r)) {
- rr = rb_inum_convert_to_BigDecimal(r, 0, true);
- }
- else if (RB_TYPE_P(r, T_FLOAT)) {
- rr = rb_float_convert_to_BigDecimal(r, 0, true);
- }
- else if (RB_TYPE_P(r, T_RATIONAL)) {
- rr = rb_rational_convert_to_BigDecimal(r, a->Prec*BASE_FIG, true);
- }
-
- if (!is_kind_of_BigDecimal(rr)) {
- return DoSomeOne(self, r, '/');
- }
-
- TypedData_Get_Struct(rr, Real, &BigDecimal_data_type, b);
- SAVE(b);
- *div = b;
-
- BigDecimal_count_precision_and_scale(self, &a_prec, NULL);
- BigDecimal_count_precision_and_scale(rr, &b_prec, NULL);
- mx = (a_prec > b_prec) ? a_prec : b_prec;
- mx *= 2;
-
- if (2*BIGDECIMAL_DOUBLE_FIGURES > mx)
- mx = 2*BIGDECIMAL_DOUBLE_FIGURES;
-
- GUARD_OBJ((*c), NewZeroWrapNolimit(1, mx + 2*BASE_FIG));
- GUARD_OBJ((*res), NewZeroWrapNolimit(1, (mx + 1)*2 + 2*BASE_FIG));
- VpDivd(*c, *res, a, b);
-
- return Qnil;
-}
-
-static VALUE BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod);
-
-/* call-seq:
- * a / b -> bigdecimal
- *
- * Divide by the specified value.
- *
- * The result precision will be the precision of the larger operand,
- * but its minimum is 2*Float::DIG.
- *
- * See BigDecimal#div.
- * See BigDecimal#quo.
- */
-static VALUE
-BigDecimal_div(VALUE self, VALUE r)
-/* For c = self/r: with round operation */
-{
- ENTER(5);
- Real *c=NULL, *res=NULL, *div = NULL;
- r = BigDecimal_divide(self, r, &c, &res, &div);
- if (!NIL_P(r)) return r; /* coerced by other */
- SAVE(c); SAVE(res); SAVE(div);
- /* a/b = c + r/b */
- /* c xxxxx
- r 00000yyyyy ==> (y/b)*BASE >= HALF_BASE
- */
- /* Round */
- if (VpHasVal(div)) { /* frac[0] must be zero for NaN,INF,Zero */
- VpInternalRound(c, 0, c->frac[c->Prec-1], (DECDIG)(VpBaseVal() * (DECDIG_DBL)res->frac[0] / div->frac[0]));
- }
- return VpCheckGetValue(c);
-}
-
-static VALUE BigDecimal_round(int argc, VALUE *argv, VALUE self);
-
-/* call-seq:
- * quo(value) -> bigdecimal
- * quo(value, digits) -> bigdecimal
- *
- * Divide by the specified value.
- *
- * digits:: If specified and less than the number of significant digits of
- * the result, the result is rounded to the given number of digits,
- * according to the rounding mode indicated by BigDecimal.mode.
- *
- * If digits is 0 or omitted, the result is the same as for the
- * / operator.
- *
- * See BigDecimal#/.
- * See BigDecimal#div.
- */
-static VALUE
-BigDecimal_quo(int argc, VALUE *argv, VALUE self)
-{
- VALUE value, digits, result;
- SIGNED_VALUE n = -1;
-
- argc = rb_scan_args(argc, argv, "11", &value, &digits);
- if (argc > 1) {
- n = check_int_precision(digits);
- }
-
- if (n > 0) {
- result = BigDecimal_div2(self, value, digits);
- }
- else {
- result = BigDecimal_div(self, value);
- }
-
- return result;
-}
-
-/*
- * %: mod = a%b = a - (a.to_f/b).floor * b
- * div = (a.to_f/b).floor
- */
-static VALUE
-BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
-{
- ENTER(8);
- Real *c=NULL, *d=NULL, *res=NULL;
- Real *a, *b;
- ssize_t a_prec, b_prec;
- size_t mx;
-
- TypedData_Get_Struct(self, Real, &BigDecimal_data_type, a);
- SAVE(a);
-
- VALUE rr = r;
- if (is_kind_of_BigDecimal(rr)) {
- /* do nothing */
- }
- else if (RB_INTEGER_TYPE_P(r)) {
- rr = rb_inum_convert_to_BigDecimal(r, 0, true);
- }
- else if (RB_TYPE_P(r, T_FLOAT)) {
- rr = rb_float_convert_to_BigDecimal(r, 0, true);
- }
- else if (RB_TYPE_P(r, T_RATIONAL)) {
- rr = rb_rational_convert_to_BigDecimal(r, a->Prec*BASE_FIG, true);
- }
-
- if (!is_kind_of_BigDecimal(rr)) {
- return Qfalse;
- }
-
- TypedData_Get_Struct(rr, Real, &BigDecimal_data_type, b);
- SAVE(b);
-
- if (VpIsNaN(a) || VpIsNaN(b)) goto NaN;
- if (VpIsInf(a) && VpIsInf(b)) goto NaN;
- if (VpIsZero(b)) {
- rb_raise(rb_eZeroDivError, "divided by 0");
- }
- if (VpIsInf(a)) {
- if (VpGetSign(a) == VpGetSign(b)) {
- VALUE inf = BigDecimal_positive_infinity();
- TypedData_Get_Struct(inf, Real, &BigDecimal_data_type, *div);
- }
- else {
- VALUE inf = BigDecimal_negative_infinity();
- TypedData_Get_Struct(inf, Real, &BigDecimal_data_type, *div);
- }
- VALUE nan = BigDecimal_nan();
- TypedData_Get_Struct(nan, Real, &BigDecimal_data_type, *mod);
- return Qtrue;
- }
- if (VpIsInf(b)) {
- VALUE zero = BigDecimal_positive_zero();
- TypedData_Get_Struct(zero, Real, &BigDecimal_data_type, *div);
- *mod = a;
- return Qtrue;
- }
- if (VpIsZero(a)) {
- VALUE zero = BigDecimal_positive_zero();
- TypedData_Get_Struct(zero, Real, &BigDecimal_data_type, *div);
- TypedData_Get_Struct(zero, Real, &BigDecimal_data_type, *mod);
- return Qtrue;
- }
-
- BigDecimal_count_precision_and_scale(self, &a_prec, NULL);
- BigDecimal_count_precision_and_scale(rr, &b_prec, NULL);
-
- mx = (a_prec > b_prec) ? a_prec : b_prec;
- mx *= 2;
-
- if (2*BIGDECIMAL_DOUBLE_FIGURES > mx)
- mx = 2*BIGDECIMAL_DOUBLE_FIGURES;
-
- GUARD_OBJ(c, NewZeroWrapLimited(1, mx + 2*BASE_FIG));
- GUARD_OBJ(res, NewZeroWrapNolimit(1, mx*2 + 2*BASE_FIG));
- VpDivd(c, res, a, b);
-
- mx = c->Prec * BASE_FIG;
- GUARD_OBJ(d, NewZeroWrapLimited(1, mx));
- VpActiveRound(d, c, VP_ROUND_DOWN, 0);
-
- VpMult(res, d, b);
- VpAddSub(c, a, res, -1);
-
- if (!VpIsZero(c) && (VpGetSign(a) * VpGetSign(b) < 0)) {
- /* result adjustment for negative case */
- res = rbd_reallocate_struct(res, d->MaxPrec);
- res->MaxPrec = d->MaxPrec;
- VpAddSub(res, d, VpOne(), -1);
- GUARD_OBJ(d, NewZeroWrapLimited(1, GetAddSubPrec(c, b) * 2*BASE_FIG));
- VpAddSub(d, c, b, 1);
- *div = res;
- *mod = d;
- }
- else {
- *div = d;
- *mod = c;
- }
- return Qtrue;
-
- NaN:
- {
- VALUE nan = BigDecimal_nan();
- TypedData_Get_Struct(nan, Real, &BigDecimal_data_type, *div);
- TypedData_Get_Struct(nan, Real, &BigDecimal_data_type, *mod);
- }
- return Qtrue;
-}
-
-/* call-seq:
- * a % b
- * a.modulo(b)
- *
- * Returns the modulus from dividing by b.
- *
- * See BigDecimal#divmod.
- */
-static VALUE
-BigDecimal_mod(VALUE self, VALUE r) /* %: a%b = a - (a.to_f/b).floor * b */
-{
- ENTER(3);
- Real *div = NULL, *mod = NULL;
-
- if (BigDecimal_DoDivmod(self, r, &div, &mod)) {
- SAVE(div); SAVE(mod);
- return VpCheckGetValue(mod);
- }
- return DoSomeOne(self, r, '%');
-}
-
-static VALUE
-BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv)
-{
- ENTER(10);
- size_t mx;
- Real *a = NULL, *b = NULL, *c = NULL, *res = NULL, *d = NULL, *rr = NULL, *ff = NULL;
- Real *f = NULL;
-
- GUARD_OBJ(a, GetVpValue(self, 1));
- if (RB_TYPE_P(r, T_FLOAT)) {
- b = GetVpValueWithPrec(r, 0, 1);
- }
- else if (RB_TYPE_P(r, T_RATIONAL)) {
- b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
- }
- else {
- b = GetVpValue(r, 0);
- }
-
- if (!b) return DoSomeOne(self, r, rb_intern("remainder"));
- SAVE(b);
-
- if (VpIsPosInf(b) || VpIsNegInf(b)) {
- GUARD_OBJ(*dv, NewZeroWrapLimited(1, 1));
- VpSetZero(*dv, 1);
- *rv = a;
- return Qnil;
- }
-
- mx = (a->MaxPrec + b->MaxPrec) *VpBaseFig();
- GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
- GUARD_OBJ(res, NewZeroWrapNolimit(1, (mx+1) * 2 + (VpBaseFig() + 1)));
- GUARD_OBJ(rr, NewZeroWrapNolimit(1, (mx+1) * 2 + (VpBaseFig() + 1)));
- GUARD_OBJ(ff, NewZeroWrapNolimit(1, (mx+1) * 2 + (VpBaseFig() + 1)));
-
- VpDivd(c, res, a, b);
-
- mx = c->Prec *(VpBaseFig() + 1);
-
- GUARD_OBJ(d, NewZeroWrapLimited(1, mx));
- GUARD_OBJ(f, NewZeroWrapLimited(1, mx));
-
- VpActiveRound(d, c, VP_ROUND_DOWN, 0); /* 0: round off */
-
- VpFrac(f, c);
- VpMult(rr, f, b);
- VpAddSub(ff, res, rr, 1);
-
- *dv = d;
- *rv = ff;
- return Qnil;
-}
-
-/* call-seq:
- * remainder(value)
- *
- * Returns the remainder from dividing by the value.
- *
- * x.remainder(y) means x-y*(x/y).truncate
- */
-static VALUE
-BigDecimal_remainder(VALUE self, VALUE r) /* remainder */
-{
- VALUE f;
- Real *d, *rv = 0;
- f = BigDecimal_divremain(self, r, &d, &rv);
- if (!NIL_P(f)) return f;
- return VpCheckGetValue(rv);
-}
-
-/* call-seq:
- * divmod(value)
- *
- * Divides by the specified value, and returns the quotient and modulus
- * as BigDecimal numbers. The quotient is rounded towards negative infinity.
- *
- * For example:
- *
- * require 'bigdecimal'
- *
- * a = BigDecimal("42")
- * b = BigDecimal("9")
- *
- * q, m = a.divmod(b)
- *
- * c = q * b + m
- *
- * a == c #=> true
- *
- * The quotient q is (a/b).floor, and the modulus is the amount that must be
- * added to q * b to get a.
- */
-static VALUE
-BigDecimal_divmod(VALUE self, VALUE r)
-{
- ENTER(5);
- Real *div = NULL, *mod = NULL;
-
- if (BigDecimal_DoDivmod(self, r, &div, &mod)) {
- SAVE(div); SAVE(mod);
- return rb_assoc_new(VpCheckGetValue(div), VpCheckGetValue(mod));
- }
- return DoSomeOne(self,r,rb_intern("divmod"));
-}
-
-/*
- * Do the same manner as Float#div when n is nil.
- * Do the same manner as BigDecimal#quo when n is 0.
- */
-static inline VALUE
-BigDecimal_div2(VALUE self, VALUE b, VALUE n)
-{
- ENTER(5);
- SIGNED_VALUE ix;
-
- if (NIL_P(n)) { /* div in Float sense */
- Real *div = NULL;
- Real *mod;
- if (BigDecimal_DoDivmod(self, b, &div, &mod)) {
- return BigDecimal_to_i(VpCheckGetValue(div));
- }
- return DoSomeOne(self, b, rb_intern("div"));
- }
-
- /* div in BigDecimal sense */
- ix = check_int_precision(n);
- if (ix == 0) {
- return BigDecimal_div(self, b);
- }
- else {
- Real *res = NULL;
- Real *av = NULL, *bv = NULL, *cv = NULL;
- size_t mx = ix + VpBaseFig()*2;
- size_t b_prec = ix;
- size_t pl = VpSetPrecLimit(0);
-
- GUARD_OBJ(cv, NewZeroWrapLimited(1, mx + VpBaseFig()));
- GUARD_OBJ(av, GetVpValue(self, 1));
- /* TODO: I want to refactor this precision control for a float value later
- * by introducing an implicit conversion function instead of
- * GetVpValueWithPrec. */
- if (RB_FLOAT_TYPE_P(b) && b_prec > BIGDECIMAL_DOUBLE_FIGURES) {
- b_prec = BIGDECIMAL_DOUBLE_FIGURES;
- }
- GUARD_OBJ(bv, GetVpValueWithPrec(b, b_prec, 1));
- mx = av->Prec + bv->Prec + 2;
- if (mx <= cv->MaxPrec) mx = cv->MaxPrec + 1;
- GUARD_OBJ(res, NewZeroWrapNolimit(1, (mx * 2 + 2)*VpBaseFig()));
- VpDivd(cv, res, av, bv);
- VpSetPrecLimit(pl);
- VpLeftRound(cv, VpGetRoundMode(), ix);
- return VpCheckGetValue(cv);
- }
-}
-
- /*
- * Document-method: BigDecimal#div
- *
- * call-seq:
- * div(value) -> integer
- * div(value, digits) -> bigdecimal or integer
- *
- * Divide by the specified value.
- *
- * digits:: If specified and less than the number of significant digits of the
- * result, the result is rounded to that number of digits, according
- * to BigDecimal.mode.
- *
- * If digits is 0, the result is the same as for the / operator
- * or #quo.
- *
- * If digits is not specified, the result is an integer,
- * by analogy with Float#div; see also BigDecimal#divmod.
- *
- * See BigDecimal#/.
- * See BigDecimal#quo.
- *
- * Examples:
- *
- * a = BigDecimal("4")
- * b = BigDecimal("3")
- *
- * a.div(b, 3) # => 0.133e1
- *
- * a.div(b, 0) # => 0.1333333333333333333e1
- * a / b # => 0.1333333333333333333e1
- * a.quo(b) # => 0.1333333333333333333e1
- *
- * a.div(b) # => 1
- */
-static VALUE
-BigDecimal_div3(int argc, VALUE *argv, VALUE self)
-{
- VALUE b,n;
-
- rb_scan_args(argc, argv, "11", &b, &n);
-
- return BigDecimal_div2(self, b, n);
-}
-
- /*
- * call-seq:
- * add(value, ndigits) -> new_bigdecimal
- *
- * Returns the \BigDecimal sum of +self+ and +value+
- * with a precision of +ndigits+ decimal digits.
- *
- * When +ndigits+ is less than the number of significant digits
- * in the sum, the sum is rounded to that number of digits,
- * according to the current rounding mode; see BigDecimal.mode.
- *
- * Examples:
- *
- * # Set the rounding mode.
- * BigDecimal.mode(BigDecimal::ROUND_MODE, :half_up)
- * b = BigDecimal('111111.111')
- * b.add(1, 0) # => 0.111112111e6
- * b.add(1, 3) # => 0.111e6
- * b.add(1, 6) # => 0.111112e6
- * b.add(1, 15) # => 0.111112111e6
- * b.add(1.0, 15) # => 0.111112111e6
- * b.add(Rational(1, 1), 15) # => 0.111112111e6
- *
- */
-
-static VALUE
-BigDecimal_add2(VALUE self, VALUE b, VALUE n)
-{
- ENTER(2);
- Real *cv;
- SIGNED_VALUE mx = check_int_precision(n);
- if (mx == 0) return BigDecimal_add(self, b);
- else {
- size_t pl = VpSetPrecLimit(0);
- VALUE c = BigDecimal_add(self, b);
- VpSetPrecLimit(pl);
- GUARD_OBJ(cv, GetVpValue(c, 1));
- VpLeftRound(cv, VpGetRoundMode(), mx);
- return VpCheckGetValue(cv);
- }
-}
-
-/* call-seq:
- * sub(value, digits) -> bigdecimal
- *
- * Subtract the specified value.
- *
- * e.g.
- * c = a.sub(b,n)
- *
- * digits:: If specified and less than the number of significant digits of the
- * result, the result is rounded to that number of digits, according
- * to BigDecimal.mode.
- *
- */
-static VALUE
-BigDecimal_sub2(VALUE self, VALUE b, VALUE n)
-{
- ENTER(2);
- Real *cv;
- SIGNED_VALUE mx = check_int_precision(n);
- if (mx == 0) return BigDecimal_sub(self, b);
- else {
- size_t pl = VpSetPrecLimit(0);
- VALUE c = BigDecimal_sub(self, b);
- VpSetPrecLimit(pl);
- GUARD_OBJ(cv, GetVpValue(c, 1));
- VpLeftRound(cv, VpGetRoundMode(), mx);
- return VpCheckGetValue(cv);
- }
-}
-
- /*
- * call-seq:
- * mult(other, ndigits) -> bigdecimal
- *
- * Returns the \BigDecimal product of +self+ and +value+
- * with a precision of +ndigits+ decimal digits.
- *
- * When +ndigits+ is less than the number of significant digits
- * in the sum, the sum is rounded to that number of digits,
- * according to the current rounding mode; see BigDecimal.mode.
- *
- * Examples:
- *
- * # Set the rounding mode.
- * BigDecimal.mode(BigDecimal::ROUND_MODE, :half_up)
- * b = BigDecimal('555555.555')
- * b.mult(3, 0) # => 0.1666666665e7
- * b.mult(3, 3) # => 0.167e7
- * b.mult(3, 6) # => 0.166667e7
- * b.mult(3, 15) # => 0.1666666665e7
- * b.mult(3.0, 0) # => 0.1666666665e7
- * b.mult(Rational(3, 1), 0) # => 0.1666666665e7
- * b.mult(Complex(3, 0), 0) # => (0.1666666665e7+0.0i)
- *
- */
-
-static VALUE
-BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
-{
- ENTER(2);
- Real *cv;
- SIGNED_VALUE mx = check_int_precision(n);
- if (mx == 0) return BigDecimal_mult(self, b);
- else {
- size_t pl = VpSetPrecLimit(0);
- VALUE c = BigDecimal_mult(self, b);
- VpSetPrecLimit(pl);
- GUARD_OBJ(cv, GetVpValue(c, 1));
- VpLeftRound(cv, VpGetRoundMode(), mx);
- return VpCheckGetValue(cv);
- }
-}
-
-/*
- * call-seq:
- * abs -> bigdecimal
- *
- * Returns the \BigDecimal absolute value of +self+:
- *
- * BigDecimal('5').abs # => 0.5e1
- * BigDecimal('-3').abs # => 0.3e1
- *
- */
-
-static VALUE
-BigDecimal_abs(VALUE self)
-{
- ENTER(5);
- Real *c, *a;
- size_t mx;
-
- GUARD_OBJ(a, GetVpValue(self, 1));
- mx = a->Prec *(VpBaseFig() + 1);
- GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
- VpAsgn(c, a, 1);
- VpChangeSign(c, 1);
- return VpCheckGetValue(c);
-}
-
-/* call-seq:
- * sqrt(n)
- *
- * Returns the square root of the value.
- *
- * Result has at least n significant digits.
- */
-static VALUE
-BigDecimal_sqrt(VALUE self, VALUE nFig)
-{
- ENTER(5);
- Real *c, *a;
- size_t mx, n;
-
- GUARD_OBJ(a, GetVpValue(self, 1));
- mx = a->Prec * (VpBaseFig() + 1);
-
- n = check_int_precision(nFig);
- n += VpDblFig() + VpBaseFig();
- if (mx <= n) mx = n;
- GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
- VpSqrt(c, a);
- return VpCheckGetValue(c);
-}
-
-/* Return the integer part of the number, as a BigDecimal.
- */
-static VALUE
-BigDecimal_fix(VALUE self)
-{
- ENTER(5);
- Real *c, *a;
- size_t mx;
-
- GUARD_OBJ(a, GetVpValue(self, 1));
- mx = a->Prec *(VpBaseFig() + 1);
- GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
- VpActiveRound(c, a, VP_ROUND_DOWN, 0); /* 0: round off */
- return VpCheckGetValue(c);
-}
-
-/* call-seq:
- * round(n, mode)
- *
- * Round to the nearest integer (by default), returning the result as a
- * BigDecimal if n is specified, or as an Integer if it isn't.
- *
- * BigDecimal('3.14159').round #=> 3
- * BigDecimal('8.7').round #=> 9
- * BigDecimal('-9.9').round #=> -10
- *
- * BigDecimal('3.14159').round(2).class.name #=> "BigDecimal"
- * BigDecimal('3.14159').round.class.name #=> "Integer"
- *
- * If n is specified and positive, the fractional part of the result has no
- * more than that many digits.
- *
- * If n is specified and negative, at least that many digits to the left of the
- * decimal point will be 0 in the result, and return value will be an Integer.
- *
- * BigDecimal('3.14159').round(3) #=> 3.142
- * BigDecimal('13345.234').round(-2) #=> 13300
- *
- * The value of the optional mode argument can be used to determine how
- * rounding is performed; see BigDecimal.mode.
- */
-static VALUE
-BigDecimal_round(int argc, VALUE *argv, VALUE self)
-{
- ENTER(5);
- Real *c, *a;
- int iLoc = 0;
- VALUE vLoc;
- VALUE vRound;
- int round_to_int = 0;
- size_t mx, pl;
-
- unsigned short sw = VpGetRoundMode();
-
- switch (rb_scan_args(argc, argv, "02", &vLoc, &vRound)) {
- case 0:
- iLoc = 0;
- round_to_int = 1;
- break;
- case 1:
- if (RB_TYPE_P(vLoc, T_HASH)) {
- sw = check_rounding_mode_option(vLoc);
- }
- else {
- iLoc = NUM2INT(vLoc);
- if (iLoc < 1) round_to_int = 1;
- }
- break;
- case 2:
- iLoc = NUM2INT(vLoc);
- if (RB_TYPE_P(vRound, T_HASH)) {
- sw = check_rounding_mode_option(vRound);
- }
- else {
- sw = check_rounding_mode(vRound);
- }
- break;
- default:
- break;
- }
-
- pl = VpSetPrecLimit(0);
- GUARD_OBJ(a, GetVpValue(self, 1));
- mx = a->Prec * (VpBaseFig() + 1);
- GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
- VpSetPrecLimit(pl);
- VpActiveRound(c, a, sw, iLoc);
- if (round_to_int) {
- return BigDecimal_to_i(VpCheckGetValue(c));
- }
- return VpCheckGetValue(c);
-}
-
-/* call-seq:
- * truncate(n)
- *
- * Truncate to the nearest integer (by default), returning the result as a
- * BigDecimal.
- *
- * BigDecimal('3.14159').truncate #=> 3
- * BigDecimal('8.7').truncate #=> 8
- * BigDecimal('-9.9').truncate #=> -9
- *
- * If n is specified and positive, the fractional part of the result has no
- * more than that many digits.
- *
- * If n is specified and negative, at least that many digits to the left of the
- * decimal point will be 0 in the result.
- *
- * BigDecimal('3.14159').truncate(3) #=> 3.141
- * BigDecimal('13345.234').truncate(-2) #=> 13300.0
- */
-static VALUE
-BigDecimal_truncate(int argc, VALUE *argv, VALUE self)
-{
- ENTER(5);
- Real *c, *a;
- int iLoc;
- VALUE vLoc;
- size_t mx, pl = VpSetPrecLimit(0);
-
- if (rb_scan_args(argc, argv, "01", &vLoc) == 0) {
- iLoc = 0;
- }
- else {
- iLoc = NUM2INT(vLoc);
- }
-
- GUARD_OBJ(a, GetVpValue(self, 1));
- mx = a->Prec * (VpBaseFig() + 1);
- GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
- VpSetPrecLimit(pl);
- VpActiveRound(c, a, VP_ROUND_DOWN, iLoc); /* 0: truncate */
- if (argc == 0) {
- return BigDecimal_to_i(VpCheckGetValue(c));
- }
- return VpCheckGetValue(c);
-}
-
-/* Return the fractional part of the number, as a BigDecimal.
- */
-static VALUE
-BigDecimal_frac(VALUE self)
-{
- ENTER(5);
- Real *c, *a;
- size_t mx;
-
- GUARD_OBJ(a, GetVpValue(self, 1));
- mx = a->Prec * (VpBaseFig() + 1);
- GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
- VpFrac(c, a);
- return VpCheckGetValue(c);
-}
-
-/* call-seq:
- * floor(n)
- *
- * Return the largest integer less than or equal to the value, as a BigDecimal.
- *
- * BigDecimal('3.14159').floor #=> 3
- * BigDecimal('-9.1').floor #=> -10
- *
- * If n is specified and positive, the fractional part of the result has no
- * more than that many digits.
- *
- * If n is specified and negative, at least that
- * many digits to the left of the decimal point will be 0 in the result.
- *
- * BigDecimal('3.14159').floor(3) #=> 3.141
- * BigDecimal('13345.234').floor(-2) #=> 13300.0
- */
-static VALUE
-BigDecimal_floor(int argc, VALUE *argv, VALUE self)
-{
- ENTER(5);
- Real *c, *a;
- int iLoc;
- VALUE vLoc;
- size_t mx, pl = VpSetPrecLimit(0);
-
- if (rb_scan_args(argc, argv, "01", &vLoc)==0) {
- iLoc = 0;
- }
- else {
- iLoc = NUM2INT(vLoc);
- }
-
- GUARD_OBJ(a, GetVpValue(self, 1));
- mx = a->Prec * (VpBaseFig() + 1);
- GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
- VpSetPrecLimit(pl);
- VpActiveRound(c, a, VP_ROUND_FLOOR, iLoc);
-#ifdef BIGDECIMAL_DEBUG
- VPrint(stderr, "floor: c=%\n", c);
-#endif
- if (argc == 0) {
- return BigDecimal_to_i(VpCheckGetValue(c));
- }
- return VpCheckGetValue(c);
-}
-
-/* call-seq:
- * ceil(n)
- *
- * Return the smallest integer greater than or equal to the value, as a BigDecimal.
- *
- * BigDecimal('3.14159').ceil #=> 4
- * BigDecimal('-9.1').ceil #=> -9
- *
- * If n is specified and positive, the fractional part of the result has no
- * more than that many digits.
- *
- * If n is specified and negative, at least that
- * many digits to the left of the decimal point will be 0 in the result.
- *
- * BigDecimal('3.14159').ceil(3) #=> 3.142
- * BigDecimal('13345.234').ceil(-2) #=> 13400.0
- */
-static VALUE
-BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
-{
- ENTER(5);
- Real *c, *a;
- int iLoc;
- VALUE vLoc;
- size_t mx, pl = VpSetPrecLimit(0);
-
- if (rb_scan_args(argc, argv, "01", &vLoc) == 0) {
- iLoc = 0;
- } else {
- iLoc = NUM2INT(vLoc);
- }
-
- GUARD_OBJ(a, GetVpValue(self, 1));
- mx = a->Prec * (VpBaseFig() + 1);
- GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
- VpSetPrecLimit(pl);
- VpActiveRound(c, a, VP_ROUND_CEIL, iLoc);
- if (argc == 0) {
- return BigDecimal_to_i(VpCheckGetValue(c));
- }
- return VpCheckGetValue(c);
-}
-
-/* call-seq:
- * to_s(s)
- *
- * Converts the value to a string.
- *
- * The default format looks like 0.xxxxEnn.
- *
- * The optional parameter s consists of either an integer; or an optional '+'
- * or ' ', followed by an optional number, followed by an optional 'E' or 'F'.
- *
- * If there is a '+' at the start of s, positive values are returned with
- * a leading '+'.
- *
- * A space at the start of s returns positive values with a leading space.
- *
- * If s contains a number, a space is inserted after each group of that many
- * digits, starting from '.' and counting outwards.
- *
- * If s ends with an 'E', engineering notation (0.xxxxEnn) is used.
- *
- * If s ends with an 'F', conventional floating point notation is used.
- *
- * Examples:
- *
- * BigDecimal('-1234567890123.45678901234567890').to_s('5F')
- * #=> '-123 45678 90123.45678 90123 45678 9'
- *
- * BigDecimal('1234567890123.45678901234567890').to_s('+8F')
- * #=> '+12345 67890123.45678901 23456789'
- *
- * BigDecimal('1234567890123.45678901234567890').to_s(' F')
- * #=> ' 1234567890123.4567890123456789'
- */
-static VALUE
-BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
-{
- ENTER(5);
- int fmt = 0; /* 0: E format, 1: F format */
- int fPlus = 0; /* 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
- Real *vp;
- volatile VALUE str;
- char *psz;
- char ch;
- size_t nc, mc = 0;
- SIGNED_VALUE m;
- VALUE f;
-
- GUARD_OBJ(vp, GetVpValue(self, 1));
-
- if (rb_scan_args(argc, argv, "01", &f) == 1) {
- if (RB_TYPE_P(f, T_STRING)) {
- psz = StringValueCStr(f);
- if (*psz == ' ') {
- fPlus = 1;
- psz++;
- }
- else if (*psz == '+') {
- fPlus = 2;
- psz++;
- }
- while ((ch = *psz++) != 0) {
- if (ISSPACE(ch)) {
- continue;
- }
- if (!ISDIGIT(ch)) {
- if (ch == 'F' || ch == 'f') {
- fmt = 1; /* F format */
- }
- break;
- }
- mc = mc*10 + ch - '0';
- }
- }
- else {
- m = NUM2INT(f);
- if (m <= 0) {
- rb_raise(rb_eArgError, "argument must be positive");
- }
- mc = (size_t)m;
- }
- }
- if (fmt) {
- nc = VpNumOfChars(vp, "F");
- }
- else {
- nc = VpNumOfChars(vp, "E");
- }
- if (mc > 0) {
- nc += (nc + mc - 1) / mc + 1;
- }
-
- str = rb_usascii_str_new(0, nc);
- psz = RSTRING_PTR(str);
-
- if (fmt) {
- VpToFString(vp, psz, RSTRING_LEN(str), mc, fPlus);
- }
- else {
- VpToString (vp, psz, RSTRING_LEN(str), mc, fPlus);
- }
- rb_str_resize(str, strlen(psz));
- return str;
-}
-
-/* Splits a BigDecimal number into four parts, returned as an array of values.
- *
- * The first value represents the sign of the BigDecimal, and is -1 or 1, or 0
- * if the BigDecimal is Not a Number.
- *
- * The second value is a string representing the significant digits of the
- * BigDecimal, with no leading zeros.
- *
- * The third value is the base used for arithmetic (currently always 10) as an
- * Integer.
- *
- * The fourth value is an Integer exponent.
- *
- * If the BigDecimal can be represented as 0.xxxxxx*10**n, then xxxxxx is the
- * string of significant digits with no leading zeros, and n is the exponent.
- *
- * From these values, you can translate a BigDecimal to a float as follows:
- *
- * sign, significant_digits, base, exponent = a.split
- * f = sign * "0.#{significant_digits}".to_f * (base ** exponent)
- *
- * (Note that the to_f method is provided as a more convenient way to translate
- * a BigDecimal to a Float.)
- */
-static VALUE
-BigDecimal_split(VALUE self)
-{
- ENTER(5);
- Real *vp;
- VALUE obj,str;
- ssize_t e, s;
- char *psz1;
-
- GUARD_OBJ(vp, GetVpValue(self, 1));
- str = rb_str_new(0, VpNumOfChars(vp, "E"));
- psz1 = RSTRING_PTR(str);
- VpSzMantissa(vp, psz1, RSTRING_LEN(str));
- s = 1;
- if(psz1[0] == '-') {
- size_t len = strlen(psz1 + 1);
-
- memmove(psz1, psz1 + 1, len);
- psz1[len] = '\0';
- s = -1;
- }
- if (psz1[0] == 'N') s = 0; /* NaN */
- e = VpExponent10(vp);
- obj = rb_ary_new2(4);
- rb_ary_push(obj, INT2FIX(s));
- rb_ary_push(obj, str);
- rb_str_resize(str, strlen(psz1));
- rb_ary_push(obj, INT2FIX(10));
- rb_ary_push(obj, SSIZET2NUM(e));
- return obj;
-}
-
-/* Returns the exponent of the BigDecimal number, as an Integer.
- *
- * If the number can be represented as 0.xxxxxx*10**n where xxxxxx is a string
- * of digits with no leading zeros, then n is the exponent.
- */
-static VALUE
-BigDecimal_exponent(VALUE self)
-{
- ssize_t e = VpExponent10(GetVpValue(self, 1));
- return SSIZET2NUM(e);
-}
-
-/* Returns a string representation of self.
- *
- * BigDecimal("1234.5678").inspect
- * #=> "0.12345678e4"
- */
-static VALUE
-BigDecimal_inspect(VALUE self)
-{
- ENTER(5);
- Real *vp;
- volatile VALUE str;
- size_t nc;
-
- GUARD_OBJ(vp, GetVpValue(self, 1));
- nc = VpNumOfChars(vp, "E");
-
- str = rb_str_new(0, nc);
- VpToString(vp, RSTRING_PTR(str), RSTRING_LEN(str), 0, 0);
- rb_str_resize(str, strlen(RSTRING_PTR(str)));
- return str;
-}
-
-static VALUE BigMath_s_exp(VALUE, VALUE, VALUE);
-static VALUE BigMath_s_log(VALUE, VALUE, VALUE);
-
-#define BigMath_exp(x, n) BigMath_s_exp(rb_mBigMath, (x), (n))
-#define BigMath_log(x, n) BigMath_s_log(rb_mBigMath, (x), (n))
-
-inline static int
-is_integer(VALUE x)
-{
- return (RB_TYPE_P(x, T_FIXNUM) || RB_TYPE_P(x, T_BIGNUM));
-}
-
-inline static int
-is_negative(VALUE x)
-{
- if (FIXNUM_P(x)) {
- return FIX2LONG(x) < 0;
- }
- else if (RB_TYPE_P(x, T_BIGNUM)) {
- return FIX2INT(rb_big_cmp(x, INT2FIX(0))) < 0;
- }
- else if (RB_TYPE_P(x, T_FLOAT)) {
- return RFLOAT_VALUE(x) < 0.0;
- }
- return RTEST(rb_funcall(x, '<', 1, INT2FIX(0)));
-}
-
-#define is_positive(x) (!is_negative(x))
-
-inline static int
-is_zero(VALUE x)
-{
- VALUE num;
-
- switch (TYPE(x)) {
- case T_FIXNUM:
- return FIX2LONG(x) == 0;
-
- case T_BIGNUM:
- return Qfalse;
-
- case T_RATIONAL:
- num = rb_rational_num(x);
- return FIXNUM_P(num) && FIX2LONG(num) == 0;
-
- default:
- break;
- }
-
- return RTEST(rb_funcall(x, id_eq, 1, INT2FIX(0)));
-}
-
-inline static int
-is_one(VALUE x)
-{
- VALUE num, den;
-
- switch (TYPE(x)) {
- case T_FIXNUM:
- return FIX2LONG(x) == 1;
-
- case T_BIGNUM:
- return Qfalse;
-
- case T_RATIONAL:
- num = rb_rational_num(x);
- den = rb_rational_den(x);
- return FIXNUM_P(den) && FIX2LONG(den) == 1 &&
- FIXNUM_P(num) && FIX2LONG(num) == 1;
-
- default:
- break;
- }
-
- return RTEST(rb_funcall(x, id_eq, 1, INT2FIX(1)));
-}
-
-inline static int
-is_even(VALUE x)
-{
- switch (TYPE(x)) {
- case T_FIXNUM:
- return (FIX2LONG(x) % 2) == 0;
-
- case T_BIGNUM:
- {
- unsigned long l;
- rb_big_pack(x, &l, 1);
- return l % 2 == 0;
- }
-
- default:
- break;
- }
-
- return 0;
-}
-
-static VALUE
-bigdecimal_power_by_bigdecimal(Real const* x, Real const* exp, ssize_t const n)
-{
- VALUE log_x, multiplied, y;
- volatile VALUE obj = exp->obj;
-
- if (VpIsZero(exp)) {
- return VpCheckGetValue(NewOneWrapLimited(1, n));
- }
-
- log_x = BigMath_log(x->obj, SSIZET2NUM(n+1));
- multiplied = BigDecimal_mult2(exp->obj, log_x, SSIZET2NUM(n+1));
- y = BigMath_exp(multiplied, SSIZET2NUM(n));
- RB_GC_GUARD(obj);
-
- return y;
-}
-
-/* call-seq:
- * power(n)
- * power(n, prec)
- *
- * Returns the value raised to the power of n.
- *
- * Note that n must be an Integer.
- *
- * Also available as the operator **.
- */
-static VALUE
-BigDecimal_power(int argc, VALUE*argv, VALUE self)
-{
- ENTER(5);
- VALUE vexp, prec;
- Real* exp = NULL;
- Real *x, *y;
- ssize_t mp, ma, n;
- SIGNED_VALUE int_exp;
- double d;
-
- rb_scan_args(argc, argv, "11", &vexp, &prec);
-
- GUARD_OBJ(x, GetVpValue(self, 1));
- n = NIL_P(prec) ? (ssize_t)(x->Prec*VpBaseFig()) : NUM2SSIZET(prec);
-
- if (VpIsNaN(x)) {
- y = NewZeroWrapLimited(1, n);
- VpSetNaN(y);
- RB_GC_GUARD(y->obj);
- return VpCheckGetValue(y);
- }
-
- retry:
- switch (TYPE(vexp)) {
- case T_FIXNUM:
- break;
-
- case T_BIGNUM:
- break;
-
- case T_FLOAT:
- d = RFLOAT_VALUE(vexp);
- if (d == round(d)) {
- if (FIXABLE(d)) {
- vexp = LONG2FIX((long)d);
- }
- else {
- vexp = rb_dbl2big(d);
- }
- goto retry;
- }
- if (NIL_P(prec)) {
- n += BIGDECIMAL_DOUBLE_FIGURES;
- }
- exp = GetVpValueWithPrec(vexp, 0, 1);
- break;
-
- case T_RATIONAL:
- if (is_zero(rb_rational_num(vexp))) {
- if (is_positive(vexp)) {
- vexp = INT2FIX(0);
- goto retry;
- }
- }
- else if (is_one(rb_rational_den(vexp))) {
- vexp = rb_rational_num(vexp);
- goto retry;
- }
- exp = GetVpValueWithPrec(vexp, n, 1);
- if (NIL_P(prec)) {
- n += n;
- }
- break;
-
- case T_DATA:
- if (is_kind_of_BigDecimal(vexp)) {
- VALUE zero = INT2FIX(0);
- VALUE rounded = BigDecimal_round(1, &zero, vexp);
- if (RTEST(BigDecimal_eq(vexp, rounded))) {
- vexp = BigDecimal_to_i(vexp);
- goto retry;
- }
- if (NIL_P(prec)) {
- GUARD_OBJ(y, GetVpValue(vexp, 1));
- n += y->Prec*VpBaseFig();
- }
- exp = DATA_PTR(vexp);
- break;
- }
- /* fall through */
- default:
- rb_raise(rb_eTypeError,
- "wrong argument type %"PRIsVALUE" (expected scalar Numeric)",
- RB_OBJ_CLASSNAME(vexp));
- }
-
- if (VpIsZero(x)) {
- if (is_negative(vexp)) {
- y = NewZeroWrapNolimit(1, n);
- if (BIGDECIMAL_NEGATIVE_P(x)) {
- if (is_integer(vexp)) {
- if (is_even(vexp)) {
- /* (-0) ** (-even_integer) -> Infinity */
- VpSetPosInf(y);
- }
- else {
- /* (-0) ** (-odd_integer) -> -Infinity */
- VpSetNegInf(y);
- }
- }
- else {
- /* (-0) ** (-non_integer) -> Infinity */
- VpSetPosInf(y);
- }
- }
- else {
- /* (+0) ** (-num) -> Infinity */
- VpSetPosInf(y);
- }
- RB_GC_GUARD(y->obj);
- return VpCheckGetValue(y);
- }
- else if (is_zero(vexp)) {
- return VpCheckGetValue(NewOneWrapLimited(1, n));
- }
- else {
- return VpCheckGetValue(NewZeroWrapLimited(1, n));
- }
- }
-
- if (is_zero(vexp)) {
- return VpCheckGetValue(NewOneWrapLimited(1, n));
- }
- else if (is_one(vexp)) {
- return self;
- }
-
- if (VpIsInf(x)) {
- if (is_negative(vexp)) {
- if (BIGDECIMAL_NEGATIVE_P(x)) {
- if (is_integer(vexp)) {
- if (is_even(vexp)) {
- /* (-Infinity) ** (-even_integer) -> +0 */
- return VpCheckGetValue(NewZeroWrapLimited(1, n));
- }
- else {
- /* (-Infinity) ** (-odd_integer) -> -0 */
- return VpCheckGetValue(NewZeroWrapLimited(-1, n));
- }
- }
- else {
- /* (-Infinity) ** (-non_integer) -> -0 */
- return VpCheckGetValue(NewZeroWrapLimited(-1, n));
- }
- }
- else {
- return VpCheckGetValue(NewZeroWrapLimited(1, n));
- }
- }
- else {
- y = NewZeroWrapLimited(1, n);
- if (BIGDECIMAL_NEGATIVE_P(x)) {
- if (is_integer(vexp)) {
- if (is_even(vexp)) {
- VpSetPosInf(y);
- }
- else {
- VpSetNegInf(y);
- }
- }
- else {
- /* TODO: support complex */
- rb_raise(rb_eMathDomainError,
- "a non-integral exponent for a negative base");
- }
- }
- else {
- VpSetPosInf(y);
- }
- return VpCheckGetValue(y);
- }
- }
-
- if (exp != NULL) {
- return bigdecimal_power_by_bigdecimal(x, exp, n);
- }
- else if (RB_TYPE_P(vexp, T_BIGNUM)) {
- VALUE abs_value = BigDecimal_abs(self);
- if (is_one(abs_value)) {
- return VpCheckGetValue(NewOneWrapLimited(1, n));
- }
- else if (RTEST(rb_funcall(abs_value, '<', 1, INT2FIX(1)))) {
- if (is_negative(vexp)) {
- y = NewZeroWrapLimited(1, n);
- VpSetInf(y, (is_even(vexp) ? 1 : -1) * VpGetSign(x));
- return VpCheckGetValue(y);
- }
- else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
- return VpCheckGetValue(NewZeroWrapLimited(-1, n));
- }
- else {
- return VpCheckGetValue(NewZeroWrapLimited(1, n));
- }
- }
- else {
- if (is_positive(vexp)) {
- y = NewZeroWrapLimited(1, n);
- VpSetInf(y, (is_even(vexp) ? 1 : -1) * VpGetSign(x));
- return VpCheckGetValue(y);
- }
- else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
- return VpCheckGetValue(NewZeroWrapLimited(-1, n));
- }
- else {
- return VpCheckGetValue(NewZeroWrapLimited(1, n));
- }
- }
- }
-
- int_exp = FIX2LONG(vexp);
- ma = int_exp;
- if (ma < 0) ma = -ma;
- if (ma == 0) ma = 1;
-
- if (VpIsDef(x)) {
- mp = x->Prec * (VpBaseFig() + 1);
- GUARD_OBJ(y, NewZeroWrapLimited(1, mp * (ma + 1)));
- }
- else {
- GUARD_OBJ(y, NewZeroWrapLimited(1, 1));
- }
- VpPowerByInt(y, x, int_exp);
- if (!NIL_P(prec) && VpIsDef(y)) {
- VpMidRound(y, VpGetRoundMode(), n);
- }
- return VpCheckGetValue(y);
-}
-
-/* call-seq:
- * self ** other -> bigdecimal
- *
- * Returns the \BigDecimal value of +self+ raised to power +other+:
- *
- * b = BigDecimal('3.14')
- * b ** 2 # => 0.98596e1
- * b ** 2.0 # => 0.98596e1
- * b ** Rational(2, 1) # => 0.98596e1
- *
- * Related: BigDecimal#power.
- *
- */
-static VALUE
-BigDecimal_power_op(VALUE self, VALUE exp)
-{
- return BigDecimal_power(1, &exp, self);
-}
-
-/* :nodoc:
- *
- * private method for dup and clone the provided BigDecimal +other+
- */
-static VALUE
-BigDecimal_initialize_copy(VALUE self, VALUE other)
-{
- Real *pv = rb_check_typeddata(self, &BigDecimal_data_type);
- Real *x = rb_check_typeddata(other, &BigDecimal_data_type);
-
- if (self != other) {
- DATA_PTR(self) = VpCopy(pv, x);
- }
- return self;
-}
-
-static VALUE
-BigDecimal_clone(VALUE self)
-{
- return self;
-}
-
-#ifdef HAVE_RB_OPTS_EXCEPTION_P
-int rb_opts_exception_p(VALUE opts, int default_value);
-#define opts_exception_p(opts) rb_opts_exception_p((opts), 1)
-#else
-static int
-opts_exception_p(VALUE opts)
-{
- static ID kwds[1];
- VALUE exception;
- if (!kwds[0]) {
- kwds[0] = rb_intern_const("exception");
- }
- if (!rb_get_kwargs(opts, kwds, 0, 1, &exception)) return 1;
- switch (exception) {
- case Qtrue: case Qfalse:
- break;
- default:
- rb_raise(rb_eArgError, "true or false is expected as exception: %+"PRIsVALUE,
- exception);
- }
- return exception != Qfalse;
-}
-#endif
-
-static VALUE
-check_exception(VALUE bd)
-{
- assert(is_kind_of_BigDecimal(bd));
-
- Real *vp;
- TypedData_Get_Struct(bd, Real, &BigDecimal_data_type, vp);
- VpCheckGetValue(vp); /* VpCheckGetValue performs exception check */
-
- return bd;
-}
-
-static VALUE
-rb_uint64_convert_to_BigDecimal(uint64_t uval, RB_UNUSED_VAR(size_t digs), int raise_exception)
-{
- VALUE obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0);
-
- Real *vp;
- if (uval == 0) {
- vp = rbd_allocate_struct(1);
- vp->MaxPrec = 1;
- vp->Prec = 1;
- vp->exponent = 1;
- VpSetZero(vp, 1);
- vp->frac[0] = 0;
- }
- else if (uval < BASE) {
- vp = rbd_allocate_struct(1);
- vp->MaxPrec = 1;
- vp->Prec = 1;
- vp->exponent = 1;
- VpSetSign(vp, 1);
- vp->frac[0] = (DECDIG)uval;
- }
- else {
- DECDIG buf[BIGDECIMAL_INT64_MAX_LENGTH] = {0,};
- DECDIG r = uval % BASE;
- size_t len = 0, ntz = 0;
- if (r == 0) {
- // Count and skip trailing zeros
- for (; r == 0 && uval > 0; ++ntz) {
- uval /= BASE;
- r = uval % BASE;
- }
- }
- for (; uval > 0; ++len) {
- // Store digits
- buf[BIGDECIMAL_INT64_MAX_LENGTH - len - 1] = r;
- uval /= BASE;
- r = uval % BASE;
- }
-
- const size_t exp = len + ntz;
- vp = rbd_allocate_struct(len);
- vp->MaxPrec = len;
- vp->Prec = len;
- vp->exponent = exp;
- VpSetSign(vp, 1);
- MEMCPY(vp->frac, buf + BIGDECIMAL_INT64_MAX_LENGTH - len, DECDIG, len);
- }
-
- return BigDecimal_wrap_struct(obj, vp);
-}
-
-static VALUE
-rb_int64_convert_to_BigDecimal(int64_t ival, size_t digs, int raise_exception)
-{
- const uint64_t uval = (ival < 0) ? (((uint64_t)-(ival+1))+1) : (uint64_t)ival;
- VALUE bd = rb_uint64_convert_to_BigDecimal(uval, digs, raise_exception);
- if (ival < 0) {
- Real *vp;
- TypedData_Get_Struct(bd, Real, &BigDecimal_data_type, vp);
- VpSetSign(vp, -1);
- }
- return bd;
-}
-
-static VALUE
-rb_big_convert_to_BigDecimal(VALUE val, RB_UNUSED_VAR(size_t digs), int raise_exception)
-{
- assert(RB_TYPE_P(val, T_BIGNUM));
-
- int leading_zeros;
- size_t size = rb_absint_size(val, &leading_zeros);
- int sign = FIX2INT(rb_big_cmp(val, INT2FIX(0)));
- if (sign < 0 && leading_zeros == 0) {
- size += 1;
- }
- if (size <= sizeof(long)) {
- if (sign < 0) {
- return rb_int64_convert_to_BigDecimal(NUM2LONG(val), digs, raise_exception);
- }
- else {
- return rb_uint64_convert_to_BigDecimal(NUM2ULONG(val), digs, raise_exception);
- }
- }
-#if defined(SIZEOF_LONG_LONG) && SIZEOF_LONG < SIZEOF_LONG_LONG
- else if (size <= sizeof(LONG_LONG)) {
- if (sign < 0) {
- return rb_int64_convert_to_BigDecimal(NUM2LL(val), digs, raise_exception);
- }
- else {
- return rb_uint64_convert_to_BigDecimal(NUM2ULL(val), digs, raise_exception);
- }
- }
-#endif
- else {
- VALUE str = rb_big2str(val, 10);
- Real *vp = VpCreateRbObject(RSTRING_LEN(str) + BASE_FIG + 1,
- RSTRING_PTR(str), true);
- RB_GC_GUARD(str);
- return check_exception(vp->obj);
- }
-}
-
-static VALUE
-rb_inum_convert_to_BigDecimal(VALUE val, RB_UNUSED_VAR(size_t digs), int raise_exception)
-{
- assert(RB_INTEGER_TYPE_P(val));
- if (FIXNUM_P(val)) {
- return rb_int64_convert_to_BigDecimal(FIX2LONG(val), digs, raise_exception);
- }
- else {
- return rb_big_convert_to_BigDecimal(val, digs, raise_exception);
- }
-}
-
-static VALUE
-rb_float_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
-{
- assert(RB_FLOAT_TYPE_P(val));
-
- double d = RFLOAT_VALUE(val);
-
- if (isnan(d)) {
- VALUE obj = BigDecimal_nan();
- return check_exception(obj);
- }
- else if (isinf(d)) {
- VALUE obj;
- if (d > 0) {
- obj = BigDecimal_positive_infinity();
- }
- else {
- obj = BigDecimal_negative_infinity();
- }
- return check_exception(obj);
- }
- else if (d == 0.0) {
- if (1/d < 0.0) {
- return BigDecimal_negative_zero();
- }
- else {
- return BigDecimal_positive_zero();
- }
- }
-
- if (digs == SIZE_MAX) {
- if (!raise_exception)
- return Qnil;
- rb_raise(rb_eArgError,
- "can't omit precision for a %"PRIsVALUE".",
- CLASS_OF(val));
- }
- else if (digs > BIGDECIMAL_DOUBLE_FIGURES) {
- if (!raise_exception)
- return Qnil;
- rb_raise(rb_eArgError, "precision too large.");
- }
-
- /* Use the same logic in flo_to_s to convert a float to a decimal string */
- char buf[BIGDECIMAL_DOUBLE_FIGURES + BASE_FIG + 2 + 1]; /* sizeof(buf) == 28 in the typical case */
- int decpt, negative_p;
- char *e;
- const int mode = digs == 0 ? 0 : 2;
- char *p = BigDecimal_dtoa(d, mode, (int)digs, &decpt, &negative_p, &e);
- int len10 = (int)(e - p);
- if (len10 > BIGDECIMAL_DOUBLE_FIGURES) {
- /* TODO: Presumably, rounding should be done here. */
- len10 = BIGDECIMAL_DOUBLE_FIGURES;
- }
- memcpy(buf, p, len10);
- xfree(p);
-
- VALUE inum;
- size_t RB_UNUSED_VAR(prec) = 0;
- SIGNED_VALUE exp = 0;
- if (decpt > 0) {
- if (decpt < len10) {
- /*
- * len10 |---------------|
- * : |-------| frac_len10 = len10 - decpt
- * decpt |-------| |--| ntz10 = BASE_FIG - frac_len10 % BASE_FIG
- * : : :
- * 00 dd dddd.dddd dd 00
- * prec |-----.----.----.-----| prec = exp + roomof(frac_len, BASE_FIG)
- * exp |-----.----| exp = roomof(decpt, BASE_FIG)
- */
- const size_t frac_len10 = len10 - decpt;
- const size_t ntz10 = BASE_FIG - frac_len10 % BASE_FIG;
- memset(buf + len10, '0', ntz10);
- buf[len10 + ntz10] = '\0';
- inum = rb_cstr_to_inum(buf, 10, false);
-
- exp = roomof(decpt, BASE_FIG);
- prec = exp + roomof(frac_len10, BASE_FIG);
- }
- else {
- /*
- * decpt |-----------------------|
- * len10 |----------| :
- * : |------------| exp10
- * : : :
- * 00 dd dddd dd 00 0000 0000.0
- * : : : :
- * : |--| ntz10 = exp10 % BASE_FIG
- * prec |-----.----.-----| :
- * : |----.----| exp10 / BASE_FIG
- * exp |-----.----.-----.----.----|
- */
- const size_t exp10 = decpt - len10;
- const size_t ntz10 = exp10 % BASE_FIG;
-
- memset(buf + len10, '0', ntz10);
- buf[len10 + ntz10] = '\0';
- inum = rb_cstr_to_inum(buf, 10, false);
-
- prec = roomof(len10 + ntz10, BASE_FIG);
- exp = prec + exp10 / BASE_FIG;
- }
- }
- else if (decpt == 0) {
- /*
- * len10 |------------|
- * : :
- * 0.dddd dddd dd 00
- * : : :
- * : |--| ntz10 = prec * BASE_FIG - len10
- * prec |----.----.-----| roomof(len10, BASE_FIG)
- */
- prec = roomof(len10, BASE_FIG);
- const size_t ntz10 = prec * BASE_FIG - len10;
-
- memset(buf + len10, '0', ntz10);
- buf[len10 + ntz10] = '\0';
- inum = rb_cstr_to_inum(buf, 10, false);
- }
- else {
- /*
- * len10 |---------------|
- * : :
- * decpt |-------| |--| ntz10 = prec * BASE_FIG - nlz10 - len10
- * : : :
- * 0.0000 00 dd dddd dddd dd 00
- * : : :
- * nlz10 |--| : decpt % BASE_FIG
- * prec |-----.----.----.-----| roomof(decpt + len10, BASE_FIG) - exp
- * exp |----| decpt / BASE_FIG
- */
- decpt = -decpt;
-
- const size_t nlz10 = decpt % BASE_FIG;
- exp = decpt / BASE_FIG;
- prec = roomof(decpt + len10, BASE_FIG) - exp;
- const size_t ntz10 = prec * BASE_FIG - nlz10 - len10;
-
- if (nlz10 > 0) {
- memmove(buf + nlz10, buf, len10);
- memset(buf, '0', nlz10);
- }
- memset(buf + nlz10 + len10, '0', ntz10);
- buf[nlz10 + len10 + ntz10] = '\0';
- inum = rb_cstr_to_inum(buf, 10, false);
-
- exp = -exp;
- }
-
- VALUE bd = rb_inum_convert_to_BigDecimal(inum, SIZE_MAX, raise_exception);
- Real *vp;
- TypedData_Get_Struct(bd, Real, &BigDecimal_data_type, vp);
- assert(vp->Prec == prec);
- vp->exponent = exp;
-
- if (negative_p) VpSetSign(vp, -1);
- return bd;
-}
-
-static VALUE
-rb_rational_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
-{
- assert(RB_TYPE_P(val, T_RATIONAL));
-
- if (digs == SIZE_MAX) {
- if (!raise_exception)
- return Qnil;
- rb_raise(rb_eArgError,
- "can't omit precision for a %"PRIsVALUE".",
- CLASS_OF(val));
- }
-
- VALUE num = rb_inum_convert_to_BigDecimal(rb_rational_num(val), 0, raise_exception);
- VALUE d = BigDecimal_div2(num, rb_rational_den(val), SIZET2NUM(digs));
- return d;
-}
-
-static VALUE
-rb_cstr_convert_to_BigDecimal(const char *c_str, size_t digs, int raise_exception)
-{
- if (digs == SIZE_MAX)
- digs = 0;
-
- Real *vp = VpCreateRbObject(digs, c_str, raise_exception);
- if (!vp)
- return Qnil;
- return VpCheckGetValue(vp);
-}
-
-static inline VALUE
-rb_str_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
-{
- const char *c_str = StringValueCStr(val);
- return rb_cstr_convert_to_BigDecimal(c_str, digs, raise_exception);
-}
-
-static VALUE
-rb_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
-{
- switch (val) {
- case Qnil:
- case Qtrue:
- case Qfalse:
- if (raise_exception) {
- const char *cname = NIL_P(val) ? "nil" :
- val == Qtrue ? "true" :
- val == Qfalse ? "false" :
- NULL;
- rb_raise(rb_eTypeError,
- "can't convert %s into BigDecimal", cname);
- }
- return Qnil;
-
- default:
- break;
- }
-
- if (is_kind_of_BigDecimal(val)) {
- if (digs == SIZE_MAX)
- return check_exception(val);
-
- Real *vp;
- TypedData_Get_Struct(val, Real, &BigDecimal_data_type, vp);
-
- VALUE copy = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0);
- vp = VpCopy(NULL, vp);
- /* TODO: rounding */
- BigDecimal_wrap_struct(copy, vp);
- return VpCheckGetValue(vp);
- }
- else if (RB_INTEGER_TYPE_P(val)) {
- return rb_inum_convert_to_BigDecimal(val, digs, raise_exception);
- }
- else if (RB_FLOAT_TYPE_P(val)) {
- return rb_float_convert_to_BigDecimal(val, digs, raise_exception);
- }
- else if (RB_TYPE_P(val, T_RATIONAL)) {
- return rb_rational_convert_to_BigDecimal(val, digs, raise_exception);
- }
- else if (RB_TYPE_P(val, T_COMPLEX)) {
- VALUE im = rb_complex_imag(val);
- if (!is_zero(im)) {
- /* TODO: handle raise_exception */
- rb_raise(rb_eArgError,
- "Unable to make a BigDecimal from non-zero imaginary number");
- }
- return rb_convert_to_BigDecimal(rb_complex_real(val), digs, raise_exception);
- }
- else if (RB_TYPE_P(val, T_STRING)) {
- return rb_str_convert_to_BigDecimal(val, digs, raise_exception);
- }
-
- /* TODO: chheck to_d */
- /* TODO: chheck to_int */
-
- VALUE str = rb_check_convert_type(val, T_STRING, "String", "to_str");
- if (!RB_TYPE_P(str, T_STRING)) {
- if (raise_exception) {
- rb_raise(rb_eTypeError,
- "can't convert %"PRIsVALUE" into BigDecimal", rb_obj_class(val));
- }
- return Qnil;
- }
- return rb_str_convert_to_BigDecimal(str, digs, raise_exception);
-}
-
-/* call-seq:
- * BigDecimal(value, exception: true) -> bigdecimal
- * BigDecimal(value, ndigits, exception: true) -> bigdecimal
- *
- * Returns the \BigDecimal converted from +value+
- * with a precision of +ndigits+ decimal digits.
- *
- * When +ndigits+ is less than the number of significant digits
- * in the value, the result is rounded to that number of digits,
- * according to the current rounding mode; see BigDecimal.mode.
- *
- * When +ndigits+ is 0, the number of digits to correctly represent a float number
- * is determined automatically.
- *
- * Returns +value+ converted to a \BigDecimal, depending on the type of +value+:
- *
- * - Integer, Float, Rational, Complex, or BigDecimal: converted directly:
- *
- * # Integer, Complex, or BigDecimal value does not require ndigits; ignored if given.
- * BigDecimal(2) # => 0.2e1
- * BigDecimal(Complex(2, 0)) # => 0.2e1
- * BigDecimal(BigDecimal(2)) # => 0.2e1
- * # Float or Rational value requires ndigits.
- * BigDecimal(2.0, 0) # => 0.2e1
- * BigDecimal(Rational(2, 1), 0) # => 0.2e1
- *
- * - String: converted by parsing if it contains an integer or floating-point literal;
- * leading and trailing whitespace is ignored:
- *
- * # String does not require ndigits; ignored if given.
- * BigDecimal('2') # => 0.2e1
- * BigDecimal('2.0') # => 0.2e1
- * BigDecimal('0.2e1') # => 0.2e1
- * BigDecimal(' 2.0 ') # => 0.2e1
- *
- * - Other type that responds to method <tt>:to_str</tt>:
- * first converted to a string, then converted to a \BigDecimal, as above.
- *
- * - Other type:
- *
- * - Raises an exception if keyword argument +exception+ is +true+.
- * - Returns +nil+ if keyword argument +exception+ is +false+.
- *
- * Raises an exception if +value+ evaluates to a Float
- * and +digits+ is larger than Float::DIG + 1.
- *
- */
-static VALUE
-f_BigDecimal(int argc, VALUE *argv, VALUE self)
-{
- VALUE val, digs_v, opts = Qnil;
- argc = rb_scan_args(argc, argv, "11:", &val, &digs_v, &opts);
- int exception = opts_exception_p(opts);
-
- size_t digs = SIZE_MAX; /* this means digs is omitted */
- if (argc > 1) {
- digs_v = rb_to_int(digs_v);
- if (FIXNUM_P(digs_v)) {
- long n = FIX2LONG(digs_v);
- if (n < 0)
- goto negative_digs;
- digs = (size_t)n;
- }
- else {
- if (RBIGNUM_NEGATIVE_P(digs_v)) {
- negative_digs:
- if (!exception)
- return Qnil;
- rb_raise(rb_eArgError, "negative precision");
- }
- digs = NUM2SIZET(digs_v);
- }
- }
-
- return rb_convert_to_BigDecimal(val, digs, exception);
-}
-
-static VALUE
-BigDecimal_s_interpret_loosely(VALUE klass, VALUE str)
-{
- char const *c_str = StringValueCStr(str);
- Real *vp = VpNewRbClass(0, c_str, klass, false, true);
- if (!vp)
- return Qnil;
- else
- return VpCheckGetValue(vp);
-}
-
- /* call-seq:
- * BigDecimal.limit(digits)
- *
- * Limit the number of significant digits in newly created BigDecimal
- * numbers to the specified value. Rounding is performed as necessary,
- * as specified by BigDecimal.mode.
- *
- * A limit of 0, the default, means no upper limit.
- *
- * The limit specified by this method takes less priority over any limit
- * specified to instance methods such as ceil, floor, truncate, or round.
- */
-static VALUE
-BigDecimal_limit(int argc, VALUE *argv, VALUE self)
-{
- VALUE nFig;
- VALUE nCur = SIZET2NUM(VpGetPrecLimit());
-
- if (rb_scan_args(argc, argv, "01", &nFig) == 1) {
- int nf;
- if (NIL_P(nFig)) return nCur;
- nf = NUM2INT(nFig);
- if (nf < 0) {
- rb_raise(rb_eArgError, "argument must be positive");
- }
- VpSetPrecLimit(nf);
- }
- return nCur;
-}
-
-/* Returns the sign of the value.
- *
- * Returns a positive value if > 0, a negative value if < 0.
- * It behaves the same with zeros -
- * it returns a positive value for a positive zero (BigDecimal('0')) and
- * a negative value for a negative zero (BigDecimal('-0')).
- *
- * The specific value returned indicates the type and sign of the BigDecimal,
- * as follows:
- *
- * BigDecimal::SIGN_NaN:: value is Not a Number
- * BigDecimal::SIGN_POSITIVE_ZERO:: value is +0
- * BigDecimal::SIGN_NEGATIVE_ZERO:: value is -0
- * BigDecimal::SIGN_POSITIVE_INFINITE:: value is +Infinity
- * BigDecimal::SIGN_NEGATIVE_INFINITE:: value is -Infinity
- * BigDecimal::SIGN_POSITIVE_FINITE:: value is positive
- * BigDecimal::SIGN_NEGATIVE_FINITE:: value is negative
- */
-static VALUE
-BigDecimal_sign(VALUE self)
-{ /* sign */
- int s = GetVpValue(self, 1)->sign;
- return INT2FIX(s);
-}
-
-/*
- * call-seq: BigDecimal.save_exception_mode { ... }
- *
- * Execute the provided block, but preserve the exception mode
- *
- * BigDecimal.save_exception_mode do
- * BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
- * BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
- *
- * BigDecimal(BigDecimal('Infinity'))
- * BigDecimal(BigDecimal('-Infinity'))
- * BigDecimal(BigDecimal('NaN'))
- * end
- *
- * For use with the BigDecimal::EXCEPTION_*
- *
- * See BigDecimal.mode
- */
-static VALUE
-BigDecimal_save_exception_mode(VALUE self)
-{
- unsigned short const exception_mode = VpGetException();
- int state;
- VALUE ret = rb_protect(rb_yield, Qnil, &state);
- VpSetException(exception_mode);
- if (state) rb_jump_tag(state);
- return ret;
-}
-
-/*
- * call-seq: BigDecimal.save_rounding_mode { ... }
- *
- * Execute the provided block, but preserve the rounding mode
- *
- * BigDecimal.save_rounding_mode do
- * BigDecimal.mode(BigDecimal::ROUND_MODE, :up)
- * puts BigDecimal.mode(BigDecimal::ROUND_MODE)
- * end
- *
- * For use with the BigDecimal::ROUND_*
- *
- * See BigDecimal.mode
- */
-static VALUE
-BigDecimal_save_rounding_mode(VALUE self)
-{
- unsigned short const round_mode = VpGetRoundMode();
- int state;
- VALUE ret = rb_protect(rb_yield, Qnil, &state);
- VpSetRoundMode(round_mode);
- if (state) rb_jump_tag(state);
- return ret;
-}
-
-/*
- * call-seq: BigDecimal.save_limit { ... }
- *
- * Execute the provided block, but preserve the precision limit
- *
- * BigDecimal.limit(100)
- * puts BigDecimal.limit
- * BigDecimal.save_limit do
- * BigDecimal.limit(200)
- * puts BigDecimal.limit
- * end
- * puts BigDecimal.limit
- *
- */
-static VALUE
-BigDecimal_save_limit(VALUE self)
-{
- size_t const limit = VpGetPrecLimit();
- int state;
- VALUE ret = rb_protect(rb_yield, Qnil, &state);
- VpSetPrecLimit(limit);
- if (state) rb_jump_tag(state);
- return ret;
-}
-
-/* call-seq:
- * BigMath.exp(decimal, numeric) -> BigDecimal
- *
- * Computes the value of e (the base of natural logarithms) raised to the
- * power of +decimal+, to the specified number of digits of precision.
- *
- * If +decimal+ is infinity, returns Infinity.
- *
- * If +decimal+ is NaN, returns NaN.
- */
-static VALUE
-BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
-{
- ssize_t prec, n, i;
- Real* vx = NULL;
- VALUE one, d, y;
- int negative = 0;
- int infinite = 0;
- int nan = 0;
- double flo;
-
- prec = NUM2SSIZET(vprec);
- if (prec <= 0) {
- rb_raise(rb_eArgError, "Zero or negative precision for exp");
- }
-
- /* TODO: the following switch statement is almost same as one in the
- * BigDecimalCmp function. */
- switch (TYPE(x)) {
- case T_DATA:
- if (!is_kind_of_BigDecimal(x)) break;
- vx = DATA_PTR(x);
- negative = BIGDECIMAL_NEGATIVE_P(vx);
- infinite = VpIsPosInf(vx) || VpIsNegInf(vx);
- nan = VpIsNaN(vx);
- break;
-
- case T_FIXNUM:
- /* fall through */
- case T_BIGNUM:
- vx = GetVpValue(x, 0);
- break;
-
- case T_FLOAT:
- flo = RFLOAT_VALUE(x);
- negative = flo < 0;
- infinite = isinf(flo);
- nan = isnan(flo);
- if (!infinite && !nan) {
- vx = GetVpValueWithPrec(x, 0, 0);
- }
- break;
-
- case T_RATIONAL:
- vx = GetVpValueWithPrec(x, prec, 0);
- break;
-
- default:
- break;
- }
- if (infinite) {
- if (negative) {
- return VpCheckGetValue(GetVpValueWithPrec(INT2FIX(0), prec, 1));
- }
- else {
- Real* vy = NewZeroWrapNolimit(1, prec);
- VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
- RB_GC_GUARD(vy->obj);
- return VpCheckGetValue(vy);
- }
- }
- else if (nan) {
- Real* vy = NewZeroWrapNolimit(1, prec);
- VpSetNaN(vy);
- RB_GC_GUARD(vy->obj);
- return VpCheckGetValue(vy);
- }
- else if (vx == NULL) {
- cannot_be_coerced_into_BigDecimal(rb_eArgError, x);
- }
- x = vx->obj;
-
- n = prec + BIGDECIMAL_DOUBLE_FIGURES;
- negative = BIGDECIMAL_NEGATIVE_P(vx);
- if (negative) {
- VALUE x_zero = INT2NUM(1);
- VALUE x_copy = f_BigDecimal(1, &x_zero, klass);
- x = BigDecimal_initialize_copy(x_copy, x);
- vx = DATA_PTR(x);
- VpSetSign(vx, 1);
- }
-
- one = VpCheckGetValue(NewOneWrapLimited(1, 1));
- y = one;
- d = y;
- i = 1;
-
- while (!VpIsZero((Real*)DATA_PTR(d))) {
- SIGNED_VALUE const ey = VpExponent10(DATA_PTR(y));
- SIGNED_VALUE const ed = VpExponent10(DATA_PTR(d));
- ssize_t m = n - vabs(ey - ed);
-
- rb_thread_check_ints();
-
- if (m <= 0) {
- break;
- }
- else if ((size_t)m < BIGDECIMAL_DOUBLE_FIGURES) {
- m = BIGDECIMAL_DOUBLE_FIGURES;
- }
-
- d = BigDecimal_mult(d, x); /* d <- d * x */
- d = BigDecimal_div2(d, SSIZET2NUM(i), SSIZET2NUM(m)); /* d <- d / i */
- y = BigDecimal_add(y, d); /* y <- y + d */
- ++i; /* i <- i + 1 */
- }
-
- if (negative) {
- return BigDecimal_div2(one, y, vprec);
- }
- else {
- vprec = SSIZET2NUM(prec - VpExponent10(DATA_PTR(y)));
- return BigDecimal_round(1, &vprec, y);
- }
-
- RB_GC_GUARD(one);
- RB_GC_GUARD(x);
- RB_GC_GUARD(y);
- RB_GC_GUARD(d);
-}
-
-/* call-seq:
- * BigMath.log(decimal, numeric) -> BigDecimal
- *
- * Computes the natural logarithm of +decimal+ to the specified number of
- * digits of precision, +numeric+.
- *
- * If +decimal+ is zero or negative, raises Math::DomainError.
- *
- * If +decimal+ is positive infinity, returns Infinity.
- *
- * If +decimal+ is NaN, returns NaN.
- */
-static VALUE
-BigMath_s_log(VALUE klass, VALUE x, VALUE vprec)
-{
- ssize_t prec, n, i;
- SIGNED_VALUE expo;
- Real* vx = NULL;
- VALUE vn, one, two, w, x2, y, d;
- int zero = 0;
- int negative = 0;
- int infinite = 0;
- int nan = 0;
- double flo;
- long fix;
-
- if (!is_integer(vprec)) {
- rb_raise(rb_eArgError, "precision must be an Integer");
- }
-
- prec = NUM2SSIZET(vprec);
- if (prec <= 0) {
- rb_raise(rb_eArgError, "Zero or negative precision for exp");
- }
-
- /* TODO: the following switch statement is almost same as one in the
- * BigDecimalCmp function. */
- switch (TYPE(x)) {
- case T_DATA:
- if (!is_kind_of_BigDecimal(x)) break;
- vx = DATA_PTR(x);
- zero = VpIsZero(vx);
- negative = BIGDECIMAL_NEGATIVE_P(vx);
- infinite = VpIsPosInf(vx) || VpIsNegInf(vx);
- nan = VpIsNaN(vx);
- break;
-
- case T_FIXNUM:
- fix = FIX2LONG(x);
- zero = fix == 0;
- negative = fix < 0;
- goto get_vp_value;
-
- case T_BIGNUM:
- i = FIX2INT(rb_big_cmp(x, INT2FIX(0)));
- zero = i == 0;
- negative = i < 0;
-get_vp_value:
- if (zero || negative) break;
- vx = GetVpValue(x, 0);
- break;
-
- case T_FLOAT:
- flo = RFLOAT_VALUE(x);
- zero = flo == 0;
- negative = flo < 0;
- infinite = isinf(flo);
- nan = isnan(flo);
- if (!zero && !negative && !infinite && !nan) {
- vx = GetVpValueWithPrec(x, 0, 1);
- }
- break;
-
- case T_RATIONAL:
- zero = RRATIONAL_ZERO_P(x);
- negative = RRATIONAL_NEGATIVE_P(x);
- if (zero || negative) break;
- vx = GetVpValueWithPrec(x, prec, 1);
- break;
-
- case T_COMPLEX:
- rb_raise(rb_eMathDomainError,
- "Complex argument for BigMath.log");
-
- default:
- break;
- }
- if (infinite && !negative) {
- Real *vy = NewZeroWrapNolimit(1, prec);
- RB_GC_GUARD(vy->obj);
- VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
- return VpCheckGetValue(vy);
- }
- else if (nan) {
- Real* vy = NewZeroWrapNolimit(1, prec);
- RB_GC_GUARD(vy->obj);
- VpSetNaN(vy);
- return VpCheckGetValue(vy);
- }
- else if (zero || negative) {
- rb_raise(rb_eMathDomainError,
- "Zero or negative argument for log");
- }
- else if (vx == NULL) {
- cannot_be_coerced_into_BigDecimal(rb_eArgError, x);
- }
- x = VpCheckGetValue(vx);
-
- one = VpCheckGetValue(NewOneWrapLimited(1, 1));
- two = VpCheckGetValue(VpCreateRbObject(1, "2", true));
-
- n = prec + BIGDECIMAL_DOUBLE_FIGURES;
- vn = SSIZET2NUM(n);
- expo = VpExponent10(vx);
- if (expo < 0 || expo >= 3) {
- char buf[DECIMAL_SIZE_OF_BITS(SIZEOF_VALUE * CHAR_BIT) + 4];
- snprintf(buf, sizeof(buf), "1E%"PRIdVALUE, -expo);
- x = BigDecimal_mult2(x, VpCheckGetValue(VpCreateRbObject(1, buf, true)), vn);
- }
- else {
- expo = 0;
- }
- w = BigDecimal_sub(x, one);
- x = BigDecimal_div2(w, BigDecimal_add(x, one), vn);
- x2 = BigDecimal_mult2(x, x, vn);
- y = x;
- d = y;
- i = 1;
- while (!VpIsZero((Real*)DATA_PTR(d))) {
- SIGNED_VALUE const ey = VpExponent10(DATA_PTR(y));
- SIGNED_VALUE const ed = VpExponent10(DATA_PTR(d));
- ssize_t m = n - vabs(ey - ed);
- if (m <= 0) {
- break;
- }
- else if ((size_t)m < BIGDECIMAL_DOUBLE_FIGURES) {
- m = BIGDECIMAL_DOUBLE_FIGURES;
- }
-
- x = BigDecimal_mult2(x2, x, vn);
- i += 2;
- d = BigDecimal_div2(x, SSIZET2NUM(i), SSIZET2NUM(m));
- y = BigDecimal_add(y, d);
- }
-
- y = BigDecimal_mult(y, two);
- if (expo != 0) {
- VALUE log10, vexpo, dy;
- log10 = BigMath_s_log(klass, INT2FIX(10), vprec);
- vexpo = VpCheckGetValue(GetVpValue(SSIZET2NUM(expo), 1));
- dy = BigDecimal_mult(log10, vexpo);
- y = BigDecimal_add(y, dy);
- }
-
- RB_GC_GUARD(one);
- RB_GC_GUARD(two);
- RB_GC_GUARD(vn);
- RB_GC_GUARD(x2);
- RB_GC_GUARD(y);
- RB_GC_GUARD(d);
-
- return y;
-}
-
-static VALUE BIGDECIMAL_NAN = Qnil;
-
-static VALUE
-BigDecimal_nan(void)
-{
- return BIGDECIMAL_NAN;
-}
-
-static VALUE BIGDECIMAL_POSITIVE_INFINITY = Qnil;
-
-static VALUE
-BigDecimal_positive_infinity(void)
-{
- return BIGDECIMAL_POSITIVE_INFINITY;
-}
-
-static VALUE BIGDECIMAL_NEGATIVE_INFINITY = Qnil;
-
-static VALUE
-BigDecimal_negative_infinity(void)
-{
- return BIGDECIMAL_NEGATIVE_INFINITY;
-}
-
-static VALUE BIGDECIMAL_POSITIVE_ZERO = Qnil;
-
-static VALUE
-BigDecimal_positive_zero(void)
-{
- return BIGDECIMAL_POSITIVE_ZERO;
-}
-
-static VALUE BIGDECIMAL_NEGATIVE_ZERO = Qnil;
-
-static VALUE
-BigDecimal_negative_zero(void)
-{
- return BIGDECIMAL_NEGATIVE_ZERO;
-}
-
-/* Document-class: BigDecimal
- * BigDecimal provides arbitrary-precision floating point decimal arithmetic.
- *
- * == Introduction
- *
- * Ruby provides built-in support for arbitrary precision integer arithmetic.
- *
- * For example:
- *
- * 42**13 #=> 1265437718438866624512
- *
- * BigDecimal provides similar support for very large or very accurate floating
- * point numbers.
- *
- * Decimal arithmetic is also useful for general calculation, because it
- * provides the correct answers people expect--whereas normal binary floating
- * point arithmetic often introduces subtle errors because of the conversion
- * between base 10 and base 2.
- *
- * For example, try:
- *
- * sum = 0
- * 10_000.times do
- * sum = sum + 0.0001
- * end
- * print sum #=> 0.9999999999999062
- *
- * and contrast with the output from:
- *
- * require 'bigdecimal'
- *
- * sum = BigDecimal("0")
- * 10_000.times do
- * sum = sum + BigDecimal("0.0001")
- * end
- * print sum #=> 0.1E1
- *
- * Similarly:
- *
- * (BigDecimal("1.2") - BigDecimal("1.0")) == BigDecimal("0.2") #=> true
- *
- * (1.2 - 1.0) == 0.2 #=> false
- *
- * == A Note About Precision
- *
- * For a calculation using a \BigDecimal and another +value+,
- * the precision of the result depends on the type of +value+:
- *
- * - If +value+ is a \Float,
- * the precision is Float::DIG + 1.
- * - If +value+ is a \Rational, the precision is larger than Float::DIG + 1.
- * - If +value+ is a \BigDecimal, the precision is +value+'s precision in the
- * internal representation, which is platform-dependent.
- * - If +value+ is other object, the precision is determined by the result of +BigDecimal(value)+.
- *
- * == Special features of accurate decimal arithmetic
- *
- * Because BigDecimal is more accurate than normal binary floating point
- * arithmetic, it requires some special values.
- *
- * === Infinity
- *
- * BigDecimal sometimes needs to return infinity, for example if you divide
- * a value by zero.
- *
- * BigDecimal("1.0") / BigDecimal("0.0") #=> Infinity
- * BigDecimal("-1.0") / BigDecimal("0.0") #=> -Infinity
- *
- * You can represent infinite numbers to BigDecimal using the strings
- * <code>'Infinity'</code>, <code>'+Infinity'</code> and
- * <code>'-Infinity'</code> (case-sensitive)
- *
- * === Not a Number
- *
- * When a computation results in an undefined value, the special value +NaN+
- * (for 'not a number') is returned.
- *
- * Example:
- *
- * BigDecimal("0.0") / BigDecimal("0.0") #=> NaN
- *
- * You can also create undefined values.
- *
- * NaN is never considered to be the same as any other value, even NaN itself:
- *
- * n = BigDecimal('NaN')
- * n == 0.0 #=> false
- * n == n #=> false
- *
- * === Positive and negative zero
- *
- * If a computation results in a value which is too small to be represented as
- * a BigDecimal within the currently specified limits of precision, zero must
- * be returned.
- *
- * If the value which is too small to be represented is negative, a BigDecimal
- * value of negative zero is returned.
- *
- * BigDecimal("1.0") / BigDecimal("-Infinity") #=> -0.0
- *
- * If the value is positive, a value of positive zero is returned.
- *
- * BigDecimal("1.0") / BigDecimal("Infinity") #=> 0.0
- *
- * (See BigDecimal.mode for how to specify limits of precision.)
- *
- * Note that +-0.0+ and +0.0+ are considered to be the same for the purposes of
- * comparison.
- *
- * Note also that in mathematics, there is no particular concept of negative
- * or positive zero; true mathematical zero has no sign.
- *
- * == bigdecimal/util
- *
- * When you require +bigdecimal/util+, the #to_d method will be
- * available on BigDecimal and the native Integer, Float, Rational,
- * and String classes:
- *
- * require 'bigdecimal/util'
- *
- * 42.to_d # => 0.42e2
- * 0.5.to_d # => 0.5e0
- * (2/3r).to_d(3) # => 0.667e0
- * "0.5".to_d # => 0.5e0
- *
- * == License
- *
- * Copyright (C) 2002 by Shigeo Kobayashi <shigeo@tinyforest.gr.jp>.
- *
- * BigDecimal is released under the Ruby and 2-clause BSD licenses.
- * See LICENSE.txt for details.
- *
- * Maintained by mrkn <mrkn@mrkn.jp> and ruby-core members.
- *
- * Documented by zzak <zachary@zacharyscott.net>, mathew <meta@pobox.com>, and
- * many other contributors.
- */
-void
-Init_bigdecimal(void)
-{
-#ifdef HAVE_RB_EXT_RACTOR_SAFE
- rb_ext_ractor_safe(true);
-#endif
- VALUE arg;
-
- id_BigDecimal_exception_mode = rb_intern_const("BigDecimal.exception_mode");
- id_BigDecimal_rounding_mode = rb_intern_const("BigDecimal.rounding_mode");
- id_BigDecimal_precision_limit = rb_intern_const("BigDecimal.precision_limit");
-
- /* Initialize VP routines */
- VpInit(0UL);
-
- /* Class and method registration */
- rb_cBigDecimal = rb_define_class("BigDecimal", rb_cNumeric);
-
- /* Global function */
- rb_define_global_function("BigDecimal", f_BigDecimal, -1);
-
- /* Class methods */
- rb_undef_alloc_func(rb_cBigDecimal);
- rb_undef_method(CLASS_OF(rb_cBigDecimal), "new");
- rb_define_singleton_method(rb_cBigDecimal, "interpret_loosely", BigDecimal_s_interpret_loosely, 1);
- rb_define_singleton_method(rb_cBigDecimal, "mode", BigDecimal_mode, -1);
- rb_define_singleton_method(rb_cBigDecimal, "limit", BigDecimal_limit, -1);
- rb_define_singleton_method(rb_cBigDecimal, "double_fig", BigDecimal_double_fig, 0);
- rb_define_singleton_method(rb_cBigDecimal, "_load", BigDecimal_load, 1);
-
- rb_define_singleton_method(rb_cBigDecimal, "save_exception_mode", BigDecimal_save_exception_mode, 0);
- rb_define_singleton_method(rb_cBigDecimal, "save_rounding_mode", BigDecimal_save_rounding_mode, 0);
- rb_define_singleton_method(rb_cBigDecimal, "save_limit", BigDecimal_save_limit, 0);
-
- /* Constants definition */
-
- /*
- * The version of bigdecimal library
- */
- rb_define_const(rb_cBigDecimal, "VERSION", rb_str_new2(BIGDECIMAL_VERSION));
-
- /*
- * Base value used in internal calculations. On a 32 bit system, BASE
- * is 10000, indicating that calculation is done in groups of 4 digits.
- * (If it were larger, BASE**2 wouldn't fit in 32 bits, so you couldn't
- * guarantee that two groups could always be multiplied together without
- * overflow.)
- */
- rb_define_const(rb_cBigDecimal, "BASE", INT2FIX((SIGNED_VALUE)VpBaseVal()));
-
- /* Exceptions */
-
- /*
- * 0xff: Determines whether overflow, underflow or zero divide result in
- * an exception being thrown. See BigDecimal.mode.
- */
- rb_define_const(rb_cBigDecimal, "EXCEPTION_ALL", INT2FIX(VP_EXCEPTION_ALL));
-
- /*
- * 0x02: Determines what happens when the result of a computation is not a
- * number (NaN). See BigDecimal.mode.
- */
- rb_define_const(rb_cBigDecimal, "EXCEPTION_NaN", INT2FIX(VP_EXCEPTION_NaN));
-
- /*
- * 0x01: Determines what happens when the result of a computation is
- * infinity. See BigDecimal.mode.
- */
- rb_define_const(rb_cBigDecimal, "EXCEPTION_INFINITY", INT2FIX(VP_EXCEPTION_INFINITY));
-
- /*
- * 0x04: Determines what happens when the result of a computation is an
- * underflow (a result too small to be represented). See BigDecimal.mode.
- */
- rb_define_const(rb_cBigDecimal, "EXCEPTION_UNDERFLOW", INT2FIX(VP_EXCEPTION_UNDERFLOW));
-
- /*
- * 0x01: Determines what happens when the result of a computation is an
- * overflow (a result too large to be represented). See BigDecimal.mode.
- */
- rb_define_const(rb_cBigDecimal, "EXCEPTION_OVERFLOW", INT2FIX(VP_EXCEPTION_OVERFLOW));
-
- /*
- * 0x10: Determines what happens when a division by zero is performed.
- * See BigDecimal.mode.
- */
- rb_define_const(rb_cBigDecimal, "EXCEPTION_ZERODIVIDE", INT2FIX(VP_EXCEPTION_ZERODIVIDE));
-
- /*
- * 0x100: Determines what happens when a result must be rounded in order to
- * fit in the appropriate number of significant digits. See
- * BigDecimal.mode.
- */
- rb_define_const(rb_cBigDecimal, "ROUND_MODE", INT2FIX(VP_ROUND_MODE));
-
- /* 1: Indicates that values should be rounded away from zero. See
- * BigDecimal.mode.
- */
- rb_define_const(rb_cBigDecimal, "ROUND_UP", INT2FIX(VP_ROUND_UP));
-
- /* 2: Indicates that values should be rounded towards zero. See
- * BigDecimal.mode.
- */
- rb_define_const(rb_cBigDecimal, "ROUND_DOWN", INT2FIX(VP_ROUND_DOWN));
-
- /* 3: Indicates that digits >= 5 should be rounded up, others rounded down.
- * See BigDecimal.mode. */
- rb_define_const(rb_cBigDecimal, "ROUND_HALF_UP", INT2FIX(VP_ROUND_HALF_UP));
-
- /* 4: Indicates that digits >= 6 should be rounded up, others rounded down.
- * See BigDecimal.mode.
- */
- rb_define_const(rb_cBigDecimal, "ROUND_HALF_DOWN", INT2FIX(VP_ROUND_HALF_DOWN));
- /* 5: Round towards +Infinity. See BigDecimal.mode. */
- rb_define_const(rb_cBigDecimal, "ROUND_CEILING", INT2FIX(VP_ROUND_CEIL));
-
- /* 6: Round towards -Infinity. See BigDecimal.mode. */
- rb_define_const(rb_cBigDecimal, "ROUND_FLOOR", INT2FIX(VP_ROUND_FLOOR));
-
- /* 7: Round towards the even neighbor. See BigDecimal.mode. */
- rb_define_const(rb_cBigDecimal, "ROUND_HALF_EVEN", INT2FIX(VP_ROUND_HALF_EVEN));
-
- /* 0: Indicates that a value is not a number. See BigDecimal.sign. */
- rb_define_const(rb_cBigDecimal, "SIGN_NaN", INT2FIX(VP_SIGN_NaN));
-
- /* 1: Indicates that a value is +0. See BigDecimal.sign. */
- rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_ZERO", INT2FIX(VP_SIGN_POSITIVE_ZERO));
-
- /* -1: Indicates that a value is -0. See BigDecimal.sign. */
- rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_ZERO", INT2FIX(VP_SIGN_NEGATIVE_ZERO));
-
- /* 2: Indicates that a value is positive and finite. See BigDecimal.sign. */
- rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_FINITE", INT2FIX(VP_SIGN_POSITIVE_FINITE));
-
- /* -2: Indicates that a value is negative and finite. See BigDecimal.sign. */
- rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_FINITE", INT2FIX(VP_SIGN_NEGATIVE_FINITE));
-
- /* 3: Indicates that a value is positive and infinite. See BigDecimal.sign. */
- rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_INFINITE", INT2FIX(VP_SIGN_POSITIVE_INFINITE));
-
- /* -3: Indicates that a value is negative and infinite. See BigDecimal.sign. */
- rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_INFINITE", INT2FIX(VP_SIGN_NEGATIVE_INFINITE));
-
- /* Positive zero value. */
- arg = rb_str_new2("+0");
- BIGDECIMAL_POSITIVE_ZERO = f_BigDecimal(1, &arg, rb_cBigDecimal);
- rb_gc_register_mark_object(BIGDECIMAL_POSITIVE_ZERO);
-
- /* Negative zero value. */
- arg = rb_str_new2("-0");
- BIGDECIMAL_NEGATIVE_ZERO = f_BigDecimal(1, &arg, rb_cBigDecimal);
- rb_gc_register_mark_object(BIGDECIMAL_NEGATIVE_ZERO);
-
- /* Positive infinity value. */
- arg = rb_str_new2("+Infinity");
- BIGDECIMAL_POSITIVE_INFINITY = f_BigDecimal(1, &arg, rb_cBigDecimal);
- rb_gc_register_mark_object(BIGDECIMAL_POSITIVE_INFINITY);
-
- /* Negative infinity value. */
- arg = rb_str_new2("-Infinity");
- BIGDECIMAL_NEGATIVE_INFINITY = f_BigDecimal(1, &arg, rb_cBigDecimal);
- rb_gc_register_mark_object(BIGDECIMAL_NEGATIVE_INFINITY);
-
- /* 'Not a Number' value. */
- arg = rb_str_new2("NaN");
- BIGDECIMAL_NAN = f_BigDecimal(1, &arg, rb_cBigDecimal);
- rb_gc_register_mark_object(BIGDECIMAL_NAN);
-
- /* Special value constants */
- rb_define_const(rb_cBigDecimal, "INFINITY", BIGDECIMAL_POSITIVE_INFINITY);
- rb_define_const(rb_cBigDecimal, "NAN", BIGDECIMAL_NAN);
-
- /* instance methods */
- rb_define_method(rb_cBigDecimal, "precs", BigDecimal_prec, 0);
- rb_define_method(rb_cBigDecimal, "precision", BigDecimal_precision, 0);
- rb_define_method(rb_cBigDecimal, "scale", BigDecimal_scale, 0);
- rb_define_method(rb_cBigDecimal, "precision_scale", BigDecimal_precision_scale, 0);
- rb_define_method(rb_cBigDecimal, "n_significant_digits", BigDecimal_n_significant_digits, 0);
-
- rb_define_method(rb_cBigDecimal, "add", BigDecimal_add2, 2);
- rb_define_method(rb_cBigDecimal, "sub", BigDecimal_sub2, 2);
- rb_define_method(rb_cBigDecimal, "mult", BigDecimal_mult2, 2);
- rb_define_method(rb_cBigDecimal, "div", BigDecimal_div3, -1);
- rb_define_method(rb_cBigDecimal, "hash", BigDecimal_hash, 0);
- rb_define_method(rb_cBigDecimal, "to_s", BigDecimal_to_s, -1);
- rb_define_method(rb_cBigDecimal, "to_i", BigDecimal_to_i, 0);
- rb_define_method(rb_cBigDecimal, "to_int", BigDecimal_to_i, 0);
- rb_define_method(rb_cBigDecimal, "to_r", BigDecimal_to_r, 0);
- rb_define_method(rb_cBigDecimal, "split", BigDecimal_split, 0);
- rb_define_method(rb_cBigDecimal, "+", BigDecimal_add, 1);
- rb_define_method(rb_cBigDecimal, "-", BigDecimal_sub, 1);
- rb_define_method(rb_cBigDecimal, "+@", BigDecimal_uplus, 0);
- rb_define_method(rb_cBigDecimal, "-@", BigDecimal_neg, 0);
- rb_define_method(rb_cBigDecimal, "*", BigDecimal_mult, 1);
- rb_define_method(rb_cBigDecimal, "/", BigDecimal_div, 1);
- rb_define_method(rb_cBigDecimal, "quo", BigDecimal_quo, -1);
- rb_define_method(rb_cBigDecimal, "%", BigDecimal_mod, 1);
- rb_define_method(rb_cBigDecimal, "modulo", BigDecimal_mod, 1);
- rb_define_method(rb_cBigDecimal, "remainder", BigDecimal_remainder, 1);
- rb_define_method(rb_cBigDecimal, "divmod", BigDecimal_divmod, 1);
- rb_define_method(rb_cBigDecimal, "clone", BigDecimal_clone, 0);
- rb_define_method(rb_cBigDecimal, "dup", BigDecimal_clone, 0);
- rb_define_method(rb_cBigDecimal, "to_f", BigDecimal_to_f, 0);
- rb_define_method(rb_cBigDecimal, "abs", BigDecimal_abs, 0);
- rb_define_method(rb_cBigDecimal, "sqrt", BigDecimal_sqrt, 1);
- rb_define_method(rb_cBigDecimal, "fix", BigDecimal_fix, 0);
- rb_define_method(rb_cBigDecimal, "round", BigDecimal_round, -1);
- rb_define_method(rb_cBigDecimal, "frac", BigDecimal_frac, 0);
- rb_define_method(rb_cBigDecimal, "floor", BigDecimal_floor, -1);
- rb_define_method(rb_cBigDecimal, "ceil", BigDecimal_ceil, -1);
- rb_define_method(rb_cBigDecimal, "power", BigDecimal_power, -1);
- rb_define_method(rb_cBigDecimal, "**", BigDecimal_power_op, 1);
- rb_define_method(rb_cBigDecimal, "<=>", BigDecimal_comp, 1);
- rb_define_method(rb_cBigDecimal, "==", BigDecimal_eq, 1);
- rb_define_method(rb_cBigDecimal, "===", BigDecimal_eq, 1);
- rb_define_method(rb_cBigDecimal, "eql?", BigDecimal_eq, 1);
- rb_define_method(rb_cBigDecimal, "<", BigDecimal_lt, 1);
- rb_define_method(rb_cBigDecimal, "<=", BigDecimal_le, 1);
- rb_define_method(rb_cBigDecimal, ">", BigDecimal_gt, 1);
- rb_define_method(rb_cBigDecimal, ">=", BigDecimal_ge, 1);
- rb_define_method(rb_cBigDecimal, "zero?", BigDecimal_zero, 0);
- rb_define_method(rb_cBigDecimal, "nonzero?", BigDecimal_nonzero, 0);
- rb_define_method(rb_cBigDecimal, "coerce", BigDecimal_coerce, 1);
- rb_define_method(rb_cBigDecimal, "inspect", BigDecimal_inspect, 0);
- rb_define_method(rb_cBigDecimal, "exponent", BigDecimal_exponent, 0);
- rb_define_method(rb_cBigDecimal, "sign", BigDecimal_sign, 0);
- rb_define_method(rb_cBigDecimal, "nan?", BigDecimal_IsNaN, 0);
- rb_define_method(rb_cBigDecimal, "infinite?", BigDecimal_IsInfinite, 0);
- rb_define_method(rb_cBigDecimal, "finite?", BigDecimal_IsFinite, 0);
- rb_define_method(rb_cBigDecimal, "truncate", BigDecimal_truncate, -1);
- rb_define_method(rb_cBigDecimal, "_dump", BigDecimal_dump, -1);
-
- rb_mBigMath = rb_define_module("BigMath");
- rb_define_singleton_method(rb_mBigMath, "exp", BigMath_s_exp, 2);
- rb_define_singleton_method(rb_mBigMath, "log", BigMath_s_log, 2);
-
-#define ROUNDING_MODE(i, name, value) \
- id_##name = rb_intern_const(#name); \
- rbd_rounding_modes[i].id = id_##name; \
- rbd_rounding_modes[i].mode = value;
-
- ROUNDING_MODE(0, up, RBD_ROUND_UP);
- ROUNDING_MODE(1, down, RBD_ROUND_DOWN);
- ROUNDING_MODE(2, half_up, RBD_ROUND_HALF_UP);
- ROUNDING_MODE(3, half_down, RBD_ROUND_HALF_DOWN);
- ROUNDING_MODE(4, ceil, RBD_ROUND_CEIL);
- ROUNDING_MODE(5, floor, RBD_ROUND_FLOOR);
- ROUNDING_MODE(6, half_even, RBD_ROUND_HALF_EVEN);
-
- ROUNDING_MODE(7, default, RBD_ROUND_DEFAULT);
- ROUNDING_MODE(8, truncate, RBD_ROUND_TRUNCATE);
- ROUNDING_MODE(9, banker, RBD_ROUND_BANKER);
- ROUNDING_MODE(10, ceiling, RBD_ROUND_CEILING);
-
-#undef ROUNDING_MODE
-
- id_to_r = rb_intern_const("to_r");
- id_eq = rb_intern_const("==");
- id_half = rb_intern_const("half");
-
- (void)VPrint; /* suppress unused warning */
-}
-
-/*
- *
- * ============================================================================
- *
- * vp_ routines begin from here.
- *
- * ============================================================================
- *
- */
-#ifdef BIGDECIMAL_DEBUG
-static int gfDebug = 1; /* Debug switch */
-#if 0
-static int gfCheckVal = 1; /* Value checking flag in VpNmlz() */
-#endif
-#endif /* BIGDECIMAL_DEBUG */
-
-static Real *VpConstOne; /* constant 1.0 */
-static Real *VpConstPt5; /* constant 0.5 */
-#define maxnr 100UL /* Maximum iterations for calculating sqrt. */
- /* used in VpSqrt() */
-
-/* ETC */
-#define MemCmp(x,y,z) memcmp(x,y,z)
-#define StrCmp(x,y) strcmp(x,y)
-
-enum op_sw {
- OP_SW_ADD = 1, /* + */
- OP_SW_SUB, /* - */
- OP_SW_MULT, /* * */
- OP_SW_DIV /* / */
-};
-
-static int VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw);
-static int AddExponent(Real *a, SIGNED_VALUE n);
-static DECDIG VpAddAbs(Real *a,Real *b,Real *c);
-static DECDIG VpSubAbs(Real *a,Real *b,Real *c);
-static size_t VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos, DECDIG *av, DECDIG *bv);
-static int VpNmlz(Real *a);
-static void VpFormatSt(char *psz, size_t fFmt);
-static int VpRdup(Real *m, size_t ind_m);
-
-#ifdef BIGDECIMAL_DEBUG
-# ifdef HAVE_RB_EXT_RACTOR_SAFE
-# error Need to make rewiting gnAlloc atomic
-# endif
-static int gnAlloc = 0; /* Memory allocation counter */
-#endif /* BIGDECIMAL_DEBUG */
-
-/*
- * EXCEPTION Handling.
- */
-
-#define bigdecimal_set_thread_local_exception_mode(mode) \
- rb_thread_local_aset( \
- rb_thread_current(), \
- id_BigDecimal_exception_mode, \
- INT2FIX((int)(mode)) \
- )
-
-static unsigned short
-VpGetException (void)
-{
- VALUE const vmode = rb_thread_local_aref(
- rb_thread_current(),
- id_BigDecimal_exception_mode
- );
-
- if (NIL_P(vmode)) {
- bigdecimal_set_thread_local_exception_mode(BIGDECIMAL_EXCEPTION_MODE_DEFAULT);
- return BIGDECIMAL_EXCEPTION_MODE_DEFAULT;
- }
-
- return NUM2USHORT(vmode);
-}
-
-static void
-VpSetException(unsigned short f)
-{
- bigdecimal_set_thread_local_exception_mode(f);
-}
-
-static void
-VpCheckException(Real *p, bool always)
-{
- if (VpIsNaN(p)) {
- VpException(VP_EXCEPTION_NaN, "Computation results in 'NaN' (Not a Number)", always);
- }
- else if (VpIsPosInf(p)) {
- VpException(VP_EXCEPTION_INFINITY, "Computation results in 'Infinity'", always);
- }
- else if (VpIsNegInf(p)) {
- VpException(VP_EXCEPTION_INFINITY, "Computation results in '-Infinity'", always);
- }
-}
-
-static VALUE
-VpCheckGetValue(Real *p)
-{
- VpCheckException(p, false);
- return p->obj;
-}
-
-/*
- * Precision limit.
- */
-
-#define bigdecimal_set_thread_local_precision_limit(limit) \
- rb_thread_local_aset( \
- rb_thread_current(), \
- id_BigDecimal_precision_limit, \
- SIZET2NUM(limit) \
- )
-#define BIGDECIMAL_PRECISION_LIMIT_DEFAULT ((size_t)0)
-
-/* These 2 functions added at v1.1.7 */
-VP_EXPORT size_t
-VpGetPrecLimit(void)
-{
- VALUE const vlimit = rb_thread_local_aref(
- rb_thread_current(),
- id_BigDecimal_precision_limit
- );
-
- if (NIL_P(vlimit)) {
- bigdecimal_set_thread_local_precision_limit(BIGDECIMAL_PRECISION_LIMIT_DEFAULT);
- return BIGDECIMAL_PRECISION_LIMIT_DEFAULT;
- }
-
- return NUM2SIZET(vlimit);
-}
-
-VP_EXPORT size_t
-VpSetPrecLimit(size_t n)
-{
- size_t const s = VpGetPrecLimit();
- bigdecimal_set_thread_local_precision_limit(n);
- return s;
-}
-
-/*
- * Rounding mode.
- */
-
-#define bigdecimal_set_thread_local_rounding_mode(mode) \
- rb_thread_local_aset( \
- rb_thread_current(), \
- id_BigDecimal_rounding_mode, \
- INT2FIX((int)(mode)) \
- )
-
-VP_EXPORT unsigned short
-VpGetRoundMode(void)
-{
- VALUE const vmode = rb_thread_local_aref(
- rb_thread_current(),
- id_BigDecimal_rounding_mode
- );
-
- if (NIL_P(vmode)) {
- bigdecimal_set_thread_local_rounding_mode(BIGDECIMAL_ROUNDING_MODE_DEFAULT);
- return BIGDECIMAL_ROUNDING_MODE_DEFAULT;
- }
-
- return NUM2USHORT(vmode);
-}
-
-VP_EXPORT int
-VpIsRoundMode(unsigned short n)
-{
- switch (n) {
- case VP_ROUND_UP:
- case VP_ROUND_DOWN:
- case VP_ROUND_HALF_UP:
- case VP_ROUND_HALF_DOWN:
- case VP_ROUND_CEIL:
- case VP_ROUND_FLOOR:
- case VP_ROUND_HALF_EVEN:
- return 1;
-
- default:
- return 0;
- }
-}
-
-VP_EXPORT unsigned short
-VpSetRoundMode(unsigned short n)
-{
- if (VpIsRoundMode(n)) {
- bigdecimal_set_thread_local_rounding_mode(n);
- return n;
- }
-
- return VpGetRoundMode();
-}
-
-/*
- * 0.0 & 1.0 generator
- * These gZero_..... and gOne_..... can be any name
- * referenced from nowhere except Zero() and One().
- * gZero_..... and gOne_..... must have global scope
- * (to let the compiler know they may be changed in outside
- * (... but not actually..)).
- */
-volatile const double gOne_ABCED9B4_CE73__00400511F31D = 1.0;
-
-static double
-One(void)
-{
- return gOne_ABCED9B4_CE73__00400511F31D;
-}
-
-/*
- ----------------------------------------------------------------
- Value of sign in Real structure is reserved for future use.
- short sign;
- ==0 : NaN
- 1 : Positive zero
- -1 : Negative zero
- 2 : Positive number
- -2 : Negative number
- 3 : Positive infinite number
- -3 : Negative infinite number
- ----------------------------------------------------------------
-*/
-
-VP_EXPORT double
-VpGetDoubleNaN(void) /* Returns the value of NaN */
-{
- return nan("");
-}
-
-VP_EXPORT double
-VpGetDoublePosInf(void) /* Returns the value of +Infinity */
-{
- return HUGE_VAL;
-}
-
-VP_EXPORT double
-VpGetDoubleNegInf(void) /* Returns the value of -Infinity */
-{
- return -HUGE_VAL;
-}
-
-VP_EXPORT double
-VpGetDoubleNegZero(void) /* Returns the value of -0 */
-{
- static double nzero = 1000.0;
- if (nzero != 0.0) nzero = (One()/VpGetDoubleNegInf());
- return nzero;
-}
-
-#if 0 /* unused */
-VP_EXPORT int
-VpIsNegDoubleZero(double v)
-{
- double z = VpGetDoubleNegZero();
- return MemCmp(&v,&z,sizeof(v))==0;
-}
-#endif
-
-VP_EXPORT int
-VpException(unsigned short f, const char *str,int always)
-{
- unsigned short const exception_mode = VpGetException();
-
- if (f == VP_EXCEPTION_OP) always = 1;
-
- if (always || (exception_mode & f)) {
- switch(f) {
- /* case VP_EXCEPTION_OVERFLOW: */
- case VP_EXCEPTION_ZERODIVIDE:
- case VP_EXCEPTION_INFINITY:
- case VP_EXCEPTION_NaN:
- case VP_EXCEPTION_UNDERFLOW:
- case VP_EXCEPTION_OP:
- rb_raise(rb_eFloatDomainError, "%s", str);
- break;
- default:
- rb_fatal("%s", str);
- }
- }
- return 0; /* 0 Means VpException() raised no exception */
-}
-
-/* Throw exception or returns 0,when resulting c is Inf or NaN */
-/* sw=1:+ 2:- 3:* 4:/ */
-static int
-VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw)
-{
- if (VpIsNaN(a) || VpIsNaN(b)) {
- /* at least a or b is NaN */
- VpSetNaN(c);
- goto NaN;
- }
-
- if (VpIsInf(a)) {
- if (VpIsInf(b)) {
- switch(sw) {
- case OP_SW_ADD: /* + */
- if (VpGetSign(a) == VpGetSign(b)) {
- VpSetInf(c, VpGetSign(a));
- goto Inf;
- }
- else {
- VpSetNaN(c);
- goto NaN;
- }
- case OP_SW_SUB: /* - */
- if (VpGetSign(a) != VpGetSign(b)) {
- VpSetInf(c, VpGetSign(a));
- goto Inf;
- }
- else {
- VpSetNaN(c);
- goto NaN;
- }
- case OP_SW_MULT: /* * */
- VpSetInf(c, VpGetSign(a)*VpGetSign(b));
- goto Inf;
- case OP_SW_DIV: /* / */
- VpSetNaN(c);
- goto NaN;
- }
- VpSetNaN(c);
- goto NaN;
- }
- /* Inf op Finite */
- switch(sw) {
- case OP_SW_ADD: /* + */
- case OP_SW_SUB: /* - */
- VpSetInf(c, VpGetSign(a));
- break;
- case OP_SW_MULT: /* * */
- if (VpIsZero(b)) {
- VpSetNaN(c);
- goto NaN;
- }
- VpSetInf(c, VpGetSign(a)*VpGetSign(b));
- break;
- case OP_SW_DIV: /* / */
- VpSetInf(c, VpGetSign(a)*VpGetSign(b));
- }
- goto Inf;
- }
-
- if (VpIsInf(b)) {
- switch(sw) {
- case OP_SW_ADD: /* + */
- VpSetInf(c, VpGetSign(b));
- break;
- case OP_SW_SUB: /* - */
- VpSetInf(c, -VpGetSign(b));
- break;
- case OP_SW_MULT: /* * */
- if (VpIsZero(a)) {
- VpSetNaN(c);
- goto NaN;
- }
- VpSetInf(c, VpGetSign(a)*VpGetSign(b));
- break;
- case OP_SW_DIV: /* / */
- VpSetZero(c, VpGetSign(a)*VpGetSign(b));
- }
- goto Inf;
- }
- return 1; /* Results OK */
-
-Inf:
- if (VpIsPosInf(c)) {
- return VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 0);
- }
- else {
- return VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 0);
- }
-
-NaN:
- return VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'", 0);
-}
-
-/*
- ----------------------------------------------------------------
-*/
-
-/*
- * returns number of chars needed to represent vp in specified format.
- */
-VP_EXPORT size_t
-VpNumOfChars(Real *vp,const char *pszFmt)
-{
- SIGNED_VALUE ex;
- size_t nc;
-
- if (vp == NULL) return BASE_FIG*2+6;
- if (!VpIsDef(vp)) return 32; /* not sure,may be OK */
-
- switch(*pszFmt) {
- case 'F':
- nc = BASE_FIG*(vp->Prec + 1)+2;
- ex = vp->exponent;
- if (ex < 0) {
- nc += BASE_FIG*(size_t)(-ex);
- }
- else {
- if ((size_t)ex > vp->Prec) {
- nc += BASE_FIG*((size_t)ex - vp->Prec);
- }
- }
- break;
- case 'E':
- /* fall through */
- default:
- nc = BASE_FIG*(vp->Prec + 2)+6; /* 3: sign + exponent chars */
- }
- return nc;
-}
-
-/*
- * Initializer for Vp routines and constants used.
- * [Input]
- * BaseVal: Base value(assigned to BASE) for Vp calculation.
- * It must be the form BaseVal=10**n.(n=1,2,3,...)
- * If Base <= 0L,then the BASE will be calculated so
- * that BASE is as large as possible satisfying the
- * relation MaxVal <= BASE*(BASE+1). Where the value
- * MaxVal is the largest value which can be represented
- * by one DECDIG word in the computer used.
- *
- * [Returns]
- * BIGDECIMAL_DOUBLE_FIGURES ... OK
- */
-VP_EXPORT size_t
-VpInit(DECDIG BaseVal)
-{
- /* Setup +/- Inf NaN -0 */
- VpGetDoubleNegZero();
-
- /* Const 1.0 */
- VpConstOne = NewOneNolimit(1, 1);
-
- /* Const 0.5 */
- VpConstPt5 = NewOneNolimit(1, 1);
- VpConstPt5->exponent = 0;
- VpConstPt5->frac[0] = 5*BASE1;
-
-#ifdef BIGDECIMAL_DEBUG
- gnAlloc = 0;
-#endif /* BIGDECIMAL_DEBUG */
-
-#ifdef BIGDECIMAL_DEBUG
- if (gfDebug) {
- printf("VpInit: BaseVal = %"PRIuDECDIG"\n", BaseVal);
- printf("\tBASE = %"PRIuDECDIG"\n", BASE);
- printf("\tHALF_BASE = %"PRIuDECDIG"\n", HALF_BASE);
- printf("\tBASE1 = %"PRIuDECDIG"\n", BASE1);
- printf("\tBASE_FIG = %u\n", BASE_FIG);
- printf("\tBIGDECIMAL_DOUBLE_FIGURES = %d\n", BIGDECIMAL_DOUBLE_FIGURES);
- }
-#endif /* BIGDECIMAL_DEBUG */
-
- return BIGDECIMAL_DOUBLE_FIGURES;
-}
-
-VP_EXPORT Real *
-VpOne(void)
-{
- return VpConstOne;
-}
-
-/* If exponent overflows,then raise exception or returns 0 */
-static int
-AddExponent(Real *a, SIGNED_VALUE n)
-{
- SIGNED_VALUE e = a->exponent;
- SIGNED_VALUE m = e+n;
- SIGNED_VALUE eb, mb;
- if (e > 0) {
- if (n > 0) {
- if (MUL_OVERFLOW_SIGNED_VALUE_P(m, (SIGNED_VALUE)BASE_FIG) ||
- MUL_OVERFLOW_SIGNED_VALUE_P(e, (SIGNED_VALUE)BASE_FIG))
- goto overflow;
- mb = m*(SIGNED_VALUE)BASE_FIG;
- eb = e*(SIGNED_VALUE)BASE_FIG;
- if (eb - mb > 0) goto overflow;
- }
- }
- else if (n < 0) {
- if (MUL_OVERFLOW_SIGNED_VALUE_P(m, (SIGNED_VALUE)BASE_FIG) ||
- MUL_OVERFLOW_SIGNED_VALUE_P(e, (SIGNED_VALUE)BASE_FIG))
- goto underflow;
- mb = m*(SIGNED_VALUE)BASE_FIG;
- eb = e*(SIGNED_VALUE)BASE_FIG;
- if (mb - eb > 0) goto underflow;
- }
- a->exponent = m;
- return 1;
-
-/* Overflow/Underflow ==> Raise exception or returns 0 */
-underflow:
- VpSetZero(a, VpGetSign(a));
- return VpException(VP_EXCEPTION_UNDERFLOW, "Exponent underflow", 0);
-
-overflow:
- VpSetInf(a, VpGetSign(a));
- return VpException(VP_EXCEPTION_OVERFLOW, "Exponent overflow", 0);
-}
-
-Real *
-bigdecimal_parse_special_string(const char *str)
-{
- static const struct {
- const char *str;
- size_t len;
- int sign;
- } table[] = {
- { SZ_INF, sizeof(SZ_INF) - 1, VP_SIGN_POSITIVE_INFINITE },
- { SZ_PINF, sizeof(SZ_PINF) - 1, VP_SIGN_POSITIVE_INFINITE },
- { SZ_NINF, sizeof(SZ_NINF) - 1, VP_SIGN_NEGATIVE_INFINITE },
- { SZ_NaN, sizeof(SZ_NaN) - 1, VP_SIGN_NaN }
- };
- static const size_t table_length = sizeof(table) / sizeof(table[0]);
- size_t i;
-
- for (i = 0; i < table_length; ++i) {
- const char *p;
- if (strncmp(str, table[i].str, table[i].len) != 0) {
- continue;
- }
-
- p = str + table[i].len;
- while (*p && ISSPACE(*p)) ++p;
- if (*p == '\0') {
- Real *vp = rbd_allocate_struct(1);
- vp->MaxPrec = 1;
- switch (table[i].sign) {
- default:
- UNREACHABLE; break;
- case VP_SIGN_POSITIVE_INFINITE:
- VpSetPosInf(vp);
- return vp;
- case VP_SIGN_NEGATIVE_INFINITE:
- VpSetNegInf(vp);
- return vp;
- case VP_SIGN_NaN:
- VpSetNaN(vp);
- return vp;
- }
- }
- }
-
- return NULL;
-}
-
-/*
- * Allocates variable.
- * [Input]
- * mx ... The number of decimal digits to be allocated, if zero then mx is determined by szVal.
- * The mx will be the number of significant digits can to be stored.
- * szVal ... The value assigned(char). If szVal==NULL, then zero is assumed.
- * If szVal[0]=='#' then MaxPrec is not affected by the precision limit
- * so that the full precision specified by szVal is allocated.
- *
- * [Returns]
- * Pointer to the newly allocated variable, or
- * NULL be returned if memory allocation is failed,or any error.
- */
-VP_EXPORT Real *
-VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
-{
- const char *orig_szVal = szVal;
- size_t i, j, ni, ipf, nf, ipe, ne, dot_seen, exp_seen, nalloc;
- size_t len;
- char v, *psz;
- int sign=1;
- Real *vp = NULL;
- VALUE buf;
-
- if (szVal == NULL) {
- return_zero:
- /* necessary to be able to store */
- /* at least mx digits. */
- /* szVal==NULL ==> allocate zero value. */
- vp = rbd_allocate_struct(mx);
- vp->MaxPrec = rbd_calculate_internal_digits(mx, false); /* Must false */
- VpSetZero(vp, 1); /* initialize vp to zero. */
- return vp;
- }
-
- /* Skipping leading spaces */
- while (ISSPACE(*szVal)) szVal++;
-
- /* Check on Inf & NaN */
- if ((vp = bigdecimal_parse_special_string(szVal)) != NULL) {
- return vp;
- }
-
- /* Processing the leading one `#` */
- if (*szVal != '#') {
- len = rbd_calculate_internal_digits(mx, true);
- }
- else {
- len = rbd_calculate_internal_digits(mx, false);
- ++szVal;
- }
-
- /* Scanning digits */
-
- /* A buffer for keeping scanned digits */
- buf = rb_str_tmp_new(strlen(szVal) + 1);
- psz = RSTRING_PTR(buf);
-
- /* cursor: i for psz, and j for szVal */
- i = j = 0;
-
- /* Scanning: sign part */
- v = psz[i] = szVal[j];
- if ((v == '-') || (v == '+')) {
- sign = -(v == '-');
- ++i;
- ++j;
- }
-
- /* Scanning: integer part */
- ni = 0; /* number of digits in the integer part */
- while ((v = psz[i] = szVal[j]) != '\0') {
- if (!strict_p && ISSPACE(v)) {
- v = psz[i] = '\0';
- break;
- }
- if (v == '_') {
- if (ni > 0) {
- v = szVal[j+1];
- if (v == '\0' || ISSPACE(v) || ISDIGIT(v)) {
- ++j;
- continue;
- }
- if (!strict_p) {
- v = psz[i] = '\0';
- break;
- }
- }
- goto invalid_value;
- }
- if (!ISDIGIT(v)) {
- break;
- }
- ++ni;
- ++i;
- ++j;
- }
-
- /* Scanning: fractional part */
- nf = 0; /* number of digits in the fractional part */
- ne = 0; /* number of digits in the exponential part */
- ipf = 0; /* index of the beginning of the fractional part */
- ipe = 0; /* index of the beginning of the exponential part */
- dot_seen = 0;
- exp_seen = 0;
-
- if (v != '\0') {
- /* Scanning fractional part */
- if ((psz[i] = szVal[j]) == '.') {
- dot_seen = 1;
- ++i;
- ++j;
- ipf = i;
- while ((v = psz[i] = szVal[j]) != '\0') {
- if (!strict_p && ISSPACE(v)) {
- v = psz[i] = '\0';
- break;
- }
- if (v == '_') {
- if (nf > 0 && ISDIGIT(szVal[j+1])) {
- ++j;
- continue;
- }
- if (!strict_p) {
- v = psz[i] = '\0';
- if (nf == 0) {
- dot_seen = 0;
- }
- break;
- }
- goto invalid_value;
- }
- if (!ISDIGIT(v)) break;
- ++i;
- ++j;
- ++nf;
- }
- }
-
- /* Scanning exponential part */
- if (v != '\0') {
- switch ((psz[i] = szVal[j])) {
- case '\0':
- break;
- case 'e': case 'E':
- case 'd': case 'D':
- exp_seen = 1;
- ++i;
- ++j;
- ipe = i;
- v = psz[i] = szVal[j];
- if ((v == '-') || (v == '+')) {
- ++i;
- ++j;
- }
- while ((v = psz[i] = szVal[j]) != '\0') {
- if (!strict_p && ISSPACE(v)) {
- v = psz[i] = '\0';
- break;
- }
- if (v == '_') {
- if (ne > 0 && ISDIGIT(szVal[j+1])) {
- ++j;
- continue;
- }
- if (!strict_p) {
- v = psz[i] = '\0';
- if (ne == 0) {
- exp_seen = 0;
- }
- break;
- }
- goto invalid_value;
- }
- if (!ISDIGIT(v)) break;
- ++i;
- ++j;
- ++ne;
- }
- break;
- default:
- break;
- }
- }
-
- if (v != '\0') {
- /* Scanning trailing spaces */
- while (ISSPACE(szVal[j])) ++j;
-
- /* Invalid character */
- if (szVal[j] && strict_p) {
- goto invalid_value;
- }
- }
- }
-
- psz[i] = '\0';
-
- if (strict_p && (((ni == 0 || dot_seen) && nf == 0) || (exp_seen && ne == 0))) {
- VALUE str;
- invalid_value:
- if (!strict_p) {
- goto return_zero;
- }
- if (!exc) {
- return NULL;
- }
- str = rb_str_new2(orig_szVal);
- rb_raise(rb_eArgError, "invalid value for BigDecimal(): \"%"PRIsVALUE"\"", str);
- }
-
- nalloc = (ni + nf + BASE_FIG - 1) / BASE_FIG + 1; /* set effective allocation */
- /* units for szVal[] */
- if (len == 0) len = 1;
- nalloc = Max(nalloc, len);
- len = nalloc;
- vp = rbd_allocate_struct(len);
- vp->MaxPrec = len; /* set max precision */
- VpSetZero(vp, sign);
- VpCtoV(vp, psz, ni, psz + ipf, nf, psz + ipe, ne);
- rb_str_resize(buf, 0);
- return vp;
-}
-
-/*
- * Assignment(c=a).
- * [Input]
- * a ... RHSV
- * isw ... switch for assignment.
- * c = a when isw > 0
- * c = -a when isw < 0
- * if c->MaxPrec < a->Prec,then round operation
- * will be performed.
- * [Output]
- * c ... LHSV
- */
-VP_EXPORT size_t
-VpAsgn(Real *c, Real *a, int isw)
-{
- size_t n;
- if (VpIsNaN(a)) {
- VpSetNaN(c);
- return 0;
- }
- if (VpIsInf(a)) {
- VpSetInf(c, isw * VpGetSign(a));
- return 0;
- }
-
- /* check if the RHS is zero */
- if (!VpIsZero(a)) {
- c->exponent = a->exponent; /* store exponent */
- VpSetSign(c, isw * VpGetSign(a)); /* set sign */
- n = (a->Prec < c->MaxPrec) ? (a->Prec) : (c->MaxPrec);
- c->Prec = n;
- memcpy(c->frac, a->frac, n * sizeof(DECDIG));
- /* Needs round ? */
- if (isw != 10) {
- /* Not in ActiveRound */
- if(c->Prec < a->Prec) {
- VpInternalRound(c, n, (n>0) ? a->frac[n-1] : 0, a->frac[n]);
- }
- else {
- VpLimitRound(c,0);
- }
- }
- }
- else {
- /* The value of 'a' is zero. */
- VpSetZero(c, isw * VpGetSign(a));
- return 1;
- }
- return c->Prec * BASE_FIG;
-}
-
-/*
- * c = a + b when operation = 1 or 2
- * c = a - b when operation = -1 or -2.
- * Returns number of significant digits of c
- */
-VP_EXPORT size_t
-VpAddSub(Real *c, Real *a, Real *b, int operation)
-{
- short sw, isw;
- Real *a_ptr, *b_ptr;
- size_t n, na, nb, i;
- DECDIG mrv;
-
-#ifdef BIGDECIMAL_DEBUG
- if (gfDebug) {
- VPrint(stdout, "VpAddSub(enter) a=% \n", a);
- VPrint(stdout, " b=% \n", b);
- printf(" operation=%d\n", operation);
- }
-#endif /* BIGDECIMAL_DEBUG */
-
- if (!VpIsDefOP(c, a, b, (operation > 0) ? OP_SW_ADD : OP_SW_SUB)) return 0; /* No significant digits */
-
- /* check if a or b is zero */
- if (VpIsZero(a)) {
- /* a is zero,then assign b to c */
- if (!VpIsZero(b)) {
- VpAsgn(c, b, operation);
- }
- else {
- /* Both a and b are zero. */
- if (VpGetSign(a) < 0 && operation * VpGetSign(b) < 0) {
- /* -0 -0 */
- VpSetZero(c, -1);
- }
- else {
- VpSetZero(c, 1);
- }
- return 1; /* 0: 1 significant digits */
- }
- return c->Prec * BASE_FIG;
- }
- if (VpIsZero(b)) {
- /* b is zero,then assign a to c. */
- VpAsgn(c, a, 1);
- return c->Prec*BASE_FIG;
- }
-
- if (operation < 0) sw = -1;
- else sw = 1;
-
- /* compare absolute value. As a result,|a_ptr|>=|b_ptr| */
- if (a->exponent > b->exponent) {
- a_ptr = a;
- b_ptr = b;
- } /* |a|>|b| */
- else if (a->exponent < b->exponent) {
- a_ptr = b;
- b_ptr = a;
- } /* |a|<|b| */
- else {
- /* Exponent part of a and b is the same,then compare fraction */
- /* part */
- na = a->Prec;
- nb = b->Prec;
- n = Min(na, nb);
- for (i=0; i < n; ++i) {
- if (a->frac[i] > b->frac[i]) {
- a_ptr = a;
- b_ptr = b;
- goto end_if;
- }
- else if (a->frac[i] < b->frac[i]) {
- a_ptr = b;
- b_ptr = a;
- goto end_if;
- }
- }
- if (na > nb) {
- a_ptr = a;
- b_ptr = b;
- goto end_if;
- }
- else if (na < nb) {
- a_ptr = b;
- b_ptr = a;
- goto end_if;
- }
- /* |a| == |b| */
- if (VpGetSign(a) + sw *VpGetSign(b) == 0) {
- VpSetZero(c, 1); /* abs(a)=abs(b) and operation = '-' */
- return c->Prec * BASE_FIG;
- }
- a_ptr = a;
- b_ptr = b;
- }
-
-end_if:
- isw = VpGetSign(a) + sw *VpGetSign(b);
- /*
- * isw = 0 ...( 1)+(-1),( 1)-( 1),(-1)+(1),(-1)-(-1)
- * = 2 ...( 1)+( 1),( 1)-(-1)
- * =-2 ...(-1)+(-1),(-1)-( 1)
- * If isw==0, then c =(Sign a_ptr)(|a_ptr|-|b_ptr|)
- * else c =(Sign ofisw)(|a_ptr|+|b_ptr|)
- */
- if (isw) { /* addition */
- VpSetSign(c, 1);
- mrv = VpAddAbs(a_ptr, b_ptr, c);
- VpSetSign(c, isw / 2);
- }
- else { /* subtraction */
- VpSetSign(c, 1);
- mrv = VpSubAbs(a_ptr, b_ptr, c);
- if (a_ptr == a) {
- VpSetSign(c,VpGetSign(a));
- }
- else {
- VpSetSign(c, VpGetSign(a_ptr) * sw);
- }
- }
- VpInternalRound(c, 0, (c->Prec > 0) ? c->frac[c->Prec-1] : 0, mrv);
-
-#ifdef BIGDECIMAL_DEBUG
- if (gfDebug) {
- VPrint(stdout, "VpAddSub(result) c=% \n", c);
- VPrint(stdout, " a=% \n", a);
- VPrint(stdout, " b=% \n", b);
- printf(" operation=%d\n", operation);
- }
-#endif /* BIGDECIMAL_DEBUG */
- return c->Prec * BASE_FIG;
-}
-
-/*
- * Addition of two values with variable precision
- * a and b assuming abs(a)>abs(b).
- * c = abs(a) + abs(b) ; where |a|>=|b|
- */
-static DECDIG
-VpAddAbs(Real *a, Real *b, Real *c)
-{
- size_t word_shift;
- size_t ap;
- size_t bp;
- size_t cp;
- size_t a_pos;
- size_t b_pos, b_pos_with_word_shift;
- size_t c_pos;
- DECDIG av, bv, carry, mrv;
-
-#ifdef BIGDECIMAL_DEBUG
- if (gfDebug) {
- VPrint(stdout, "VpAddAbs called: a = %\n", a);
- VPrint(stdout, " b = %\n", b);
- }
-#endif /* BIGDECIMAL_DEBUG */
-
- word_shift = VpSetPTR(a, b, c, &ap, &bp, &cp, &av, &bv);
- a_pos = ap;
- b_pos = bp;
- c_pos = cp;
-
- if (word_shift == (size_t)-1L) return 0; /* Overflow */
- if (b_pos == (size_t)-1L) goto Assign_a;
-
- mrv = av + bv; /* Most right val. Used for round. */
-
- /* Just assign the last few digits of b to c because a has no */
- /* corresponding digits to be added. */
- if (b_pos > 0) {
- while (b_pos > 0 && b_pos + word_shift > a_pos) {
- c->frac[--c_pos] = b->frac[--b_pos];
- }
- }
- if (b_pos == 0 && word_shift > a_pos) {
- while (word_shift-- > a_pos) {
- c->frac[--c_pos] = 0;
- }
- }
-
- /* Just assign the last few digits of a to c because b has no */
- /* corresponding digits to be added. */
- b_pos_with_word_shift = b_pos + word_shift;
- while (a_pos > b_pos_with_word_shift) {
- c->frac[--c_pos] = a->frac[--a_pos];
- }
- carry = 0; /* set first carry be zero */
-
- /* Now perform addition until every digits of b will be */
- /* exhausted. */
- while (b_pos > 0) {
- c->frac[--c_pos] = a->frac[--a_pos] + b->frac[--b_pos] + carry;
- if (c->frac[c_pos] >= BASE) {
- c->frac[c_pos] -= BASE;
- carry = 1;
- }
- else {
- carry = 0;
- }
- }
-
- /* Just assign the first few digits of a with considering */
- /* the carry obtained so far because b has been exhausted. */
- while (a_pos > 0) {
- c->frac[--c_pos] = a->frac[--a_pos] + carry;
- if (c->frac[c_pos] >= BASE) {
- c->frac[c_pos] -= BASE;
- carry = 1;
- }
- else {
- carry = 0;
- }
- }
- if (c_pos) c->frac[c_pos - 1] += carry;
- goto Exit;
-
-Assign_a:
- VpAsgn(c, a, 1);
- mrv = 0;
-
-Exit:
-
-#ifdef BIGDECIMAL_DEBUG
- if (gfDebug) {
- VPrint(stdout, "VpAddAbs exit: c=% \n", c);
- }
-#endif /* BIGDECIMAL_DEBUG */
- return mrv;
-}
-
-/*
- * c = abs(a) - abs(b)
- */
-static DECDIG
-VpSubAbs(Real *a, Real *b, Real *c)
-{
- size_t word_shift;
- size_t ap;
- size_t bp;
- size_t cp;
- size_t a_pos;
- size_t b_pos, b_pos_with_word_shift;
- size_t c_pos;
- DECDIG av, bv, borrow, mrv;
-
-#ifdef BIGDECIMAL_DEBUG
- if (gfDebug) {
- VPrint(stdout, "VpSubAbs called: a = %\n", a);
- VPrint(stdout, " b = %\n", b);
- }
-#endif /* BIGDECIMAL_DEBUG */
-
- word_shift = VpSetPTR(a, b, c, &ap, &bp, &cp, &av, &bv);
- a_pos = ap;
- b_pos = bp;
- c_pos = cp;
- if (word_shift == (size_t)-1L) return 0; /* Overflow */
- if (b_pos == (size_t)-1L) goto Assign_a;
-
- if (av >= bv) {
- mrv = av - bv;
- borrow = 0;
- }
- else {
- mrv = 0;
- borrow = 1;
- }
-
- /* Just assign the values which are the BASE subtracted by */
- /* each of the last few digits of the b because the a has no */
- /* corresponding digits to be subtracted. */
- if (b_pos + word_shift > a_pos) {
- while (b_pos > 0 && b_pos + word_shift > a_pos) {
- c->frac[--c_pos] = BASE - b->frac[--b_pos] - borrow;
- borrow = 1;
- }
- if (b_pos == 0) {
- while (word_shift > a_pos) {
- --word_shift;
- c->frac[--c_pos] = BASE - borrow;
- borrow = 1;
- }
- }
- }
- /* Just assign the last few digits of a to c because b has no */
- /* corresponding digits to subtract. */
-
- b_pos_with_word_shift = b_pos + word_shift;
- while (a_pos > b_pos_with_word_shift) {
- c->frac[--c_pos] = a->frac[--a_pos];
- }
-
- /* Now perform subtraction until every digits of b will be */
- /* exhausted. */
- while (b_pos > 0) {
- --c_pos;
- if (a->frac[--a_pos] < b->frac[--b_pos] + borrow) {
- c->frac[c_pos] = BASE + a->frac[a_pos] - b->frac[b_pos] - borrow;
- borrow = 1;
- }
- else {
- c->frac[c_pos] = a->frac[a_pos] - b->frac[b_pos] - borrow;
- borrow = 0;
- }
- }
-
- /* Just assign the first few digits of a with considering */
- /* the borrow obtained so far because b has been exhausted. */
- while (a_pos > 0) {
- --c_pos;
- if (a->frac[--a_pos] < borrow) {
- c->frac[c_pos] = BASE + a->frac[a_pos] - borrow;
- borrow = 1;
- }
- else {
- c->frac[c_pos] = a->frac[a_pos] - borrow;
- borrow = 0;
- }
- }
- if (c_pos) c->frac[c_pos - 1] -= borrow;
- goto Exit;
-
-Assign_a:
- VpAsgn(c, a, 1);
- mrv = 0;
-
-Exit:
-#ifdef BIGDECIMAL_DEBUG
- if (gfDebug) {
- VPrint(stdout, "VpSubAbs exit: c=% \n", c);
- }
-#endif /* BIGDECIMAL_DEBUG */
- return mrv;
-}
-
-/*
- * Note: If(av+bv)>= HALF_BASE,then 1 will be added to the least significant
- * digit of c(In case of addition).
- * ------------------------- figure of output -----------------------------------
- * a = xxxxxxxxxxx
- * b = xxxxxxxxxx
- * c =xxxxxxxxxxxxxxx
- * word_shift = | |
- * right_word = | | (Total digits in RHSV)
- * left_word = | | (Total digits in LHSV)
- * a_pos = |
- * b_pos = |
- * c_pos = |
- */
-static size_t
-VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos, DECDIG *av, DECDIG *bv)
-{
- size_t left_word, right_word, word_shift;
-
- size_t const round_limit = (VpGetPrecLimit() + BASE_FIG - 1) / BASE_FIG;
-
- assert(a->exponent >= b->exponent);
-
- c->frac[0] = 0;
- *av = *bv = 0;
-
- word_shift = (a->exponent - b->exponent);
- left_word = b->Prec + word_shift;
- right_word = Max(a->Prec, left_word);
- left_word = c->MaxPrec - 1; /* -1 ... prepare for round up */
-
- /*
- * check if 'round' is needed.
- */
- if (right_word > left_word) { /* round ? */
- /*---------------------------------
- * Actual size of a = xxxxxxAxx
- * Actual size of b = xxxBxxxxx
- * Max. size of c = xxxxxx
- * Round off = |-----|
- * c_pos = |
- * right_word = |
- * a_pos = |
- */
- *c_pos = right_word = left_word + 1; /* Set resulting precision */
- /* be equal to that of c */
- if (a->Prec >= c->MaxPrec) {
- /*
- * a = xxxxxxAxxx
- * c = xxxxxx
- * a_pos = |
- */
- *a_pos = left_word;
- if (*a_pos <= round_limit) {
- *av = a->frac[*a_pos]; /* av is 'A' shown in above. */
- }
- }
- else {
- /*
- * a = xxxxxxx
- * c = xxxxxxxxxx
- * a_pos = |
- */
- *a_pos = a->Prec;
- }
- if (b->Prec + word_shift >= c->MaxPrec) {
- /*
- * a = xxxxxxxxx
- * b = xxxxxxxBxxx
- * c = xxxxxxxxxxx
- * b_pos = |
- */
- if (c->MaxPrec >= word_shift + 1) {
- *b_pos = c->MaxPrec - word_shift - 1;
- if (*b_pos + word_shift <= round_limit) {
- *bv = b->frac[*b_pos];
- }
- }
- else {
- *b_pos = -1L;
- }
- }
- else {
- /*
- * a = xxxxxxxxxxxxxxxx
- * b = xxxxxx
- * c = xxxxxxxxxxxxx
- * b_pos = |
- */
- *b_pos = b->Prec;
- }
- }
- else { /* The MaxPrec of c - 1 > The Prec of a + b */
- /*
- * a = xxxxxxx
- * b = xxxxxx
- * c = xxxxxxxxxxx
- * c_pos = |
- */
- *b_pos = b->Prec;
- *a_pos = a->Prec;
- *c_pos = right_word + 1;
- }
- c->Prec = *c_pos;
- c->exponent = a->exponent;
- if (!AddExponent(c, 1)) return (size_t)-1L;
- return word_shift;
-}
-
-/*
- * Return number of significant digits
- * c = a * b , Where a = a0a1a2 ... an
- * b = b0b1b2 ... bm
- * c = c0c1c2 ... cl
- * a0 a1 ... an * bm
- * a0 a1 ... an * bm-1
- * . . .
- * . . .
- * a0 a1 .... an * b0
- * +_____________________________
- * c0 c1 c2 ...... cl
- * nc <---|
- * MaxAB |--------------------|
- */
-VP_EXPORT size_t
-VpMult(Real *c, Real *a, Real *b)
-{
- size_t MxIndA, MxIndB, MxIndAB, MxIndC;
- size_t ind_c, i, ii, nc;
- size_t ind_as, ind_ae, ind_bs;
- DECDIG carry;
- DECDIG_DBL s;
- Real *w;
-
-#ifdef BIGDECIMAL_DEBUG
- if (gfDebug) {
- VPrint(stdout, "VpMult(Enter): a=% \n", a);
- VPrint(stdout, " b=% \n", b);
- }
-#endif /* BIGDECIMAL_DEBUG */
-
- if (!VpIsDefOP(c, a, b, OP_SW_MULT)) return 0; /* No significant digit */
-
- if (VpIsZero(a) || VpIsZero(b)) {
- /* at least a or b is zero */
- VpSetZero(c, VpGetSign(a) * VpGetSign(b));
- return 1; /* 0: 1 significant digit */
- }
-
- if (VpIsOne(a)) {
- VpAsgn(c, b, VpGetSign(a));
- goto Exit;
- }
- if (VpIsOne(b)) {
- VpAsgn(c, a, VpGetSign(b));
- goto Exit;
- }
- if (b->Prec > a->Prec) {
- /* Adjust so that digits(a)>digits(b) */
- w = a;
- a = b;
- b = w;
- }
- w = NULL;
- MxIndA = a->Prec - 1;
- MxIndB = b->Prec - 1;
- MxIndC = c->MaxPrec - 1;
- MxIndAB = a->Prec + b->Prec - 1;
-
- if (MxIndC < MxIndAB) { /* The Max. prec. of c < Prec(a)+Prec(b) */
- w = c;
- c = NewZeroNolimit(1, (size_t)((MxIndAB + 1) * BASE_FIG));
- MxIndC = MxIndAB;
- }
-
- /* set LHSV c info */
-
- c->exponent = a->exponent; /* set exponent */
- if (!AddExponent(c, b->exponent)) {
- if (w) rbd_free_struct(c);
- return 0;
- }
- VpSetSign(c, VpGetSign(a) * VpGetSign(b)); /* set sign */
- carry = 0;
- nc = ind_c = MxIndAB;
- memset(c->frac, 0, (nc + 1) * sizeof(DECDIG)); /* Initialize c */
- c->Prec = nc + 1; /* set precision */
- for (nc = 0; nc < MxIndAB; ++nc, --ind_c) {
- if (nc < MxIndB) { /* The left triangle of the Fig. */
- ind_as = MxIndA - nc;
- ind_ae = MxIndA;
- ind_bs = MxIndB;
- }
- else if (nc <= MxIndA) { /* The middle rectangular of the Fig. */
- ind_as = MxIndA - nc;
- ind_ae = MxIndA - (nc - MxIndB);
- ind_bs = MxIndB;
- }
- else /* if (nc > MxIndA) */ { /* The right triangle of the Fig. */
- ind_as = 0;
- ind_ae = MxIndAB - nc - 1;
- ind_bs = MxIndB - (nc - MxIndA);
- }
-
- for (i = ind_as; i <= ind_ae; ++i) {
- s = (DECDIG_DBL)a->frac[i] * b->frac[ind_bs--];
- carry = (DECDIG)(s / BASE);
- s -= (DECDIG_DBL)carry * BASE;
- c->frac[ind_c] += (DECDIG)s;
- if (c->frac[ind_c] >= BASE) {
- s = c->frac[ind_c] / BASE;
- carry += (DECDIG)s;
- c->frac[ind_c] -= (DECDIG)(s * BASE);
- }
- if (carry) {
- ii = ind_c;
- while (ii-- > 0) {
- c->frac[ii] += carry;
- if (c->frac[ii] >= BASE) {
- carry = c->frac[ii] / BASE;
- c->frac[ii] -= (carry * BASE);
- }
- else {
- break;
- }
- }
- }
- }
- }
- if (w != NULL) { /* free work variable */
- VpNmlz(c);
- VpAsgn(w, c, 1);
- rbd_free_struct(c);
- c = w;
- }
- else {
- VpLimitRound(c,0);
- }
-
-Exit:
-#ifdef BIGDECIMAL_DEBUG
- if (gfDebug) {
- VPrint(stdout, "VpMult(c=a*b): c=% \n", c);
- VPrint(stdout, " a=% \n", a);
- VPrint(stdout, " b=% \n", b);
- }
-#endif /*BIGDECIMAL_DEBUG */
- return c->Prec*BASE_FIG;
-}
-
-/*
- * c = a / b, remainder = r
- */
-VP_EXPORT size_t
-VpDivd(Real *c, Real *r, Real *a, Real *b)
-{
- size_t word_a, word_b, word_c, word_r;
- size_t i, n, ind_a, ind_b, ind_c, ind_r;
- size_t nLoop;
- DECDIG_DBL q, b1, b1p1, b1b2, b1b2p1, r1r2;
- DECDIG borrow, borrow1, borrow2;
- DECDIG_DBL qb;
-
-#ifdef BIGDECIMAL_DEBUG
- if (gfDebug) {
- VPrint(stdout, " VpDivd(c=a/b) a=% \n", a);
- VPrint(stdout, " b=% \n", b);
- }
-#endif /*BIGDECIMAL_DEBUG */
-
- VpSetNaN(r);
- if (!VpIsDefOP(c, a, b, OP_SW_DIV)) goto Exit;
- if (VpIsZero(a) && VpIsZero(b)) {
- VpSetNaN(c);
- return VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'", 0);
- }
- if (VpIsZero(b)) {
- VpSetInf(c, VpGetSign(a) * VpGetSign(b));
- return VpException(VP_EXCEPTION_ZERODIVIDE, "Divide by zero", 0);
- }
- if (VpIsZero(a)) {
- /* numerator a is zero */
- VpSetZero(c, VpGetSign(a) * VpGetSign(b));
- VpSetZero(r, VpGetSign(a) * VpGetSign(b));
- goto Exit;
- }
- if (VpIsOne(b)) {
- /* divide by one */
- VpAsgn(c, a, VpGetSign(b));
- VpSetZero(r, VpGetSign(a));
- goto Exit;
- }
-
- word_a = a->Prec;
- word_b = b->Prec;
- word_c = c->MaxPrec;
- word_r = r->MaxPrec;
-
- if (word_a >= word_r) goto space_error;
-
- ind_r = 1;
- r->frac[0] = 0;
- while (ind_r <= word_a) {
- r->frac[ind_r] = a->frac[ind_r - 1];
- ++ind_r;
- }
- while (ind_r < word_r) r->frac[ind_r++] = 0;
-
- ind_c = 0;
- while (ind_c < word_c) c->frac[ind_c++] = 0;
-
- /* initial procedure */
- b1 = b1p1 = b->frac[0];
- if (b->Prec <= 1) {
- b1b2p1 = b1b2 = b1p1 * BASE;
- }
- else {
- b1p1 = b1 + 1;
- b1b2p1 = b1b2 = b1 * BASE + b->frac[1];
- if (b->Prec > 2) ++b1b2p1;
- }
-
- /* */
- /* loop start */
- ind_c = word_r - 1;
- nLoop = Min(word_c,ind_c);
- ind_c = 1;
- while (ind_c < nLoop) {
- if (r->frac[ind_c] == 0) {
- ++ind_c;
- continue;
- }
- r1r2 = (DECDIG_DBL)r->frac[ind_c] * BASE + r->frac[ind_c + 1];
- if (r1r2 == b1b2) {
- /* The first two word digits is the same */
- ind_b = 2;
- ind_a = ind_c + 2;
- while (ind_b < word_b) {
- if (r->frac[ind_a] < b->frac[ind_b]) goto div_b1p1;
- if (r->frac[ind_a] > b->frac[ind_b]) break;
- ++ind_a;
- ++ind_b;
- }
- /* The first few word digits of r and b is the same and */
- /* the first different word digit of w is greater than that */
- /* of b, so quotient is 1 and just subtract b from r. */
- borrow = 0; /* quotient=1, then just r-b */
- ind_b = b->Prec - 1;
- ind_r = ind_c + ind_b;
- if (ind_r >= word_r) goto space_error;
- n = ind_b;
- for (i = 0; i <= n; ++i) {
- if (r->frac[ind_r] < b->frac[ind_b] + borrow) {
- r->frac[ind_r] += (BASE - (b->frac[ind_b] + borrow));
- borrow = 1;
- }
- else {
- r->frac[ind_r] = r->frac[ind_r] - b->frac[ind_b] - borrow;
- borrow = 0;
- }
- --ind_r;
- --ind_b;
- }
- ++c->frac[ind_c];
- goto carry;
- }
- /* The first two word digits is not the same, */
- /* then compare magnitude, and divide actually. */
- if (r1r2 >= b1b2p1) {
- q = r1r2 / b1b2p1; /* q == (DECDIG)q */
- c->frac[ind_c] += (DECDIG)q;
- ind_r = b->Prec + ind_c - 1;
- goto sub_mult;
- }
-
-div_b1p1:
- if (ind_c + 1 >= word_c) goto out_side;
- q = r1r2 / b1p1; /* q == (DECDIG)q */
- c->frac[ind_c + 1] += (DECDIG)q;
- ind_r = b->Prec + ind_c;
-
-sub_mult:
- borrow1 = borrow2 = 0;
- ind_b = word_b - 1;
- if (ind_r >= word_r) goto space_error;
- n = ind_b;
- for (i = 0; i <= n; ++i) {
- /* now, perform r = r - q * b */
- qb = q * b->frac[ind_b];
- if (qb < BASE) borrow1 = 0;
- else {
- borrow1 = (DECDIG)(qb / BASE);
- qb -= (DECDIG_DBL)borrow1 * BASE; /* get qb < BASE */
- }
- if(r->frac[ind_r] < qb) {
- r->frac[ind_r] += (DECDIG)(BASE - qb);
- borrow2 = borrow2 + borrow1 + 1;
- }
- else {
- r->frac[ind_r] -= (DECDIG)qb;
- borrow2 += borrow1;
- }
- if (borrow2) {
- if(r->frac[ind_r - 1] < borrow2) {
- r->frac[ind_r - 1] += (BASE - borrow2);
- borrow2 = 1;
- }
- else {
- r->frac[ind_r - 1] -= borrow2;
- borrow2 = 0;
- }
- }
- --ind_r;
- --ind_b;
- }
-
- r->frac[ind_r] -= borrow2;
-carry:
- ind_r = ind_c;
- while (c->frac[ind_r] >= BASE) {
- c->frac[ind_r] -= BASE;
- --ind_r;
- ++c->frac[ind_r];
- }
- }
- /* End of operation, now final arrangement */
-out_side:
- c->Prec = word_c;
- c->exponent = a->exponent;
- if (!AddExponent(c, 2)) return 0;
- if (!AddExponent(c, -(b->exponent))) return 0;
-
- VpSetSign(c, VpGetSign(a) * VpGetSign(b));
- VpNmlz(c); /* normalize c */
- r->Prec = word_r;
- r->exponent = a->exponent;
- if (!AddExponent(r, 1)) return 0;
- VpSetSign(r, VpGetSign(a));
- VpNmlz(r); /* normalize r(remainder) */
- goto Exit;
-
-space_error:
-#ifdef BIGDECIMAL_DEBUG
- if (gfDebug) {
- printf(" word_a=%"PRIuSIZE"\n", word_a);
- printf(" word_b=%"PRIuSIZE"\n", word_b);
- printf(" word_c=%"PRIuSIZE"\n", word_c);
- printf(" word_r=%"PRIuSIZE"\n", word_r);
- printf(" ind_r =%"PRIuSIZE"\n", ind_r);
- }
-#endif /* BIGDECIMAL_DEBUG */
- rb_bug("ERROR(VpDivd): space for remainder too small.");
-
-Exit:
-#ifdef BIGDECIMAL_DEBUG
- if (gfDebug) {
- VPrint(stdout, " VpDivd(c=a/b), c=% \n", c);
- VPrint(stdout, " r=% \n", r);
- }
-#endif /* BIGDECIMAL_DEBUG */
- return c->Prec * BASE_FIG;
-}
-
-/*
- * Input a = 00000xxxxxxxx En(5 preceding zeros)
- * Output a = xxxxxxxx En-5
- */
-static int
-VpNmlz(Real *a)
-{
- size_t ind_a, i;
-
- if (!VpIsDef(a)) goto NoVal;
- if (VpIsZero(a)) goto NoVal;
-
- ind_a = a->Prec;
- while (ind_a--) {
- if (a->frac[ind_a]) {
- a->Prec = ind_a + 1;
- i = 0;
- while (a->frac[i] == 0) ++i; /* skip the first few zeros */
- if (i) {
- a->Prec -= i;
- if (!AddExponent(a, -(SIGNED_VALUE)i)) return 0;
- memmove(&a->frac[0], &a->frac[i], a->Prec*sizeof(DECDIG));
- }
- return 1;
- }
- }
- /* a is zero(no non-zero digit) */
- VpSetZero(a, VpGetSign(a));
- return 0;
-
-NoVal:
- a->frac[0] = 0;
- a->Prec = 1;
- return 0;
-}
-
-/*
- * VpComp = 0 ... if a=b,
- * Pos ... a>b,
- * Neg ... a<b.
- * 999 ... result undefined(NaN)
- */
-VP_EXPORT int
-VpComp(Real *a, Real *b)
-{
- int val;
- size_t mx, ind;
- int e;
- val = 0;
- if (VpIsNaN(a) || VpIsNaN(b)) return 999;
- if (!VpIsDef(a)) {
- if (!VpIsDef(b)) e = a->sign - b->sign;
- else e = a->sign;
-
- if (e > 0) return 1;
- else if (e < 0) return -1;
- else return 0;
- }
- if (!VpIsDef(b)) {
- e = -b->sign;
- if (e > 0) return 1;
- else return -1;
- }
- /* Zero check */
- if (VpIsZero(a)) {
- if (VpIsZero(b)) return 0; /* both zero */
- val = -VpGetSign(b);
- goto Exit;
- }
- if (VpIsZero(b)) {
- val = VpGetSign(a);
- goto Exit;
- }
-
- /* compare sign */
- if (VpGetSign(a) > VpGetSign(b)) {
- val = 1; /* a>b */
- goto Exit;
- }
- if (VpGetSign(a) < VpGetSign(b)) {
- val = -1; /* a<b */
- goto Exit;
- }
-
- /* a and b have same sign, && sign!=0,then compare exponent */
- if (a->exponent > b->exponent) {
- val = VpGetSign(a);
- goto Exit;
- }
- if (a->exponent < b->exponent) {
- val = -VpGetSign(b);
- goto Exit;
- }
-
- /* a and b have same exponent, then compare their significand. */
- mx = (a->Prec < b->Prec) ? a->Prec : b->Prec;
- ind = 0;
- while (ind < mx) {
- if (a->frac[ind] > b->frac[ind]) {
- val = VpGetSign(a);
- goto Exit;
- }
- if (a->frac[ind] < b->frac[ind]) {
- val = -VpGetSign(b);
- goto Exit;
- }
- ++ind;
- }
- if (a->Prec > b->Prec) {
- val = VpGetSign(a);
- }
- else if (a->Prec < b->Prec) {
- val = -VpGetSign(b);
- }
-
-Exit:
- if (val > 1) val = 1;
- else if (val < -1) val = -1;
-
-#ifdef BIGDECIMAL_DEBUG
- if (gfDebug) {
- VPrint(stdout, " VpComp a=%\n", a);
- VPrint(stdout, " b=%\n", b);
- printf(" ans=%d\n", val);
- }
-#endif /* BIGDECIMAL_DEBUG */
- return (int)val;
-}
-
-/*
- * cntl_chr ... ASCIIZ Character, print control characters
- * Available control codes:
- * % ... VP variable. To print '%', use '%%'.
- * \n ... new line
- * \b ... backspace
- * \t ... tab
- * Note: % must not appear more than once
- * a ... VP variable to be printed
- */
-static int
-VPrint(FILE *fp, const char *cntl_chr, Real *a)
-{
- size_t i, j, nc, nd, ZeroSup, sep = 10;
- DECDIG m, e, nn;
-
- j = 0;
- nd = nc = 0; /* nd : number of digits in fraction part(every 10 digits, */
- /* nd<=10). */
- /* nc : number of characters printed */
- ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
- while (*(cntl_chr + j)) {
- if (*(cntl_chr + j) == '%' && *(cntl_chr + j + 1) != '%') {
- nc = 0;
- if (VpIsNaN(a)) {
- fprintf(fp, SZ_NaN);
- nc += 8;
- }
- else if (VpIsPosInf(a)) {
- fprintf(fp, SZ_INF);
- nc += 8;
- }
- else if (VpIsNegInf(a)) {
- fprintf(fp, SZ_NINF);
- nc += 9;
- }
- else if (!VpIsZero(a)) {
- if (BIGDECIMAL_NEGATIVE_P(a)) {
- fprintf(fp, "-");
- ++nc;
- }
- nc += fprintf(fp, "0.");
- switch (*(cntl_chr + j + 1)) {
- default:
- break;
-
- case '0': case 'z':
- ZeroSup = 0;
- ++j;
- sep = cntl_chr[j] == 'z' ? BIGDECIMAL_COMPONENT_FIGURES : 10;
- break;
- }
- for (i = 0; i < a->Prec; ++i) {
- m = BASE1;
- e = a->frac[i];
- while (m) {
- nn = e / m;
- if (!ZeroSup || nn) {
- nc += fprintf(fp, "%lu", (unsigned long)nn); /* The leading zero(s) */
- /* as 0.00xx will not */
- /* be printed. */
- ++nd;
- ZeroSup = 0; /* Set to print succeeding zeros */
- }
- if (nd >= sep) { /* print ' ' after every 10 digits */
- nd = 0;
- nc += fprintf(fp, " ");
- }
- e = e - nn * m;
- m /= 10;
- }
- }
- nc += fprintf(fp, "E%"PRIdSIZE, VpExponent10(a));
- nc += fprintf(fp, " (%"PRIdVALUE", %"PRIuSIZE", %"PRIuSIZE")", a->exponent, a->Prec, a->MaxPrec);
- }
- else {
- nc += fprintf(fp, "0.0");
- }
- }
- else {
- ++nc;
- if (*(cntl_chr + j) == '\\') {
- switch (*(cntl_chr + j + 1)) {
- case 'n':
- fprintf(fp, "\n");
- ++j;
- break;
- case 't':
- fprintf(fp, "\t");
- ++j;
- break;
- case 'b':
- fprintf(fp, "\n");
- ++j;
- break;
- default:
- fprintf(fp, "%c", *(cntl_chr + j));
- break;
- }
- }
- else {
- fprintf(fp, "%c", *(cntl_chr + j));
- if (*(cntl_chr + j) == '%') ++j;
- }
- }
- j++;
- }
-
- return (int)nc;
-}
-
-static void
-VpFormatSt(char *psz, size_t fFmt)
-{
- size_t ie, i, nf = 0;
- char ch;
-
- if (fFmt == 0) return;
-
- ie = strlen(psz);
- for (i = 0; i < ie; ++i) {
- ch = psz[i];
- if (!ch) break;
- if (ISSPACE(ch) || ch=='-' || ch=='+') continue;
- if (ch == '.') { nf = 0; continue; }
- if (ch == 'E' || ch == 'e') break;
-
- if (++nf > fFmt) {
- memmove(psz + i + 1, psz + i, ie - i + 1);
- ++ie;
- nf = 0;
- psz[i] = ' ';
- }
- }
-}
-
-VP_EXPORT ssize_t
-VpExponent10(Real *a)
-{
- ssize_t ex;
- size_t n;
-
- if (!VpHasVal(a)) return 0;
-
- ex = a->exponent * (ssize_t)BASE_FIG;
- n = BASE1;
- while ((a->frac[0] / n) == 0) {
- --ex;
- n /= 10;
- }
- return ex;
-}
-
-VP_EXPORT void
-VpSzMantissa(Real *a, char *buf, size_t buflen)
-{
- size_t i, n, ZeroSup;
- DECDIG_DBL m, e, nn;
-
- if (VpIsNaN(a)) {
- snprintf(buf, buflen, SZ_NaN);
- return;
- }
- if (VpIsPosInf(a)) {
- snprintf(buf, buflen, SZ_INF);
- return;
- }
- if (VpIsNegInf(a)) {
- snprintf(buf, buflen, SZ_NINF);
- return;
- }
-
- ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
- if (!VpIsZero(a)) {
- if (BIGDECIMAL_NEGATIVE_P(a)) *buf++ = '-';
- n = a->Prec;
- for (i = 0; i < n; ++i) {
- m = BASE1;
- e = a->frac[i];
- while (m) {
- nn = e / m;
- if (!ZeroSup || nn) {
- snprintf(buf, buflen, "%lu", (unsigned long)nn); /* The leading zero(s) */
- buf += strlen(buf);
- /* as 0.00xx will be ignored. */
- ZeroSup = 0; /* Set to print succeeding zeros */
- }
- e = e - nn * m;
- m /= 10;
- }
- }
- *buf = 0;
- while (buf[-1] == '0') *(--buf) = 0;
- }
- else {
- if (VpIsPosZero(a)) snprintf(buf, buflen, "0");
- else snprintf(buf, buflen, "-0");
- }
-}
-
-VP_EXPORT int
-VpToSpecialString(Real *a, char *buf, size_t buflen, int fPlus)
-/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
-{
- if (VpIsNaN(a)) {
- snprintf(buf, buflen, SZ_NaN);
- return 1;
- }
-
- if (VpIsPosInf(a)) {
- if (fPlus == 1) {
- *buf++ = ' ';
- }
- else if (fPlus == 2) {
- *buf++ = '+';
- }
- snprintf(buf, buflen, SZ_INF);
- return 1;
- }
- if (VpIsNegInf(a)) {
- snprintf(buf, buflen, SZ_NINF);
- return 1;
- }
- if (VpIsZero(a)) {
- if (VpIsPosZero(a)) {
- if (fPlus == 1) snprintf(buf, buflen, " 0.0");
- else if (fPlus == 2) snprintf(buf, buflen, "+0.0");
- else snprintf(buf, buflen, "0.0");
- }
- else snprintf(buf, buflen, "-0.0");
- return 1;
- }
- return 0;
-}
-
-VP_EXPORT void
-VpToString(Real *a, char *buf, size_t buflen, size_t fFmt, int fPlus)
-/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
-{
- size_t i, n, ZeroSup;
- DECDIG shift, m, e, nn;
- char *p = buf;
- size_t plen = buflen;
- ssize_t ex;
-
- if (VpToSpecialString(a, buf, buflen, fPlus)) return;
-
- ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
-
-#define ADVANCE(n) do { \
- if (plen < n) goto overflow; \
- p += n; \
- plen -= n; \
-} while (0)
-
- if (BIGDECIMAL_NEGATIVE_P(a)) {
- *p = '-';
- ADVANCE(1);
- }
- else if (fPlus == 1) {
- *p = ' ';
- ADVANCE(1);
- }
- else if (fPlus == 2) {
- *p = '+';
- ADVANCE(1);
- }
-
- *p = '0'; ADVANCE(1);
- *p = '.'; ADVANCE(1);
-
- n = a->Prec;
- for (i = 0; i < n; ++i) {
- m = BASE1;
- e = a->frac[i];
- while (m) {
- nn = e / m;
- if (!ZeroSup || nn) {
- /* The reading zero(s) */
- size_t n = (size_t)snprintf(p, plen, "%lu", (unsigned long)nn);
- if (n > plen) goto overflow;
- ADVANCE(n);
- /* as 0.00xx will be ignored. */
- ZeroSup = 0; /* Set to print succeeding zeros */
- }
- e = e - nn * m;
- m /= 10;
- }
- }
-
- ex = a->exponent * (ssize_t)BASE_FIG;
- shift = BASE1;
- while (a->frac[0] / shift == 0) {
- --ex;
- shift /= 10;
- }
- while (p - 1 > buf && p[-1] == '0') {
- *(--p) = '\0';
- ++plen;
- }
- snprintf(p, plen, "e%"PRIdSIZE, ex);
- if (fFmt) VpFormatSt(buf, fFmt);
-
- overflow:
- return;
-#undef ADVANCE
-}
-
-VP_EXPORT void
-VpToFString(Real *a, char *buf, size_t buflen, size_t fFmt, int fPlus)
-/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
-{
- size_t i, n;
- DECDIG m, e;
- char *p = buf;
- size_t plen = buflen, delim = fFmt;
- ssize_t ex;
-
- if (VpToSpecialString(a, buf, buflen, fPlus)) return;
-
-#define APPEND(c, group) do { \
- if (plen < 1) goto overflow; \
- if (group && delim == 0) { \
- *p = ' '; \
- p += 1; \
- plen -= 1; \
- } \
- if (plen < 1) goto overflow; \
- *p = c; \
- p += 1; \
- plen -= 1; \
- if (group) delim = (delim + 1) % fFmt; \
-} while (0)
-
-
- if (BIGDECIMAL_NEGATIVE_P(a)) {
- APPEND('-', false);
- }
- else if (fPlus == 1) {
- APPEND(' ', false);
- }
- else if (fPlus == 2) {
- APPEND('+', false);
- }
-
- n = a->Prec;
- ex = a->exponent;
- if (ex <= 0) {
- APPEND('0', false);
- APPEND('.', false);
- }
- while (ex < 0) {
- for (i=0; i < BASE_FIG; ++i) {
- APPEND('0', fFmt > 0);
- }
- ++ex;
- }
-
- for (i = 0; i < n; ++i) {
- m = BASE1;
- e = a->frac[i];
- if (i == 0 && ex > 0) {
- for (delim = 0; e / m == 0; delim++) {
- m /= 10;
- }
- if (fFmt > 0) {
- delim = 2*fFmt - (ex * BASE_FIG - delim) % fFmt;
- }
- }
- while (m && (e || (i < n - 1) || ex > 0)) {
- APPEND((char)(e / m + '0'), fFmt > 0);
- e %= m;
- m /= 10;
- }
- if (--ex == 0) {
- APPEND('.', false);
- delim = fFmt;
- }
- }
-
- while (ex > 0) {
- for (i=0; i < BASE_FIG; ++i) {
- APPEND('0', fFmt > 0);
- }
- if (--ex == 0) {
- APPEND('.', false);
- }
- }
-
- *p = '\0';
- if (p - 1 > buf && p[-1] == '.') {
- snprintf(p, plen, "0");
- }
-
- overflow:
- return;
-#undef APPEND
-}
-
-/*
- * [Output]
- * a[] ... variable to be assigned the value.
- * [Input]
- * int_chr[] ... integer part(may include '+/-').
- * ni ... number of characters in int_chr[],not including '+/-'.
- * frac[] ... fraction part.
- * nf ... number of characters in frac[].
- * exp_chr[] ... exponent part(including '+/-').
- * ne ... number of characters in exp_chr[],not including '+/-'.
- */
-VP_EXPORT int
-VpCtoV(Real *a, const char *int_chr, size_t ni, const char *frac, size_t nf, const char *exp_chr, size_t ne)
-{
- size_t i, j, ind_a, ma, mi, me;
- SIGNED_VALUE e, es, eb, ef;
- int sign, signe, exponent_overflow;
-
- /* get exponent part */
- e = 0;
- ma = a->MaxPrec;
- mi = ni;
- me = ne;
- signe = 1;
- exponent_overflow = 0;
- memset(a->frac, 0, ma * sizeof(DECDIG));
- if (ne > 0) {
- i = 0;
- if (exp_chr[0] == '-') {
- signe = -1;
- ++i;
- ++me;
- }
- else if (exp_chr[0] == '+') {
- ++i;
- ++me;
- }
- while (i < me) {
- if (MUL_OVERFLOW_SIGNED_VALUE_P(e, (SIGNED_VALUE)BASE_FIG)) {
- es = e;
- goto exp_overflow;
- }
- es = e * (SIGNED_VALUE)BASE_FIG;
- if (MUL_OVERFLOW_SIGNED_VALUE_P(e, 10) ||
- SIGNED_VALUE_MAX - (exp_chr[i] - '0') < e * 10)
- goto exp_overflow;
- e = e * 10 + exp_chr[i] - '0';
- if (MUL_OVERFLOW_SIGNED_VALUE_P(e, (SIGNED_VALUE)BASE_FIG))
- goto exp_overflow;
- if (es > (SIGNED_VALUE)(e * BASE_FIG)) {
- exp_overflow:
- exponent_overflow = 1;
- e = es; /* keep sign */
- break;
- }
- ++i;
- }
- }
-
- /* get integer part */
- i = 0;
- sign = 1;
- if (1 /*ni >= 0*/) {
- if (int_chr[0] == '-') {
- sign = -1;
- ++i;
- ++mi;
- }
- else if (int_chr[0] == '+') {
- ++i;
- ++mi;
- }
- }
-
- e = signe * e; /* e: The value of exponent part. */
- e = e + ni; /* set actual exponent size. */
-
- if (e > 0) signe = 1;
- else signe = -1;
-
- /* Adjust the exponent so that it is the multiple of BASE_FIG. */
- j = 0;
- ef = 1;
- while (ef) {
- if (e >= 0) eb = e;
- else eb = -e;
- ef = eb / (SIGNED_VALUE)BASE_FIG;
- ef = eb - ef * (SIGNED_VALUE)BASE_FIG;
- if (ef) {
- ++j; /* Means to add one more preceding zero */
- ++e;
- }
- }
-
- eb = e / (SIGNED_VALUE)BASE_FIG;
-
- if (exponent_overflow) {
- int zero = 1;
- for ( ; i < mi && zero; i++) zero = int_chr[i] == '0';
- for (i = 0; i < nf && zero; i++) zero = frac[i] == '0';
- if (!zero && signe > 0) {
- VpSetInf(a, sign);
- VpException(VP_EXCEPTION_INFINITY, "exponent overflow",0);
- }
- else VpSetZero(a, sign);
- return 1;
- }
-
- ind_a = 0;
- while (i < mi) {
- a->frac[ind_a] = 0;
- while (j < BASE_FIG && i < mi) {
- a->frac[ind_a] = a->frac[ind_a] * 10 + int_chr[i] - '0';
- ++j;
- ++i;
- }
- if (i < mi) {
- ++ind_a;
- if (ind_a >= ma) goto over_flow;
- j = 0;
- }
- }
-
- /* get fraction part */
-
- i = 0;
- while (i < nf) {
- while (j < BASE_FIG && i < nf) {
- a->frac[ind_a] = a->frac[ind_a] * 10 + frac[i] - '0';
- ++j;
- ++i;
- }
- if (i < nf) {
- ++ind_a;
- if (ind_a >= ma) goto over_flow;
- j = 0;
- }
- }
- goto Final;
-
-over_flow:
- rb_warn("Conversion from String to BigDecimal overflow (last few digits discarded).");
-
-Final:
- if (ind_a >= ma) ind_a = ma - 1;
- while (j < BASE_FIG) {
- a->frac[ind_a] = a->frac[ind_a] * 10;
- ++j;
- }
- a->Prec = ind_a + 1;
- a->exponent = eb;
- VpSetSign(a, sign);
- VpNmlz(a);
- return 1;
-}
-
-/*
- * [Input]
- * *m ... Real
- * [Output]
- * *d ... fraction part of m(d = 0.xxxxxxx). where # of 'x's is fig.
- * *e ... exponent of m.
- * BIGDECIMAL_DOUBLE_FIGURES ... Number of digits in a double variable.
- *
- * m -> d*10**e, 0<d<BASE
- * [Returns]
- * 0 ... Zero
- * 1 ... Normal
- * 2 ... Infinity
- * -1 ... NaN
- */
-VP_EXPORT int
-VpVtoD(double *d, SIGNED_VALUE *e, Real *m)
-{
- size_t ind_m, mm, fig;
- double div;
- int f = 1;
-
- if (VpIsNaN(m)) {
- *d = VpGetDoubleNaN();
- *e = 0;
- f = -1; /* NaN */
- goto Exit;
- }
- else if (VpIsPosZero(m)) {
- *d = 0.0;
- *e = 0;
- f = 0;
- goto Exit;
- }
- else if (VpIsNegZero(m)) {
- *d = VpGetDoubleNegZero();
- *e = 0;
- f = 0;
- goto Exit;
- }
- else if (VpIsPosInf(m)) {
- *d = VpGetDoublePosInf();
- *e = 0;
- f = 2;
- goto Exit;
- }
- else if (VpIsNegInf(m)) {
- *d = VpGetDoubleNegInf();
- *e = 0;
- f = 2;
- goto Exit;
- }
- /* Normal number */
- fig = roomof(BIGDECIMAL_DOUBLE_FIGURES, BASE_FIG);
- ind_m = 0;
- mm = Min(fig, m->Prec);
- *d = 0.0;
- div = 1.;
- while (ind_m < mm) {
- div /= (double)BASE;
- *d = *d + (double)m->frac[ind_m++] * div;
- }
- *e = m->exponent * (SIGNED_VALUE)BASE_FIG;
- *d *= VpGetSign(m);
-
-Exit:
-#ifdef BIGDECIMAL_DEBUG
- if (gfDebug) {
- VPrint(stdout, " VpVtoD: m=%\n", m);
- printf(" d=%e * 10 **%ld\n", *d, *e);
- printf(" BIGDECIMAL_DOUBLE_FIGURES = %d\n", BIGDECIMAL_DOUBLE_FIGURES);
- }
-#endif /*BIGDECIMAL_DEBUG */
- return f;
-}
-
-/*
- * m <- d
- */
-VP_EXPORT void
-VpDtoV(Real *m, double d)
-{
- size_t ind_m, mm;
- SIGNED_VALUE ne;
- DECDIG i;
- double val, val2;
-
- if (isnan(d)) {
- VpSetNaN(m);
- goto Exit;
- }
- if (isinf(d)) {
- if (d > 0.0) VpSetPosInf(m);
- else VpSetNegInf(m);
- goto Exit;
- }
-
- if (d == 0.0) {
- VpSetZero(m, 1);
- goto Exit;
- }
- val = (d > 0.) ? d : -d;
- ne = 0;
- if (val >= 1.0) {
- while (val >= 1.0) {
- val /= (double)BASE;
- ++ne;
- }
- }
- else {
- val2 = 1.0 / (double)BASE;
- while (val < val2) {
- val *= (double)BASE;
- --ne;
- }
- }
- /* Now val = 0.xxxxx*BASE**ne */
-
- mm = m->MaxPrec;
- memset(m->frac, 0, mm * sizeof(DECDIG));
- for (ind_m = 0; val > 0.0 && ind_m < mm; ind_m++) {
- val *= (double)BASE;
- i = (DECDIG)val;
- val -= (double)i;
- m->frac[ind_m] = i;
- }
- if (ind_m >= mm) ind_m = mm - 1;
- VpSetSign(m, (d > 0.0) ? 1 : -1);
- m->Prec = ind_m + 1;
- m->exponent = ne;
-
- VpInternalRound(m, 0, (m->Prec > 0) ? m->frac[m->Prec-1] : 0,
- (DECDIG)(val*(double)BASE));
-
-Exit:
-#ifdef BIGDECIMAL_DEBUG
- if (gfDebug) {
- printf("VpDtoV d=%30.30e\n", d);
- VPrint(stdout, " m=%\n", m);
- }
-#endif /* BIGDECIMAL_DEBUG */
- return;
-}
-
-/*
- * m <- ival
- */
-#if 0 /* unused */
-VP_EXPORT void
-VpItoV(Real *m, SIGNED_VALUE ival)
-{
- size_t mm, ind_m;
- size_t val, v1, v2, v;
- int isign;
- SIGNED_VALUE ne;
-
- if (ival == 0) {
- VpSetZero(m, 1);
- goto Exit;
- }
- isign = 1;
- val = ival;
- if (ival < 0) {
- isign = -1;
- val =(size_t)(-ival);
- }
- ne = 0;
- ind_m = 0;
- mm = m->MaxPrec;
- while (ind_m < mm) {
- m->frac[ind_m] = 0;
- ++ind_m;
- }
- ind_m = 0;
- while (val > 0) {
- if (val) {
- v1 = val;
- v2 = 1;
- while (v1 >= BASE) {
- v1 /= BASE;
- v2 *= BASE;
- }
- val = val - v2 * v1;
- v = v1;
- }
- else {
- v = 0;
- }
- m->frac[ind_m] = v;
- ++ind_m;
- ++ne;
- }
- m->Prec = ind_m - 1;
- m->exponent = ne;
- VpSetSign(m, isign);
- VpNmlz(m);
-
-Exit:
-#ifdef BIGDECIMAL_DEBUG
- if (gfDebug) {
- printf(" VpItoV i=%d\n", ival);
- VPrint(stdout, " m=%\n", m);
- }
-#endif /* BIGDECIMAL_DEBUG */
- return;
-}
-#endif
-
-/*
- * y = SQRT(x), y*y - x =>0
- */
-VP_EXPORT int
-VpSqrt(Real *y, Real *x)
-{
- Real *f = NULL;
- Real *r = NULL;
- size_t y_prec;
- SIGNED_VALUE n, e;
- ssize_t nr;
- double val;
-
- /* Zero or +Infinity ? */
- if (VpIsZero(x) || VpIsPosInf(x)) {
- VpAsgn(y,x,1);
- goto Exit;
- }
-
- /* Negative ? */
- if (BIGDECIMAL_NEGATIVE_P(x)) {
- VpSetNaN(y);
- return VpException(VP_EXCEPTION_OP, "sqrt of negative value", 0);
- }
-
- /* NaN ? */
- if (VpIsNaN(x)) {
- VpSetNaN(y);
- return VpException(VP_EXCEPTION_OP, "sqrt of 'NaN'(Not a Number)", 0);
- }
-
- /* One ? */
- if (VpIsOne(x)) {
- VpSetOne(y);
- goto Exit;
- }
-
- n = (SIGNED_VALUE)y->MaxPrec;
- if (x->MaxPrec > (size_t)n) n = (ssize_t)x->MaxPrec;
-
- /* allocate temporally variables */
- /* TODO: reconsider MaxPrec of f and r */
- f = NewOneNolimit(1, y->MaxPrec * (BASE_FIG + 2));
- r = NewOneNolimit(1, (n + n) * (BASE_FIG + 2));
-
- nr = 0;
- y_prec = y->MaxPrec;
-
- VpVtoD(&val, &e, x); /* val <- x */
- e /= (SIGNED_VALUE)BASE_FIG;
- n = e / 2;
- if (e - n * 2 != 0) {
- val /= BASE;
- n = (e + 1) / 2;
- }
- VpDtoV(y, sqrt(val)); /* y <- sqrt(val) */
- y->exponent += n;
- n = (SIGNED_VALUE)roomof(BIGDECIMAL_DOUBLE_FIGURES, BASE_FIG);
- y->MaxPrec = Min((size_t)n , y_prec);
- f->MaxPrec = y->MaxPrec + 1;
- n = (SIGNED_VALUE)(y_prec * BASE_FIG);
- if (n < (SIGNED_VALUE)maxnr) n = (SIGNED_VALUE)maxnr;
-
- /*
- * Perform: y_{n+1} = (y_n - x/y_n) / 2
- */
- do {
- y->MaxPrec *= 2;
- if (y->MaxPrec > y_prec) y->MaxPrec = y_prec;
- f->MaxPrec = y->MaxPrec;
- VpDivd(f, r, x, y); /* f = x/y */
- VpAddSub(r, f, y, -1); /* r = f - y */
- VpMult(f, VpConstPt5, r); /* f = 0.5*r */
- if (VpIsZero(f))
- goto converge;
- VpAddSub(r, f, y, 1); /* r = y + f */
- VpAsgn(y, r, 1); /* y = r */
- } while (++nr < n);
-
-#ifdef BIGDECIMAL_DEBUG
- if (gfDebug) {
- printf("ERROR(VpSqrt): did not converge within %ld iterations.\n", nr);
- }
-#endif /* BIGDECIMAL_DEBUG */
- y->MaxPrec = y_prec;
-
-converge:
- VpChangeSign(y, 1);
-#ifdef BIGDECIMAL_DEBUG
- if (gfDebug) {
- VpMult(r, y, y);
- VpAddSub(f, x, r, -1);
- printf("VpSqrt: iterations = %"PRIdSIZE"\n", nr);
- VPrint(stdout, " y =% \n", y);
- VPrint(stdout, " x =% \n", x);
- VPrint(stdout, " x-y*y = % \n", f);
- }
-#endif /* BIGDECIMAL_DEBUG */
- y->MaxPrec = y_prec;
-
-Exit:
- rbd_free_struct(f);
- rbd_free_struct(r);
- return 1;
-}
-
-/*
- * Round relatively from the decimal point.
- * f: rounding mode
- * nf: digit location to round from the decimal point.
- */
-VP_EXPORT int
-VpMidRound(Real *y, unsigned short f, ssize_t nf)
-{
- /* fracf: any positive digit under rounding position? */
- /* fracf_1further: any positive digits under one further than the rounding position? */
- /* exptoadd: number of digits needed to compensate negative nf */
- int fracf, fracf_1further;
- ssize_t n,i,ix,ioffset, exptoadd;
- DECDIG v, shifter;
- DECDIG div;
-
- nf += y->exponent * (ssize_t)BASE_FIG;
- exptoadd=0;
- if (nf < 0) {
- /* rounding position too left(large). */
- if (f != VP_ROUND_CEIL && f != VP_ROUND_FLOOR) {
- VpSetZero(y, VpGetSign(y)); /* truncate everything */
- return 0;
- }
- exptoadd = -nf;
- nf = 0;
- }
-
- ix = nf / (ssize_t)BASE_FIG;
- if ((size_t)ix >= y->Prec) return 0; /* rounding position too right(small). */
- v = y->frac[ix];
-
- ioffset = nf - ix*(ssize_t)BASE_FIG;
- n = (ssize_t)BASE_FIG - ioffset - 1;
- for (shifter = 1, i = 0; i < n; ++i) shifter *= 10;
-
- /* so the representation used (in y->frac) is an array of DECDIG, where
- each DECDIG contains a value between 0 and BASE-1, consisting of BASE_FIG
- decimal places.
-
- (that numbers of decimal places are typed as ssize_t is somewhat confusing)
-
- nf is now position (in decimal places) of the digit from the start of
- the array.
-
- ix is the position (in DECDIGs) of the DECDIG containing the decimal digit,
- from the start of the array.
-
- v is the value of this DECDIG
-
- ioffset is the number of extra decimal places along of this decimal digit
- within v.
-
- n is the number of decimal digits remaining within v after this decimal digit
- shifter is 10**n,
-
- v % shifter are the remaining digits within v
- v % (shifter * 10) are the digit together with the remaining digits within v
- v / shifter are the digit's predecessors together with the digit
- div = v / shifter / 10 is just the digit's precessors
- (v / shifter) - div*10 is just the digit, which is what v ends up being reassigned to.
- */
-
- fracf = (v % (shifter * 10) > 0);
- fracf_1further = ((v % shifter) > 0);
-
- v /= shifter;
- div = v / 10;
- v = v - div*10;
- /* now v is just the digit required.
- now fracf is whether the digit or any of the remaining digits within v are non-zero
- now fracf_1further is whether any of the remaining digits within v are non-zero
- */
-
- /* now check all the remaining DECDIGs for zero-ness a whole DECDIG at a time.
- if we spot any non-zeroness, that means that we found a positive digit under
- rounding position, and we also found a positive digit under one further than
- the rounding position, so both searches (to see if any such non-zero digit exists)
- can stop */
-
- for (i = ix + 1; (size_t)i < y->Prec; i++) {
- if (y->frac[i] % BASE) {
- fracf = fracf_1further = 1;
- break;
- }
- }
-
- /* now fracf = does any positive digit exist under the rounding position?
- now fracf_1further = does any positive digit exist under one further than the
- rounding position?
- now v = the first digit under the rounding position */
-
- /* drop digits after pointed digit */
- memset(y->frac + ix + 1, 0, (y->Prec - (ix + 1)) * sizeof(DECDIG));
-
- switch (f) {
- case VP_ROUND_DOWN: /* Truncate */
- break;
- case VP_ROUND_UP: /* Roundup */
- if (fracf) ++div;
- break;
- case VP_ROUND_HALF_UP:
- if (v>=5) ++div;
- break;
- case VP_ROUND_HALF_DOWN:
- if (v > 5 || (v == 5 && fracf_1further)) ++div;
- break;
- case VP_ROUND_CEIL:
- if (fracf && BIGDECIMAL_POSITIVE_P(y)) ++div;
- break;
- case VP_ROUND_FLOOR:
- if (fracf && BIGDECIMAL_NEGATIVE_P(y)) ++div;
- break;
- case VP_ROUND_HALF_EVEN: /* Banker's rounding */
- if (v > 5) ++div;
- else if (v == 5) {
- if (fracf_1further) {
- ++div;
- }
- else {
- if (ioffset == 0) {
- /* v is the first decimal digit of its DECDIG;
- need to grab the previous DECDIG if present
- to check for evenness of the previous decimal
- digit (which is same as that of the DECDIG since
- base 10 has a factor of 2) */
- if (ix && (y->frac[ix-1] % 2)) ++div;
- }
- else {
- if (div % 2) ++div;
- }
- }
- }
- break;
- }
- for (i = 0; i <= n; ++i) div *= 10;
- if (div >= BASE) {
- if (ix) {
- y->frac[ix] = 0;
- VpRdup(y, ix);
- }
- else {
- short s = VpGetSign(y);
- SIGNED_VALUE e = y->exponent;
- VpSetOne(y);
- VpSetSign(y, s);
- y->exponent = e + 1;
- }
- }
- else {
- y->frac[ix] = div;
- VpNmlz(y);
- }
- if (exptoadd > 0) {
- y->exponent += (SIGNED_VALUE)(exptoadd / BASE_FIG);
- exptoadd %= (ssize_t)BASE_FIG;
- for (i = 0; i < exptoadd; i++) {
- y->frac[0] *= 10;
- if (y->frac[0] >= BASE) {
- y->frac[0] /= BASE;
- y->exponent++;
- }
- }
- }
- return 1;
-}
-
-VP_EXPORT int
-VpLeftRound(Real *y, unsigned short f, ssize_t nf)
-/*
- * Round from the left hand side of the digits.
- */
-{
- DECDIG v;
- if (!VpHasVal(y)) return 0; /* Unable to round */
- v = y->frac[0];
- nf -= VpExponent(y) * (ssize_t)BASE_FIG;
- while ((v /= 10) != 0) nf--;
- nf += (ssize_t)BASE_FIG-1;
- return VpMidRound(y, f, nf);
-}
-
-VP_EXPORT int
-VpActiveRound(Real *y, Real *x, unsigned short f, ssize_t nf)
-{
- /* First,assign whole value in truncation mode */
- if (VpAsgn(y, x, 10) <= 1) return 0; /* Zero,NaN,or Infinity */
- return VpMidRound(y, f, nf);
-}
-
-static int
-VpLimitRound(Real *c, size_t ixDigit)
-{
- size_t ix = VpGetPrecLimit();
- if (!VpNmlz(c)) return -1;
- if (!ix) return 0;
- if (!ixDigit) ixDigit = c->Prec-1;
- if ((ix + BASE_FIG - 1) / BASE_FIG > ixDigit + 1) return 0;
- return VpLeftRound(c, VpGetRoundMode(), (ssize_t)ix);
-}
-
-/* If I understand correctly, this is only ever used to round off the final decimal
- digit of precision */
-static void
-VpInternalRound(Real *c, size_t ixDigit, DECDIG vPrev, DECDIG v)
-{
- int f = 0;
-
- unsigned short const rounding_mode = VpGetRoundMode();
-
- if (VpLimitRound(c, ixDigit)) return;
- if (!v) return;
-
- v /= BASE1;
- switch (rounding_mode) {
- case VP_ROUND_DOWN:
- break;
- case VP_ROUND_UP:
- if (v) f = 1;
- break;
- case VP_ROUND_HALF_UP:
- if (v >= 5) f = 1;
- break;
- case VP_ROUND_HALF_DOWN:
- /* this is ok - because this is the last digit of precision,
- the case where v == 5 and some further digits are nonzero
- will never occur */
- if (v >= 6) f = 1;
- break;
- case VP_ROUND_CEIL:
- if (v && BIGDECIMAL_POSITIVE_P(c)) f = 1;
- break;
- case VP_ROUND_FLOOR:
- if (v && BIGDECIMAL_NEGATIVE_P(c)) f = 1;
- break;
- case VP_ROUND_HALF_EVEN: /* Banker's rounding */
- /* as per VP_ROUND_HALF_DOWN, because this is the last digit of precision,
- there is no case to worry about where v == 5 and some further digits are nonzero */
- if (v > 5) f = 1;
- else if (v == 5 && vPrev % 2) f = 1;
- break;
- }
- if (f) {
- VpRdup(c, ixDigit);
- VpNmlz(c);
- }
-}
-
-/*
- * Rounds up m(plus one to final digit of m).
- */
-static int
-VpRdup(Real *m, size_t ind_m)
-{
- DECDIG carry;
-
- if (!ind_m) ind_m = m->Prec;
-
- carry = 1;
- while (carry > 0 && ind_m--) {
- m->frac[ind_m] += carry;
- if (m->frac[ind_m] >= BASE) m->frac[ind_m] -= BASE;
- else carry = 0;
- }
- if (carry > 0) { /* Overflow,count exponent and set fraction part be 1 */
- if (!AddExponent(m, 1)) return 0;
- m->Prec = m->frac[0] = 1;
- }
- else {
- VpNmlz(m);
- }
- return 1;
-}
-
-/*
- * y = x - fix(x)
- */
-VP_EXPORT void
-VpFrac(Real *y, Real *x)
-{
- size_t my, ind_y, ind_x;
-
- if (!VpHasVal(x)) {
- VpAsgn(y, x, 1);
- goto Exit;
- }
-
- if (x->exponent > 0 && (size_t)x->exponent >= x->Prec) {
- VpSetZero(y, VpGetSign(x));
- goto Exit;
- }
- else if (x->exponent <= 0) {
- VpAsgn(y, x, 1);
- goto Exit;
- }
-
- /* satisfy: x->exponent > 0 */
-
- y->Prec = x->Prec - (size_t)x->exponent;
- y->Prec = Min(y->Prec, y->MaxPrec);
- y->exponent = 0;
- VpSetSign(y, VpGetSign(x));
- ind_y = 0;
- my = y->Prec;
- ind_x = x->exponent;
- while (ind_y < my) {
- y->frac[ind_y] = x->frac[ind_x];
- ++ind_y;
- ++ind_x;
- }
- VpNmlz(y);
-
-Exit:
-#ifdef BIGDECIMAL_DEBUG
- if (gfDebug) {
- VPrint(stdout, "VpFrac y=%\n", y);
- VPrint(stdout, " x=%\n", x);
- }
-#endif /* BIGDECIMAL_DEBUG */
- return;
-}
-
-/*
- * y = x ** n
- */
-VP_EXPORT int
-VpPowerByInt(Real *y, Real *x, SIGNED_VALUE n)
-{
- size_t s, ss;
- ssize_t sign;
- Real *w1 = NULL;
- Real *w2 = NULL;
-
- if (VpIsZero(x)) {
- if (n == 0) {
- VpSetOne(y);
- goto Exit;
- }
- sign = VpGetSign(x);
- if (n < 0) {
- n = -n;
- if (sign < 0) sign = (n % 2) ? -1 : 1;
- VpSetInf(y, sign);
- }
- else {
- if (sign < 0) sign = (n % 2) ? -1 : 1;
- VpSetZero(y,sign);
- }
- goto Exit;
- }
- if (VpIsNaN(x)) {
- VpSetNaN(y);
- goto Exit;
- }
- if (VpIsInf(x)) {
- if (n == 0) {
- VpSetOne(y);
- goto Exit;
- }
- if (n > 0) {
- VpSetInf(y, (n % 2 == 0 || VpIsPosInf(x)) ? 1 : -1);
- goto Exit;
- }
- VpSetZero(y, (n % 2 == 0 || VpIsPosInf(x)) ? 1 : -1);
- goto Exit;
- }
-
- if (x->exponent == 1 && x->Prec == 1 && x->frac[0] == 1) {
- /* abs(x) = 1 */
- VpSetOne(y);
- if (BIGDECIMAL_POSITIVE_P(x)) goto Exit;
- if ((n % 2) == 0) goto Exit;
- VpSetSign(y, -1);
- goto Exit;
- }
-
- if (n > 0) sign = 1;
- else if (n < 0) {
- sign = -1;
- n = -n;
- }
- else {
- VpSetOne(y);
- goto Exit;
- }
-
- /* Allocate working variables */
- /* TODO: reconsider MaxPrec of w1 and w2 */
- w1 = NewZeroNolimit(1, (y->MaxPrec + 2) * BASE_FIG);
- w2 = NewZeroNolimit(1, (w1->MaxPrec * 2 + 1) * BASE_FIG);
-
- /* calculation start */
-
- VpAsgn(y, x, 1);
- --n;
- while (n > 0) {
- VpAsgn(w1, x, 1);
- s = 1;
- while (ss = s, (s += s) <= (size_t)n) {
- VpMult(w2, w1, w1);
- VpAsgn(w1, w2, 1);
- }
- n -= (SIGNED_VALUE)ss;
- VpMult(w2, y, w1);
- VpAsgn(y, w2, 1);
- }
- if (sign < 0) {
- VpDivd(w1, w2, VpConstOne, y);
- VpAsgn(y, w1, 1);
- }
-
-Exit:
-#ifdef BIGDECIMAL_DEBUG
- if (gfDebug) {
- VPrint(stdout, "VpPowerByInt y=%\n", y);
- VPrint(stdout, "VpPowerByInt x=%\n", x);
- printf(" n=%"PRIdVALUE"\n", n);
- }
-#endif /* BIGDECIMAL_DEBUG */
- rbd_free_struct(w2);
- rbd_free_struct(w1);
- return 1;
-}
-
-#ifdef BIGDECIMAL_DEBUG
-int
-VpVarCheck(Real * v)
-/*
- * Checks the validity of the Real variable v.
- * [Input]
- * v ... Real *, variable to be checked.
- * [Returns]
- * 0 ... correct v.
- * other ... error
- */
-{
- size_t i;
-
- if (v->MaxPrec == 0) {
- printf("ERROR(VpVarCheck): Illegal Max. Precision(=%"PRIuSIZE")\n",
- v->MaxPrec);
- return 1;
- }
- if (v->Prec == 0 || v->Prec > v->MaxPrec) {
- printf("ERROR(VpVarCheck): Illegal Precision(=%"PRIuSIZE")\n", v->Prec);
- printf(" Max. Prec.=%"PRIuSIZE"\n", v->MaxPrec);
- return 2;
- }
- for (i = 0; i < v->Prec; ++i) {
- if (v->frac[i] >= BASE) {
- printf("ERROR(VpVarCheck): Illegal fraction\n");
- printf(" Frac[%"PRIuSIZE"]=%"PRIuDECDIG"\n", i, v->frac[i]);
- printf(" Prec. =%"PRIuSIZE"\n", v->Prec);
- printf(" Exp. =%"PRIdVALUE"\n", v->exponent);
- printf(" BASE =%"PRIuDECDIG"\n", BASE);
- return 3;
- }
- }
- return 0;
-}
-#endif /* BIGDECIMAL_DEBUG */
diff --git a/ext/bigdecimal/bigdecimal.gemspec b/ext/bigdecimal/bigdecimal.gemspec
deleted file mode 100644
index f9f3b45616..0000000000
--- a/ext/bigdecimal/bigdecimal.gemspec
+++ /dev/null
@@ -1,54 +0,0 @@
-# coding: utf-8
-
-name = File.basename(__FILE__, '.*')
-source_version = ["", "ext/#{name}/"].find do |dir|
- begin
- break File.foreach(File.join(__dir__, "#{dir}#{name}.c")) {|line|
- break $1.sub("-", ".") if /^#define\s+#{name.upcase}_VERSION\s+"(.+)"/o =~ line
- }
- rescue Errno::ENOENT
- end
-end or raise "can't find #{name.upcase}_VERSION"
-
-Gem::Specification.new do |s|
- s.name = name
- s.version = source_version
- s.authors = ["Kenta Murata", "Zachary Scott", "Shigeo Kobayashi"]
- s.email = ["mrkn@mrkn.jp"]
-
- s.summary = "Arbitrary-precision decimal floating-point number library."
- s.description = "This library provides arbitrary-precision decimal floating-point number class."
- s.homepage = "https://github.com/ruby/bigdecimal"
- s.licenses = ["Ruby", "BSD-2-Clause"]
-
- s.require_paths = %w[lib]
- s.files = %w[
- bigdecimal.gemspec
- lib/bigdecimal.rb
- lib/bigdecimal/jacobian.rb
- lib/bigdecimal/ludcmp.rb
- lib/bigdecimal/math.rb
- lib/bigdecimal/newton.rb
- lib/bigdecimal/util.rb
- sample/linear.rb
- sample/nlsolve.rb
- sample/pi.rb
- ]
- if Gem::Platform === s.platform and s.platform =~ 'java' or RUBY_ENGINE == 'jruby'
- s.platform = 'java'
- else
- s.extensions = %w[ext/bigdecimal/extconf.rb]
- s.files += %w[
- ext/bigdecimal/bigdecimal.c
- ext/bigdecimal/bigdecimal.h
- ext/bigdecimal/bits.h
- ext/bigdecimal/feature.h
- ext/bigdecimal/missing.c
- ext/bigdecimal/missing.h
- ext/bigdecimal/missing/dtoa.c
- ext/bigdecimal/static_assert.h
- ]
- end
-
- s.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
-end
diff --git a/ext/bigdecimal/bigdecimal.h b/ext/bigdecimal/bigdecimal.h
deleted file mode 100644
index 54fed811fb..0000000000
--- a/ext/bigdecimal/bigdecimal.h
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- *
- * Ruby BigDecimal(Variable decimal precision) extension library.
- *
- * Copyright(C) 2002 by Shigeo Kobayashi(shigeo@tinyforest.gr.jp)
- *
- */
-
-#ifndef RUBY_BIG_DECIMAL_H
-#define RUBY_BIG_DECIMAL_H 1
-
-#define RUBY_NO_OLD_COMPATIBILITY
-#include "ruby/ruby.h"
-#include "missing.h"
-
-#ifdef HAVE_FLOAT_H
-# include <float.h>
-#endif
-
-#ifdef HAVE_INT64_T
-# define DECDIG uint32_t
-# define DECDIG_DBL uint64_t
-# define DECDIG_DBL_SIGNED int64_t
-# define SIZEOF_DECDIG 4
-# define PRI_DECDIG_PREFIX ""
-# ifdef PRI_LL_PREFIX
-# define PRI_DECDIG_DBL_PREFIX PRI_LL_PREFIX
-# else
-# define PRI_DECDIG_DBL_PREFIX "l"
-# endif
-#else
-# define DECDIG uint16_t
-# define DECDIG_DBL uint32_t
-# define DECDIG_DBL_SIGNED int32_t
-# define SIZEOF_DECDIG 2
-# define PRI_DECDIG_PREFIX "h"
-# define PRI_DECDIG_DBL_PREFIX ""
-#endif
-
-#define PRIdDECDIG PRI_DECDIG_PREFIX"d"
-#define PRIiDECDIG PRI_DECDIG_PREFIX"i"
-#define PRIoDECDIG PRI_DECDIG_PREFIX"o"
-#define PRIuDECDIG PRI_DECDIG_PREFIX"u"
-#define PRIxDECDIG PRI_DECDIG_PREFIX"x"
-#define PRIXDECDIG PRI_DECDIG_PREFIX"X"
-
-#define PRIdDECDIG_DBL PRI_DECDIG_DBL_PREFIX"d"
-#define PRIiDECDIG_DBL PRI_DECDIG_DBL_PREFIX"i"
-#define PRIoDECDIG_DBL PRI_DECDIG_DBL_PREFIX"o"
-#define PRIuDECDIG_DBL PRI_DECDIG_DBL_PREFIX"u"
-#define PRIxDECDIG_DBL PRI_DECDIG_DBL_PREFIX"x"
-#define PRIXDECDIG_DBL PRI_DECDIG_DBL_PREFIX"X"
-
-#if SIZEOF_DECDIG == 4
-# define BIGDECIMAL_BASE ((DECDIG)1000000000U)
-# define BIGDECIMAL_COMPONENT_FIGURES 9
-/*
- * The number of components required for a 64-bit integer.
- *
- * INT64_MAX: 9_223372036_854775807
- * UINT64_MAX: 18_446744073_709551615
- */
-# define BIGDECIMAL_INT64_MAX_LENGTH 3
-
-#elif SIZEOF_DECDIG == 2
-# define BIGDECIMAL_BASE ((DECDIG)10000U)
-# define BIGDECIMAL_COMPONENT_FIGURES 4
-/*
- * The number of components required for a 64-bit integer.
- *
- * INT64_MAX: 922_3372_0368_5477_5807
- * UINT64_MAX: 1844_6744_0737_0955_1615
- */
-# define BIGDECIMAL_INT64_MAX_LENGTH 5
-
-#else
-# error Unknown size of DECDIG
-#endif
-
-#define BIGDECIMAL_DOUBLE_FIGURES (1+DBL_DIG)
-
-#if defined(__cplusplus)
-extern "C" {
-#if 0
-} /* satisfy cc-mode */
-#endif
-#endif
-
-extern VALUE rb_cBigDecimal;
-
-/*
- * NaN & Infinity
- */
-#define SZ_NaN "NaN"
-#define SZ_INF "Infinity"
-#define SZ_PINF "+Infinity"
-#define SZ_NINF "-Infinity"
-
-/*
- * #define VP_EXPORT other than static to let VP_ routines
- * be called from outside of this module.
- */
-#define VP_EXPORT static
-
-/* Exception mode */
-#define VP_EXCEPTION_ALL ((unsigned short)0x00FF)
-#define VP_EXCEPTION_INFINITY ((unsigned short)0x0001)
-#define VP_EXCEPTION_NaN ((unsigned short)0x0002)
-#define VP_EXCEPTION_UNDERFLOW ((unsigned short)0x0004)
-#define VP_EXCEPTION_OVERFLOW ((unsigned short)0x0001) /* 0x0008) */
-#define VP_EXCEPTION_ZERODIVIDE ((unsigned short)0x0010)
-
-/* Following 2 exceptions can't controlled by user */
-#define VP_EXCEPTION_OP ((unsigned short)0x0020)
-
-#define BIGDECIMAL_EXCEPTION_MODE_DEFAULT 0U
-
-/* This is used in BigDecimal#mode */
-#define VP_ROUND_MODE ((unsigned short)0x0100)
-
-/* Rounding mode */
-#define VP_ROUND_UP RBD_ROUND_UP
-#define VP_ROUND_DOWN RBD_ROUND_DOWN
-#define VP_ROUND_HALF_UP RBD_ROUND_HALF_UP
-#define VP_ROUND_HALF_DOWN RBD_ROUND_HALF_DOWN
-#define VP_ROUND_CEIL RBD_ROUND_CEIL
-#define VP_ROUND_FLOOR RBD_ROUND_FLOOR
-#define VP_ROUND_HALF_EVEN RBD_ROUND_HALF_EVEN
-
-enum rbd_rounding_mode {
- RBD_ROUND_UP = 1,
- RBD_ROUND_DOWN = 2,
- RBD_ROUND_HALF_UP = 3,
- RBD_ROUND_HALF_DOWN = 4,
- RBD_ROUND_CEIL = 5,
- RBD_ROUND_FLOOR = 6,
- RBD_ROUND_HALF_EVEN = 7,
-
- RBD_ROUND_DEFAULT = RBD_ROUND_HALF_UP,
- RBD_ROUND_TRUNCATE = RBD_ROUND_DOWN,
- RBD_ROUND_BANKER = RBD_ROUND_HALF_EVEN,
- RBD_ROUND_CEILING = RBD_ROUND_CEIL
-};
-
-#define BIGDECIMAL_ROUNDING_MODE_DEFAULT VP_ROUND_HALF_UP
-
-/* Sign flag */
-#define VP_SIGN_NaN 0 /* NaN */
-#define VP_SIGN_POSITIVE_ZERO 1 /* Positive zero */
-#define VP_SIGN_NEGATIVE_ZERO -1 /* Negative zero */
-#define VP_SIGN_POSITIVE_FINITE 2 /* Positive finite number */
-#define VP_SIGN_NEGATIVE_FINITE -2 /* Negative finite number */
-#define VP_SIGN_POSITIVE_INFINITE 3 /* Positive infinite number */
-#define VP_SIGN_NEGATIVE_INFINITE -3 /* Negative infinite number */
-
-/* The size of fraction part array */
-#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
-#define FLEXIBLE_ARRAY_SIZE /* */
-#elif defined(__GNUC__) && !defined(__STRICT_ANSI__)
-#define FLEXIBLE_ARRAY_SIZE 0
-#else
-#define FLEXIBLE_ARRAY_SIZE 1
-#endif
-
-/*
- * VP representation
- * r = 0.xxxxxxxxx *BASE**exponent
- */
-typedef struct {
- VALUE obj; /* Back pointer(VALUE) for Ruby object. */
- size_t MaxPrec; /* Maximum precision size */
- /* This is the actual size of frac[] */
- /*(frac[0] to frac[MaxPrec] are available). */
- size_t Prec; /* Current precision size. */
- /* This indicates how much the */
- /* array frac[] is actually used. */
- SIGNED_VALUE exponent; /* Exponent part. */
- short sign; /* Attributes of the value. */
- /*
- * ==0 : NaN
- * 1 : Positive zero
- * -1 : Negative zero
- * 2 : Positive number
- * -2 : Negative number
- * 3 : Positive infinite number
- * -3 : Negative infinite number
- */
- short flag; /* Not used in vp_routines,space for user. */
- DECDIG frac[FLEXIBLE_ARRAY_SIZE]; /* Array of fraction part. */
-} Real;
-
-/*
- * ------------------
- * EXPORTables.
- * ------------------
- */
-
-VP_EXPORT Real *VpNewRbClass(size_t mx, char const *str, VALUE klass, bool strict_p, bool raise_exception);
-
-VP_EXPORT Real *VpCreateRbObject(size_t mx, const char *str, bool raise_exception);
-
-#define VpBaseFig() BIGDECIMAL_COMPONENT_FIGURES
-#define VpDblFig() BIGDECIMAL_DOUBLE_FIGURES
-#define VpBaseVal() BIGDECIMAL_BASE
-
-/* Zero,Inf,NaN (isinf(),isnan() used to check) */
-VP_EXPORT double VpGetDoubleNaN(void);
-VP_EXPORT double VpGetDoublePosInf(void);
-VP_EXPORT double VpGetDoubleNegInf(void);
-VP_EXPORT double VpGetDoubleNegZero(void);
-
-/* These 2 functions added at v1.1.7 */
-VP_EXPORT size_t VpGetPrecLimit(void);
-VP_EXPORT size_t VpSetPrecLimit(size_t n);
-
-/* Round mode */
-VP_EXPORT int VpIsRoundMode(unsigned short n);
-VP_EXPORT unsigned short VpGetRoundMode(void);
-VP_EXPORT unsigned short VpSetRoundMode(unsigned short n);
-
-VP_EXPORT int VpException(unsigned short f,const char *str,int always);
-#if 0 /* unused */
-VP_EXPORT int VpIsNegDoubleZero(double v);
-#endif
-VP_EXPORT size_t VpNumOfChars(Real *vp,const char *pszFmt);
-VP_EXPORT size_t VpInit(DECDIG BaseVal);
-VP_EXPORT Real *VpAlloc(size_t mx, const char *szVal, int strict_p, int exc);
-VP_EXPORT size_t VpAsgn(Real *c, Real *a, int isw);
-VP_EXPORT size_t VpAddSub(Real *c,Real *a,Real *b,int operation);
-VP_EXPORT size_t VpMult(Real *c,Real *a,Real *b);
-VP_EXPORT size_t VpDivd(Real *c,Real *r,Real *a,Real *b);
-VP_EXPORT int VpComp(Real *a,Real *b);
-VP_EXPORT ssize_t VpExponent10(Real *a);
-VP_EXPORT void VpSzMantissa(Real *a, char *buf, size_t bufsize);
-VP_EXPORT int VpToSpecialString(Real *a, char *buf, size_t bufsize, int fPlus);
-VP_EXPORT void VpToString(Real *a, char *buf, size_t bufsize, size_t fFmt, int fPlus);
-VP_EXPORT void VpToFString(Real *a, char *buf, size_t bufsize, size_t fFmt, int fPlus);
-VP_EXPORT int VpCtoV(Real *a, const char *int_chr, size_t ni, const char *frac, size_t nf, const char *exp_chr, size_t ne);
-VP_EXPORT int VpVtoD(double *d, SIGNED_VALUE *e, Real *m);
-VP_EXPORT void VpDtoV(Real *m,double d);
-#if 0 /* unused */
-VP_EXPORT void VpItoV(Real *m,S_INT ival);
-#endif
-VP_EXPORT int VpSqrt(Real *y,Real *x);
-VP_EXPORT int VpActiveRound(Real *y, Real *x, unsigned short f, ssize_t il);
-VP_EXPORT int VpMidRound(Real *y, unsigned short f, ssize_t nf);
-VP_EXPORT int VpLeftRound(Real *y, unsigned short f, ssize_t nf);
-VP_EXPORT void VpFrac(Real *y, Real *x);
-VP_EXPORT int VpPowerByInt(Real *y, Real *x, SIGNED_VALUE n);
-#define VpPower VpPowerByInt
-
-/* VP constants */
-VP_EXPORT Real *VpOne(void);
-
-/*
- * ------------------
- * MACRO definitions.
- * ------------------
- */
-#define Abs(a) (((a)>= 0)?(a):(-(a)))
-#define Max(a, b) (((a)>(b))?(a):(b))
-#define Min(a, b) (((a)>(b))?(b):(a))
-
-#define VpMaxPrec(a) ((a)->MaxPrec)
-#define VpPrec(a) ((a)->Prec)
-#define VpGetFlag(a) ((a)->flag)
-
-/* Sign */
-
-/* VpGetSign(a) returns 1,-1 if a>0,a<0 respectively */
-#define VpGetSign(a) (((a)->sign>0)?1:(-1))
-/* Change sign of a to a>0,a<0 if s = 1,-1 respectively */
-#define VpChangeSign(a,s) {if((s)>0) (a)->sign=(short)Abs((ssize_t)(a)->sign);else (a)->sign=-(short)Abs((ssize_t)(a)->sign);}
-/* Sets sign of a to a>0,a<0 if s = 1,-1 respectively */
-#define VpSetSign(a,s) {if((s)>0) (a)->sign=(short)VP_SIGN_POSITIVE_FINITE;else (a)->sign=(short)VP_SIGN_NEGATIVE_FINITE;}
-
-/* 1 */
-#define VpSetOne(a) {(a)->Prec=(a)->exponent=(a)->frac[0]=1;(a)->sign=VP_SIGN_POSITIVE_FINITE;}
-
-/* ZEROs */
-#define VpIsPosZero(a) ((a)->sign==VP_SIGN_POSITIVE_ZERO)
-#define VpIsNegZero(a) ((a)->sign==VP_SIGN_NEGATIVE_ZERO)
-#define VpIsZero(a) (VpIsPosZero(a) || VpIsNegZero(a))
-#define VpSetPosZero(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_POSITIVE_ZERO)
-#define VpSetNegZero(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_NEGATIVE_ZERO)
-#define VpSetZero(a,s) (void)(((s)>0)?VpSetPosZero(a):VpSetNegZero(a))
-
-/* NaN */
-#define VpIsNaN(a) ((a)->sign==VP_SIGN_NaN)
-#define VpSetNaN(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_NaN)
-
-/* Infinity */
-#define VpIsPosInf(a) ((a)->sign==VP_SIGN_POSITIVE_INFINITE)
-#define VpIsNegInf(a) ((a)->sign==VP_SIGN_NEGATIVE_INFINITE)
-#define VpIsInf(a) (VpIsPosInf(a) || VpIsNegInf(a))
-#define VpIsDef(a) ( !(VpIsNaN(a)||VpIsInf(a)) )
-#define VpSetPosInf(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_POSITIVE_INFINITE)
-#define VpSetNegInf(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_NEGATIVE_INFINITE)
-#define VpSetInf(a,s) (void)(((s)>0)?VpSetPosInf(a):VpSetNegInf(a))
-#define VpHasVal(a) (a->frac[0])
-#define VpIsOne(a) ((a->Prec==1)&&(a->frac[0]==1)&&(a->exponent==1))
-#define VpExponent(a) (a->exponent)
-#ifdef BIGDECIMAL_DEBUG
-int VpVarCheck(Real * v);
-#endif /* BIGDECIMAL_DEBUG */
-
-#if defined(__cplusplus)
-#if 0
-{ /* satisfy cc-mode */
-#endif
-} /* extern "C" { */
-#endif
-#endif /* RUBY_BIG_DECIMAL_H */
diff --git a/ext/bigdecimal/bits.h b/ext/bigdecimal/bits.h
deleted file mode 100644
index 6e1e4776e3..0000000000
--- a/ext/bigdecimal/bits.h
+++ /dev/null
@@ -1,141 +0,0 @@
-#ifndef BIGDECIMAL_BITS_H
-#define BIGDECIMAL_BITS_H
-
-#include "feature.h"
-#include "static_assert.h"
-
-#if defined(__x86_64__) && defined(HAVE_X86INTRIN_H)
-# include <x86intrin.h> /* for _lzcnt_u64, etc. */
-#elif defined(_MSC_VER) && defined(HAVE_INTRIN_H)
-# include <intrin.h> /* for the following intrinsics */
-#endif
-
-#if defined(_MSC_VER) && defined(__AVX2__)
-# pragma intrinsic(__lzcnt)
-# pragma intrinsic(__lzcnt64)
-#endif
-
-#define numberof(array) ((int)(sizeof(array) / sizeof((array)[0])))
-#define roomof(x, y) (((x) + (y) - 1) / (y))
-#define type_roomof(x, y) roomof(sizeof(x), sizeof(y))
-
-#define MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max) ( \
- (a) == 0 ? 0 : \
- (a) == -1 ? (b) < -(max) : \
- (a) > 0 ? \
- ((b) > 0 ? (max) / (a) < (b) : (min) / (a) > (b)) : \
- ((b) > 0 ? (min) / (a) < (b) : (max) / (a) > (b)))
-
-#ifdef HAVE_UINT128_T
-# define bit_length(x) \
- (unsigned int) \
- (sizeof(x) <= sizeof(int32_t) ? 32 - nlz_int32((uint32_t)(x)) : \
- sizeof(x) <= sizeof(int64_t) ? 64 - nlz_int64((uint64_t)(x)) : \
- 128 - nlz_int128((uint128_t)(x)))
-#else
-# define bit_length(x) \
- (unsigned int) \
- (sizeof(x) <= sizeof(int32_t) ? 32 - nlz_int32((uint32_t)(x)) : \
- 64 - nlz_int64((uint64_t)(x)))
-#endif
-
-static inline unsigned nlz_int32(uint32_t x);
-static inline unsigned nlz_int64(uint64_t x);
-#ifdef HAVE_UINT128_T
-static inline unsigned nlz_int128(uint128_t x);
-#endif
-
-static inline unsigned int
-nlz_int32(uint32_t x)
-{
-#if defined(_MSC_VER) && defined(__AVX2__) && defined(HAVE___LZCNT)
- /* Note: It seems there is no such thing like __LZCNT__ predefined in MSVC.
- * AMD CPUs have had this instruction for decades (since K10) but for
- * Intel, Haswell is the oldest one. We need to use __AVX2__ for maximum
- * safety. */
- return (unsigned int)__lzcnt(x);
-
-#elif defined(__x86_64__) && defined(__LZCNT__) && defined(HAVE__LZCNT_U32)
- return (unsigned int)_lzcnt_u32(x);
-
-#elif defined(_MSC_VER) && defined(HAVE__BITSCANREVERSE)
- unsigned long r;
- return _BitScanReverse(&r, x) ? (31 - (int)r) : 32;
-
-#elif __has_builtin(__builtin_clz)
- STATIC_ASSERT(sizeof_int, sizeof(int) * CHAR_BIT == 32);
- return x ? (unsigned int)__builtin_clz(x) : 32;
-
-#else
- uint32_t y;
- unsigned n = 32;
- y = x >> 16; if (y) {n -= 16; x = y;}
- y = x >> 8; if (y) {n -= 8; x = y;}
- y = x >> 4; if (y) {n -= 4; x = y;}
- y = x >> 2; if (y) {n -= 2; x = y;}
- y = x >> 1; if (y) {return n - 2;}
- return (unsigned int)(n - x);
-#endif
-}
-
-static inline unsigned int
-nlz_int64(uint64_t x)
-{
-#if defined(_MSC_VER) && defined(__AVX2__) && defined(HAVE___LZCNT64)
- return (unsigned int)__lzcnt64(x);
-
-#elif defined(__x86_64__) && defined(__LZCNT__) && defined(HAVE__LZCNT_U64)
- return (unsigned int)_lzcnt_u64(x);
-
-#elif defined(_WIN64) && defined(_MSC_VER) && defined(HAVE__BITSCANREVERSE64)
- unsigned long r;
- return _BitScanReverse64(&r, x) ? (63u - (unsigned int)r) : 64;
-
-#elif __has_builtin(__builtin_clzl) && __has_builtin(__builtin_clzll) && !(defined(__sun) && defined(__sparc))
- if (x == 0) {
- return 64;
- }
- else if (sizeof(long) * CHAR_BIT == 64) {
- return (unsigned int)__builtin_clzl((unsigned long)x);
- }
- else if (sizeof(long long) * CHAR_BIT == 64) {
- return (unsigned int)__builtin_clzll((unsigned long long)x);
- }
- else {
- /* :FIXME: Is there a way to make this branch a compile-time error? */
- __builtin_unreachable();
- }
-
-#else
- uint64_t y;
- unsigned int n = 64;
- y = x >> 32; if (y) {n -= 32; x = y;}
- y = x >> 16; if (y) {n -= 16; x = y;}
- y = x >> 8; if (y) {n -= 8; x = y;}
- y = x >> 4; if (y) {n -= 4; x = y;}
- y = x >> 2; if (y) {n -= 2; x = y;}
- y = x >> 1; if (y) {return n - 2;}
- return (unsigned int)(n - x);
-
-#endif
-}
-
-#ifdef HAVE_UINT128_T
-static inline unsigned int
-nlz_int128(uint128_t x)
-{
- uint64_t y = (uint64_t)(x >> 64);
-
- if (x == 0) {
- return 128;
- }
- else if (y == 0) {
- return (unsigned int)nlz_int64(x) + 64;
- }
- else {
- return (unsigned int)nlz_int64(y);
- }
-}
-#endif
-
-#endif /* BIGDECIMAL_BITS_H */
diff --git a/ext/bigdecimal/depend b/ext/bigdecimal/depend
deleted file mode 100644
index a2455ebbda..0000000000
--- a/ext/bigdecimal/depend
+++ /dev/null
@@ -1,327 +0,0 @@
-Makefile: $(BIGDECIMAL_RB)
-
-# AUTOGENERATED DEPENDENCIES START
-bigdecimal.o: $(RUBY_EXTCONF_H)
-bigdecimal.o: $(arch_hdrdir)/ruby/config.h
-bigdecimal.o: $(hdrdir)/ruby/assert.h
-bigdecimal.o: $(hdrdir)/ruby/backward/2/assume.h
-bigdecimal.o: $(hdrdir)/ruby/backward/2/attributes.h
-bigdecimal.o: $(hdrdir)/ruby/backward/2/bool.h
-bigdecimal.o: $(hdrdir)/ruby/backward/2/inttypes.h
-bigdecimal.o: $(hdrdir)/ruby/backward/2/limits.h
-bigdecimal.o: $(hdrdir)/ruby/backward/2/long_long.h
-bigdecimal.o: $(hdrdir)/ruby/backward/2/stdalign.h
-bigdecimal.o: $(hdrdir)/ruby/backward/2/stdarg.h
-bigdecimal.o: $(hdrdir)/ruby/defines.h
-bigdecimal.o: $(hdrdir)/ruby/intern.h
-bigdecimal.o: $(hdrdir)/ruby/internal/abi.h
-bigdecimal.o: $(hdrdir)/ruby/internal/anyargs.h
-bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic.h
-bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/char.h
-bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/double.h
-bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
-bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
-bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/int.h
-bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
-bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/long.h
-bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
-bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
-bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
-bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
-bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/short.h
-bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
-bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
-bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
-bigdecimal.o: $(hdrdir)/ruby/internal/assume.h
-bigdecimal.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
-bigdecimal.o: $(hdrdir)/ruby/internal/attr/artificial.h
-bigdecimal.o: $(hdrdir)/ruby/internal/attr/cold.h
-bigdecimal.o: $(hdrdir)/ruby/internal/attr/const.h
-bigdecimal.o: $(hdrdir)/ruby/internal/attr/constexpr.h
-bigdecimal.o: $(hdrdir)/ruby/internal/attr/deprecated.h
-bigdecimal.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
-bigdecimal.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
-bigdecimal.o: $(hdrdir)/ruby/internal/attr/error.h
-bigdecimal.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
-bigdecimal.o: $(hdrdir)/ruby/internal/attr/forceinline.h
-bigdecimal.o: $(hdrdir)/ruby/internal/attr/format.h
-bigdecimal.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
-bigdecimal.o: $(hdrdir)/ruby/internal/attr/noalias.h
-bigdecimal.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
-bigdecimal.o: $(hdrdir)/ruby/internal/attr/noexcept.h
-bigdecimal.o: $(hdrdir)/ruby/internal/attr/noinline.h
-bigdecimal.o: $(hdrdir)/ruby/internal/attr/nonnull.h
-bigdecimal.o: $(hdrdir)/ruby/internal/attr/noreturn.h
-bigdecimal.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
-bigdecimal.o: $(hdrdir)/ruby/internal/attr/pure.h
-bigdecimal.o: $(hdrdir)/ruby/internal/attr/restrict.h
-bigdecimal.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
-bigdecimal.o: $(hdrdir)/ruby/internal/attr/warning.h
-bigdecimal.o: $(hdrdir)/ruby/internal/attr/weakref.h
-bigdecimal.o: $(hdrdir)/ruby/internal/cast.h
-bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is.h
-bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
-bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
-bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
-bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
-bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
-bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
-bigdecimal.o: $(hdrdir)/ruby/internal/compiler_since.h
-bigdecimal.o: $(hdrdir)/ruby/internal/config.h
-bigdecimal.o: $(hdrdir)/ruby/internal/constant_p.h
-bigdecimal.o: $(hdrdir)/ruby/internal/core.h
-bigdecimal.o: $(hdrdir)/ruby/internal/core/rarray.h
-bigdecimal.o: $(hdrdir)/ruby/internal/core/rbasic.h
-bigdecimal.o: $(hdrdir)/ruby/internal/core/rbignum.h
-bigdecimal.o: $(hdrdir)/ruby/internal/core/rclass.h
-bigdecimal.o: $(hdrdir)/ruby/internal/core/rdata.h
-bigdecimal.o: $(hdrdir)/ruby/internal/core/rfile.h
-bigdecimal.o: $(hdrdir)/ruby/internal/core/rhash.h
-bigdecimal.o: $(hdrdir)/ruby/internal/core/robject.h
-bigdecimal.o: $(hdrdir)/ruby/internal/core/rregexp.h
-bigdecimal.o: $(hdrdir)/ruby/internal/core/rstring.h
-bigdecimal.o: $(hdrdir)/ruby/internal/core/rstruct.h
-bigdecimal.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
-bigdecimal.o: $(hdrdir)/ruby/internal/ctype.h
-bigdecimal.o: $(hdrdir)/ruby/internal/dllexport.h
-bigdecimal.o: $(hdrdir)/ruby/internal/dosish.h
-bigdecimal.o: $(hdrdir)/ruby/internal/error.h
-bigdecimal.o: $(hdrdir)/ruby/internal/eval.h
-bigdecimal.o: $(hdrdir)/ruby/internal/event.h
-bigdecimal.o: $(hdrdir)/ruby/internal/fl_type.h
-bigdecimal.o: $(hdrdir)/ruby/internal/gc.h
-bigdecimal.o: $(hdrdir)/ruby/internal/glob.h
-bigdecimal.o: $(hdrdir)/ruby/internal/globals.h
-bigdecimal.o: $(hdrdir)/ruby/internal/has/attribute.h
-bigdecimal.o: $(hdrdir)/ruby/internal/has/builtin.h
-bigdecimal.o: $(hdrdir)/ruby/internal/has/c_attribute.h
-bigdecimal.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
-bigdecimal.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
-bigdecimal.o: $(hdrdir)/ruby/internal/has/extension.h
-bigdecimal.o: $(hdrdir)/ruby/internal/has/feature.h
-bigdecimal.o: $(hdrdir)/ruby/internal/has/warning.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/array.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/bignum.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/class.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/compar.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/complex.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/cont.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/dir.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/enum.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/enumerator.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/error.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/eval.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/file.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/hash.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/io.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/load.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/marshal.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/numeric.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/object.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/parse.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/proc.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/process.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/random.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/range.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/rational.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/re.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/ruby.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/select.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/signal.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/sprintf.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/string.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/struct.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/thread.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/time.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/variable.h
-bigdecimal.o: $(hdrdir)/ruby/internal/intern/vm.h
-bigdecimal.o: $(hdrdir)/ruby/internal/interpreter.h
-bigdecimal.o: $(hdrdir)/ruby/internal/iterator.h
-bigdecimal.o: $(hdrdir)/ruby/internal/memory.h
-bigdecimal.o: $(hdrdir)/ruby/internal/method.h
-bigdecimal.o: $(hdrdir)/ruby/internal/module.h
-bigdecimal.o: $(hdrdir)/ruby/internal/newobj.h
-bigdecimal.o: $(hdrdir)/ruby/internal/scan_args.h
-bigdecimal.o: $(hdrdir)/ruby/internal/special_consts.h
-bigdecimal.o: $(hdrdir)/ruby/internal/static_assert.h
-bigdecimal.o: $(hdrdir)/ruby/internal/stdalign.h
-bigdecimal.o: $(hdrdir)/ruby/internal/stdbool.h
-bigdecimal.o: $(hdrdir)/ruby/internal/symbol.h
-bigdecimal.o: $(hdrdir)/ruby/internal/value.h
-bigdecimal.o: $(hdrdir)/ruby/internal/value_type.h
-bigdecimal.o: $(hdrdir)/ruby/internal/variable.h
-bigdecimal.o: $(hdrdir)/ruby/internal/warning_push.h
-bigdecimal.o: $(hdrdir)/ruby/internal/xmalloc.h
-bigdecimal.o: $(hdrdir)/ruby/missing.h
-bigdecimal.o: $(hdrdir)/ruby/ruby.h
-bigdecimal.o: $(hdrdir)/ruby/st.h
-bigdecimal.o: $(hdrdir)/ruby/subst.h
-bigdecimal.o: $(hdrdir)/ruby/util.h
-bigdecimal.o: bigdecimal.c
-bigdecimal.o: bigdecimal.h
-bigdecimal.o: bits.h
-bigdecimal.o: feature.h
-bigdecimal.o: missing.h
-bigdecimal.o: static_assert.h
-missing.o: $(RUBY_EXTCONF_H)
-missing.o: $(arch_hdrdir)/ruby/config.h
-missing.o: $(hdrdir)/ruby/assert.h
-missing.o: $(hdrdir)/ruby/atomic.h
-missing.o: $(hdrdir)/ruby/backward.h
-missing.o: $(hdrdir)/ruby/backward/2/assume.h
-missing.o: $(hdrdir)/ruby/backward/2/attributes.h
-missing.o: $(hdrdir)/ruby/backward/2/bool.h
-missing.o: $(hdrdir)/ruby/backward/2/inttypes.h
-missing.o: $(hdrdir)/ruby/backward/2/limits.h
-missing.o: $(hdrdir)/ruby/backward/2/long_long.h
-missing.o: $(hdrdir)/ruby/backward/2/stdalign.h
-missing.o: $(hdrdir)/ruby/backward/2/stdarg.h
-missing.o: $(hdrdir)/ruby/defines.h
-missing.o: $(hdrdir)/ruby/intern.h
-missing.o: $(hdrdir)/ruby/internal/abi.h
-missing.o: $(hdrdir)/ruby/internal/anyargs.h
-missing.o: $(hdrdir)/ruby/internal/arithmetic.h
-missing.o: $(hdrdir)/ruby/internal/arithmetic/char.h
-missing.o: $(hdrdir)/ruby/internal/arithmetic/double.h
-missing.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
-missing.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
-missing.o: $(hdrdir)/ruby/internal/arithmetic/int.h
-missing.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
-missing.o: $(hdrdir)/ruby/internal/arithmetic/long.h
-missing.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
-missing.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
-missing.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
-missing.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
-missing.o: $(hdrdir)/ruby/internal/arithmetic/short.h
-missing.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
-missing.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
-missing.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
-missing.o: $(hdrdir)/ruby/internal/assume.h
-missing.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
-missing.o: $(hdrdir)/ruby/internal/attr/artificial.h
-missing.o: $(hdrdir)/ruby/internal/attr/cold.h
-missing.o: $(hdrdir)/ruby/internal/attr/const.h
-missing.o: $(hdrdir)/ruby/internal/attr/constexpr.h
-missing.o: $(hdrdir)/ruby/internal/attr/deprecated.h
-missing.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
-missing.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
-missing.o: $(hdrdir)/ruby/internal/attr/error.h
-missing.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
-missing.o: $(hdrdir)/ruby/internal/attr/forceinline.h
-missing.o: $(hdrdir)/ruby/internal/attr/format.h
-missing.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
-missing.o: $(hdrdir)/ruby/internal/attr/noalias.h
-missing.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
-missing.o: $(hdrdir)/ruby/internal/attr/noexcept.h
-missing.o: $(hdrdir)/ruby/internal/attr/noinline.h
-missing.o: $(hdrdir)/ruby/internal/attr/nonnull.h
-missing.o: $(hdrdir)/ruby/internal/attr/noreturn.h
-missing.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
-missing.o: $(hdrdir)/ruby/internal/attr/pure.h
-missing.o: $(hdrdir)/ruby/internal/attr/restrict.h
-missing.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
-missing.o: $(hdrdir)/ruby/internal/attr/warning.h
-missing.o: $(hdrdir)/ruby/internal/attr/weakref.h
-missing.o: $(hdrdir)/ruby/internal/cast.h
-missing.o: $(hdrdir)/ruby/internal/compiler_is.h
-missing.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
-missing.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
-missing.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
-missing.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
-missing.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
-missing.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
-missing.o: $(hdrdir)/ruby/internal/compiler_since.h
-missing.o: $(hdrdir)/ruby/internal/config.h
-missing.o: $(hdrdir)/ruby/internal/constant_p.h
-missing.o: $(hdrdir)/ruby/internal/core.h
-missing.o: $(hdrdir)/ruby/internal/core/rarray.h
-missing.o: $(hdrdir)/ruby/internal/core/rbasic.h
-missing.o: $(hdrdir)/ruby/internal/core/rbignum.h
-missing.o: $(hdrdir)/ruby/internal/core/rclass.h
-missing.o: $(hdrdir)/ruby/internal/core/rdata.h
-missing.o: $(hdrdir)/ruby/internal/core/rfile.h
-missing.o: $(hdrdir)/ruby/internal/core/rhash.h
-missing.o: $(hdrdir)/ruby/internal/core/robject.h
-missing.o: $(hdrdir)/ruby/internal/core/rregexp.h
-missing.o: $(hdrdir)/ruby/internal/core/rstring.h
-missing.o: $(hdrdir)/ruby/internal/core/rstruct.h
-missing.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
-missing.o: $(hdrdir)/ruby/internal/ctype.h
-missing.o: $(hdrdir)/ruby/internal/dllexport.h
-missing.o: $(hdrdir)/ruby/internal/dosish.h
-missing.o: $(hdrdir)/ruby/internal/error.h
-missing.o: $(hdrdir)/ruby/internal/eval.h
-missing.o: $(hdrdir)/ruby/internal/event.h
-missing.o: $(hdrdir)/ruby/internal/fl_type.h
-missing.o: $(hdrdir)/ruby/internal/gc.h
-missing.o: $(hdrdir)/ruby/internal/glob.h
-missing.o: $(hdrdir)/ruby/internal/globals.h
-missing.o: $(hdrdir)/ruby/internal/has/attribute.h
-missing.o: $(hdrdir)/ruby/internal/has/builtin.h
-missing.o: $(hdrdir)/ruby/internal/has/c_attribute.h
-missing.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
-missing.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
-missing.o: $(hdrdir)/ruby/internal/has/extension.h
-missing.o: $(hdrdir)/ruby/internal/has/feature.h
-missing.o: $(hdrdir)/ruby/internal/has/warning.h
-missing.o: $(hdrdir)/ruby/internal/intern/array.h
-missing.o: $(hdrdir)/ruby/internal/intern/bignum.h
-missing.o: $(hdrdir)/ruby/internal/intern/class.h
-missing.o: $(hdrdir)/ruby/internal/intern/compar.h
-missing.o: $(hdrdir)/ruby/internal/intern/complex.h
-missing.o: $(hdrdir)/ruby/internal/intern/cont.h
-missing.o: $(hdrdir)/ruby/internal/intern/dir.h
-missing.o: $(hdrdir)/ruby/internal/intern/enum.h
-missing.o: $(hdrdir)/ruby/internal/intern/enumerator.h
-missing.o: $(hdrdir)/ruby/internal/intern/error.h
-missing.o: $(hdrdir)/ruby/internal/intern/eval.h
-missing.o: $(hdrdir)/ruby/internal/intern/file.h
-missing.o: $(hdrdir)/ruby/internal/intern/hash.h
-missing.o: $(hdrdir)/ruby/internal/intern/io.h
-missing.o: $(hdrdir)/ruby/internal/intern/load.h
-missing.o: $(hdrdir)/ruby/internal/intern/marshal.h
-missing.o: $(hdrdir)/ruby/internal/intern/numeric.h
-missing.o: $(hdrdir)/ruby/internal/intern/object.h
-missing.o: $(hdrdir)/ruby/internal/intern/parse.h
-missing.o: $(hdrdir)/ruby/internal/intern/proc.h
-missing.o: $(hdrdir)/ruby/internal/intern/process.h
-missing.o: $(hdrdir)/ruby/internal/intern/random.h
-missing.o: $(hdrdir)/ruby/internal/intern/range.h
-missing.o: $(hdrdir)/ruby/internal/intern/rational.h
-missing.o: $(hdrdir)/ruby/internal/intern/re.h
-missing.o: $(hdrdir)/ruby/internal/intern/ruby.h
-missing.o: $(hdrdir)/ruby/internal/intern/select.h
-missing.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
-missing.o: $(hdrdir)/ruby/internal/intern/signal.h
-missing.o: $(hdrdir)/ruby/internal/intern/sprintf.h
-missing.o: $(hdrdir)/ruby/internal/intern/string.h
-missing.o: $(hdrdir)/ruby/internal/intern/struct.h
-missing.o: $(hdrdir)/ruby/internal/intern/thread.h
-missing.o: $(hdrdir)/ruby/internal/intern/time.h
-missing.o: $(hdrdir)/ruby/internal/intern/variable.h
-missing.o: $(hdrdir)/ruby/internal/intern/vm.h
-missing.o: $(hdrdir)/ruby/internal/interpreter.h
-missing.o: $(hdrdir)/ruby/internal/iterator.h
-missing.o: $(hdrdir)/ruby/internal/memory.h
-missing.o: $(hdrdir)/ruby/internal/method.h
-missing.o: $(hdrdir)/ruby/internal/module.h
-missing.o: $(hdrdir)/ruby/internal/newobj.h
-missing.o: $(hdrdir)/ruby/internal/scan_args.h
-missing.o: $(hdrdir)/ruby/internal/special_consts.h
-missing.o: $(hdrdir)/ruby/internal/static_assert.h
-missing.o: $(hdrdir)/ruby/internal/stdalign.h
-missing.o: $(hdrdir)/ruby/internal/stdbool.h
-missing.o: $(hdrdir)/ruby/internal/symbol.h
-missing.o: $(hdrdir)/ruby/internal/value.h
-missing.o: $(hdrdir)/ruby/internal/value_type.h
-missing.o: $(hdrdir)/ruby/internal/variable.h
-missing.o: $(hdrdir)/ruby/internal/warning_push.h
-missing.o: $(hdrdir)/ruby/internal/xmalloc.h
-missing.o: $(hdrdir)/ruby/missing.h
-missing.o: $(hdrdir)/ruby/ruby.h
-missing.o: $(hdrdir)/ruby/st.h
-missing.o: $(hdrdir)/ruby/subst.h
-missing.o: missing.c
-missing.o: missing/dtoa.c
-# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/bigdecimal/extconf.rb b/ext/bigdecimal/extconf.rb
deleted file mode 100644
index 23904ed60e..0000000000
--- a/ext/bigdecimal/extconf.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-# frozen_string_literal: false
-require 'mkmf'
-
-def have_builtin_func(name, check_expr, opt = "", &b)
- checking_for checking_message(name.funcall_style, nil, opt) do
- if try_compile(<<SRC, opt, &b)
-int foo;
-int main() { #{check_expr}; return 0; }
-SRC
- $defs.push(format("-DHAVE_BUILTIN_%s", name.tr_cpp))
- true
- else
- false
- end
- end
-end
-
-have_builtin_func("__builtin_clz", "__builtin_clz(0)")
-have_builtin_func("__builtin_clzl", "__builtin_clzl(0)")
-have_builtin_func("__builtin_clzll", "__builtin_clzll(0)")
-
-have_header("float.h")
-have_header("math.h")
-have_header("stdbool.h")
-have_header("stdlib.h")
-
-have_header("x86intrin.h")
-have_func("_lzcnt_u32", "x86intrin.h")
-have_func("_lzcnt_u64", "x86intrin.h")
-
-have_header("intrin.h")
-have_func("__lzcnt", "intrin.h")
-have_func("__lzcnt64", "intrin.h")
-have_func("_BitScanReverse", "intrin.h")
-have_func("_BitScanReverse64", "intrin.h")
-
-have_func("labs", "stdlib.h")
-have_func("llabs", "stdlib.h")
-have_func("finite", "math.h")
-have_func("isfinite", "math.h")
-
-have_header("ruby/atomic.h")
-have_header("ruby/internal/has/builtin.h")
-have_header("ruby/internal/static_assert.h")
-
-have_func("rb_rational_num", "ruby.h")
-have_func("rb_rational_den", "ruby.h")
-have_func("rb_complex_real", "ruby.h")
-have_func("rb_complex_imag", "ruby.h")
-have_func("rb_opts_exception_p", "ruby.h")
-have_func("rb_category_warn", "ruby.h")
-have_const("RB_WARN_CATEGORY_DEPRECATED", "ruby.h")
-
-if File.file?(File.expand_path('../lib/bigdecimal.rb', __FILE__))
- bigdecimal_rb = "$(srcdir)/lib/bigdecimal.rb"
-else
- bigdecimal_rb = "$(srcdir)/../../lib/bigdecimal.rb"
-end
-
-create_makefile('bigdecimal') {|mf|
- mf << "BIGDECIMAL_RB = #{bigdecimal_rb}\n"
-}
diff --git a/ext/bigdecimal/feature.h b/ext/bigdecimal/feature.h
deleted file mode 100644
index f628514500..0000000000
--- a/ext/bigdecimal/feature.h
+++ /dev/null
@@ -1,68 +0,0 @@
-#ifndef BIGDECIMAL_HAS_FEATURE_H
-#define BIGDECIMAL_HAS_FEATURE_H
-
-/* ======== __has_feature ======== */
-
-#ifndef __has_feature
-# define __has_feature(_) 0
-#endif
-
-/* ======== __has_extension ======== */
-
-#ifndef __has_extension
-# define __has_extension __has_feature
-#endif
-
-/* ======== __has_builtin ======== */
-
-#ifdef HAVE_RUBY_INTERNAL_HAS_BUILTIN_H
-# include <ruby/internal/has/builtin.h>
-#endif
-
-#ifdef RBIMPL_HAS_BUILTIN
-# define BIGDECIMAL_HAS_BUILTIN(...) RBIMPL_HAS_BUILTIN(__VA_ARGS__)
-
-#else
-# /* The following section is copied from CRuby's builtin.h */
-#
-# ifdef __has_builtin
-# if defined(__INTEL_COMPILER)
-# /* :TODO: Intel C Compiler has __has_builtin (since 19.1 maybe?), and is
-# * reportedly broken. We have to skip them. However the situation can
-# * change. They might improve someday. We need to revisit here later. */
-# elif defined(__GNUC__) && ! __has_builtin(__builtin_alloca)
-# /* FreeBSD's <sys/cdefs.h> defines its own *broken* version of
-# * __has_builtin. Cygwin copied that content to be a victim of the
-# * broken-ness. We don't take them into account. */
-# else
-# define HAVE___HAS_BUILTIN 1
-# endif
-# endif
-#
-# if defined(HAVE___HAS_BUILTIN)
-# define BIGDECIMAL_HAS_BUILTIN(_) __has_builtin(_)
-#
-# elif defined(__GNUC__)
-# define BIGDECIMAL_HAS_BUILTIN(_) BIGDECIMAL_HAS_BUILTIN_ ## _
-# if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 6))
-# define BIGDECIMAL_HAS_BUILTIN___builtin_clz 1
-# define BIGDECIMAL_HAS_BUILTIN___builtin_clzl 1
-# else
-# define BIGDECIMAL_HAS_BUILTIN___builtin_clz 0
-# define BIGDECIMAL_HAS_BUILTIN___builtin_clzl 0
-# endif
-# elif defined(_MSC_VER)
-# define BIGDECIMAL_HAS_BUILTIN(_) 0
-#
-# else
-# define BIGDECIMAL_HAS_BUILTIN(_) BIGDECIMAL_HAS_BUILTIN_ ## _
-# define BIGDECIMAL_HAS_BUILTIN___builtin_clz HAVE_BUILTIN___BUILTIN_CLZ
-# define BIGDECIMAL_HAS_BUILTIN___builtin_clzl HAVE_BUILTIN___BUILTIN_CLZL
-# endif
-#endif /* RBIMPL_HAS_BUILTIN */
-
-#ifndef __has_builtin
-# define __has_builtin(...) BIGDECIMAL_HAS_BUILTIN(__VA_ARGS__)
-#endif
-
-#endif /* BIGDECIMAL_HAS_FEATURE_H */
diff --git a/ext/bigdecimal/lib/bigdecimal.rb b/ext/bigdecimal/lib/bigdecimal.rb
deleted file mode 100644
index 82b3e1b7b9..0000000000
--- a/ext/bigdecimal/lib/bigdecimal.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-if RUBY_ENGINE == 'jruby'
- JRuby::Util.load_ext("org.jruby.ext.bigdecimal.BigDecimalLibrary")
-else
- require 'bigdecimal.so'
-end
diff --git a/ext/bigdecimal/lib/bigdecimal/jacobian.rb b/ext/bigdecimal/lib/bigdecimal/jacobian.rb
deleted file mode 100644
index 4448024c74..0000000000
--- a/ext/bigdecimal/lib/bigdecimal/jacobian.rb
+++ /dev/null
@@ -1,90 +0,0 @@
-# frozen_string_literal: false
-
-require 'bigdecimal'
-
-# require 'bigdecimal/jacobian'
-#
-# Provides methods to compute the Jacobian matrix of a set of equations at a
-# point x. In the methods below:
-#
-# f is an Object which is used to compute the Jacobian matrix of the equations.
-# It must provide the following methods:
-#
-# f.values(x):: returns the values of all functions at x
-#
-# f.zero:: returns 0.0
-# f.one:: returns 1.0
-# f.two:: returns 2.0
-# f.ten:: returns 10.0
-#
-# f.eps:: returns the convergence criterion (epsilon value) used to determine whether two values are considered equal. If |a-b| < epsilon, the two values are considered equal.
-#
-# x is the point at which to compute the Jacobian.
-#
-# fx is f.values(x).
-#
-module Jacobian
- module_function
-
- # Determines the equality of two numbers by comparing to zero, or using the epsilon value
- def isEqual(a,b,zero=0.0,e=1.0e-8)
- aa = a.abs
- bb = b.abs
- if aa == zero && bb == zero then
- true
- else
- if ((a-b)/(aa+bb)).abs < e then
- true
- else
- false
- end
- end
- end
-
-
- # Computes the derivative of +f[i]+ at +x[i]+.
- # +fx+ is the value of +f+ at +x+.
- def dfdxi(f,fx,x,i)
- nRetry = 0
- n = x.size
- xSave = x[i]
- ok = 0
- ratio = f.ten*f.ten*f.ten
- dx = x[i].abs/ratio
- dx = fx[i].abs/ratio if isEqual(dx,f.zero,f.zero,f.eps)
- dx = f.one/f.ten if isEqual(dx,f.zero,f.zero,f.eps)
- until ok>0 do
- deriv = []
- nRetry += 1
- if nRetry > 100
- raise "Singular Jacobian matrix. No change at x[" + i.to_s + "]"
- end
- dx = dx*f.two
- x[i] += dx
- fxNew = f.values(x)
- for j in 0...n do
- if !isEqual(fxNew[j],fx[j],f.zero,f.eps) then
- ok += 1
- deriv <<= (fxNew[j]-fx[j])/dx
- else
- deriv <<= f.zero
- end
- end
- x[i] = xSave
- end
- deriv
- end
-
- # Computes the Jacobian of +f+ at +x+. +fx+ is the value of +f+ at +x+.
- def jacobian(f,fx,x)
- n = x.size
- dfdx = Array.new(n*n)
- for i in 0...n do
- df = dfdxi(f,fx,x,i)
- for j in 0...n do
- dfdx[j*n+i] = df[j]
- end
- end
- dfdx
- end
-end
diff --git a/ext/bigdecimal/lib/bigdecimal/ludcmp.rb b/ext/bigdecimal/lib/bigdecimal/ludcmp.rb
deleted file mode 100644
index dd265e482a..0000000000
--- a/ext/bigdecimal/lib/bigdecimal/ludcmp.rb
+++ /dev/null
@@ -1,89 +0,0 @@
-# frozen_string_literal: false
-require 'bigdecimal'
-
-#
-# Solves a*x = b for x, using LU decomposition.
-#
-module LUSolve
- module_function
-
- # Performs LU decomposition of the n by n matrix a.
- def ludecomp(a,n,zero=0,one=1)
- prec = BigDecimal.limit(nil)
- ps = []
- scales = []
- for i in 0...n do # pick up largest(abs. val.) element in each row.
- ps <<= i
- nrmrow = zero
- ixn = i*n
- for j in 0...n do
- biggst = a[ixn+j].abs
- nrmrow = biggst if biggst>nrmrow
- end
- if nrmrow>zero then
- scales <<= one.div(nrmrow,prec)
- else
- raise "Singular matrix"
- end
- end
- n1 = n - 1
- for k in 0...n1 do # Gaussian elimination with partial pivoting.
- biggst = zero;
- for i in k...n do
- size = a[ps[i]*n+k].abs*scales[ps[i]]
- if size>biggst then
- biggst = size
- pividx = i
- end
- end
- raise "Singular matrix" if biggst<=zero
- if pividx!=k then
- j = ps[k]
- ps[k] = ps[pividx]
- ps[pividx] = j
- end
- pivot = a[ps[k]*n+k]
- for i in (k+1)...n do
- psin = ps[i]*n
- a[psin+k] = mult = a[psin+k].div(pivot,prec)
- if mult!=zero then
- pskn = ps[k]*n
- for j in (k+1)...n do
- a[psin+j] -= mult.mult(a[pskn+j],prec)
- end
- end
- end
- end
- raise "Singular matrix" if a[ps[n1]*n+n1] == zero
- ps
- end
-
- # Solves a*x = b for x, using LU decomposition.
- #
- # a is a matrix, b is a constant vector, x is the solution vector.
- #
- # ps is the pivot, a vector which indicates the permutation of rows performed
- # during LU decomposition.
- def lusolve(a,b,ps,zero=0.0)
- prec = BigDecimal.limit(nil)
- n = ps.size
- x = []
- for i in 0...n do
- dot = zero
- psin = ps[i]*n
- for j in 0...i do
- dot = a[psin+j].mult(x[j],prec) + dot
- end
- x <<= b[ps[i]] - dot
- end
- (n-1).downto(0) do |i|
- dot = zero
- psin = ps[i]*n
- for j in (i+1)...n do
- dot = a[psin+j].mult(x[j],prec) + dot
- end
- x[i] = (x[i]-dot).div(a[psin+i],prec)
- end
- x
- end
-end
diff --git a/ext/bigdecimal/lib/bigdecimal/math.rb b/ext/bigdecimal/lib/bigdecimal/math.rb
deleted file mode 100644
index 0b9d0648bb..0000000000
--- a/ext/bigdecimal/lib/bigdecimal/math.rb
+++ /dev/null
@@ -1,232 +0,0 @@
-# frozen_string_literal: false
-require 'bigdecimal'
-
-#
-#--
-# Contents:
-# sqrt(x, prec)
-# sin (x, prec)
-# cos (x, prec)
-# atan(x, prec) Note: |x|<1, x=0.9999 may not converge.
-# PI (prec)
-# E (prec) == exp(1.0,prec)
-#
-# where:
-# x ... BigDecimal number to be computed.
-# |x| must be small enough to get convergence.
-# prec ... Number of digits to be obtained.
-#++
-#
-# Provides mathematical functions.
-#
-# Example:
-#
-# require "bigdecimal/math"
-#
-# include BigMath
-#
-# a = BigDecimal((PI(100)/2).to_s)
-# puts sin(a,100) # => 0.99999999999999999999......e0
-#
-module BigMath
- module_function
-
- # call-seq:
- # sqrt(decimal, numeric) -> BigDecimal
- #
- # Computes the square root of +decimal+ to the specified number of digits of
- # precision, +numeric+.
- #
- # BigMath.sqrt(BigDecimal('2'), 16).to_s
- # #=> "0.1414213562373095048801688724e1"
- #
- def sqrt(x, prec)
- x.sqrt(prec)
- end
-
- # call-seq:
- # sin(decimal, numeric) -> BigDecimal
- #
- # Computes the sine of +decimal+ to the specified number of digits of
- # precision, +numeric+.
- #
- # If +decimal+ is Infinity or NaN, returns NaN.
- #
- # BigMath.sin(BigMath.PI(5)/4, 5).to_s
- # #=> "0.70710678118654752440082036563292800375e0"
- #
- def sin(x, prec)
- raise ArgumentError, "Zero or negative precision for sin" if prec <= 0
- return BigDecimal("NaN") if x.infinite? || x.nan?
- n = prec + BigDecimal.double_fig
- one = BigDecimal("1")
- two = BigDecimal("2")
- x = -x if neg = x < 0
- if x > (twopi = two * BigMath.PI(prec))
- if x > 30
- x %= twopi
- else
- x -= twopi while x > twopi
- end
- end
- x1 = x
- x2 = x.mult(x,n)
- sign = 1
- y = x
- d = y
- i = one
- z = one
- while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
- m = BigDecimal.double_fig if m < BigDecimal.double_fig
- sign = -sign
- x1 = x2.mult(x1,n)
- i += two
- z *= (i-one) * i
- d = sign * x1.div(z,m)
- y += d
- end
- neg ? -y : y
- end
-
- # call-seq:
- # cos(decimal, numeric) -> BigDecimal
- #
- # Computes the cosine of +decimal+ to the specified number of digits of
- # precision, +numeric+.
- #
- # If +decimal+ is Infinity or NaN, returns NaN.
- #
- # BigMath.cos(BigMath.PI(4), 16).to_s
- # #=> "-0.999999999999999999999999999999856613163740061349e0"
- #
- def cos(x, prec)
- raise ArgumentError, "Zero or negative precision for cos" if prec <= 0
- return BigDecimal("NaN") if x.infinite? || x.nan?
- n = prec + BigDecimal.double_fig
- one = BigDecimal("1")
- two = BigDecimal("2")
- x = -x if x < 0
- if x > (twopi = two * BigMath.PI(prec))
- if x > 30
- x %= twopi
- else
- x -= twopi while x > twopi
- end
- end
- x1 = one
- x2 = x.mult(x,n)
- sign = 1
- y = one
- d = y
- i = BigDecimal("0")
- z = one
- while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
- m = BigDecimal.double_fig if m < BigDecimal.double_fig
- sign = -sign
- x1 = x2.mult(x1,n)
- i += two
- z *= (i-one) * i
- d = sign * x1.div(z,m)
- y += d
- end
- y
- end
-
- # call-seq:
- # atan(decimal, numeric) -> BigDecimal
- #
- # Computes the arctangent of +decimal+ to the specified number of digits of
- # precision, +numeric+.
- #
- # If +decimal+ is NaN, returns NaN.
- #
- # BigMath.atan(BigDecimal('-1'), 16).to_s
- # #=> "-0.785398163397448309615660845819878471907514682065e0"
- #
- def atan(x, prec)
- raise ArgumentError, "Zero or negative precision for atan" if prec <= 0
- return BigDecimal("NaN") if x.nan?
- pi = PI(prec)
- x = -x if neg = x < 0
- return pi.div(neg ? -2 : 2, prec) if x.infinite?
- return pi / (neg ? -4 : 4) if x.round(prec) == 1
- x = BigDecimal("1").div(x, prec) if inv = x > 1
- x = (-1 + sqrt(1 + x**2, prec))/x if dbl = x > 0.5
- n = prec + BigDecimal.double_fig
- y = x
- d = y
- t = x
- r = BigDecimal("3")
- x2 = x.mult(x,n)
- while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
- m = BigDecimal.double_fig if m < BigDecimal.double_fig
- t = -t.mult(x2,n)
- d = t.div(r,m)
- y += d
- r += 2
- end
- y *= 2 if dbl
- y = pi / 2 - y if inv
- y = -y if neg
- y
- end
-
- # call-seq:
- # PI(numeric) -> BigDecimal
- #
- # Computes the value of pi to the specified number of digits of precision,
- # +numeric+.
- #
- # BigMath.PI(10).to_s
- # #=> "0.3141592653589793238462643388813853786957412e1"
- #
- def PI(prec)
- raise ArgumentError, "Zero or negative precision for PI" if prec <= 0
- n = prec + BigDecimal.double_fig
- zero = BigDecimal("0")
- one = BigDecimal("1")
- two = BigDecimal("2")
-
- m25 = BigDecimal("-0.04")
- m57121 = BigDecimal("-57121")
-
- pi = zero
-
- d = one
- k = one
- t = BigDecimal("-80")
- while d.nonzero? && ((m = n - (pi.exponent - d.exponent).abs) > 0)
- m = BigDecimal.double_fig if m < BigDecimal.double_fig
- t = t*m25
- d = t.div(k,m)
- k = k+two
- pi = pi + d
- end
-
- d = one
- k = one
- t = BigDecimal("956")
- while d.nonzero? && ((m = n - (pi.exponent - d.exponent).abs) > 0)
- m = BigDecimal.double_fig if m < BigDecimal.double_fig
- t = t.div(m57121,n)
- d = t.div(k,m)
- pi = pi + d
- k = k+two
- end
- pi
- end
-
- # call-seq:
- # E(numeric) -> BigDecimal
- #
- # Computes e (the base of natural logarithms) to the specified number of
- # digits of precision, +numeric+.
- #
- # BigMath.E(10).to_s
- # #=> "0.271828182845904523536028752390026306410273e1"
- #
- def E(prec)
- raise ArgumentError, "Zero or negative precision for E" if prec <= 0
- BigMath.exp(1, prec)
- end
-end
diff --git a/ext/bigdecimal/lib/bigdecimal/newton.rb b/ext/bigdecimal/lib/bigdecimal/newton.rb
deleted file mode 100644
index 85bacb7f2e..0000000000
--- a/ext/bigdecimal/lib/bigdecimal/newton.rb
+++ /dev/null
@@ -1,80 +0,0 @@
-# frozen_string_literal: false
-require "bigdecimal/ludcmp"
-require "bigdecimal/jacobian"
-
-#
-# newton.rb
-#
-# Solves the nonlinear algebraic equation system f = 0 by Newton's method.
-# This program is not dependent on BigDecimal.
-#
-# To call:
-# n = nlsolve(f,x)
-# where n is the number of iterations required,
-# x is the initial value vector
-# f is an Object which is used to compute the values of the equations to be solved.
-# It must provide the following methods:
-#
-# f.values(x):: returns the values of all functions at x
-#
-# f.zero:: returns 0.0
-# f.one:: returns 1.0
-# f.two:: returns 2.0
-# f.ten:: returns 10.0
-#
-# f.eps:: returns the convergence criterion (epsilon value) used to determine whether two values are considered equal. If |a-b| < epsilon, the two values are considered equal.
-#
-# On exit, x is the solution vector.
-#
-module Newton
- include LUSolve
- include Jacobian
- module_function
-
- def norm(fv,zero=0.0) # :nodoc:
- s = zero
- n = fv.size
- for i in 0...n do
- s += fv[i]*fv[i]
- end
- s
- end
-
- # See also Newton
- def nlsolve(f,x)
- nRetry = 0
- n = x.size
-
- f0 = f.values(x)
- zero = f.zero
- one = f.one
- two = f.two
- p5 = one/two
- d = norm(f0,zero)
- minfact = f.ten*f.ten*f.ten
- minfact = one/minfact
- e = f.eps
- while d >= e do
- nRetry += 1
- # Not yet converged. => Compute Jacobian matrix
- dfdx = jacobian(f,f0,x)
- # Solve dfdx*dx = -f0 to estimate dx
- dx = lusolve(dfdx,f0,ludecomp(dfdx,n,zero,one),zero)
- fact = two
- xs = x.dup
- begin
- fact *= p5
- if fact < minfact then
- raise "Failed to reduce function values."
- end
- for i in 0...n do
- x[i] = xs[i] - dx[i]*fact
- end
- f0 = f.values(x)
- dn = norm(f0,zero)
- end while(dn>=d)
- d = dn
- end
- nRetry
- end
-end
diff --git a/ext/bigdecimal/lib/bigdecimal/util.rb b/ext/bigdecimal/lib/bigdecimal/util.rb
deleted file mode 100644
index 8bfc0ed8ed..0000000000
--- a/ext/bigdecimal/lib/bigdecimal/util.rb
+++ /dev/null
@@ -1,185 +0,0 @@
-# frozen_string_literal: false
-#
-#--
-# bigdecimal/util extends various native classes to provide the #to_d method,
-# and provides BigDecimal#to_d and BigDecimal#to_digits.
-#++
-
-require 'bigdecimal'
-
-class Integer < Numeric
- # call-seq:
- # int.to_d -> bigdecimal
- #
- # Returns the value of +int+ as a BigDecimal.
- #
- # require 'bigdecimal'
- # require 'bigdecimal/util'
- #
- # 42.to_d # => 0.42e2
- #
- # See also Kernel.BigDecimal.
- #
- def to_d
- BigDecimal(self)
- end
-end
-
-
-class Float < Numeric
- # call-seq:
- # float.to_d -> bigdecimal
- # float.to_d(precision) -> bigdecimal
- #
- # Returns the value of +float+ as a BigDecimal.
- # The +precision+ parameter is used to determine the number of
- # significant digits for the result. When +precision+ is set to +0+,
- # the number of digits to represent the float being converted is determined
- # automatically.
- # The default +precision+ is +0+.
- #
- # require 'bigdecimal'
- # require 'bigdecimal/util'
- #
- # 0.5.to_d # => 0.5e0
- # 1.234.to_d # => 0.1234e1
- # 1.234.to_d(2) # => 0.12e1
- #
- # See also Kernel.BigDecimal.
- #
- def to_d(precision=0)
- BigDecimal(self, precision)
- end
-end
-
-
-class String
- # call-seq:
- # str.to_d -> bigdecimal
- #
- # Returns the result of interpreting leading characters in +str+
- # as a BigDecimal.
- #
- # require 'bigdecimal'
- # require 'bigdecimal/util'
- #
- # "0.5".to_d # => 0.5e0
- # "123.45e1".to_d # => 0.12345e4
- # "45.67 degrees".to_d # => 0.4567e2
- #
- # See also Kernel.BigDecimal.
- #
- def to_d
- BigDecimal.interpret_loosely(self)
- end
-end
-
-
-class BigDecimal < Numeric
- # call-seq:
- # a.to_digits -> string
- #
- # Converts a BigDecimal to a String of the form "nnnnnn.mmm".
- # This method is deprecated; use BigDecimal#to_s("F") instead.
- #
- # require 'bigdecimal/util'
- #
- # d = BigDecimal("3.14")
- # d.to_digits # => "3.14"
- #
- def to_digits
- if self.nan? || self.infinite? || self.zero?
- self.to_s
- else
- i = self.to_i.to_s
- _,f,_,z = self.frac.split
- i + "." + ("0"*(-z)) + f
- end
- end
-
- # call-seq:
- # a.to_d -> bigdecimal
- #
- # Returns self.
- #
- # require 'bigdecimal/util'
- #
- # d = BigDecimal("3.14")
- # d.to_d # => 0.314e1
- #
- def to_d
- self
- end
-end
-
-
-class Rational < Numeric
- # call-seq:
- # rat.to_d(precision) -> bigdecimal
- #
- # Returns the value as a BigDecimal.
- #
- # The required +precision+ parameter is used to determine the number of
- # significant digits for the result.
- #
- # require 'bigdecimal'
- # require 'bigdecimal/util'
- #
- # Rational(22, 7).to_d(3) # => 0.314e1
- #
- # See also Kernel.BigDecimal.
- #
- def to_d(precision)
- BigDecimal(self, precision)
- end
-end
-
-
-class Complex < Numeric
- # call-seq:
- # cmp.to_d -> bigdecimal
- # cmp.to_d(precision) -> bigdecimal
- #
- # Returns the value as a BigDecimal.
- #
- # The +precision+ parameter is required for a rational complex number.
- # This parameter is used to determine the number of significant digits
- # for the result.
- #
- # require 'bigdecimal'
- # require 'bigdecimal/util'
- #
- # Complex(0.1234567, 0).to_d(4) # => 0.1235e0
- # Complex(Rational(22, 7), 0).to_d(3) # => 0.314e1
- #
- # See also Kernel.BigDecimal.
- #
- def to_d(*args)
- BigDecimal(self) unless self.imag.zero? # to raise eerror
-
- if args.length == 0
- case self.real
- when Rational
- BigDecimal(self.real) # to raise error
- end
- end
- self.real.to_d(*args)
- end
-end
-
-
-class NilClass
- # call-seq:
- # nil.to_d -> bigdecimal
- #
- # Returns nil represented as a BigDecimal.
- #
- # require 'bigdecimal'
- # require 'bigdecimal/util'
- #
- # nil.to_d # => 0.0
- #
- def to_d
- BigDecimal(0)
- end
-end
diff --git a/ext/bigdecimal/missing.c b/ext/bigdecimal/missing.c
deleted file mode 100644
index 703232d92f..0000000000
--- a/ext/bigdecimal/missing.c
+++ /dev/null
@@ -1,27 +0,0 @@
-#include <ruby/ruby.h>
-
-#ifdef HAVE_RUBY_ATOMIC_H
-# include <ruby/atomic.h>
-#endif
-
-#ifdef RUBY_ATOMIC_PTR_CAS
-# define ATOMIC_PTR_CAS(var, old, new) RUBY_ATOMIC_PTR_CAS(var, old, new)
-#endif
-
-#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
-/* GCC warns about unknown sanitizer, which is annoying. */
-# undef NO_SANITIZE
-# define NO_SANITIZE(x, y) \
- _Pragma("GCC diagnostic push") \
- _Pragma("GCC diagnostic ignored \"-Wattributes\"") \
- __attribute__((__no_sanitize__(x))) y; \
- _Pragma("GCC diagnostic pop")
-#endif
-
-#undef strtod
-#define strtod BigDecimal_strtod
-#undef dtoa
-#define dtoa BigDecimal_dtoa
-#undef hdtoa
-#define hdtoa BigDecimal_hdtoa
-#include "missing/dtoa.c"
diff --git a/ext/bigdecimal/missing.h b/ext/bigdecimal/missing.h
deleted file mode 100644
index 325554b5f5..0000000000
--- a/ext/bigdecimal/missing.h
+++ /dev/null
@@ -1,196 +0,0 @@
-#ifndef MISSING_H
-#define MISSING_H 1
-
-#if defined(__cplusplus)
-extern "C" {
-#if 0
-} /* satisfy cc-mode */
-#endif
-#endif
-
-#ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-#endif
-
-#ifdef HAVE_MATH_H
-# include <math.h>
-#endif
-
-#ifndef RB_UNUSED_VAR
-# if defined(_MSC_VER) && _MSC_VER >= 1911
-# define RB_UNUSED_VAR(x) x [[maybe_unused]]
-
-# elif defined(__has_cpp_attribute) && __has_cpp_attribute(maybe_unused)
-# define RB_UNUSED_VAR(x) x [[maybe_unused]]
-
-# elif defined(__has_c_attribute) && __has_c_attribute(maybe_unused)
-# define RB_UNUSED_VAR(x) x [[maybe_unused]]
-
-# elif defined(__GNUC__)
-# define RB_UNUSED_VAR(x) x __attribute__ ((unused))
-
-# else
-# define RB_UNUSED_VAR(x) x
-# endif
-#endif /* RB_UNUSED_VAR */
-
-#if defined(_MSC_VER) && _MSC_VER >= 1310
-# define HAVE___ASSUME 1
-
-#elif defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1300
-# define HAVE___ASSUME 1
-#endif
-
-#ifndef UNREACHABLE
-# if __has_builtin(__builtin_unreachable)
-# define UNREACHABLE __builtin_unreachable()
-
-# elif defined(HAVE___ASSUME)
-# define UNREACHABLE __assume(0)
-
-# else
-# define UNREACHABLE /* unreachable */
-# endif
-#endif /* UNREACHABLE */
-
-/* bool */
-
-#if defined(__bool_true_false_are_defined)
-# /* Take that. */
-
-#elif defined(HAVE_STDBOOL_H)
-# include <stdbool.h>
-
-#else
-typedef unsigned char _Bool;
-# define bool _Bool
-# define true ((_Bool)+1)
-# define false ((_Bool)-1)
-# define __bool_true_false_are_defined
-#endif
-
-/* abs */
-
-#ifndef HAVE_LABS
-static inline long
-labs(long const x)
-{
- if (x < 0) return -x;
- return x;
-}
-#endif
-
-#ifndef HAVE_LLABS
-static inline LONG_LONG
-llabs(LONG_LONG const x)
-{
- if (x < 0) return -x;
- return x;
-}
-#endif
-
-#ifdef vabs
-# undef vabs
-#endif
-#if SIZEOF_VALUE <= SIZEOF_INT
-# define vabs abs
-#elif SIZEOF_VALUE <= SIZEOF_LONG
-# define vabs labs
-#elif SIZEOF_VALUE <= SIZEOF_LONG_LONG
-# define vabs llabs
-#endif
-
-/* finite */
-
-#ifndef HAVE_FINITE
-static int
-finite(double)
-{
- return !isnan(n) && !isinf(n);
-}
-#endif
-
-#ifndef isfinite
-# ifndef HAVE_ISFINITE
-# define HAVE_ISFINITE 1
-# define isfinite(x) finite(x)
-# endif
-#endif
-
-/* dtoa */
-char *BigDecimal_dtoa(double d_, int mode, int ndigits, int *decpt, int *sign, char **rve);
-
-/* rational */
-
-#ifndef HAVE_RB_RATIONAL_NUM
-static inline VALUE
-rb_rational_num(VALUE rat)
-{
-#ifdef RRATIONAL
- return RRATIONAL(rat)->num;
-#else
- return rb_funcall(rat, rb_intern("numerator"), 0);
-#endif
-}
-#endif
-
-#ifndef HAVE_RB_RATIONAL_DEN
-static inline VALUE
-rb_rational_den(VALUE rat)
-{
-#ifdef RRATIONAL
- return RRATIONAL(rat)->den;
-#else
- return rb_funcall(rat, rb_intern("denominator"), 0);
-#endif
-}
-#endif
-
-/* complex */
-
-#ifndef HAVE_RB_COMPLEX_REAL
-static inline VALUE
-rb_complex_real(VALUE cmp)
-{
-#ifdef RCOMPLEX
- return RCOMPLEX(cmp)->real;
-#else
- return rb_funcall(cmp, rb_intern("real"), 0);
-#endif
-}
-#endif
-
-#ifndef HAVE_RB_COMPLEX_IMAG
-static inline VALUE
-rb_complex_imag(VALUE cmp)
-{
-# ifdef RCOMPLEX
- return RCOMPLEX(cmp)->imag;
-# else
- return rb_funcall(cmp, rb_intern("imag"), 0);
-# endif
-}
-#endif
-
-/* st */
-
-#ifndef ST2FIX
-# undef RB_ST2FIX
-# define RB_ST2FIX(h) LONG2FIX((long)(h))
-# define ST2FIX(h) RB_ST2FIX(h)
-#endif
-
-/* warning */
-
-#if !defined(HAVE_RB_CATEGORY_WARN) || !defined(HAVE_CONST_RB_WARN_CATEGORY_DEPRECATED)
-# define rb_category_warn(category, ...) rb_warn(__VA_ARGS__)
-#endif
-
-#if defined(__cplusplus)
-#if 0
-{ /* satisfy cc-mode */
-#endif
-} /* extern "C" { */
-#endif
-
-#endif /* MISSING_H */
diff --git a/ext/bigdecimal/missing/dtoa.c b/ext/bigdecimal/missing/dtoa.c
deleted file mode 100644
index 41b0a221d1..0000000000
--- a/ext/bigdecimal/missing/dtoa.c
+++ /dev/null
@@ -1,3462 +0,0 @@
-/****************************************************************
- *
- * The author of this software is David M. Gay.
- *
- * Copyright (c) 1991, 2000, 2001 by Lucent Technologies.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose without fee is hereby granted, provided that this entire notice
- * is included in all copies of any software which is or includes a copy
- * or modification of this software and in all copies of the supporting
- * documentation for such software.
- *
- * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
- * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
- * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
- *
- ***************************************************************/
-
-/* Please send bug reports to David M. Gay (dmg at acm dot org,
- * with " at " changed at "@" and " dot " changed to "."). */
-
-/* On a machine with IEEE extended-precision registers, it is
- * necessary to specify double-precision (53-bit) rounding precision
- * before invoking strtod or dtoa. If the machine uses (the equivalent
- * of) Intel 80x87 arithmetic, the call
- * _control87(PC_53, MCW_PC);
- * does this with many compilers. Whether this or another call is
- * appropriate depends on the compiler; for this to work, it may be
- * necessary to #include "float.h" or another system-dependent header
- * file.
- */
-
-/* strtod for IEEE-, VAX-, and IBM-arithmetic machines.
- *
- * This strtod returns a nearest machine number to the input decimal
- * string (or sets errno to ERANGE). With IEEE arithmetic, ties are
- * broken by the IEEE round-even rule. Otherwise ties are broken by
- * biased rounding (add half and chop).
- *
- * Inspired loosely by William D. Clinger's paper "How to Read Floating
- * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101].
- *
- * Modifications:
- *
- * 1. We only require IEEE, IBM, or VAX double-precision
- * arithmetic (not IEEE double-extended).
- * 2. We get by with floating-point arithmetic in a case that
- * Clinger missed -- when we're computing d * 10^n
- * for a small integer d and the integer n is not too
- * much larger than 22 (the maximum integer k for which
- * we can represent 10^k exactly), we may be able to
- * compute (d*10^k) * 10^(e-k) with just one roundoff.
- * 3. Rather than a bit-at-a-time adjustment of the binary
- * result in the hard case, we use floating-point
- * arithmetic to determine the adjustment to within
- * one bit; only in really hard cases do we need to
- * compute a second residual.
- * 4. Because of 3., we don't need a large table of powers of 10
- * for ten-to-e (just some small tables, e.g. of 10^k
- * for 0 <= k <= 22).
- */
-
-/*
- * #define IEEE_LITTLE_ENDIAN for IEEE-arithmetic machines where the least
- * significant byte has the lowest address.
- * #define IEEE_BIG_ENDIAN for IEEE-arithmetic machines where the most
- * significant byte has the lowest address.
- * #define Long int on machines with 32-bit ints and 64-bit longs.
- * #define IBM for IBM mainframe-style floating-point arithmetic.
- * #define VAX for VAX-style floating-point arithmetic (D_floating).
- * #define No_leftright to omit left-right logic in fast floating-point
- * computation of dtoa.
- * #define Honor_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3
- * and strtod and dtoa should round accordingly.
- * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3
- * and Honor_FLT_ROUNDS is not #defined.
- * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines
- * that use extended-precision instructions to compute rounded
- * products and quotients) with IBM.
- * #define ROUND_BIASED for IEEE-format with biased rounding.
- * #define Inaccurate_Divide for IEEE-format with correctly rounded
- * products but inaccurate quotients, e.g., for Intel i860.
- * #define NO_LONG_LONG on machines that do not have a "long long"
- * integer type (of >= 64 bits). On such machines, you can
- * #define Just_16 to store 16 bits per 32-bit Long when doing
- * high-precision integer arithmetic. Whether this speeds things
- * up or slows things down depends on the machine and the number
- * being converted. If long long is available and the name is
- * something other than "long long", #define Llong to be the name,
- * and if "unsigned Llong" does not work as an unsigned version of
- * Llong, #define #ULLong to be the corresponding unsigned type.
- * #define KR_headers for old-style C function headers.
- * #define Bad_float_h if your system lacks a float.h or if it does not
- * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP,
- * FLT_RADIX, FLT_ROUNDS, and DBL_MAX.
- * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n)
- * if memory is available and otherwise does something you deem
- * appropriate. If MALLOC is undefined, malloc will be invoked
- * directly -- and assumed always to succeed.
- * #define Omit_Private_Memory to omit logic (added Jan. 1998) for making
- * memory allocations from a private pool of memory when possible.
- * When used, the private pool is PRIVATE_MEM bytes long: 2304 bytes,
- * unless #defined to be a different length. This default length
- * suffices to get rid of MALLOC calls except for unusual cases,
- * such as decimal-to-binary conversion of a very long string of
- * digits. The longest string dtoa can return is about 751 bytes
- * long. For conversions by strtod of strings of 800 digits and
- * all dtoa conversions in single-threaded executions with 8-byte
- * pointers, PRIVATE_MEM >= 7400 appears to suffice; with 4-byte
- * pointers, PRIVATE_MEM >= 7112 appears adequate.
- * #define INFNAN_CHECK on IEEE systems to cause strtod to check for
- * Infinity and NaN (case insensitively). On some systems (e.g.,
- * some HP systems), it may be necessary to #define NAN_WORD0
- * appropriately -- to the most significant word of a quiet NaN.
- * (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.)
- * When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined,
- * strtod also accepts (case insensitively) strings of the form
- * NaN(x), where x is a string of hexadecimal digits and spaces;
- * if there is only one string of hexadecimal digits, it is taken
- * for the 52 fraction bits of the resulting NaN; if there are two
- * or more strings of hex digits, the first is for the high 20 bits,
- * the second and subsequent for the low 32 bits, with intervening
- * white space ignored; but if this results in none of the 52
- * fraction bits being on (an IEEE Infinity symbol), then NAN_WORD0
- * and NAN_WORD1 are used instead.
- * #define MULTIPLE_THREADS if the system offers preemptively scheduled
- * multiple threads. In this case, you must provide (or suitably
- * #define) two locks, acquired by ACQUIRE_DTOA_LOCK(n) and freed
- * by FREE_DTOA_LOCK(n) for n = 0 or 1. (The second lock, accessed
- * in pow5mult, ensures lazy evaluation of only one copy of high
- * powers of 5; omitting this lock would introduce a small
- * probability of wasting memory, but would otherwise be harmless.)
- * You must also invoke freedtoa(s) to free the value s returned by
- * dtoa. You may do so whether or not MULTIPLE_THREADS is #defined.
- * #define NO_IEEE_Scale to disable new (Feb. 1997) logic in strtod that
- * avoids underflows on inputs whose result does not underflow.
- * If you #define NO_IEEE_Scale on a machine that uses IEEE-format
- * floating-point numbers and flushes underflows to zero rather
- * than implementing gradual underflow, then you must also #define
- * Sudden_Underflow.
- * #define YES_ALIAS to permit aliasing certain double values with
- * arrays of ULongs. This leads to slightly better code with
- * some compilers and was always used prior to 19990916, but it
- * is not strictly legal and can cause trouble with aggressively
- * optimizing compilers (e.g., gcc 2.95.1 under -O2).
- * #define USE_LOCALE to use the current locale's decimal_point value.
- * #define SET_INEXACT if IEEE arithmetic is being used and extra
- * computation should be done to set the inexact flag when the
- * result is inexact and avoid setting inexact when the result
- * is exact. In this case, dtoa.c must be compiled in
- * an environment, perhaps provided by #include "dtoa.c" in a
- * suitable wrapper, that defines two functions,
- * int get_inexact(void);
- * void clear_inexact(void);
- * such that get_inexact() returns a nonzero value if the
- * inexact bit is already set, and clear_inexact() sets the
- * inexact bit to 0. When SET_INEXACT is #defined, strtod
- * also does extra computations to set the underflow and overflow
- * flags when appropriate (i.e., when the result is tiny and
- * inexact or when it is a numeric value rounded to +-infinity).
- * #define NO_ERRNO if strtod should not assign errno = ERANGE when
- * the result overflows to +-Infinity or underflows to 0.
- */
-
-#ifdef WORDS_BIGENDIAN
-#define IEEE_BIG_ENDIAN
-#else
-#define IEEE_LITTLE_ENDIAN
-#endif
-
-#ifdef __vax__
-#define VAX
-#undef IEEE_BIG_ENDIAN
-#undef IEEE_LITTLE_ENDIAN
-#endif
-
-#if defined(__arm__) && !defined(__VFP_FP__)
-#define IEEE_BIG_ENDIAN
-#undef IEEE_LITTLE_ENDIAN
-#endif
-
-#undef Long
-#undef ULong
-
-#include <limits.h>
-
-#if (INT_MAX >> 30) && !(INT_MAX >> 31)
-#define Long int
-#define ULong unsigned int
-#elif (LONG_MAX >> 30) && !(LONG_MAX >> 31)
-#define Long long int
-#define ULong unsigned long int
-#else
-#error No 32bit integer
-#endif
-
-#if HAVE_LONG_LONG
-#define Llong LONG_LONG
-#else
-#define NO_LONG_LONG
-#endif
-
-#ifdef DEBUG
-#include <stdio.h>
-#define Bug(x) {fprintf(stderr, "%s\n", (x)); exit(EXIT_FAILURE);}
-#endif
-
-#ifndef ISDIGIT
-#include <ctype.h>
-#define ISDIGIT(c) isdigit(c)
-#endif
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef USE_LOCALE
-#include <locale.h>
-#endif
-
-#ifdef MALLOC
-extern void *MALLOC(size_t);
-#else
-#define MALLOC xmalloc
-#endif
-#ifdef FREE
-extern void FREE(void*);
-#else
-#define FREE xfree
-#endif
-#ifndef NO_SANITIZE
-#define NO_SANITIZE(x, y) y
-#endif
-
-#ifndef Omit_Private_Memory
-#ifndef PRIVATE_MEM
-#define PRIVATE_MEM 2304
-#endif
-#define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
-static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
-#endif
-
-#undef IEEE_Arith
-#undef Avoid_Underflow
-#ifdef IEEE_BIG_ENDIAN
-#define IEEE_Arith
-#endif
-#ifdef IEEE_LITTLE_ENDIAN
-#define IEEE_Arith
-#endif
-
-#ifdef Bad_float_h
-
-#ifdef IEEE_Arith
-#define DBL_DIG 15
-#define DBL_MAX_10_EXP 308
-#define DBL_MAX_EXP 1024
-#define FLT_RADIX 2
-#endif /*IEEE_Arith*/
-
-#ifdef IBM
-#define DBL_DIG 16
-#define DBL_MAX_10_EXP 75
-#define DBL_MAX_EXP 63
-#define FLT_RADIX 16
-#define DBL_MAX 7.2370055773322621e+75
-#endif
-
-#ifdef VAX
-#define DBL_DIG 16
-#define DBL_MAX_10_EXP 38
-#define DBL_MAX_EXP 127
-#define FLT_RADIX 2
-#define DBL_MAX 1.7014118346046923e+38
-#endif
-
-#ifndef LONG_MAX
-#define LONG_MAX 2147483647
-#endif
-
-#else /* ifndef Bad_float_h */
-#include <float.h>
-#endif /* Bad_float_h */
-
-#include <math.h>
-
-#ifdef __cplusplus
-extern "C" {
-#if 0
-} /* satisfy cc-mode */
-#endif
-#endif
-
-#ifndef hexdigit
-static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF";
-#endif
-
-#if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN) + defined(VAX) + defined(IBM) != 1
-Exactly one of IEEE_LITTLE_ENDIAN, IEEE_BIG_ENDIAN, VAX, or IBM should be defined.
-#endif
-
-typedef union { double d; ULong L[2]; } U;
-
-#ifdef YES_ALIAS
-typedef double double_u;
-# define dval(x) (x)
-# ifdef IEEE_LITTLE_ENDIAN
-# define word0(x) (((ULong *)&(x))[1])
-# define word1(x) (((ULong *)&(x))[0])
-# else
-# define word0(x) (((ULong *)&(x))[0])
-# define word1(x) (((ULong *)&(x))[1])
-# endif
-#else
-typedef U double_u;
-# ifdef IEEE_LITTLE_ENDIAN
-# define word0(x) ((x).L[1])
-# define word1(x) ((x).L[0])
-# else
-# define word0(x) ((x).L[0])
-# define word1(x) ((x).L[1])
-# endif
-# define dval(x) ((x).d)
-#endif
-
-/* The following definition of Storeinc is appropriate for MIPS processors.
- * An alternative that might be better on some machines is
- * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
- */
-#if defined(IEEE_LITTLE_ENDIAN) + defined(VAX) + defined(__arm__)
-#define Storeinc(a,b,c) (((unsigned short *)(a))[1] = (unsigned short)(b), \
-((unsigned short *)(a))[0] = (unsigned short)(c), (a)++)
-#else
-#define Storeinc(a,b,c) (((unsigned short *)(a))[0] = (unsigned short)(b), \
-((unsigned short *)(a))[1] = (unsigned short)(c), (a)++)
-#endif
-
-/* #define P DBL_MANT_DIG */
-/* Ten_pmax = floor(P*log(2)/log(5)) */
-/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */
-/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */
-/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */
-
-#ifdef IEEE_Arith
-#define Exp_shift 20
-#define Exp_shift1 20
-#define Exp_msk1 0x100000
-#define Exp_msk11 0x100000
-#define Exp_mask 0x7ff00000
-#define P 53
-#define Bias 1023
-#define Emin (-1022)
-#define Exp_1 0x3ff00000
-#define Exp_11 0x3ff00000
-#define Ebits 11
-#define Frac_mask 0xfffff
-#define Frac_mask1 0xfffff
-#define Ten_pmax 22
-#define Bletch 0x10
-#define Bndry_mask 0xfffff
-#define Bndry_mask1 0xfffff
-#define LSB 1
-#define Sign_bit 0x80000000
-#define Log2P 1
-#define Tiny0 0
-#define Tiny1 1
-#define Quick_max 14
-#define Int_max 14
-#ifndef NO_IEEE_Scale
-#define Avoid_Underflow
-#ifdef Flush_Denorm /* debugging option */
-#undef Sudden_Underflow
-#endif
-#endif
-
-#ifndef Flt_Rounds
-#ifdef FLT_ROUNDS
-#define Flt_Rounds FLT_ROUNDS
-#else
-#define Flt_Rounds 1
-#endif
-#endif /*Flt_Rounds*/
-
-#ifdef Honor_FLT_ROUNDS
-#define Rounding rounding
-#undef Check_FLT_ROUNDS
-#define Check_FLT_ROUNDS
-#else
-#define Rounding Flt_Rounds
-#endif
-
-#else /* ifndef IEEE_Arith */
-#undef Check_FLT_ROUNDS
-#undef Honor_FLT_ROUNDS
-#undef SET_INEXACT
-#undef Sudden_Underflow
-#define Sudden_Underflow
-#ifdef IBM
-#undef Flt_Rounds
-#define Flt_Rounds 0
-#define Exp_shift 24
-#define Exp_shift1 24
-#define Exp_msk1 0x1000000
-#define Exp_msk11 0x1000000
-#define Exp_mask 0x7f000000
-#define P 14
-#define Bias 65
-#define Exp_1 0x41000000
-#define Exp_11 0x41000000
-#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */
-#define Frac_mask 0xffffff
-#define Frac_mask1 0xffffff
-#define Bletch 4
-#define Ten_pmax 22
-#define Bndry_mask 0xefffff
-#define Bndry_mask1 0xffffff
-#define LSB 1
-#define Sign_bit 0x80000000
-#define Log2P 4
-#define Tiny0 0x100000
-#define Tiny1 0
-#define Quick_max 14
-#define Int_max 15
-#else /* VAX */
-#undef Flt_Rounds
-#define Flt_Rounds 1
-#define Exp_shift 23
-#define Exp_shift1 7
-#define Exp_msk1 0x80
-#define Exp_msk11 0x800000
-#define Exp_mask 0x7f80
-#define P 56
-#define Bias 129
-#define Exp_1 0x40800000
-#define Exp_11 0x4080
-#define Ebits 8
-#define Frac_mask 0x7fffff
-#define Frac_mask1 0xffff007f
-#define Ten_pmax 24
-#define Bletch 2
-#define Bndry_mask 0xffff007f
-#define Bndry_mask1 0xffff007f
-#define LSB 0x10000
-#define Sign_bit 0x8000
-#define Log2P 1
-#define Tiny0 0x80
-#define Tiny1 0
-#define Quick_max 15
-#define Int_max 15
-#endif /* IBM, VAX */
-#endif /* IEEE_Arith */
-
-#ifndef IEEE_Arith
-#define ROUND_BIASED
-#endif
-
-#ifdef RND_PRODQUOT
-#define rounded_product(a,b) ((a) = rnd_prod((a), (b)))
-#define rounded_quotient(a,b) ((a) = rnd_quot((a), (b)))
-extern double rnd_prod(double, double), rnd_quot(double, double);
-#else
-#define rounded_product(a,b) ((a) *= (b))
-#define rounded_quotient(a,b) ((a) /= (b))
-#endif
-
-#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1))
-#define Big1 0xffffffff
-
-#ifndef Pack_32
-#define Pack_32
-#endif
-
-#define FFFFFFFF 0xffffffffUL
-
-#ifdef NO_LONG_LONG
-#undef ULLong
-#ifdef Just_16
-#undef Pack_32
-/* When Pack_32 is not defined, we store 16 bits per 32-bit Long.
- * This makes some inner loops simpler and sometimes saves work
- * during multiplications, but it often seems to make things slightly
- * slower. Hence the default is now to store 32 bits per Long.
- */
-#endif
-#else /* long long available */
-#ifndef Llong
-#define Llong long long
-#endif
-#ifndef ULLong
-#define ULLong unsigned Llong
-#endif
-#endif /* NO_LONG_LONG */
-
-#define MULTIPLE_THREADS 1
-
-#ifndef MULTIPLE_THREADS
-#define ACQUIRE_DTOA_LOCK(n) /*nothing*/
-#define FREE_DTOA_LOCK(n) /*nothing*/
-#else
-#define ACQUIRE_DTOA_LOCK(n) /*unused right now*/
-#define FREE_DTOA_LOCK(n) /*unused right now*/
-#endif
-
-#ifndef ATOMIC_PTR_CAS
-#define ATOMIC_PTR_CAS(var, old, new) ((var) = (new), (old))
-#endif
-#ifndef LIKELY
-#define LIKELY(x) (x)
-#endif
-#ifndef UNLIKELY
-#define UNLIKELY(x) (x)
-#endif
-#ifndef ASSUME
-#define ASSUME(x) (void)(x)
-#endif
-
-#define Kmax 15
-
-struct Bigint {
- struct Bigint *next;
- int k, maxwds, sign, wds;
- ULong x[1];
-};
-
-typedef struct Bigint Bigint;
-
-static Bigint *freelist[Kmax+1];
-
-static Bigint *
-Balloc(int k)
-{
- int x;
- Bigint *rv;
-#ifndef Omit_Private_Memory
- size_t len;
-#endif
-
- rv = 0;
- ACQUIRE_DTOA_LOCK(0);
- if (k <= Kmax) {
- rv = freelist[k];
- while (rv) {
- Bigint *rvn = rv;
- rv = ATOMIC_PTR_CAS(freelist[k], rv, rv->next);
- if (LIKELY(rvn == rv)) {
- ASSUME(rv);
- break;
- }
- }
- }
- if (!rv) {
- x = 1 << k;
-#ifdef Omit_Private_Memory
- rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
-#else
- len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
- /sizeof(double);
- if (k <= Kmax) {
- double *pnext = pmem_next;
- while (pnext - private_mem + len <= PRIVATE_mem) {
- double *p = pnext;
- pnext = ATOMIC_PTR_CAS(pmem_next, pnext, pnext + len);
- if (LIKELY(p == pnext)) {
- rv = (Bigint*)pnext;
- ASSUME(rv);
- break;
- }
- }
- }
- if (!rv)
- rv = (Bigint*)MALLOC(len*sizeof(double));
-#endif
- rv->k = k;
- rv->maxwds = x;
- }
- FREE_DTOA_LOCK(0);
- rv->sign = rv->wds = 0;
- return rv;
-}
-
-static void
-Bfree(Bigint *v)
-{
- Bigint *vn;
- if (v) {
- if (v->k > Kmax) {
- FREE(v);
- return;
- }
- ACQUIRE_DTOA_LOCK(0);
- do {
- vn = v->next = freelist[v->k];
- } while (UNLIKELY(ATOMIC_PTR_CAS(freelist[v->k], vn, v) != vn));
- FREE_DTOA_LOCK(0);
- }
-}
-
-#define Bcopy(x,y) memcpy((char *)&(x)->sign, (char *)&(y)->sign, \
-(y)->wds*sizeof(Long) + 2*sizeof(int))
-
-static Bigint *
-multadd(Bigint *b, int m, int a) /* multiply by m and add a */
-{
- int i, wds;
- ULong *x;
-#ifdef ULLong
- ULLong carry, y;
-#else
- ULong carry, y;
-#ifdef Pack_32
- ULong xi, z;
-#endif
-#endif
- Bigint *b1;
-
- wds = b->wds;
- x = b->x;
- i = 0;
- carry = a;
- do {
-#ifdef ULLong
- y = *x * (ULLong)m + carry;
- carry = y >> 32;
- *x++ = (ULong)(y & FFFFFFFF);
-#else
-#ifdef Pack_32
- xi = *x;
- y = (xi & 0xffff) * m + carry;
- z = (xi >> 16) * m + (y >> 16);
- carry = z >> 16;
- *x++ = (z << 16) + (y & 0xffff);
-#else
- y = *x * m + carry;
- carry = y >> 16;
- *x++ = y & 0xffff;
-#endif
-#endif
- } while (++i < wds);
- if (carry) {
- if (wds >= b->maxwds) {
- b1 = Balloc(b->k+1);
- Bcopy(b1, b);
- Bfree(b);
- b = b1;
- }
- b->x[wds++] = (ULong)carry;
- b->wds = wds;
- }
- return b;
-}
-
-static Bigint *
-s2b(const char *s, int nd0, int nd, ULong y9)
-{
- Bigint *b;
- int i, k;
- Long x, y;
-
- x = (nd + 8) / 9;
- for (k = 0, y = 1; x > y; y <<= 1, k++) ;
-#ifdef Pack_32
- b = Balloc(k);
- b->x[0] = y9;
- b->wds = 1;
-#else
- b = Balloc(k+1);
- b->x[0] = y9 & 0xffff;
- b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
-#endif
-
- i = 9;
- if (9 < nd0) {
- s += 9;
- do {
- b = multadd(b, 10, *s++ - '0');
- } while (++i < nd0);
- s++;
- }
- else
- s += 10;
- for (; i < nd; i++)
- b = multadd(b, 10, *s++ - '0');
- return b;
-}
-
-static int
-hi0bits(register ULong x)
-{
- register int k = 0;
-
- if (!(x & 0xffff0000)) {
- k = 16;
- x <<= 16;
- }
- if (!(x & 0xff000000)) {
- k += 8;
- x <<= 8;
- }
- if (!(x & 0xf0000000)) {
- k += 4;
- x <<= 4;
- }
- if (!(x & 0xc0000000)) {
- k += 2;
- x <<= 2;
- }
- if (!(x & 0x80000000)) {
- k++;
- if (!(x & 0x40000000))
- return 32;
- }
- return k;
-}
-
-static int
-lo0bits(ULong *y)
-{
- register int k;
- register ULong x = *y;
-
- if (x & 7) {
- if (x & 1)
- return 0;
- if (x & 2) {
- *y = x >> 1;
- return 1;
- }
- *y = x >> 2;
- return 2;
- }
- k = 0;
- if (!(x & 0xffff)) {
- k = 16;
- x >>= 16;
- }
- if (!(x & 0xff)) {
- k += 8;
- x >>= 8;
- }
- if (!(x & 0xf)) {
- k += 4;
- x >>= 4;
- }
- if (!(x & 0x3)) {
- k += 2;
- x >>= 2;
- }
- if (!(x & 1)) {
- k++;
- x >>= 1;
- if (!x)
- return 32;
- }
- *y = x;
- return k;
-}
-
-static Bigint *
-i2b(int i)
-{
- Bigint *b;
-
- b = Balloc(1);
- b->x[0] = i;
- b->wds = 1;
- return b;
-}
-
-static Bigint *
-mult(Bigint *a, Bigint *b)
-{
- Bigint *c;
- int k, wa, wb, wc;
- ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
- ULong y;
-#ifdef ULLong
- ULLong carry, z;
-#else
- ULong carry, z;
-#ifdef Pack_32
- ULong z2;
-#endif
-#endif
-
- if (a->wds < b->wds) {
- c = a;
- a = b;
- b = c;
- }
- k = a->k;
- wa = a->wds;
- wb = b->wds;
- wc = wa + wb;
- if (wc > a->maxwds)
- k++;
- c = Balloc(k);
- for (x = c->x, xa = x + wc; x < xa; x++)
- *x = 0;
- xa = a->x;
- xae = xa + wa;
- xb = b->x;
- xbe = xb + wb;
- xc0 = c->x;
-#ifdef ULLong
- for (; xb < xbe; xc0++) {
- if ((y = *xb++) != 0) {
- x = xa;
- xc = xc0;
- carry = 0;
- do {
- z = *x++ * (ULLong)y + *xc + carry;
- carry = z >> 32;
- *xc++ = (ULong)(z & FFFFFFFF);
- } while (x < xae);
- *xc = (ULong)carry;
- }
- }
-#else
-#ifdef Pack_32
- for (; xb < xbe; xb++, xc0++) {
- if ((y = *xb & 0xffff) != 0) {
- x = xa;
- xc = xc0;
- carry = 0;
- do {
- z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
- carry = z >> 16;
- z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
- carry = z2 >> 16;
- Storeinc(xc, z2, z);
- } while (x < xae);
- *xc = (ULong)carry;
- }
- if ((y = *xb >> 16) != 0) {
- x = xa;
- xc = xc0;
- carry = 0;
- z2 = *xc;
- do {
- z = (*x & 0xffff) * y + (*xc >> 16) + carry;
- carry = z >> 16;
- Storeinc(xc, z, z2);
- z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
- carry = z2 >> 16;
- } while (x < xae);
- *xc = z2;
- }
- }
-#else
- for (; xb < xbe; xc0++) {
- if (y = *xb++) {
- x = xa;
- xc = xc0;
- carry = 0;
- do {
- z = *x++ * y + *xc + carry;
- carry = z >> 16;
- *xc++ = z & 0xffff;
- } while (x < xae);
- *xc = (ULong)carry;
- }
- }
-#endif
-#endif
- for (xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
- c->wds = wc;
- return c;
-}
-
-static Bigint *p5s;
-
-static Bigint *
-pow5mult(Bigint *b, int k)
-{
- Bigint *b1, *p5, *p51;
- Bigint *p5tmp;
- int i;
- static const int p05[3] = { 5, 25, 125 };
-
- if ((i = k & 3) != 0)
- b = multadd(b, p05[i-1], 0);
-
- if (!(k >>= 2))
- return b;
- if (!(p5 = p5s)) {
- /* first time */
- ACQUIRE_DTOA_LOCK(1);
- if (!(p5 = p5s)) {
- p5 = i2b(625);
- p5->next = 0;
- p5tmp = ATOMIC_PTR_CAS(p5s, NULL, p5);
- if (UNLIKELY(p5tmp)) {
- Bfree(p5);
- p5 = p5tmp;
- }
- }
- FREE_DTOA_LOCK(1);
- }
- for (;;) {
- if (k & 1) {
- b1 = mult(b, p5);
- Bfree(b);
- b = b1;
- }
- if (!(k >>= 1))
- break;
- if (!(p51 = p5->next)) {
- ACQUIRE_DTOA_LOCK(1);
- if (!(p51 = p5->next)) {
- p51 = mult(p5,p5);
- p51->next = 0;
- p5tmp = ATOMIC_PTR_CAS(p5->next, NULL, p51);
- if (UNLIKELY(p5tmp)) {
- Bfree(p51);
- p51 = p5tmp;
- }
- }
- FREE_DTOA_LOCK(1);
- }
- p5 = p51;
- }
- return b;
-}
-
-static Bigint *
-lshift(Bigint *b, int k)
-{
- int i, k1, n, n1;
- Bigint *b1;
- ULong *x, *x1, *xe, z;
-
-#ifdef Pack_32
- n = k >> 5;
-#else
- n = k >> 4;
-#endif
- k1 = b->k;
- n1 = n + b->wds + 1;
- for (i = b->maxwds; n1 > i; i <<= 1)
- k1++;
- b1 = Balloc(k1);
- x1 = b1->x;
- for (i = 0; i < n; i++)
- *x1++ = 0;
- x = b->x;
- xe = x + b->wds;
-#ifdef Pack_32
- if (k &= 0x1f) {
- k1 = 32 - k;
- z = 0;
- do {
- *x1++ = *x << k | z;
- z = *x++ >> k1;
- } while (x < xe);
- if ((*x1 = z) != 0)
- ++n1;
- }
-#else
- if (k &= 0xf) {
- k1 = 16 - k;
- z = 0;
- do {
- *x1++ = *x << k & 0xffff | z;
- z = *x++ >> k1;
- } while (x < xe);
- if (*x1 = z)
- ++n1;
- }
-#endif
- else
- do {
- *x1++ = *x++;
- } while (x < xe);
- b1->wds = n1 - 1;
- Bfree(b);
- return b1;
-}
-
-static int
-cmp(Bigint *a, Bigint *b)
-{
- ULong *xa, *xa0, *xb, *xb0;
- int i, j;
-
- i = a->wds;
- j = b->wds;
-#ifdef DEBUG
- if (i > 1 && !a->x[i-1])
- Bug("cmp called with a->x[a->wds-1] == 0");
- if (j > 1 && !b->x[j-1])
- Bug("cmp called with b->x[b->wds-1] == 0");
-#endif
- if (i -= j)
- return i;
- xa0 = a->x;
- xa = xa0 + j;
- xb0 = b->x;
- xb = xb0 + j;
- for (;;) {
- if (*--xa != *--xb)
- return *xa < *xb ? -1 : 1;
- if (xa <= xa0)
- break;
- }
- return 0;
-}
-
-NO_SANITIZE("unsigned-integer-overflow", static Bigint * diff(Bigint *a, Bigint *b));
-static Bigint *
-diff(Bigint *a, Bigint *b)
-{
- Bigint *c;
- int i, wa, wb;
- ULong *xa, *xae, *xb, *xbe, *xc;
-#ifdef ULLong
- ULLong borrow, y;
-#else
- ULong borrow, y;
-#ifdef Pack_32
- ULong z;
-#endif
-#endif
-
- i = cmp(a,b);
- if (!i) {
- c = Balloc(0);
- c->wds = 1;
- c->x[0] = 0;
- return c;
- }
- if (i < 0) {
- c = a;
- a = b;
- b = c;
- i = 1;
- }
- else
- i = 0;
- c = Balloc(a->k);
- c->sign = i;
- wa = a->wds;
- xa = a->x;
- xae = xa + wa;
- wb = b->wds;
- xb = b->x;
- xbe = xb + wb;
- xc = c->x;
- borrow = 0;
-#ifdef ULLong
- do {
- y = (ULLong)*xa++ - *xb++ - borrow;
- borrow = y >> 32 & (ULong)1;
- *xc++ = (ULong)(y & FFFFFFFF);
- } while (xb < xbe);
- while (xa < xae) {
- y = *xa++ - borrow;
- borrow = y >> 32 & (ULong)1;
- *xc++ = (ULong)(y & FFFFFFFF);
- }
-#else
-#ifdef Pack_32
- do {
- y = (*xa & 0xffff) - (*xb & 0xffff) - borrow;
- borrow = (y & 0x10000) >> 16;
- z = (*xa++ >> 16) - (*xb++ >> 16) - borrow;
- borrow = (z & 0x10000) >> 16;
- Storeinc(xc, z, y);
- } while (xb < xbe);
- while (xa < xae) {
- y = (*xa & 0xffff) - borrow;
- borrow = (y & 0x10000) >> 16;
- z = (*xa++ >> 16) - borrow;
- borrow = (z & 0x10000) >> 16;
- Storeinc(xc, z, y);
- }
-#else
- do {
- y = *xa++ - *xb++ - borrow;
- borrow = (y & 0x10000) >> 16;
- *xc++ = y & 0xffff;
- } while (xb < xbe);
- while (xa < xae) {
- y = *xa++ - borrow;
- borrow = (y & 0x10000) >> 16;
- *xc++ = y & 0xffff;
- }
-#endif
-#endif
- while (!*--xc)
- wa--;
- c->wds = wa;
- return c;
-}
-
-static double
-ulp(double x_)
-{
- register Long L;
- double_u x, a;
- dval(x) = x_;
-
- L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1;
-#ifndef Avoid_Underflow
-#ifndef Sudden_Underflow
- if (L > 0) {
-#endif
-#endif
-#ifdef IBM
- L |= Exp_msk1 >> 4;
-#endif
- word0(a) = L;
- word1(a) = 0;
-#ifndef Avoid_Underflow
-#ifndef Sudden_Underflow
- }
- else {
- L = -L >> Exp_shift;
- if (L < Exp_shift) {
- word0(a) = 0x80000 >> L;
- word1(a) = 0;
- }
- else {
- word0(a) = 0;
- L -= Exp_shift;
- word1(a) = L >= 31 ? 1 : 1 << 31 - L;
- }
- }
-#endif
-#endif
- return dval(a);
-}
-
-static double
-b2d(Bigint *a, int *e)
-{
- ULong *xa, *xa0, w, y, z;
- int k;
- double_u d;
-#ifdef VAX
- ULong d0, d1;
-#else
-#define d0 word0(d)
-#define d1 word1(d)
-#endif
-
- xa0 = a->x;
- xa = xa0 + a->wds;
- y = *--xa;
-#ifdef DEBUG
- if (!y) Bug("zero y in b2d");
-#endif
- k = hi0bits(y);
- *e = 32 - k;
-#ifdef Pack_32
- if (k < Ebits) {
- d0 = Exp_1 | y >> (Ebits - k);
- w = xa > xa0 ? *--xa : 0;
- d1 = y << ((32-Ebits) + k) | w >> (Ebits - k);
- goto ret_d;
- }
- z = xa > xa0 ? *--xa : 0;
- if (k -= Ebits) {
- d0 = Exp_1 | y << k | z >> (32 - k);
- y = xa > xa0 ? *--xa : 0;
- d1 = z << k | y >> (32 - k);
- }
- else {
- d0 = Exp_1 | y;
- d1 = z;
- }
-#else
- if (k < Ebits + 16) {
- z = xa > xa0 ? *--xa : 0;
- d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
- w = xa > xa0 ? *--xa : 0;
- y = xa > xa0 ? *--xa : 0;
- d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
- goto ret_d;
- }
- z = xa > xa0 ? *--xa : 0;
- w = xa > xa0 ? *--xa : 0;
- k -= Ebits + 16;
- d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
- y = xa > xa0 ? *--xa : 0;
- d1 = w << k + 16 | y << k;
-#endif
-ret_d:
-#ifdef VAX
- word0(d) = d0 >> 16 | d0 << 16;
- word1(d) = d1 >> 16 | d1 << 16;
-#else
-#undef d0
-#undef d1
-#endif
- return dval(d);
-}
-
-static Bigint *
-d2b(double d_, int *e, int *bits)
-{
- double_u d;
- Bigint *b;
- int de, k;
- ULong *x, y, z;
-#ifndef Sudden_Underflow
- int i;
-#endif
-#ifdef VAX
- ULong d0, d1;
-#endif
- dval(d) = d_;
-#ifdef VAX
- d0 = word0(d) >> 16 | word0(d) << 16;
- d1 = word1(d) >> 16 | word1(d) << 16;
-#else
-#define d0 word0(d)
-#define d1 word1(d)
-#endif
-
-#ifdef Pack_32
- b = Balloc(1);
-#else
- b = Balloc(2);
-#endif
- x = b->x;
-
- z = d0 & Frac_mask;
- d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
-#ifdef Sudden_Underflow
- de = (int)(d0 >> Exp_shift);
-#ifndef IBM
- z |= Exp_msk11;
-#endif
-#else
- if ((de = (int)(d0 >> Exp_shift)) != 0)
- z |= Exp_msk1;
-#endif
-#ifdef Pack_32
- if ((y = d1) != 0) {
- if ((k = lo0bits(&y)) != 0) {
- x[0] = y | z << (32 - k);
- z >>= k;
- }
- else
- x[0] = y;
-#ifndef Sudden_Underflow
- i =
-#endif
- b->wds = (x[1] = z) ? 2 : 1;
- }
- else {
-#ifdef DEBUG
- if (!z)
- Bug("Zero passed to d2b");
-#endif
- k = lo0bits(&z);
- x[0] = z;
-#ifndef Sudden_Underflow
- i =
-#endif
- b->wds = 1;
- k += 32;
- }
-#else
- if (y = d1) {
- if (k = lo0bits(&y))
- if (k >= 16) {
- x[0] = y | z << 32 - k & 0xffff;
- x[1] = z >> k - 16 & 0xffff;
- x[2] = z >> k;
- i = 2;
- }
- else {
- x[0] = y & 0xffff;
- x[1] = y >> 16 | z << 16 - k & 0xffff;
- x[2] = z >> k & 0xffff;
- x[3] = z >> k+16;
- i = 3;
- }
- else {
- x[0] = y & 0xffff;
- x[1] = y >> 16;
- x[2] = z & 0xffff;
- x[3] = z >> 16;
- i = 3;
- }
- }
- else {
-#ifdef DEBUG
- if (!z)
- Bug("Zero passed to d2b");
-#endif
- k = lo0bits(&z);
- if (k >= 16) {
- x[0] = z;
- i = 0;
- }
- else {
- x[0] = z & 0xffff;
- x[1] = z >> 16;
- i = 1;
- }
- k += 32;
- }
- while (!x[i])
- --i;
- b->wds = i + 1;
-#endif
-#ifndef Sudden_Underflow
- if (de) {
-#endif
-#ifdef IBM
- *e = (de - Bias - (P-1) << 2) + k;
- *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask);
-#else
- *e = de - Bias - (P-1) + k;
- *bits = P - k;
-#endif
-#ifndef Sudden_Underflow
- }
- else {
- *e = de - Bias - (P-1) + 1 + k;
-#ifdef Pack_32
- *bits = 32*i - hi0bits(x[i-1]);
-#else
- *bits = (i+2)*16 - hi0bits(x[i]);
-#endif
- }
-#endif
- return b;
-}
-#undef d0
-#undef d1
-
-static double
-ratio(Bigint *a, Bigint *b)
-{
- double_u da, db;
- int k, ka, kb;
-
- dval(da) = b2d(a, &ka);
- dval(db) = b2d(b, &kb);
-#ifdef Pack_32
- k = ka - kb + 32*(a->wds - b->wds);
-#else
- k = ka - kb + 16*(a->wds - b->wds);
-#endif
-#ifdef IBM
- if (k > 0) {
- word0(da) += (k >> 2)*Exp_msk1;
- if (k &= 3)
- dval(da) *= 1 << k;
- }
- else {
- k = -k;
- word0(db) += (k >> 2)*Exp_msk1;
- if (k &= 3)
- dval(db) *= 1 << k;
- }
-#else
- if (k > 0)
- word0(da) += k*Exp_msk1;
- else {
- k = -k;
- word0(db) += k*Exp_msk1;
- }
-#endif
- return dval(da) / dval(db);
-}
-
-static const double
-tens[] = {
- 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
- 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
- 1e20, 1e21, 1e22
-#ifdef VAX
- , 1e23, 1e24
-#endif
-};
-
-static const double
-#ifdef IEEE_Arith
-bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
-static const double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128,
-#ifdef Avoid_Underflow
- 9007199254740992.*9007199254740992.e-256
- /* = 2^106 * 1e-53 */
-#else
- 1e-256
-#endif
-};
-/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */
-/* flag unnecessarily. It leads to a song and dance at the end of strtod. */
-#define Scale_Bit 0x10
-#define n_bigtens 5
-#else
-#ifdef IBM
-bigtens[] = { 1e16, 1e32, 1e64 };
-static const double tinytens[] = { 1e-16, 1e-32, 1e-64 };
-#define n_bigtens 3
-#else
-bigtens[] = { 1e16, 1e32 };
-static const double tinytens[] = { 1e-16, 1e-32 };
-#define n_bigtens 2
-#endif
-#endif
-
-#ifndef IEEE_Arith
-#undef INFNAN_CHECK
-#endif
-
-#ifdef INFNAN_CHECK
-
-#ifndef NAN_WORD0
-#define NAN_WORD0 0x7ff80000
-#endif
-
-#ifndef NAN_WORD1
-#define NAN_WORD1 0
-#endif
-
-static int
-match(const char **sp, char *t)
-{
- int c, d;
- const char *s = *sp;
-
- while (d = *t++) {
- if ((c = *++s) >= 'A' && c <= 'Z')
- c += 'a' - 'A';
- if (c != d)
- return 0;
- }
- *sp = s + 1;
- return 1;
-}
-
-#ifndef No_Hex_NaN
-static void
-hexnan(double *rvp, const char **sp)
-{
- ULong c, x[2];
- const char *s;
- int havedig, udx0, xshift;
-
- x[0] = x[1] = 0;
- havedig = xshift = 0;
- udx0 = 1;
- s = *sp;
- while (c = *(const unsigned char*)++s) {
- if (c >= '0' && c <= '9')
- c -= '0';
- else if (c >= 'a' && c <= 'f')
- c += 10 - 'a';
- else if (c >= 'A' && c <= 'F')
- c += 10 - 'A';
- else if (c <= ' ') {
- if (udx0 && havedig) {
- udx0 = 0;
- xshift = 1;
- }
- continue;
- }
- else if (/*(*/ c == ')' && havedig) {
- *sp = s + 1;
- break;
- }
- else
- return; /* invalid form: don't change *sp */
- havedig = 1;
- if (xshift) {
- xshift = 0;
- x[0] = x[1];
- x[1] = 0;
- }
- if (udx0)
- x[0] = (x[0] << 4) | (x[1] >> 28);
- x[1] = (x[1] << 4) | c;
- }
- if ((x[0] &= 0xfffff) || x[1]) {
- word0(*rvp) = Exp_mask | x[0];
- word1(*rvp) = x[1];
- }
-}
-#endif /*No_Hex_NaN*/
-#endif /* INFNAN_CHECK */
-
-NO_SANITIZE("unsigned-integer-overflow", double strtod(const char *s00, char **se));
-double
-strtod(const char *s00, char **se)
-{
-#ifdef Avoid_Underflow
- int scale;
-#endif
- int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
- e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
- const char *s, *s0, *s1;
- double aadj, adj;
- double_u aadj1, rv, rv0;
- Long L;
- ULong y, z;
- Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
-#ifdef SET_INEXACT
- int inexact, oldinexact;
-#endif
-#ifdef Honor_FLT_ROUNDS
- int rounding;
-#endif
-#ifdef USE_LOCALE
- const char *s2;
-#endif
-
- errno = 0;
- sign = nz0 = nz = 0;
- dval(rv) = 0.;
- for (s = s00;;s++)
- switch (*s) {
- case '-':
- sign = 1;
- /* no break */
- case '+':
- if (*++s)
- goto break2;
- /* no break */
- case 0:
- goto ret0;
- case '\t':
- case '\n':
- case '\v':
- case '\f':
- case '\r':
- case ' ':
- continue;
- default:
- goto break2;
- }
-break2:
- if (*s == '0') {
- if (s[1] == 'x' || s[1] == 'X') {
- s0 = ++s;
- adj = 0;
- aadj = 1.0;
- nd0 = -4;
-
- if (!*++s || !(s1 = strchr(hexdigit, *s))) goto ret0;
- if (*s == '0') {
- while (*++s == '0');
- s1 = strchr(hexdigit, *s);
- }
- if (s1 != NULL) {
- do {
- adj += aadj * ((s1 - hexdigit) & 15);
- nd0 += 4;
- aadj /= 16;
- } while (*++s && (s1 = strchr(hexdigit, *s)));
- }
-
- if (*s == '.') {
- dsign = 1;
- if (!*++s || !(s1 = strchr(hexdigit, *s))) goto ret0;
- if (nd0 < 0) {
- while (*s == '0') {
- s++;
- nd0 -= 4;
- }
- }
- for (; *s && (s1 = strchr(hexdigit, *s)); ++s) {
- adj += aadj * ((s1 - hexdigit) & 15);
- if ((aadj /= 16) == 0.0) {
- while (strchr(hexdigit, *++s));
- break;
- }
- }
- }
- else {
- dsign = 0;
- }
-
- if (*s == 'P' || *s == 'p') {
- dsign = 0x2C - *++s; /* +: 2B, -: 2D */
- if (abs(dsign) == 1) s++;
- else dsign = 1;
-
- nd = 0;
- c = *s;
- if (c < '0' || '9' < c) goto ret0;
- do {
- nd *= 10;
- nd += c;
- nd -= '0';
- c = *++s;
- /* Float("0x0."+("0"*267)+"1fp2095") */
- if (nd + dsign * nd0 > 2095) {
- while ('0' <= c && c <= '9') c = *++s;
- break;
- }
- } while ('0' <= c && c <= '9');
- nd0 += nd * dsign;
- }
- else {
- if (dsign) goto ret0;
- }
- dval(rv) = ldexp(adj, nd0);
- goto ret;
- }
- nz0 = 1;
- while (*++s == '0') ;
- if (!*s)
- goto ret;
- }
- s0 = s;
- y = z = 0;
- for (nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
- if (nd < 9)
- y = 10*y + c - '0';
- else if (nd < DBL_DIG + 2)
- z = 10*z + c - '0';
- nd0 = nd;
-#ifdef USE_LOCALE
- s1 = localeconv()->decimal_point;
- if (c == *s1) {
- c = '.';
- if (*++s1) {
- s2 = s;
- for (;;) {
- if (*++s2 != *s1) {
- c = 0;
- break;
- }
- if (!*++s1) {
- s = s2;
- break;
- }
- }
- }
- }
-#endif
- if (c == '.') {
- if (!ISDIGIT(s[1]))
- goto dig_done;
- c = *++s;
- if (!nd) {
- for (; c == '0'; c = *++s)
- nz++;
- if (c > '0' && c <= '9') {
- s0 = s;
- nf += nz;
- nz = 0;
- goto have_dig;
- }
- goto dig_done;
- }
- for (; c >= '0' && c <= '9'; c = *++s) {
-have_dig:
- nz++;
- if (nd > DBL_DIG * 4) {
- continue;
- }
- if (c -= '0') {
- nf += nz;
- for (i = 1; i < nz; i++)
- if (nd++ < 9)
- y *= 10;
- else if (nd <= DBL_DIG + 2)
- z *= 10;
- if (nd++ < 9)
- y = 10*y + c;
- else if (nd <= DBL_DIG + 2)
- z = 10*z + c;
- nz = 0;
- }
- }
- }
-dig_done:
- e = 0;
- if (c == 'e' || c == 'E') {
- if (!nd && !nz && !nz0) {
- goto ret0;
- }
- s00 = s;
- esign = 0;
- switch (c = *++s) {
- case '-':
- esign = 1;
- case '+':
- c = *++s;
- }
- if (c >= '0' && c <= '9') {
- while (c == '0')
- c = *++s;
- if (c > '0' && c <= '9') {
- L = c - '0';
- s1 = s;
- while ((c = *++s) >= '0' && c <= '9')
- L = 10*L + c - '0';
- if (s - s1 > 8 || L > 19999)
- /* Avoid confusion from exponents
- * so large that e might overflow.
- */
- e = 19999; /* safe for 16 bit ints */
- else
- e = (int)L;
- if (esign)
- e = -e;
- }
- else
- e = 0;
- }
- else
- s = s00;
- }
- if (!nd) {
- if (!nz && !nz0) {
-#ifdef INFNAN_CHECK
- /* Check for Nan and Infinity */
- switch (c) {
- case 'i':
- case 'I':
- if (match(&s,"nf")) {
- --s;
- if (!match(&s,"inity"))
- ++s;
- word0(rv) = 0x7ff00000;
- word1(rv) = 0;
- goto ret;
- }
- break;
- case 'n':
- case 'N':
- if (match(&s, "an")) {
- word0(rv) = NAN_WORD0;
- word1(rv) = NAN_WORD1;
-#ifndef No_Hex_NaN
- if (*s == '(') /*)*/
- hexnan(&rv, &s);
-#endif
- goto ret;
- }
- }
-#endif /* INFNAN_CHECK */
-ret0:
- s = s00;
- sign = 0;
- }
- goto ret;
- }
- e1 = e -= nf;
-
- /* Now we have nd0 digits, starting at s0, followed by a
- * decimal point, followed by nd-nd0 digits. The number we're
- * after is the integer represented by those digits times
- * 10**e */
-
- if (!nd0)
- nd0 = nd;
- k = nd < DBL_DIG + 2 ? nd : DBL_DIG + 2;
- dval(rv) = y;
- if (k > 9) {
-#ifdef SET_INEXACT
- if (k > DBL_DIG)
- oldinexact = get_inexact();
-#endif
- dval(rv) = tens[k - 9] * dval(rv) + z;
- }
- bd0 = bb = bd = bs = delta = 0;
- if (nd <= DBL_DIG
-#ifndef RND_PRODQUOT
-#ifndef Honor_FLT_ROUNDS
- && Flt_Rounds == 1
-#endif
-#endif
- ) {
- if (!e)
- goto ret;
- if (e > 0) {
- if (e <= Ten_pmax) {
-#ifdef VAX
- goto vax_ovfl_check;
-#else
-#ifdef Honor_FLT_ROUNDS
- /* round correctly FLT_ROUNDS = 2 or 3 */
- if (sign) {
- dval(rv) = -dval(rv);
- sign = 0;
- }
-#endif
- /* rv = */ rounded_product(dval(rv), tens[e]);
- goto ret;
-#endif
- }
- i = DBL_DIG - nd;
- if (e <= Ten_pmax + i) {
- /* A fancier test would sometimes let us do
- * this for larger i values.
- */
-#ifdef Honor_FLT_ROUNDS
- /* round correctly FLT_ROUNDS = 2 or 3 */
- if (sign) {
- dval(rv) = -dval(rv);
- sign = 0;
- }
-#endif
- e -= i;
- dval(rv) *= tens[i];
-#ifdef VAX
- /* VAX exponent range is so narrow we must
- * worry about overflow here...
- */
-vax_ovfl_check:
- word0(rv) -= P*Exp_msk1;
- /* rv = */ rounded_product(dval(rv), tens[e]);
- if ((word0(rv) & Exp_mask)
- > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
- goto ovfl;
- word0(rv) += P*Exp_msk1;
-#else
- /* rv = */ rounded_product(dval(rv), tens[e]);
-#endif
- goto ret;
- }
- }
-#ifndef Inaccurate_Divide
- else if (e >= -Ten_pmax) {
-#ifdef Honor_FLT_ROUNDS
- /* round correctly FLT_ROUNDS = 2 or 3 */
- if (sign) {
- dval(rv) = -dval(rv);
- sign = 0;
- }
-#endif
- /* rv = */ rounded_quotient(dval(rv), tens[-e]);
- goto ret;
- }
-#endif
- }
- e1 += nd - k;
-
-#ifdef IEEE_Arith
-#ifdef SET_INEXACT
- inexact = 1;
- if (k <= DBL_DIG)
- oldinexact = get_inexact();
-#endif
-#ifdef Avoid_Underflow
- scale = 0;
-#endif
-#ifdef Honor_FLT_ROUNDS
- if ((rounding = Flt_Rounds) >= 2) {
- if (sign)
- rounding = rounding == 2 ? 0 : 2;
- else
- if (rounding != 2)
- rounding = 0;
- }
-#endif
-#endif /*IEEE_Arith*/
-
- /* Get starting approximation = rv * 10**e1 */
-
- if (e1 > 0) {
- if ((i = e1 & 15) != 0)
- dval(rv) *= tens[i];
- if (e1 &= ~15) {
- if (e1 > DBL_MAX_10_EXP) {
-ovfl:
-#ifndef NO_ERRNO
- errno = ERANGE;
-#endif
- /* Can't trust HUGE_VAL */
-#ifdef IEEE_Arith
-#ifdef Honor_FLT_ROUNDS
- switch (rounding) {
- case 0: /* toward 0 */
- case 3: /* toward -infinity */
- word0(rv) = Big0;
- word1(rv) = Big1;
- break;
- default:
- word0(rv) = Exp_mask;
- word1(rv) = 0;
- }
-#else /*Honor_FLT_ROUNDS*/
- word0(rv) = Exp_mask;
- word1(rv) = 0;
-#endif /*Honor_FLT_ROUNDS*/
-#ifdef SET_INEXACT
- /* set overflow bit */
- dval(rv0) = 1e300;
- dval(rv0) *= dval(rv0);
-#endif
-#else /*IEEE_Arith*/
- word0(rv) = Big0;
- word1(rv) = Big1;
-#endif /*IEEE_Arith*/
- if (bd0)
- goto retfree;
- goto ret;
- }
- e1 >>= 4;
- for (j = 0; e1 > 1; j++, e1 >>= 1)
- if (e1 & 1)
- dval(rv) *= bigtens[j];
- /* The last multiplication could overflow. */
- word0(rv) -= P*Exp_msk1;
- dval(rv) *= bigtens[j];
- if ((z = word0(rv) & Exp_mask)
- > Exp_msk1*(DBL_MAX_EXP+Bias-P))
- goto ovfl;
- if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
- /* set to largest number */
- /* (Can't trust DBL_MAX) */
- word0(rv) = Big0;
- word1(rv) = Big1;
- }
- else
- word0(rv) += P*Exp_msk1;
- }
- }
- else if (e1 < 0) {
- e1 = -e1;
- if ((i = e1 & 15) != 0)
- dval(rv) /= tens[i];
- if (e1 >>= 4) {
- if (e1 >= 1 << n_bigtens)
- goto undfl;
-#ifdef Avoid_Underflow
- if (e1 & Scale_Bit)
- scale = 2*P;
- for (j = 0; e1 > 0; j++, e1 >>= 1)
- if (e1 & 1)
- dval(rv) *= tinytens[j];
- if (scale && (j = 2*P + 1 - ((word0(rv) & Exp_mask)
- >> Exp_shift)) > 0) {
- /* scaled rv is denormal; zap j low bits */
- if (j >= 32) {
- word1(rv) = 0;
- if (j >= 53)
- word0(rv) = (P+2)*Exp_msk1;
- else
- word0(rv) &= 0xffffffff << (j-32);
- }
- else
- word1(rv) &= 0xffffffff << j;
- }
-#else
- for (j = 0; e1 > 1; j++, e1 >>= 1)
- if (e1 & 1)
- dval(rv) *= tinytens[j];
- /* The last multiplication could underflow. */
- dval(rv0) = dval(rv);
- dval(rv) *= tinytens[j];
- if (!dval(rv)) {
- dval(rv) = 2.*dval(rv0);
- dval(rv) *= tinytens[j];
-#endif
- if (!dval(rv)) {
-undfl:
- dval(rv) = 0.;
-#ifndef NO_ERRNO
- errno = ERANGE;
-#endif
- if (bd0)
- goto retfree;
- goto ret;
- }
-#ifndef Avoid_Underflow
- word0(rv) = Tiny0;
- word1(rv) = Tiny1;
- /* The refinement below will clean
- * this approximation up.
- */
- }
-#endif
- }
- }
-
- /* Now the hard part -- adjusting rv to the correct value.*/
-
- /* Put digits into bd: true value = bd * 10^e */
-
- bd0 = s2b(s0, nd0, nd, y);
-
- for (;;) {
- bd = Balloc(bd0->k);
- Bcopy(bd, bd0);
- bb = d2b(dval(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
- bs = i2b(1);
-
- if (e >= 0) {
- bb2 = bb5 = 0;
- bd2 = bd5 = e;
- }
- else {
- bb2 = bb5 = -e;
- bd2 = bd5 = 0;
- }
- if (bbe >= 0)
- bb2 += bbe;
- else
- bd2 -= bbe;
- bs2 = bb2;
-#ifdef Honor_FLT_ROUNDS
- if (rounding != 1)
- bs2++;
-#endif
-#ifdef Avoid_Underflow
- j = bbe - scale;
- i = j + bbbits - 1; /* logb(rv) */
- if (i < Emin) /* denormal */
- j += P - Emin;
- else
- j = P + 1 - bbbits;
-#else /*Avoid_Underflow*/
-#ifdef Sudden_Underflow
-#ifdef IBM
- j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
-#else
- j = P + 1 - bbbits;
-#endif
-#else /*Sudden_Underflow*/
- j = bbe;
- i = j + bbbits - 1; /* logb(rv) */
- if (i < Emin) /* denormal */
- j += P - Emin;
- else
- j = P + 1 - bbbits;
-#endif /*Sudden_Underflow*/
-#endif /*Avoid_Underflow*/
- bb2 += j;
- bd2 += j;
-#ifdef Avoid_Underflow
- bd2 += scale;
-#endif
- i = bb2 < bd2 ? bb2 : bd2;
- if (i > bs2)
- i = bs2;
- if (i > 0) {
- bb2 -= i;
- bd2 -= i;
- bs2 -= i;
- }
- if (bb5 > 0) {
- bs = pow5mult(bs, bb5);
- bb1 = mult(bs, bb);
- Bfree(bb);
- bb = bb1;
- }
- if (bb2 > 0)
- bb = lshift(bb, bb2);
- if (bd5 > 0)
- bd = pow5mult(bd, bd5);
- if (bd2 > 0)
- bd = lshift(bd, bd2);
- if (bs2 > 0)
- bs = lshift(bs, bs2);
- delta = diff(bb, bd);
- dsign = delta->sign;
- delta->sign = 0;
- i = cmp(delta, bs);
-#ifdef Honor_FLT_ROUNDS
- if (rounding != 1) {
- if (i < 0) {
- /* Error is less than an ulp */
- if (!delta->x[0] && delta->wds <= 1) {
- /* exact */
-#ifdef SET_INEXACT
- inexact = 0;
-#endif
- break;
- }
- if (rounding) {
- if (dsign) {
- adj = 1.;
- goto apply_adj;
- }
- }
- else if (!dsign) {
- adj = -1.;
- if (!word1(rv)
- && !(word0(rv) & Frac_mask)) {
- y = word0(rv) & Exp_mask;
-#ifdef Avoid_Underflow
- if (!scale || y > 2*P*Exp_msk1)
-#else
- if (y)
-#endif
- {
- delta = lshift(delta,Log2P);
- if (cmp(delta, bs) <= 0)
- adj = -0.5;
- }
- }
-apply_adj:
-#ifdef Avoid_Underflow
- if (scale && (y = word0(rv) & Exp_mask)
- <= 2*P*Exp_msk1)
- word0(adj) += (2*P+1)*Exp_msk1 - y;
-#else
-#ifdef Sudden_Underflow
- if ((word0(rv) & Exp_mask) <=
- P*Exp_msk1) {
- word0(rv) += P*Exp_msk1;
- dval(rv) += adj*ulp(dval(rv));
- word0(rv) -= P*Exp_msk1;
- }
- else
-#endif /*Sudden_Underflow*/
-#endif /*Avoid_Underflow*/
- dval(rv) += adj*ulp(dval(rv));
- }
- break;
- }
- adj = ratio(delta, bs);
- if (adj < 1.)
- adj = 1.;
- if (adj <= 0x7ffffffe) {
- /* adj = rounding ? ceil(adj) : floor(adj); */
- y = adj;
- if (y != adj) {
- if (!((rounding>>1) ^ dsign))
- y++;
- adj = y;
- }
- }
-#ifdef Avoid_Underflow
- if (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
- word0(adj) += (2*P+1)*Exp_msk1 - y;
-#else
-#ifdef Sudden_Underflow
- if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
- word0(rv) += P*Exp_msk1;
- adj *= ulp(dval(rv));
- if (dsign)
- dval(rv) += adj;
- else
- dval(rv) -= adj;
- word0(rv) -= P*Exp_msk1;
- goto cont;
- }
-#endif /*Sudden_Underflow*/
-#endif /*Avoid_Underflow*/
- adj *= ulp(dval(rv));
- if (dsign)
- dval(rv) += adj;
- else
- dval(rv) -= adj;
- goto cont;
- }
-#endif /*Honor_FLT_ROUNDS*/
-
- if (i < 0) {
- /* Error is less than half an ulp -- check for
- * special case of mantissa a power of two.
- */
- if (dsign || word1(rv) || word0(rv) & Bndry_mask
-#ifdef IEEE_Arith
-#ifdef Avoid_Underflow
- || (word0(rv) & Exp_mask) <= (2*P+1)*Exp_msk1
-#else
- || (word0(rv) & Exp_mask) <= Exp_msk1
-#endif
-#endif
- ) {
-#ifdef SET_INEXACT
- if (!delta->x[0] && delta->wds <= 1)
- inexact = 0;
-#endif
- break;
- }
- if (!delta->x[0] && delta->wds <= 1) {
- /* exact result */
-#ifdef SET_INEXACT
- inexact = 0;
-#endif
- break;
- }
- delta = lshift(delta,Log2P);
- if (cmp(delta, bs) > 0)
- goto drop_down;
- break;
- }
- if (i == 0) {
- /* exactly half-way between */
- if (dsign) {
- if ((word0(rv) & Bndry_mask1) == Bndry_mask1
- && word1(rv) == (
-#ifdef Avoid_Underflow
- (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
- ? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) :
-#endif
- 0xffffffff)) {
- /*boundary case -- increment exponent*/
- word0(rv) = (word0(rv) & Exp_mask)
- + Exp_msk1
-#ifdef IBM
- | Exp_msk1 >> 4
-#endif
- ;
- word1(rv) = 0;
-#ifdef Avoid_Underflow
- dsign = 0;
-#endif
- break;
- }
- }
- else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {
-drop_down:
- /* boundary case -- decrement exponent */
-#ifdef Sudden_Underflow /*{{*/
- L = word0(rv) & Exp_mask;
-#ifdef IBM
- if (L < Exp_msk1)
-#else
-#ifdef Avoid_Underflow
- if (L <= (scale ? (2*P+1)*Exp_msk1 : Exp_msk1))
-#else
- if (L <= Exp_msk1)
-#endif /*Avoid_Underflow*/
-#endif /*IBM*/
- goto undfl;
- L -= Exp_msk1;
-#else /*Sudden_Underflow}{*/
-#ifdef Avoid_Underflow
- if (scale) {
- L = word0(rv) & Exp_mask;
- if (L <= (2*P+1)*Exp_msk1) {
- if (L > (P+2)*Exp_msk1)
- /* round even ==> */
- /* accept rv */
- break;
- /* rv = smallest denormal */
- goto undfl;
- }
- }
-#endif /*Avoid_Underflow*/
- L = (word0(rv) & Exp_mask) - Exp_msk1;
-#endif /*Sudden_Underflow}}*/
- word0(rv) = L | Bndry_mask1;
- word1(rv) = 0xffffffff;
-#ifdef IBM
- goto cont;
-#else
- break;
-#endif
- }
-#ifndef ROUND_BIASED
- if (!(word1(rv) & LSB))
- break;
-#endif
- if (dsign)
- dval(rv) += ulp(dval(rv));
-#ifndef ROUND_BIASED
- else {
- dval(rv) -= ulp(dval(rv));
-#ifndef Sudden_Underflow
- if (!dval(rv))
- goto undfl;
-#endif
- }
-#ifdef Avoid_Underflow
- dsign = 1 - dsign;
-#endif
-#endif
- break;
- }
- if ((aadj = ratio(delta, bs)) <= 2.) {
- if (dsign)
- aadj = dval(aadj1) = 1.;
- else if (word1(rv) || word0(rv) & Bndry_mask) {
-#ifndef Sudden_Underflow
- if (word1(rv) == Tiny1 && !word0(rv))
- goto undfl;
-#endif
- aadj = 1.;
- dval(aadj1) = -1.;
- }
- else {
- /* special case -- power of FLT_RADIX to be */
- /* rounded down... */
-
- if (aadj < 2./FLT_RADIX)
- aadj = 1./FLT_RADIX;
- else
- aadj *= 0.5;
- dval(aadj1) = -aadj;
- }
- }
- else {
- aadj *= 0.5;
- dval(aadj1) = dsign ? aadj : -aadj;
-#ifdef Check_FLT_ROUNDS
- switch (Rounding) {
- case 2: /* towards +infinity */
- dval(aadj1) -= 0.5;
- break;
- case 0: /* towards 0 */
- case 3: /* towards -infinity */
- dval(aadj1) += 0.5;
- }
-#else
- if (Flt_Rounds == 0)
- dval(aadj1) += 0.5;
-#endif /*Check_FLT_ROUNDS*/
- }
- y = word0(rv) & Exp_mask;
-
- /* Check for overflow */
-
- if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
- dval(rv0) = dval(rv);
- word0(rv) -= P*Exp_msk1;
- adj = dval(aadj1) * ulp(dval(rv));
- dval(rv) += adj;
- if ((word0(rv) & Exp_mask) >=
- Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
- if (word0(rv0) == Big0 && word1(rv0) == Big1)
- goto ovfl;
- word0(rv) = Big0;
- word1(rv) = Big1;
- goto cont;
- }
- else
- word0(rv) += P*Exp_msk1;
- }
- else {
-#ifdef Avoid_Underflow
- if (scale && y <= 2*P*Exp_msk1) {
- if (aadj <= 0x7fffffff) {
- if ((z = (int)aadj) <= 0)
- z = 1;
- aadj = z;
- dval(aadj1) = dsign ? aadj : -aadj;
- }
- word0(aadj1) += (2*P+1)*Exp_msk1 - y;
- }
- adj = dval(aadj1) * ulp(dval(rv));
- dval(rv) += adj;
-#else
-#ifdef Sudden_Underflow
- if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
- dval(rv0) = dval(rv);
- word0(rv) += P*Exp_msk1;
- adj = dval(aadj1) * ulp(dval(rv));
- dval(rv) += adj;
-#ifdef IBM
- if ((word0(rv) & Exp_mask) < P*Exp_msk1)
-#else
- if ((word0(rv) & Exp_mask) <= P*Exp_msk1)
-#endif
- {
- if (word0(rv0) == Tiny0 && word1(rv0) == Tiny1)
- goto undfl;
- word0(rv) = Tiny0;
- word1(rv) = Tiny1;
- goto cont;
- }
- else
- word0(rv) -= P*Exp_msk1;
- }
- else {
- adj = dval(aadj1) * ulp(dval(rv));
- dval(rv) += adj;
- }
-#else /*Sudden_Underflow*/
- /* Compute adj so that the IEEE rounding rules will
- * correctly round rv + adj in some half-way cases.
- * If rv * ulp(rv) is denormalized (i.e.,
- * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
- * trouble from bits lost to denormalization;
- * example: 1.2e-307 .
- */
- if (y <= (P-1)*Exp_msk1 && aadj > 1.) {
- dval(aadj1) = (double)(int)(aadj + 0.5);
- if (!dsign)
- dval(aadj1) = -dval(aadj1);
- }
- adj = dval(aadj1) * ulp(dval(rv));
- dval(rv) += adj;
-#endif /*Sudden_Underflow*/
-#endif /*Avoid_Underflow*/
- }
- z = word0(rv) & Exp_mask;
-#ifndef SET_INEXACT
-#ifdef Avoid_Underflow
- if (!scale)
-#endif
- if (y == z) {
- /* Can we stop now? */
- L = (Long)aadj;
- aadj -= L;
- /* The tolerances below are conservative. */
- if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
- if (aadj < .4999999 || aadj > .5000001)
- break;
- }
- else if (aadj < .4999999/FLT_RADIX)
- break;
- }
-#endif
-cont:
- Bfree(bb);
- Bfree(bd);
- Bfree(bs);
- Bfree(delta);
- }
-#ifdef SET_INEXACT
- if (inexact) {
- if (!oldinexact) {
- word0(rv0) = Exp_1 + (70 << Exp_shift);
- word1(rv0) = 0;
- dval(rv0) += 1.;
- }
- }
- else if (!oldinexact)
- clear_inexact();
-#endif
-#ifdef Avoid_Underflow
- if (scale) {
- word0(rv0) = Exp_1 - 2*P*Exp_msk1;
- word1(rv0) = 0;
- dval(rv) *= dval(rv0);
-#ifndef NO_ERRNO
- /* try to avoid the bug of testing an 8087 register value */
- if (word0(rv) == 0 && word1(rv) == 0)
- errno = ERANGE;
-#endif
- }
-#endif /* Avoid_Underflow */
-#ifdef SET_INEXACT
- if (inexact && !(word0(rv) & Exp_mask)) {
- /* set underflow bit */
- dval(rv0) = 1e-300;
- dval(rv0) *= dval(rv0);
- }
-#endif
-retfree:
- Bfree(bb);
- Bfree(bd);
- Bfree(bs);
- Bfree(bd0);
- Bfree(delta);
-ret:
- if (se)
- *se = (char *)s;
- return sign ? -dval(rv) : dval(rv);
-}
-
-NO_SANITIZE("unsigned-integer-overflow", static int quorem(Bigint *b, Bigint *S));
-static int
-quorem(Bigint *b, Bigint *S)
-{
- int n;
- ULong *bx, *bxe, q, *sx, *sxe;
-#ifdef ULLong
- ULLong borrow, carry, y, ys;
-#else
- ULong borrow, carry, y, ys;
-#ifdef Pack_32
- ULong si, z, zs;
-#endif
-#endif
-
- n = S->wds;
-#ifdef DEBUG
- /*debug*/ if (b->wds > n)
- /*debug*/ Bug("oversize b in quorem");
-#endif
- if (b->wds < n)
- return 0;
- sx = S->x;
- sxe = sx + --n;
- bx = b->x;
- bxe = bx + n;
- q = *bxe / (*sxe + 1); /* ensure q <= true quotient */
-#ifdef DEBUG
- /*debug*/ if (q > 9)
- /*debug*/ Bug("oversized quotient in quorem");
-#endif
- if (q) {
- borrow = 0;
- carry = 0;
- do {
-#ifdef ULLong
- ys = *sx++ * (ULLong)q + carry;
- carry = ys >> 32;
- y = *bx - (ys & FFFFFFFF) - borrow;
- borrow = y >> 32 & (ULong)1;
- *bx++ = (ULong)(y & FFFFFFFF);
-#else
-#ifdef Pack_32
- si = *sx++;
- ys = (si & 0xffff) * q + carry;
- zs = (si >> 16) * q + (ys >> 16);
- carry = zs >> 16;
- y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
- borrow = (y & 0x10000) >> 16;
- z = (*bx >> 16) - (zs & 0xffff) - borrow;
- borrow = (z & 0x10000) >> 16;
- Storeinc(bx, z, y);
-#else
- ys = *sx++ * q + carry;
- carry = ys >> 16;
- y = *bx - (ys & 0xffff) - borrow;
- borrow = (y & 0x10000) >> 16;
- *bx++ = y & 0xffff;
-#endif
-#endif
- } while (sx <= sxe);
- if (!*bxe) {
- bx = b->x;
- while (--bxe > bx && !*bxe)
- --n;
- b->wds = n;
- }
- }
- if (cmp(b, S) >= 0) {
- q++;
- borrow = 0;
- carry = 0;
- bx = b->x;
- sx = S->x;
- do {
-#ifdef ULLong
- ys = *sx++ + carry;
- carry = ys >> 32;
- y = *bx - (ys & FFFFFFFF) - borrow;
- borrow = y >> 32 & (ULong)1;
- *bx++ = (ULong)(y & FFFFFFFF);
-#else
-#ifdef Pack_32
- si = *sx++;
- ys = (si & 0xffff) + carry;
- zs = (si >> 16) + (ys >> 16);
- carry = zs >> 16;
- y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
- borrow = (y & 0x10000) >> 16;
- z = (*bx >> 16) - (zs & 0xffff) - borrow;
- borrow = (z & 0x10000) >> 16;
- Storeinc(bx, z, y);
-#else
- ys = *sx++ + carry;
- carry = ys >> 16;
- y = *bx - (ys & 0xffff) - borrow;
- borrow = (y & 0x10000) >> 16;
- *bx++ = y & 0xffff;
-#endif
-#endif
- } while (sx <= sxe);
- bx = b->x;
- bxe = bx + n;
- if (!*bxe) {
- while (--bxe > bx && !*bxe)
- --n;
- b->wds = n;
- }
- }
- return q;
-}
-
-#ifndef MULTIPLE_THREADS
-static char *dtoa_result;
-#endif
-
-#ifndef MULTIPLE_THREADS
-static char *
-rv_alloc(int i)
-{
- return dtoa_result = MALLOC(i);
-}
-#else
-#define rv_alloc(i) MALLOC(i)
-#endif
-
-static char *
-nrv_alloc(const char *s, char **rve, size_t n)
-{
- char *rv, *t;
-
- t = rv = rv_alloc(n);
- while ((*t = *s++) != 0) t++;
- if (rve)
- *rve = t;
- return rv;
-}
-
-#define rv_strdup(s, rve) nrv_alloc((s), (rve), strlen(s)+1)
-
-#ifndef MULTIPLE_THREADS
-/* freedtoa(s) must be used to free values s returned by dtoa
- * when MULTIPLE_THREADS is #defined. It should be used in all cases,
- * but for consistency with earlier versions of dtoa, it is optional
- * when MULTIPLE_THREADS is not defined.
- */
-
-static void
-freedtoa(char *s)
-{
- FREE(s);
-}
-#endif
-
-static const char INFSTR[] = "Infinity";
-static const char NANSTR[] = "NaN";
-static const char ZEROSTR[] = "0";
-
-/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
- *
- * Inspired by "How to Print Floating-Point Numbers Accurately" by
- * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126].
- *
- * Modifications:
- * 1. Rather than iterating, we use a simple numeric overestimate
- * to determine k = floor(log10(d)). We scale relevant
- * quantities using O(log2(k)) rather than O(k) multiplications.
- * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
- * try to generate digits strictly left to right. Instead, we
- * compute with fewer bits and propagate the carry if necessary
- * when rounding the final digit up. This is often faster.
- * 3. Under the assumption that input will be rounded nearest,
- * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
- * That is, we allow equality in stopping tests when the
- * round-nearest rule will give the same floating-point value
- * as would satisfaction of the stopping test with strict
- * inequality.
- * 4. We remove common factors of powers of 2 from relevant
- * quantities.
- * 5. When converting floating-point integers less than 1e16,
- * we use floating-point arithmetic rather than resorting
- * to multiple-precision integers.
- * 6. When asked to produce fewer than 15 digits, we first try
- * to get by with floating-point arithmetic; we resort to
- * multiple-precision integer arithmetic only if we cannot
- * guarantee that the floating-point calculation has given
- * the correctly rounded result. For k requested digits and
- * "uniformly" distributed input, the probability is
- * something like 10^(k-15) that we must resort to the Long
- * calculation.
- */
-
-char *
-dtoa(double d_, int mode, int ndigits, int *decpt, int *sign, char **rve)
-{
- /* Arguments ndigits, decpt, sign are similar to those
- of ecvt and fcvt; trailing zeros are suppressed from
- the returned string. If not null, *rve is set to point
- to the end of the return value. If d is +-Infinity or NaN,
- then *decpt is set to 9999.
-
- mode:
- 0 ==> shortest string that yields d when read in
- and rounded to nearest.
- 1 ==> like 0, but with Steele & White stopping rule;
- e.g. with IEEE P754 arithmetic , mode 0 gives
- 1e23 whereas mode 1 gives 9.999999999999999e22.
- 2 ==> max(1,ndigits) significant digits. This gives a
- return value similar to that of ecvt, except
- that trailing zeros are suppressed.
- 3 ==> through ndigits past the decimal point. This
- gives a return value similar to that from fcvt,
- except that trailing zeros are suppressed, and
- ndigits can be negative.
- 4,5 ==> similar to 2 and 3, respectively, but (in
- round-nearest mode) with the tests of mode 0 to
- possibly return a shorter string that rounds to d.
- With IEEE arithmetic and compilation with
- -DHonor_FLT_ROUNDS, modes 4 and 5 behave the same
- as modes 2 and 3 when FLT_ROUNDS != 1.
- 6-9 ==> Debugging modes similar to mode - 4: don't try
- fast floating-point estimate (if applicable).
-
- Values of mode other than 0-9 are treated as mode 0.
-
- Sufficient space is allocated to the return value
- to hold the suppressed trailing zeros.
- */
-
- int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1,
- j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
- spec_case, try_quick, half = 0;
- Long L;
-#ifndef Sudden_Underflow
- int denorm;
- ULong x;
-#endif
- Bigint *b, *b1, *delta, *mlo = 0, *mhi = 0, *S;
- double ds;
- double_u d, d2, eps;
- char *s, *s0;
-#ifdef Honor_FLT_ROUNDS
- int rounding;
-#endif
-#ifdef SET_INEXACT
- int inexact, oldinexact;
-#endif
-
- dval(d) = d_;
-
-#ifndef MULTIPLE_THREADS
- if (dtoa_result) {
- freedtoa(dtoa_result);
- dtoa_result = 0;
- }
-#endif
-
- if (word0(d) & Sign_bit) {
- /* set sign for everything, including 0's and NaNs */
- *sign = 1;
- word0(d) &= ~Sign_bit; /* clear sign bit */
- }
- else
- *sign = 0;
-
-#if defined(IEEE_Arith) + defined(VAX)
-#ifdef IEEE_Arith
- if ((word0(d) & Exp_mask) == Exp_mask)
-#else
- if (word0(d) == 0x8000)
-#endif
- {
- /* Infinity or NaN */
- *decpt = 9999;
-#ifdef IEEE_Arith
- if (!word1(d) && !(word0(d) & 0xfffff))
- return rv_strdup(INFSTR, rve);
-#endif
- return rv_strdup(NANSTR, rve);
- }
-#endif
-#ifdef IBM
- dval(d) += 0; /* normalize */
-#endif
- if (!dval(d)) {
- *decpt = 1;
- return rv_strdup(ZEROSTR, rve);
- }
-
-#ifdef SET_INEXACT
- try_quick = oldinexact = get_inexact();
- inexact = 1;
-#endif
-#ifdef Honor_FLT_ROUNDS
- if ((rounding = Flt_Rounds) >= 2) {
- if (*sign)
- rounding = rounding == 2 ? 0 : 2;
- else
- if (rounding != 2)
- rounding = 0;
- }
-#endif
-
- b = d2b(dval(d), &be, &bbits);
-#ifdef Sudden_Underflow
- i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
-#else
- if ((i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) != 0) {
-#endif
- dval(d2) = dval(d);
- word0(d2) &= Frac_mask1;
- word0(d2) |= Exp_11;
-#ifdef IBM
- if (j = 11 - hi0bits(word0(d2) & Frac_mask))
- dval(d2) /= 1 << j;
-#endif
-
- /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
- * log10(x) = log(x) / log(10)
- * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
- * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
- *
- * This suggests computing an approximation k to log10(d) by
- *
- * k = (i - Bias)*0.301029995663981
- * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
- *
- * We want k to be too large rather than too small.
- * The error in the first-order Taylor series approximation
- * is in our favor, so we just round up the constant enough
- * to compensate for any error in the multiplication of
- * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
- * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
- * adding 1e-13 to the constant term more than suffices.
- * Hence we adjust the constant term to 0.1760912590558.
- * (We could get a more accurate k by invoking log10,
- * but this is probably not worthwhile.)
- */
-
- i -= Bias;
-#ifdef IBM
- i <<= 2;
- i += j;
-#endif
-#ifndef Sudden_Underflow
- denorm = 0;
- }
- else {
- /* d is denormalized */
-
- i = bbits + be + (Bias + (P-1) - 1);
- x = i > 32 ? word0(d) << (64 - i) | word1(d) >> (i - 32)
- : word1(d) << (32 - i);
- dval(d2) = x;
- word0(d2) -= 31*Exp_msk1; /* adjust exponent */
- i -= (Bias + (P-1) - 1) + 1;
- denorm = 1;
- }
-#endif
- ds = (dval(d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
- k = (int)ds;
- if (ds < 0. && ds != k)
- k--; /* want k = floor(ds) */
- k_check = 1;
- if (k >= 0 && k <= Ten_pmax) {
- if (dval(d) < tens[k])
- k--;
- k_check = 0;
- }
- j = bbits - i - 1;
- if (j >= 0) {
- b2 = 0;
- s2 = j;
- }
- else {
- b2 = -j;
- s2 = 0;
- }
- if (k >= 0) {
- b5 = 0;
- s5 = k;
- s2 += k;
- }
- else {
- b2 -= k;
- b5 = -k;
- s5 = 0;
- }
- if (mode < 0 || mode > 9)
- mode = 0;
-
-#ifndef SET_INEXACT
-#ifdef Check_FLT_ROUNDS
- try_quick = Rounding == 1;
-#else
- try_quick = 1;
-#endif
-#endif /*SET_INEXACT*/
-
- if (mode > 5) {
- mode -= 4;
- try_quick = 0;
- }
- leftright = 1;
- ilim = ilim1 = -1;
- switch (mode) {
- case 0:
- case 1:
- i = 18;
- ndigits = 0;
- break;
- case 2:
- leftright = 0;
- /* no break */
- case 4:
- if (ndigits <= 0)
- ndigits = 1;
- ilim = ilim1 = i = ndigits;
- break;
- case 3:
- leftright = 0;
- /* no break */
- case 5:
- i = ndigits + k + 1;
- ilim = i;
- ilim1 = i - 1;
- if (i <= 0)
- i = 1;
- }
- s = s0 = rv_alloc(i+1);
-
-#ifdef Honor_FLT_ROUNDS
- if (mode > 1 && rounding != 1)
- leftright = 0;
-#endif
-
- if (ilim >= 0 && ilim <= Quick_max && try_quick) {
-
- /* Try to get by with floating-point arithmetic. */
-
- i = 0;
- dval(d2) = dval(d);
- k0 = k;
- ilim0 = ilim;
- ieps = 2; /* conservative */
- if (k > 0) {
- ds = tens[k&0xf];
- j = k >> 4;
- if (j & Bletch) {
- /* prevent overflows */
- j &= Bletch - 1;
- dval(d) /= bigtens[n_bigtens-1];
- ieps++;
- }
- for (; j; j >>= 1, i++)
- if (j & 1) {
- ieps++;
- ds *= bigtens[i];
- }
- dval(d) /= ds;
- }
- else if ((j1 = -k) != 0) {
- dval(d) *= tens[j1 & 0xf];
- for (j = j1 >> 4; j; j >>= 1, i++)
- if (j & 1) {
- ieps++;
- dval(d) *= bigtens[i];
- }
- }
- if (k_check && dval(d) < 1. && ilim > 0) {
- if (ilim1 <= 0)
- goto fast_failed;
- ilim = ilim1;
- k--;
- dval(d) *= 10.;
- ieps++;
- }
- dval(eps) = ieps*dval(d) + 7.;
- word0(eps) -= (P-1)*Exp_msk1;
- if (ilim == 0) {
- S = mhi = 0;
- dval(d) -= 5.;
- if (dval(d) > dval(eps))
- goto one_digit;
- if (dval(d) < -dval(eps))
- goto no_digits;
- goto fast_failed;
- }
-#ifndef No_leftright
- if (leftright) {
- /* Use Steele & White method of only
- * generating digits needed.
- */
- dval(eps) = 0.5/tens[ilim-1] - dval(eps);
- for (i = 0;;) {
- L = (int)dval(d);
- dval(d) -= L;
- *s++ = '0' + (int)L;
- if (dval(d) < dval(eps))
- goto ret1;
- if (1. - dval(d) < dval(eps))
- goto bump_up;
- if (++i >= ilim)
- break;
- dval(eps) *= 10.;
- dval(d) *= 10.;
- }
- }
- else {
-#endif
- /* Generate ilim digits, then fix them up. */
- dval(eps) *= tens[ilim-1];
- for (i = 1;; i++, dval(d) *= 10.) {
- L = (Long)(dval(d));
- if (!(dval(d) -= L))
- ilim = i;
- *s++ = '0' + (int)L;
- if (i == ilim) {
- if (dval(d) > 0.5 + dval(eps))
- goto bump_up;
- else if (dval(d) < 0.5 - dval(eps)) {
- while (*--s == '0') ;
- s++;
- goto ret1;
- }
- half = 1;
- if ((*(s-1) - '0') & 1) {
- goto bump_up;
- }
- break;
- }
- }
-#ifndef No_leftright
- }
-#endif
-fast_failed:
- s = s0;
- dval(d) = dval(d2);
- k = k0;
- ilim = ilim0;
- }
-
- /* Do we have a "small" integer? */
-
- if (be >= 0 && k <= Int_max) {
- /* Yes. */
- ds = tens[k];
- if (ndigits < 0 && ilim <= 0) {
- S = mhi = 0;
- if (ilim < 0 || dval(d) <= 5*ds)
- goto no_digits;
- goto one_digit;
- }
- for (i = 1;; i++, dval(d) *= 10.) {
- L = (Long)(dval(d) / ds);
- dval(d) -= L*ds;
-#ifdef Check_FLT_ROUNDS
- /* If FLT_ROUNDS == 2, L will usually be high by 1 */
- if (dval(d) < 0) {
- L--;
- dval(d) += ds;
- }
-#endif
- *s++ = '0' + (int)L;
- if (!dval(d)) {
-#ifdef SET_INEXACT
- inexact = 0;
-#endif
- break;
- }
- if (i == ilim) {
-#ifdef Honor_FLT_ROUNDS
- if (mode > 1)
- switch (rounding) {
- case 0: goto ret1;
- case 2: goto bump_up;
- }
-#endif
- dval(d) += dval(d);
- if (dval(d) > ds || (dval(d) == ds && (L & 1))) {
-bump_up:
- while (*--s == '9')
- if (s == s0) {
- k++;
- *s = '0';
- break;
- }
- ++*s++;
- }
- break;
- }
- }
- goto ret1;
- }
-
- m2 = b2;
- m5 = b5;
- if (leftright) {
- i =
-#ifndef Sudden_Underflow
- denorm ? be + (Bias + (P-1) - 1 + 1) :
-#endif
-#ifdef IBM
- 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
-#else
- 1 + P - bbits;
-#endif
- b2 += i;
- s2 += i;
- mhi = i2b(1);
- }
- if (m2 > 0 && s2 > 0) {
- i = m2 < s2 ? m2 : s2;
- b2 -= i;
- m2 -= i;
- s2 -= i;
- }
- if (b5 > 0) {
- if (leftright) {
- if (m5 > 0) {
- mhi = pow5mult(mhi, m5);
- b1 = mult(mhi, b);
- Bfree(b);
- b = b1;
- }
- if ((j = b5 - m5) != 0)
- b = pow5mult(b, j);
- }
- else
- b = pow5mult(b, b5);
- }
- S = i2b(1);
- if (s5 > 0)
- S = pow5mult(S, s5);
-
- /* Check for special case that d is a normalized power of 2. */
-
- spec_case = 0;
- if ((mode < 2 || leftright)
-#ifdef Honor_FLT_ROUNDS
- && rounding == 1
-#endif
- ) {
- if (!word1(d) && !(word0(d) & Bndry_mask)
-#ifndef Sudden_Underflow
- && word0(d) & (Exp_mask & ~Exp_msk1)
-#endif
- ) {
- /* The special case */
- b2 += Log2P;
- s2 += Log2P;
- spec_case = 1;
- }
- }
-
- /* Arrange for convenient computation of quotients:
- * shift left if necessary so divisor has 4 leading 0 bits.
- *
- * Perhaps we should just compute leading 28 bits of S once
- * and for all and pass them and a shift to quorem, so it
- * can do shifts and ors to compute the numerator for q.
- */
-#ifdef Pack_32
- if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f) != 0)
- i = 32 - i;
-#else
- if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf) != 0)
- i = 16 - i;
-#endif
- if (i > 4) {
- i -= 4;
- b2 += i;
- m2 += i;
- s2 += i;
- }
- else if (i < 4) {
- i += 28;
- b2 += i;
- m2 += i;
- s2 += i;
- }
- if (b2 > 0)
- b = lshift(b, b2);
- if (s2 > 0)
- S = lshift(S, s2);
- if (k_check) {
- if (cmp(b,S) < 0) {
- k--;
- b = multadd(b, 10, 0); /* we botched the k estimate */
- if (leftright)
- mhi = multadd(mhi, 10, 0);
- ilim = ilim1;
- }
- }
- if (ilim <= 0 && (mode == 3 || mode == 5)) {
- if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
- /* no digits, fcvt style */
-no_digits:
- k = -1 - ndigits;
- goto ret;
- }
-one_digit:
- *s++ = '1';
- k++;
- goto ret;
- }
- if (leftright) {
- if (m2 > 0)
- mhi = lshift(mhi, m2);
-
- /* Compute mlo -- check for special case
- * that d is a normalized power of 2.
- */
-
- mlo = mhi;
- if (spec_case) {
- mhi = Balloc(mhi->k);
- Bcopy(mhi, mlo);
- mhi = lshift(mhi, Log2P);
- }
-
- for (i = 1;;i++) {
- dig = quorem(b,S) + '0';
- /* Do we yet have the shortest decimal string
- * that will round to d?
- */
- j = cmp(b, mlo);
- delta = diff(S, mhi);
- j1 = delta->sign ? 1 : cmp(b, delta);
- Bfree(delta);
-#ifndef ROUND_BIASED
- if (j1 == 0 && mode != 1 && !(word1(d) & 1)
-#ifdef Honor_FLT_ROUNDS
- && rounding >= 1
-#endif
- ) {
- if (dig == '9')
- goto round_9_up;
- if (j > 0)
- dig++;
-#ifdef SET_INEXACT
- else if (!b->x[0] && b->wds <= 1)
- inexact = 0;
-#endif
- *s++ = dig;
- goto ret;
- }
-#endif
- if (j < 0 || (j == 0 && mode != 1
-#ifndef ROUND_BIASED
- && !(word1(d) & 1)
-#endif
- )) {
- if (!b->x[0] && b->wds <= 1) {
-#ifdef SET_INEXACT
- inexact = 0;
-#endif
- goto accept_dig;
- }
-#ifdef Honor_FLT_ROUNDS
- if (mode > 1)
- switch (rounding) {
- case 0: goto accept_dig;
- case 2: goto keep_dig;
- }
-#endif /*Honor_FLT_ROUNDS*/
- if (j1 > 0) {
- b = lshift(b, 1);
- j1 = cmp(b, S);
- if ((j1 > 0 || (j1 == 0 && (dig & 1))) && dig++ == '9')
- goto round_9_up;
- }
-accept_dig:
- *s++ = dig;
- goto ret;
- }
- if (j1 > 0) {
-#ifdef Honor_FLT_ROUNDS
- if (!rounding)
- goto accept_dig;
-#endif
- if (dig == '9') { /* possible if i == 1 */
-round_9_up:
- *s++ = '9';
- goto roundoff;
- }
- *s++ = dig + 1;
- goto ret;
- }
-#ifdef Honor_FLT_ROUNDS
-keep_dig:
-#endif
- *s++ = dig;
- if (i == ilim)
- break;
- b = multadd(b, 10, 0);
- if (mlo == mhi)
- mlo = mhi = multadd(mhi, 10, 0);
- else {
- mlo = multadd(mlo, 10, 0);
- mhi = multadd(mhi, 10, 0);
- }
- }
- }
- else
- for (i = 1;; i++) {
- *s++ = dig = quorem(b,S) + '0';
- if (!b->x[0] && b->wds <= 1) {
-#ifdef SET_INEXACT
- inexact = 0;
-#endif
- goto ret;
- }
- if (i >= ilim)
- break;
- b = multadd(b, 10, 0);
- }
-
- /* Round off last digit */
-
-#ifdef Honor_FLT_ROUNDS
- switch (rounding) {
- case 0: goto trimzeros;
- case 2: goto roundoff;
- }
-#endif
- b = lshift(b, 1);
- j = cmp(b, S);
- if (j > 0 || (j == 0 && (dig & 1))) {
- roundoff:
- while (*--s == '9')
- if (s == s0) {
- k++;
- *s++ = '1';
- goto ret;
- }
- if (!half || (*s - '0') & 1)
- ++*s;
- }
- else {
- while (*--s == '0') ;
- }
- s++;
-ret:
- Bfree(S);
- if (mhi) {
- if (mlo && mlo != mhi)
- Bfree(mlo);
- Bfree(mhi);
- }
-ret1:
-#ifdef SET_INEXACT
- if (inexact) {
- if (!oldinexact) {
- word0(d) = Exp_1 + (70 << Exp_shift);
- word1(d) = 0;
- dval(d) += 1.;
- }
- }
- else if (!oldinexact)
- clear_inexact();
-#endif
- Bfree(b);
- *s = 0;
- *decpt = k + 1;
- if (rve)
- *rve = s;
- return s0;
-}
-
-/*-
- * Copyright (c) 2004-2008 David Schultz <das@FreeBSD.ORG>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#define DBL_MANH_SIZE 20
-#define DBL_MANL_SIZE 32
-#define DBL_ADJ (DBL_MAX_EXP - 2)
-#define SIGFIGS ((DBL_MANT_DIG + 3) / 4 + 1)
-#define dexp_get(u) ((int)(word0(u) >> Exp_shift) & ~Exp_msk1)
-#define dexp_set(u,v) (word0(u) = (((int)(word0(u)) & ~Exp_mask) | ((v) << Exp_shift)))
-#define dmanh_get(u) ((uint32_t)(word0(u) & Frac_mask))
-#define dmanl_get(u) ((uint32_t)word1(u))
-
-
-/*
- * This procedure converts a double-precision number in IEEE format
- * into a string of hexadecimal digits and an exponent of 2. Its
- * behavior is bug-for-bug compatible with dtoa() in mode 2, with the
- * following exceptions:
- *
- * - An ndigits < 0 causes it to use as many digits as necessary to
- * represent the number exactly.
- * - The additional xdigs argument should point to either the string
- * "0123456789ABCDEF" or the string "0123456789abcdef", depending on
- * which case is desired.
- * - This routine does not repeat dtoa's mistake of setting decpt
- * to 9999 in the case of an infinity or NaN. INT_MAX is used
- * for this purpose instead.
- *
- * Note that the C99 standard does not specify what the leading digit
- * should be for non-zero numbers. For instance, 0x1.3p3 is the same
- * as 0x2.6p2 is the same as 0x4.cp3. This implementation always makes
- * the leading digit a 1. This ensures that the exponent printed is the
- * actual base-2 exponent, i.e., ilogb(d).
- *
- * Inputs: d, xdigs, ndigits
- * Outputs: decpt, sign, rve
- */
-char *
-hdtoa(double d, const char *xdigs, int ndigits, int *decpt, int *sign, char **rve)
-{
- U u;
- char *s, *s0;
- int bufsize;
- uint32_t manh, manl;
-
- u.d = d;
- if (word0(u) & Sign_bit) {
- /* set sign for everything, including 0's and NaNs */
- *sign = 1;
- word0(u) &= ~Sign_bit; /* clear sign bit */
- }
- else
- *sign = 0;
-
- if (isinf(d)) { /* FP_INFINITE */
- *decpt = INT_MAX;
- return rv_strdup(INFSTR, rve);
- }
- else if (isnan(d)) { /* FP_NAN */
- *decpt = INT_MAX;
- return rv_strdup(NANSTR, rve);
- }
- else if (d == 0.0) { /* FP_ZERO */
- *decpt = 1;
- return rv_strdup(ZEROSTR, rve);
- }
- else if (dexp_get(u)) { /* FP_NORMAL */
- *decpt = dexp_get(u) - DBL_ADJ;
- }
- else { /* FP_SUBNORMAL */
- u.d *= 5.363123171977039e+154 /* 0x1p514 */;
- *decpt = dexp_get(u) - (514 + DBL_ADJ);
- }
-
- if (ndigits == 0) /* dtoa() compatibility */
- ndigits = 1;
-
- /*
- * If ndigits < 0, we are expected to auto-size, so we allocate
- * enough space for all the digits.
- */
- bufsize = (ndigits > 0) ? ndigits : SIGFIGS;
- s0 = rv_alloc(bufsize+1);
-
- /* Round to the desired number of digits. */
- if (SIGFIGS > ndigits && ndigits > 0) {
- float redux = 1.0f;
- int offset = 4 * ndigits + DBL_MAX_EXP - 4 - DBL_MANT_DIG;
- dexp_set(u, offset);
- u.d += redux;
- u.d -= redux;
- *decpt += dexp_get(u) - offset;
- }
-
- manh = dmanh_get(u);
- manl = dmanl_get(u);
- *s0 = '1';
- for (s = s0 + 1; s < s0 + bufsize; s++) {
- *s = xdigs[(manh >> (DBL_MANH_SIZE - 4)) & 0xf];
- manh = (manh << 4) | (manl >> (DBL_MANL_SIZE - 4));
- manl <<= 4;
- }
-
- /* If ndigits < 0, we are expected to auto-size the precision. */
- if (ndigits < 0) {
- for (ndigits = SIGFIGS; s0[ndigits - 1] == '0'; ndigits--)
- ;
- }
-
- s = s0 + ndigits;
- *s = '\0';
- if (rve != NULL)
- *rve = s;
- return (s0);
-}
-
-#ifdef __cplusplus
-#if 0
-{ /* satisfy cc-mode */
-#endif
-}
-#endif
diff --git a/ext/bigdecimal/sample/linear.rb b/ext/bigdecimal/sample/linear.rb
deleted file mode 100644
index 516c2473be..0000000000
--- a/ext/bigdecimal/sample/linear.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/usr/local/bin/ruby
-# frozen_string_literal: false
-
-#
-# linear.rb
-#
-# Solves linear equation system(A*x = b) by LU decomposition method.
-# where A is a coefficient matrix,x is an answer vector,b is a constant vector.
-#
-# USAGE:
-# ruby linear.rb [input file solved]
-#
-
-# :stopdoc:
-require "bigdecimal"
-require "bigdecimal/ludcmp"
-
-#
-# NOTE:
-# Change following BigDecimal.limit() if needed.
-BigDecimal.limit(100)
-#
-
-include LUSolve
-def rd_order(na)
- printf("Number of equations ?") if(na <= 0)
- n = ARGF.gets().to_i
-end
-
-na = ARGV.size
-zero = BigDecimal("0.0")
-one = BigDecimal("1.0")
-
-while (n=rd_order(na))>0
- a = []
- as= []
- b = []
- if na <= 0
- # Read data from console.
- printf("\nEnter coefficient matrix element A[i,j]\n")
- for i in 0...n do
- for j in 0...n do
- printf("A[%d,%d]? ",i,j); s = ARGF.gets
- a << BigDecimal(s)
- as << BigDecimal(s)
- end
- printf("Contatant vector element b[%d] ? ",i)
- b << BigDecimal(ARGF.gets)
- end
- else
- # Read data from specified file.
- printf("Coefficient matrix and constant vector.\n")
- for i in 0...n do
- s = ARGF.gets
- printf("%d) %s",i,s)
- s = s.split
- for j in 0...n do
- a << BigDecimal(s[j])
- as << BigDecimal(s[j])
- end
- b << BigDecimal(s[n])
- end
- end
- x = lusolve(a,b,ludecomp(a,n,zero,one),zero)
- printf("Answer(x[i] & (A*x-b)[i]) follows\n")
- for i in 0...n do
- printf("x[%d]=%s ",i,x[i].to_s)
- s = zero
- for j in 0...n do
- s = s + as[i*n+j]*x[j]
- end
- printf(" & %s\n",(s-b[i]).to_s)
- end
-end
diff --git a/ext/bigdecimal/sample/nlsolve.rb b/ext/bigdecimal/sample/nlsolve.rb
deleted file mode 100644
index c2227dac73..0000000000
--- a/ext/bigdecimal/sample/nlsolve.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/local/bin/ruby
-# frozen_string_literal: false
-
-#
-# nlsolve.rb
-# An example for solving nonlinear algebraic equation system.
-#
-
-require "bigdecimal"
-require "bigdecimal/newton"
-include Newton
-
-class Function # :nodoc: all
- def initialize()
- @zero = BigDecimal("0.0")
- @one = BigDecimal("1.0")
- @two = BigDecimal("2.0")
- @ten = BigDecimal("10.0")
- @eps = BigDecimal("1.0e-16")
- end
- def zero;@zero;end
- def one ;@one ;end
- def two ;@two ;end
- def ten ;@ten ;end
- def eps ;@eps ;end
- def values(x) # <= defines functions solved
- f = []
- f1 = x[0]*x[0] + x[1]*x[1] - @two # f1 = x**2 + y**2 - 2 => 0
- f2 = x[0] - x[1] # f2 = x - y => 0
- f <<= f1
- f <<= f2
- f
- end
-end
-
-f = BigDecimal.limit(100)
-f = Function.new
-x = [f.zero,f.zero] # Initial values
-n = nlsolve(f,x)
-p x
diff --git a/ext/bigdecimal/sample/pi.rb b/ext/bigdecimal/sample/pi.rb
deleted file mode 100644
index ea9663896c..0000000000
--- a/ext/bigdecimal/sample/pi.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/local/bin/ruby
-# frozen_string_literal: false
-
-#
-# pi.rb
-#
-# Calculates 3.1415.... (the number of times that a circle's diameter
-# will fit around the circle) using J. Machin's formula.
-#
-
-require "bigdecimal"
-require "bigdecimal/math.rb"
-
-include BigMath
-
-if ARGV.size == 1
- print "PI("+ARGV[0]+"):\n"
- p PI(ARGV[0].to_i)
-else
- print "TRY: ruby pi.rb 1000 \n"
-end
diff --git a/ext/bigdecimal/static_assert.h b/ext/bigdecimal/static_assert.h
deleted file mode 100644
index 9295729bf6..0000000000
--- a/ext/bigdecimal/static_assert.h
+++ /dev/null
@@ -1,54 +0,0 @@
-#ifndef BIGDECIMAL_STATIC_ASSERT_H
-#define BIGDECIMAL_STATIC_ASSERT_H
-
-#include "feature.h"
-
-#ifdef HAVE_RUBY_INTERNAL_STATIC_ASSERT_H
-# include <ruby/internal/static_assert.h>
-#endif
-
-#ifdef RBIMPL_STATIC_ASSERT
-# define STATIC_ASSERT RBIMPL_STATIC_ASSERT
-#endif
-
-#ifndef STATIC_ASSERT
-# /* The following section is copied from CRuby's static_assert.h */
-
-# if defined(__cplusplus) && defined(__cpp_static_assert)
-# /* https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations */
-# define BIGDECIMAL_STATIC_ASSERT0 static_assert
-
-# elif defined(__cplusplus) && defined(_MSC_VER) && _MSC_VER >= 1600
-# define BIGDECIMAL_STATIC_ASSERT0 static_assert
-
-# elif defined(__INTEL_CXX11_MODE__)
-# define BIGDECIMAL_STATIC_ASSERT0 static_assert
-
-# elif defined(__cplusplus) && __cplusplus >= 201103L
-# define BIGDECIMAL_STATIC_ASSERT0 static_assert
-
-# elif defined(__cplusplus) && __has_extension(cxx_static_assert)
-# define BIGDECIMAL_STATIC_ASSERT0 __extension__ static_assert
-
-# elif defined(__STDC_VERSION__) && __has_extension(c_static_assert)
-# define BIGDECIMAL_STATIC_ASSERT0 __extension__ _Static_assert
-
-# elif defined(__STDC_VERSION__) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
-# define BIGDECIMAL_STATIC_ASSERT0 __extension__ _Static_assert
-#endif
-
-# if defined(__DOXYGEN__)
-# define STATIC_ASSERT static_assert
-
-# elif defined(BIGDECIMAL_STATIC_ASSERT0)
-# define STATIC_ASSERT(name, expr) \
- BIGDECIMAL_STATIC_ASSERT0(expr, #name ": " #expr)
-
-# else
-# define STATIC_ASSERT(name, expr) \
- typedef int static_assert_ ## name ## _check[1 - 2 * !(expr)]
-# endif
-#endif /* STATIC_ASSERT */
-
-
-#endif /* BIGDECIMAL_STATIC_ASSERT_H */
diff --git a/ext/cgi/escape/depend b/ext/cgi/escape/depend
index 37304a24f4..746b47246a 100644
--- a/ext/cgi/escape/depend
+++ b/ext/cgi/escape/depend
@@ -157,6 +157,7 @@ escape.o: $(hdrdir)/ruby/internal/special_consts.h
escape.o: $(hdrdir)/ruby/internal/static_assert.h
escape.o: $(hdrdir)/ruby/internal/stdalign.h
escape.o: $(hdrdir)/ruby/internal/stdbool.h
+escape.o: $(hdrdir)/ruby/internal/stdckdint.h
escape.o: $(hdrdir)/ruby/internal/symbol.h
escape.o: $(hdrdir)/ruby/internal/value.h
escape.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/cgi/escape/escape.c b/ext/cgi/escape/escape.c
index 17a134aa1a..495ad83aa3 100644
--- a/ext/cgi/escape/escape.c
+++ b/ext/cgi/escape/escape.c
@@ -83,7 +83,7 @@ optimized_unescape_html(VALUE str)
unsigned long charlimit = (strcasecmp(rb_enc_name(enc), "UTF-8") == 0 ? UNICODE_MAX :
strcasecmp(rb_enc_name(enc), "ISO-8859-1") == 0 ? 256 :
128);
- long i, len, beg = 0;
+ long i, j, len, beg = 0;
size_t clen, plen;
int overflow;
const char *cstr;
@@ -100,6 +100,7 @@ optimized_unescape_html(VALUE str)
plen = i - beg;
if (++i >= len) break;
c = (unsigned char)cstr[i];
+ j = i;
#define MATCH(s) (len - i >= (int)rb_strlen_lit(s) && \
memcmp(&cstr[i], s, rb_strlen_lit(s)) == 0 && \
(i += rb_strlen_lit(s) - 1, 1))
@@ -112,28 +113,40 @@ optimized_unescape_html(VALUE str)
else if (MATCH("mp;")) {
c = '&';
}
- else continue;
+ else {
+ i = j;
+ continue;
+ }
break;
case 'q':
++i;
if (MATCH("uot;")) {
c = '"';
}
- else continue;
+ else {
+ i = j;
+ continue;
+ }
break;
case 'g':
++i;
if (MATCH("t;")) {
c = '>';
}
- else continue;
+ else {
+ i = j;
+ continue;
+ }
break;
case 'l':
++i;
if (MATCH("t;")) {
c = '<';
}
- else continue;
+ else {
+ i = j;
+ continue;
+ }
break;
case '#':
if (len - ++i >= 2 && ISDIGIT(cstr[i])) {
@@ -142,9 +155,15 @@ optimized_unescape_html(VALUE str)
else if ((cstr[i] == 'x' || cstr[i] == 'X') && len - ++i >= 2 && ISXDIGIT(cstr[i])) {
cc = ruby_scan_digits(&cstr[i], len-i, 16, &clen, &overflow);
}
- else continue;
+ else {
+ i = j;
+ continue;
+ }
i += clen;
- if (overflow || cc >= charlimit || cstr[i] != ';') continue;
+ if (overflow || cc >= charlimit || cstr[i] != ';') {
+ i = j;
+ continue;
+ }
if (!dest) {
dest = rb_str_buf_new(len);
}
diff --git a/ext/continuation/depend b/ext/continuation/depend
index f0333d7fe6..b40e52e29b 100644
--- a/ext/continuation/depend
+++ b/ext/continuation/depend
@@ -146,6 +146,7 @@ continuation.o: $(hdrdir)/ruby/internal/special_consts.h
continuation.o: $(hdrdir)/ruby/internal/static_assert.h
continuation.o: $(hdrdir)/ruby/internal/stdalign.h
continuation.o: $(hdrdir)/ruby/internal/stdbool.h
+continuation.o: $(hdrdir)/ruby/internal/stdckdint.h
continuation.o: $(hdrdir)/ruby/internal/symbol.h
continuation.o: $(hdrdir)/ruby/internal/value.h
continuation.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/coverage/coverage.c b/ext/coverage/coverage.c
index a3381901ee..9fc93bb58d 100644
--- a/ext/coverage/coverage.c
+++ b/ext/coverage/coverage.c
@@ -353,7 +353,8 @@ rb_coverage_peek_result(VALUE klass)
rb_raise(rb_eRuntimeError, "coverage measurement is not enabled");
}
OBJ_WB_UNPROTECT(coverages);
- st_foreach(RHASH_TBL_RAW(coverages), coverage_peek_result_i, ncoverages);
+
+ rb_hash_foreach(coverages, coverage_peek_result_i, ncoverages);
if (current_mode & COVERAGE_TARGET_METHODS) {
rb_objspace_each_objects(method_coverage_i, &ncoverages);
diff --git a/ext/coverage/depend b/ext/coverage/depend
index 0a6c61d5c6..1be81c5e9a 100644
--- a/ext/coverage/depend
+++ b/ext/coverage/depend
@@ -159,6 +159,7 @@ coverage.o: $(hdrdir)/ruby/internal/special_consts.h
coverage.o: $(hdrdir)/ruby/internal/static_assert.h
coverage.o: $(hdrdir)/ruby/internal/stdalign.h
coverage.o: $(hdrdir)/ruby/internal/stdbool.h
+coverage.o: $(hdrdir)/ruby/internal/stdckdint.h
coverage.o: $(hdrdir)/ruby/internal/symbol.h
coverage.o: $(hdrdir)/ruby/internal/value.h
coverage.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/date/date.gemspec b/ext/date/date.gemspec
index 660353ebc5..bd42b1518a 100644
--- a/ext/date/date.gemspec
+++ b/ext/date/date.gemspec
@@ -31,4 +31,6 @@ Gem::Specification.new do |s|
s.email = [nil]
s.homepage = "https://github.com/ruby/date"
s.licenses = ["Ruby", "BSD-2-Clause"]
+
+ s.metadata["changelog_uri"] = s.homepage + "/releases"
end
diff --git a/ext/date/date_core.c b/ext/date/date_core.c
index f4b390584b..ca9449f0e9 100644
--- a/ext/date/date_core.c
+++ b/ext/date/date_core.c
@@ -4464,12 +4464,6 @@ check_limit(VALUE str, VALUE opt)
{
size_t slen, limit;
if (NIL_P(str)) return;
- if (SYMBOL_P(str)) {
- rb_category_warn(RB_WARN_CATEGORY_DEPRECATED,
- "The ability to parse Symbol is an unintentional bug and is deprecated");
- str = rb_sym2str(str);
- }
-
StringValue(str);
slen = RSTRING_LEN(str);
limit = get_limit(opt);
@@ -6332,9 +6326,11 @@ minus_dd(VALUE self, VALUE other)
* call-seq:
* d - other -> date or rational
*
- * Returns the difference between the two dates if the other is a date
- * object. If the other is a numeric value, returns a date object
- * pointing +other+ days before self. If the other is a fractional number,
+ * If the other is a date object, returns a Rational
+ * whose value is the difference between the two dates in days.
+ * If the other is a numeric value, returns a date object
+ * pointing +other+ days before self.
+ * If the other is a fractional number,
* assumes its precision is at most nanosecond.
*
* Date.new(2001,2,3) - 1 #=> #<Date: 2001-02-02 ...>
@@ -8961,18 +8957,22 @@ time_to_datetime(VALUE self)
static VALUE
date_to_time(VALUE self)
{
+ VALUE t;
+
get_d1a(self);
if (m_julian_p(adat)) {
- VALUE tmp = d_lite_gregorian(self);
- get_d1b(tmp);
+ self = d_lite_gregorian(self);
+ get_d1b(self);
adat = bdat;
}
- return f_local3(rb_cTime,
+ t = f_local3(rb_cTime,
m_real_year(adat),
INT2FIX(m_mon(adat)),
INT2FIX(m_mday(adat)));
+ RB_GC_GUARD(self); /* may be the converted gregorian */
+ return t;
}
/*
@@ -9061,6 +9061,7 @@ datetime_to_time(VALUE self)
f_add(INT2FIX(m_sec(dat)),
m_sf_in_sec(dat)),
INT2FIX(m_of(dat)));
+ RB_GC_GUARD(self); /* may be the converted gregorian */
return t;
}
}
diff --git a/ext/date/depend b/ext/date/depend
index 82f85f7bf3..d07f10a593 100644
--- a/ext/date/depend
+++ b/ext/date/depend
@@ -157,6 +157,7 @@ date_core.o: $(hdrdir)/ruby/internal/special_consts.h
date_core.o: $(hdrdir)/ruby/internal/static_assert.h
date_core.o: $(hdrdir)/ruby/internal/stdalign.h
date_core.o: $(hdrdir)/ruby/internal/stdbool.h
+date_core.o: $(hdrdir)/ruby/internal/stdckdint.h
date_core.o: $(hdrdir)/ruby/internal/symbol.h
date_core.o: $(hdrdir)/ruby/internal/value.h
date_core.o: $(hdrdir)/ruby/internal/value_type.h
@@ -331,6 +332,7 @@ date_parse.o: $(hdrdir)/ruby/internal/special_consts.h
date_parse.o: $(hdrdir)/ruby/internal/static_assert.h
date_parse.o: $(hdrdir)/ruby/internal/stdalign.h
date_parse.o: $(hdrdir)/ruby/internal/stdbool.h
+date_parse.o: $(hdrdir)/ruby/internal/stdckdint.h
date_parse.o: $(hdrdir)/ruby/internal/symbol.h
date_parse.o: $(hdrdir)/ruby/internal/value.h
date_parse.o: $(hdrdir)/ruby/internal/value_type.h
@@ -495,6 +497,7 @@ date_strftime.o: $(hdrdir)/ruby/internal/special_consts.h
date_strftime.o: $(hdrdir)/ruby/internal/static_assert.h
date_strftime.o: $(hdrdir)/ruby/internal/stdalign.h
date_strftime.o: $(hdrdir)/ruby/internal/stdbool.h
+date_strftime.o: $(hdrdir)/ruby/internal/stdckdint.h
date_strftime.o: $(hdrdir)/ruby/internal/symbol.h
date_strftime.o: $(hdrdir)/ruby/internal/value.h
date_strftime.o: $(hdrdir)/ruby/internal/value_type.h
@@ -666,6 +669,7 @@ date_strptime.o: $(hdrdir)/ruby/internal/special_consts.h
date_strptime.o: $(hdrdir)/ruby/internal/static_assert.h
date_strptime.o: $(hdrdir)/ruby/internal/stdalign.h
date_strptime.o: $(hdrdir)/ruby/internal/stdbool.h
+date_strptime.o: $(hdrdir)/ruby/internal/stdckdint.h
date_strptime.o: $(hdrdir)/ruby/internal/symbol.h
date_strptime.o: $(hdrdir)/ruby/internal/value.h
date_strptime.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/digest/.document b/ext/digest/.document
new file mode 100644
index 0000000000..beab275b5a
--- /dev/null
+++ b/ext/digest/.document
@@ -0,0 +1,3 @@
+digest.c
+bubblebabble/bubblebabble.c
+*/*init.c
diff --git a/ext/digest/bubblebabble/bubblebabble.c b/ext/digest/bubblebabble/bubblebabble.c
index 358ab416b9..dac603c0d7 100644
--- a/ext/digest/bubblebabble/bubblebabble.c
+++ b/ext/digest/bubblebabble/bubblebabble.c
@@ -129,15 +129,14 @@ Init_bubblebabble(void)
rb_require("digest");
- rb_mDigest = rb_path2class("Digest");
- rb_mDigest_Instance = rb_path2class("Digest::Instance");
- rb_cDigest_Class = rb_path2class("Digest::Class");
-
#if 0
rb_mDigest = rb_define_module("Digest");
rb_mDigest_Instance = rb_define_module_under(rb_mDigest, "Instance");
rb_cDigest_Class = rb_define_class_under(rb_mDigest, "Class", rb_cObject);
#endif
+ rb_mDigest = rb_digest_namespace();
+ rb_mDigest_Instance = rb_const_get(rb_mDigest, rb_intern_const("Instance"));
+ rb_cDigest_Class = rb_const_get(rb_mDigest, rb_intern_const("Class"));
rb_define_module_function(rb_mDigest, "bubblebabble", rb_digest_s_bubblebabble, 1);
rb_define_singleton_method(rb_cDigest_Class, "bubblebabble", rb_digest_class_s_bubblebabble, -1);
diff --git a/ext/digest/bubblebabble/depend b/ext/digest/bubblebabble/depend
index 6f0003a66d..0da9c223ee 100644
--- a/ext/digest/bubblebabble/depend
+++ b/ext/digest/bubblebabble/depend
@@ -147,6 +147,7 @@ bubblebabble.o: $(hdrdir)/ruby/internal/special_consts.h
bubblebabble.o: $(hdrdir)/ruby/internal/static_assert.h
bubblebabble.o: $(hdrdir)/ruby/internal/stdalign.h
bubblebabble.o: $(hdrdir)/ruby/internal/stdbool.h
+bubblebabble.o: $(hdrdir)/ruby/internal/stdckdint.h
bubblebabble.o: $(hdrdir)/ruby/internal/symbol.h
bubblebabble.o: $(hdrdir)/ruby/internal/value.h
bubblebabble.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/digest/depend b/ext/digest/depend
index 6df940a679..cb9e8d4813 100644
--- a/ext/digest/depend
+++ b/ext/digest/depend
@@ -147,6 +147,7 @@ digest.o: $(hdrdir)/ruby/internal/special_consts.h
digest.o: $(hdrdir)/ruby/internal/static_assert.h
digest.o: $(hdrdir)/ruby/internal/stdalign.h
digest.o: $(hdrdir)/ruby/internal/stdbool.h
+digest.o: $(hdrdir)/ruby/internal/stdckdint.h
digest.o: $(hdrdir)/ruby/internal/symbol.h
digest.o: $(hdrdir)/ruby/internal/value.h
digest.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/digest/digest.c b/ext/digest/digest.c
index 68837a674c..bd8d3e815f 100644
--- a/ext/digest/digest.c
+++ b/ext/digest/digest.c
@@ -534,9 +534,39 @@ rb_digest_class_init(VALUE self)
*
*
* rb_ivar_set(cDigest_SHA1, rb_intern("metadata"),
- * Data_Wrap_Struct(0, 0, 0, (void *)&sha1));
+ * rb_digest_make_metadata(&sha1));
*/
+#ifdef DIGEST_USE_RB_EXT_RESOLVE_SYMBOL
+static const rb_data_type_t metadata_type = {
+ "digest/metadata",
+ {0},
+};
+
+RUBY_FUNC_EXPORTED VALUE
+rb_digest_wrap_metadata(const rb_digest_metadata_t *meta)
+{
+ return rb_obj_freeze(TypedData_Wrap_Struct(0, &metadata_type, (void *)meta));
+}
+#endif
+
+static rb_digest_metadata_t *
+get_metadata_ptr(VALUE obj)
+{
+ rb_digest_metadata_t *algo;
+
+#ifdef DIGEST_USE_RB_EXT_RESOLVE_SYMBOL
+ if (!rb_typeddata_is_kind_of(obj, &metadata_type)) return 0;
+ algo = RTYPEDDATA_DATA(obj);
+#else
+# undef RUBY_UNTYPED_DATA_WARNING
+# define RUBY_UNTYPED_DATA_WARNING 0
+ Data_Get_Struct(obj, rb_digest_metadata_t, algo);
+#endif
+
+ return algo;
+}
+
static rb_digest_metadata_t *
get_digest_base_metadata(VALUE klass)
{
@@ -554,8 +584,8 @@ get_digest_base_metadata(VALUE klass)
if (NIL_P(p))
rb_raise(rb_eRuntimeError, "Digest::Base cannot be directly inherited in Ruby");
- if (!RB_TYPE_P(obj, T_DATA) || RTYPEDDATA_P(obj)) {
- wrong:
+ algo = get_metadata_ptr(obj);
+ if (!algo) {
if (p == klass)
rb_raise(rb_eTypeError, "%"PRIsVALUE"::metadata is not initialized properly",
klass);
@@ -564,12 +594,6 @@ get_digest_base_metadata(VALUE klass)
klass, p);
}
-#undef RUBY_UNTYPED_DATA_WARNING
-#define RUBY_UNTYPED_DATA_WARNING 0
- Data_Get_Struct(obj, rb_digest_metadata_t, algo);
-
- if (!algo) goto wrong;
-
switch (algo->api_version) {
case 3:
break;
diff --git a/ext/digest/digest.h b/ext/digest/digest.h
index 68a3da5dd2..4503929bab 100644
--- a/ext/digest/digest.h
+++ b/ext/digest/digest.h
@@ -64,10 +64,29 @@ rb_id_metadata(void)
return rb_intern_const("metadata");
}
+#if !defined(HAVE_RB_EXT_RESOLVE_SYMBOL)
+#elif !defined(RUBY_UNTYPED_DATA_WARNING)
+# error RUBY_UNTYPED_DATA_WARNING is not defined
+#elif RUBY_UNTYPED_DATA_WARNING
+/* rb_ext_resolve_symbol() has been defined since Ruby 3.3, but digest
+ * bundled with 3.3 didn't use it. */
+# define DIGEST_USE_RB_EXT_RESOLVE_SYMBOL 1
+#endif
+
static inline VALUE
rb_digest_make_metadata(const rb_digest_metadata_t *meta)
{
+#ifdef DIGEST_USE_RB_EXT_RESOLVE_SYMBOL
+ typedef VALUE (*wrapper_func_type)(const rb_digest_metadata_t *meta);
+ static wrapper_func_type wrapper;
+ if (!wrapper) {
+ wrapper = (wrapper_func_type)rb_ext_resolve_symbol("digest.so", "rb_digest_wrap_metadata");
+ if (!wrapper) rb_raise(rb_eLoadError, "rb_digest_wrap_metadata not found");
+ }
+ return wrapper(meta);
+#else
#undef RUBY_UNTYPED_DATA_WARNING
#define RUBY_UNTYPED_DATA_WARNING 0
return rb_obj_freeze(Data_Wrap_Struct(0, 0, 0, (void *)meta));
+#endif
}
diff --git a/ext/digest/md5/depend b/ext/digest/md5/depend
index da1b345999..e71915e5b4 100644
--- a/ext/digest/md5/depend
+++ b/ext/digest/md5/depend
@@ -150,6 +150,7 @@ md5.o: $(hdrdir)/ruby/internal/special_consts.h
md5.o: $(hdrdir)/ruby/internal/static_assert.h
md5.o: $(hdrdir)/ruby/internal/stdalign.h
md5.o: $(hdrdir)/ruby/internal/stdbool.h
+md5.o: $(hdrdir)/ruby/internal/stdckdint.h
md5.o: $(hdrdir)/ruby/internal/symbol.h
md5.o: $(hdrdir)/ruby/internal/value.h
md5.o: $(hdrdir)/ruby/internal/value_type.h
@@ -311,6 +312,7 @@ md5init.o: $(hdrdir)/ruby/internal/special_consts.h
md5init.o: $(hdrdir)/ruby/internal/static_assert.h
md5init.o: $(hdrdir)/ruby/internal/stdalign.h
md5init.o: $(hdrdir)/ruby/internal/stdbool.h
+md5init.o: $(hdrdir)/ruby/internal/stdckdint.h
md5init.o: $(hdrdir)/ruby/internal/symbol.h
md5init.o: $(hdrdir)/ruby/internal/value.h
md5init.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/digest/md5/md5init.c b/ext/digest/md5/md5init.c
index 52cba78bf1..b81fd94864 100644
--- a/ext/digest/md5/md5init.c
+++ b/ext/digest/md5/md5init.c
@@ -53,9 +53,8 @@ Init_md5(void)
mDigest = rb_define_module("Digest"); /* let rdoc know */
#endif
mDigest = rb_digest_namespace();
- cDigest_Base = rb_path2class("Digest::Base");
+ cDigest_Base = rb_const_get(mDigest, rb_intern_const("Base"));
cDigest_MD5 = rb_define_class_under(mDigest, "MD5", cDigest_Base);
-
rb_iv_set(cDigest_MD5, "metadata", rb_digest_make_metadata(&md5));
}
diff --git a/ext/digest/rmd160/depend b/ext/digest/rmd160/depend
index abfa08b023..09558ad92b 100644
--- a/ext/digest/rmd160/depend
+++ b/ext/digest/rmd160/depend
@@ -150,6 +150,7 @@ rmd160.o: $(hdrdir)/ruby/internal/special_consts.h
rmd160.o: $(hdrdir)/ruby/internal/static_assert.h
rmd160.o: $(hdrdir)/ruby/internal/stdalign.h
rmd160.o: $(hdrdir)/ruby/internal/stdbool.h
+rmd160.o: $(hdrdir)/ruby/internal/stdckdint.h
rmd160.o: $(hdrdir)/ruby/internal/symbol.h
rmd160.o: $(hdrdir)/ruby/internal/value.h
rmd160.o: $(hdrdir)/ruby/internal/value_type.h
@@ -311,6 +312,7 @@ rmd160init.o: $(hdrdir)/ruby/internal/special_consts.h
rmd160init.o: $(hdrdir)/ruby/internal/static_assert.h
rmd160init.o: $(hdrdir)/ruby/internal/stdalign.h
rmd160init.o: $(hdrdir)/ruby/internal/stdbool.h
+rmd160init.o: $(hdrdir)/ruby/internal/stdckdint.h
rmd160init.o: $(hdrdir)/ruby/internal/symbol.h
rmd160init.o: $(hdrdir)/ruby/internal/value.h
rmd160init.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/digest/rmd160/rmd160init.c b/ext/digest/rmd160/rmd160init.c
index 2ae81ec4d6..e4b707ed9e 100644
--- a/ext/digest/rmd160/rmd160init.c
+++ b/ext/digest/rmd160/rmd160init.c
@@ -49,9 +49,8 @@ Init_rmd160(void)
mDigest = rb_define_module("Digest"); /* let rdoc know */
#endif
mDigest = rb_digest_namespace();
- cDigest_Base = rb_path2class("Digest::Base");
+ cDigest_Base = rb_const_get(mDigest, rb_intern_const("Base"));
cDigest_RMD160 = rb_define_class_under(mDigest, "RMD160", cDigest_Base);
-
rb_iv_set(cDigest_RMD160, "metadata", rb_digest_make_metadata(&rmd160));
}
diff --git a/ext/digest/sha1/depend b/ext/digest/sha1/depend
index d17338e92b..827b8a0852 100644
--- a/ext/digest/sha1/depend
+++ b/ext/digest/sha1/depend
@@ -150,6 +150,7 @@ sha1.o: $(hdrdir)/ruby/internal/special_consts.h
sha1.o: $(hdrdir)/ruby/internal/static_assert.h
sha1.o: $(hdrdir)/ruby/internal/stdalign.h
sha1.o: $(hdrdir)/ruby/internal/stdbool.h
+sha1.o: $(hdrdir)/ruby/internal/stdckdint.h
sha1.o: $(hdrdir)/ruby/internal/symbol.h
sha1.o: $(hdrdir)/ruby/internal/value.h
sha1.o: $(hdrdir)/ruby/internal/value_type.h
@@ -311,6 +312,7 @@ sha1init.o: $(hdrdir)/ruby/internal/special_consts.h
sha1init.o: $(hdrdir)/ruby/internal/static_assert.h
sha1init.o: $(hdrdir)/ruby/internal/stdalign.h
sha1init.o: $(hdrdir)/ruby/internal/stdbool.h
+sha1init.o: $(hdrdir)/ruby/internal/stdckdint.h
sha1init.o: $(hdrdir)/ruby/internal/symbol.h
sha1init.o: $(hdrdir)/ruby/internal/value.h
sha1init.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/digest/sha1/sha1init.c b/ext/digest/sha1/sha1init.c
index f7047bc6d3..c39959f428 100644
--- a/ext/digest/sha1/sha1init.c
+++ b/ext/digest/sha1/sha1init.c
@@ -55,9 +55,8 @@ Init_sha1(void)
mDigest = rb_define_module("Digest"); /* let rdoc know */
#endif
mDigest = rb_digest_namespace();
- cDigest_Base = rb_path2class("Digest::Base");
+ cDigest_Base = rb_const_get(mDigest, rb_intern_const("Base"));
cDigest_SHA1 = rb_define_class_under(mDigest, "SHA1", cDigest_Base);
-
rb_iv_set(cDigest_SHA1, "metadata", rb_digest_make_metadata(&sha1));
}
diff --git a/ext/digest/sha2/depend b/ext/digest/sha2/depend
index 7b88b6411f..af1600d346 100644
--- a/ext/digest/sha2/depend
+++ b/ext/digest/sha2/depend
@@ -150,6 +150,7 @@ sha2.o: $(hdrdir)/ruby/internal/special_consts.h
sha2.o: $(hdrdir)/ruby/internal/static_assert.h
sha2.o: $(hdrdir)/ruby/internal/stdalign.h
sha2.o: $(hdrdir)/ruby/internal/stdbool.h
+sha2.o: $(hdrdir)/ruby/internal/stdckdint.h
sha2.o: $(hdrdir)/ruby/internal/symbol.h
sha2.o: $(hdrdir)/ruby/internal/value.h
sha2.o: $(hdrdir)/ruby/internal/value_type.h
@@ -311,6 +312,7 @@ sha2init.o: $(hdrdir)/ruby/internal/special_consts.h
sha2init.o: $(hdrdir)/ruby/internal/static_assert.h
sha2init.o: $(hdrdir)/ruby/internal/stdalign.h
sha2init.o: $(hdrdir)/ruby/internal/stdbool.h
+sha2init.o: $(hdrdir)/ruby/internal/stdckdint.h
sha2init.o: $(hdrdir)/ruby/internal/symbol.h
sha2init.o: $(hdrdir)/ruby/internal/value.h
sha2init.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/digest/sha2/sha2init.c b/ext/digest/sha2/sha2init.c
index 94cccf3feb..3923e3724c 100644
--- a/ext/digest/sha2/sha2init.c
+++ b/ext/digest/sha2/sha2init.c
@@ -25,29 +25,50 @@ static const rb_digest_metadata_t sha##bitlen = { \
FOREACH_BITLEN(DEFINE_ALGO_METADATA)
/*
+ * Document-class: Digest::SHA256 < Digest::Base
+ *
* Classes for calculating message digests using the SHA-256/384/512
* Secure Hash Algorithm(s) by NIST (the US' National Institute of
* Standards and Technology), described in FIPS PUB 180-2.
+ *
+ * See SHA2.
+ */
+/*
+ * Document-class: Digest::SHA384 < Digest::Base
+ *
+ * Classes for calculating message digests using the SHA-256/384/512
+ * Secure Hash Algorithm(s) by NIST (the US' National Institute of
+ * Standards and Technology), described in FIPS PUB 180-2.
+ *
+ * See SHA2.
+ */
+/*
+ * Document-class: Digest::SHA512 < Digest::Base
+ *
+ * Classes for calculating message digests using the SHA-256/384/512
+ * Secure Hash Algorithm(s) by NIST (the US' National Institute of
+ * Standards and Technology), described in FIPS PUB 180-2.
+ *
+ * See SHA2.
*/
void
Init_sha2(void)
{
- VALUE mDigest, cDigest_Base;
+ VALUE mDigest, cDigest_Base, cDigest_SHA2;
ID id_metadata = rb_id_metadata();
-#define DECLARE_ALGO_CLASS(bitlen) \
- VALUE cDigest_SHA##bitlen;
-
- FOREACH_BITLEN(DECLARE_ALGO_CLASS)
-
+#if 0
+ mDigest = rb_define_module("Digest"); /* let rdoc know */
+#endif
mDigest = rb_digest_namespace();
- cDigest_Base = rb_path2class("Digest::Base");
+ cDigest_Base = rb_const_get(mDigest, rb_intern_const("Base"));
+
+ cDigest_SHA2 = rb_define_class_under(mDigest, "SHA256", cDigest_Base);
+ rb_ivar_set(cDigest_SHA2, id_metadata, rb_digest_make_metadata(&sha256));
-#define DEFINE_ALGO_CLASS(bitlen) \
- cDigest_SHA##bitlen = rb_define_class_under(mDigest, "SHA" #bitlen, cDigest_Base); \
-\
- rb_ivar_set(cDigest_SHA##bitlen, id_metadata, \
- rb_digest_make_metadata(&sha##bitlen));
+ cDigest_SHA2 = rb_define_class_under(mDigest, "SHA384", cDigest_Base);
+ rb_ivar_set(cDigest_SHA2, id_metadata, rb_digest_make_metadata(&sha384));
- FOREACH_BITLEN(DEFINE_ALGO_CLASS)
+ cDigest_SHA2 = rb_define_class_under(mDigest, "SHA512", cDigest_Base);
+ rb_ivar_set(cDigest_SHA2, id_metadata, rb_digest_make_metadata(&sha512));
}
diff --git a/ext/erb/escape/extconf.rb b/ext/erb/escape/extconf.rb
index c1002548ad..783e8c1f55 100644
--- a/ext/erb/escape/extconf.rb
+++ b/ext/erb/escape/extconf.rb
@@ -1,6 +1,7 @@
require 'mkmf'
-if RUBY_ENGINE == 'truffleruby'
+case RUBY_ENGINE
+when 'jruby', 'truffleruby'
File.write('Makefile', dummy_makefile($srcdir).join)
else
create_makefile 'erb/escape'
diff --git a/ext/etc/.document b/ext/etc/.document
new file mode 100644
index 0000000000..9bbea23b92
--- /dev/null
+++ b/ext/etc/.document
@@ -0,0 +1,2 @@
+etc.c
+constdefs.h
diff --git a/ext/etc/depend b/ext/etc/depend
index 00787b6aaf..675699b129 100644
--- a/ext/etc/depend
+++ b/ext/etc/depend
@@ -162,6 +162,7 @@ etc.o: $(hdrdir)/ruby/internal/special_consts.h
etc.o: $(hdrdir)/ruby/internal/static_assert.h
etc.o: $(hdrdir)/ruby/internal/stdalign.h
etc.o: $(hdrdir)/ruby/internal/stdbool.h
+etc.o: $(hdrdir)/ruby/internal/stdckdint.h
etc.o: $(hdrdir)/ruby/internal/symbol.h
etc.o: $(hdrdir)/ruby/internal/value.h
etc.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/etc/etc.c b/ext/etc/etc.c
index 69c33f46b0..fcbd1af1b5 100644
--- a/ext/etc/etc.c
+++ b/ext/etc/etc.c
@@ -56,7 +56,7 @@ static VALUE sGroup;
#endif
RUBY_EXTERN char *getlogin(void);
-#define RUBY_ETC_VERSION "1.4.3.dev.1"
+#define RUBY_ETC_VERSION "1.4.3"
#ifdef HAVE_RB_DEPRECATE_CONSTANT
void rb_deprecate_constant(VALUE mod, const char *name);
@@ -203,7 +203,7 @@ setup_passwd(struct passwd *pwd)
#endif
/* call-seq:
- * getpwuid(uid) -> Passwd
+ * getpwuid(uid) -> Etc::Passwd
*
* Returns the <tt>/etc/passwd</tt> information for the user with the given
* integer +uid+.
@@ -215,7 +215,7 @@ setup_passwd(struct passwd *pwd)
*
* See the unix manpage for <code>getpwuid(3)</code> for more detail.
*
- * === Example:
+ * *Example:*
*
* Etc.getpwuid(0)
* #=> #<struct Etc::Passwd name="root", passwd="x", uid=0, gid=0, gecos="root",dir="/root", shell="/bin/bash">
@@ -243,7 +243,7 @@ etc_getpwuid(int argc, VALUE *argv, VALUE obj)
}
/* call-seq:
- * getpwnam(name) -> Passwd
+ * getpwnam(name) -> Etc::Passwd
*
* Returns the <tt>/etc/passwd</tt> information for the user with specified
* login +name+.
@@ -252,7 +252,7 @@ etc_getpwuid(int argc, VALUE *argv, VALUE obj)
*
* See the unix manpage for <code>getpwnam(3)</code> for more detail.
*
- * === Example:
+ * *Example:*
*
* Etc.getpwnam('root')
* #=> #<struct Etc::Passwd name="root", passwd="x", uid=0, gid=0, gecos="root",dir="/root", shell="/bin/bash">
@@ -307,8 +307,8 @@ each_passwd(void)
#endif
/* call-seq:
- * Etc.passwd { |struct| block } -> Passwd
- * Etc.passwd -> Passwd
+ * passwd { |struct| block }
+ * passwd -> Etc::Passwd
*
* Provides a convenient Ruby iterator which executes a block for each entry
* in the <tt>/etc/passwd</tt> file.
@@ -317,7 +317,7 @@ each_passwd(void)
*
* See ::getpwent above for details.
*
- * Example:
+ * *Example:*
*
* require 'etc'
*
@@ -343,7 +343,7 @@ etc_passwd(VALUE obj)
}
/* call-seq:
- * Etc::Passwd.each { |struct| block } -> Passwd
+ * Etc::Passwd.each { |struct| block } -> Etc::Passwd
* Etc::Passwd.each -> Enumerator
*
* Iterates for each entry in the <tt>/etc/passwd</tt> file if a block is
@@ -355,7 +355,7 @@ etc_passwd(VALUE obj)
*
* See Etc.getpwent above for details.
*
- * Example:
+ * *Example:*
*
* require 'etc'
*
@@ -377,7 +377,10 @@ etc_each_passwd(VALUE obj)
return obj;
}
-/* Resets the process of reading the <tt>/etc/passwd</tt> file, so that the
+/* call-seq:
+ * setpwent
+ *
+ * Resets the process of reading the <tt>/etc/passwd</tt> file, so that the
* next call to ::getpwent will return the first entry again.
*/
static VALUE
@@ -389,7 +392,10 @@ etc_setpwent(VALUE obj)
return Qnil;
}
-/* Ends the process of scanning through the <tt>/etc/passwd</tt> file begun
+/* call-seq:
+ * endpwent
+ *
+ * Ends the process of scanning through the <tt>/etc/passwd</tt> file begun
* with ::getpwent, and closes the file.
*/
static VALUE
@@ -401,7 +407,10 @@ etc_endpwent(VALUE obj)
return Qnil;
}
-/* Returns an entry from the <tt>/etc/passwd</tt> file.
+/* call-seq:
+ * getpwent -> Etc::Passwd
+ *
+ * Returns an entry from the <tt>/etc/passwd</tt> file.
*
* The first time it is called it opens the file and returns the first entry;
* each successive call returns the next entry, or +nil+ if the end of the file
@@ -449,7 +458,7 @@ setup_group(struct group *grp)
#endif
/* call-seq:
- * getgrgid(group_id) -> Group
+ * getgrgid(group_id) -> Etc::Group
*
* Returns information about the group with specified integer +group_id+,
* as found in <tt>/etc/group</tt>.
@@ -458,7 +467,7 @@ setup_group(struct group *grp)
*
* See the unix manpage for <code>getgrgid(3)</code> for more detail.
*
- * === Example:
+ * *Example:*
*
* Etc.getgrgid(100)
* #=> #<struct Etc::Group name="users", passwd="x", gid=100, mem=["meta", "root"]>
@@ -487,7 +496,7 @@ etc_getgrgid(int argc, VALUE *argv, VALUE obj)
}
/* call-seq:
- * getgrnam(name) -> Group
+ * getgrnam(name) -> Etc::Group
*
* Returns information about the group with specified +name+, as found in
* <tt>/etc/group</tt>.
@@ -496,7 +505,7 @@ etc_getgrgid(int argc, VALUE *argv, VALUE obj)
*
* See the unix manpage for <code>getgrnam(3)</code> for more detail.
*
- * === Example:
+ * *Example:*
*
* Etc.getgrnam('users')
* #=> #<struct Etc::Group name="users", passwd="x", gid=100, mem=["meta", "root"]>
@@ -529,7 +538,6 @@ group_ensure(VALUE _)
return Qnil;
}
-
static VALUE
group_iterate(VALUE _)
{
@@ -552,14 +560,18 @@ each_group(void)
}
#endif
-/* Provides a convenient Ruby iterator which executes a block for each entry
+/* call-seq:
+ * group { |struct| block }
+ * group -> Etc::Group
+ *
+ * Provides a convenient Ruby iterator which executes a block for each entry
* in the <tt>/etc/group</tt> file.
*
* The code block is passed an Group struct.
*
* See ::getgrent above for details.
*
- * Example:
+ * *Example:*
*
* require 'etc'
*
@@ -586,7 +598,7 @@ etc_group(VALUE obj)
#ifdef HAVE_GETGRENT
/* call-seq:
- * Etc::Group.each { |group| block } -> obj
+ * Etc::Group.each { |group| block } -> Etc::Group
* Etc::Group.each -> Enumerator
*
* Iterates for each entry in the <tt>/etc/group</tt> file if a block is
@@ -596,7 +608,7 @@ etc_group(VALUE obj)
*
* The code block is passed a Group struct.
*
- * Example:
+ * *Example:*
*
* require 'etc'
*
@@ -617,7 +629,10 @@ etc_each_group(VALUE obj)
}
#endif
-/* Resets the process of reading the <tt>/etc/group</tt> file, so that the
+/* call-seq:
+ * setgrent
+ *
+ * Resets the process of reading the <tt>/etc/group</tt> file, so that the
* next call to ::getgrent will return the first entry again.
*/
static VALUE
@@ -629,7 +644,10 @@ etc_setgrent(VALUE obj)
return Qnil;
}
-/* Ends the process of scanning through the <tt>/etc/group</tt> file begun
+/* call-seq:
+ * endgrent
+ *
+ * Ends the process of scanning through the <tt>/etc/group</tt> file begun
* by ::getgrent, and closes the file.
*/
static VALUE
@@ -641,7 +659,10 @@ etc_endgrent(VALUE obj)
return Qnil;
}
-/* Returns an entry from the <tt>/etc/group</tt> file.
+/* call-seq:
+ * getgrent -> Etc::Group
+ *
+ * Returns an entry from the <tt>/etc/group</tt> file.
*
* The first time it is called it opens the file and returns the first entry;
* each successive call returns the next entry, or +nil+ if the end of the file
@@ -672,7 +693,9 @@ UINT rb_w32_system_tmpdir(WCHAR *path, UINT len);
VALUE rb_w32_conv_from_wchar(const WCHAR *wstr, rb_encoding *enc);
#endif
-/*
+/* call-seq:
+ * sysconfdir -> String
+ *
* Returns system configuration directory.
*
* This is typically <code>"/etc"</code>, but is modified by the prefix used
@@ -692,7 +715,9 @@ etc_sysconfdir(VALUE obj)
#endif
}
-/*
+/* call-seq:
+ * systmpdir -> String
+ *
* Returns system temporary directory; typically "/tmp".
*/
static VALUE
@@ -736,13 +761,15 @@ etc_systmpdir(VALUE _)
}
#ifdef HAVE_UNAME
-/*
+/* call-seq:
+ * uname -> hash
+ *
* Returns the system information obtained by uname system call.
*
* The return value is a hash which has 5 keys at least:
* :sysname, :nodename, :release, :version, :machine
*
- * Example:
+ * *Example:*
*
* require 'etc'
* require 'pp'
@@ -852,7 +879,9 @@ etc_uname(VALUE obj)
#endif
#ifdef HAVE_SYSCONF
-/*
+/* call-seq:
+ * sysconf(name) -> Integer
+ *
* Returns system configuration variable using sysconf().
*
* _name_ should be a constant under <code>Etc</code> which begins with <code>SC_</code>.
@@ -886,7 +915,9 @@ etc_sysconf(VALUE obj, VALUE arg)
#endif
#ifdef HAVE_CONFSTR
-/*
+/* call-seq:
+ * confstr(name) -> String
+ *
* Returns system configuration variable using confstr().
*
* _name_ should be a constant under <code>Etc</code> which begins with <code>CS_</code>.
@@ -933,7 +964,9 @@ etc_confstr(VALUE obj, VALUE arg)
#endif
#ifdef HAVE_FPATHCONF
-/*
+/* call-seq:
+ * pathconf(name) -> Integer
+ *
* Returns pathname configuration variable using fpathconf().
*
* _name_ should be a constant under <code>Etc</code> which begins with <code>PC_</code>.
@@ -1025,7 +1058,9 @@ etc_nprocessors_affin(void)
}
#endif
-/*
+/* call-seq:
+ * nprocessors -> Integer
+ *
* Returns the number of online processors.
*
* The result is intended as the number of processes to
@@ -1035,7 +1070,7 @@ etc_nprocessors_affin(void)
* - sched_getaffinity(): Linux
* - sysconf(_SC_NPROCESSORS_ONLN): GNU/Linux, NetBSD, FreeBSD, OpenBSD, DragonFly BSD, OpenIndiana, Mac OS X, AIX
*
- * Example:
+ * *Example:*
*
* require 'etc'
* p Etc.nprocessors #=> 4
@@ -1044,7 +1079,7 @@ etc_nprocessors_affin(void)
* process is bound to specific cpus. This is intended for getting better
* parallel processing.
*
- * Example: (Linux)
+ * *Example:* (Linux)
*
* linux$ taskset 0x3 ./ruby -retc -e "p Etc.nprocessors" #=> 2
*
@@ -1094,7 +1129,7 @@ etc_nprocessors(VALUE obj)
* The Etc module provides a more reliable way to access information about
* the logged in user than environment variables such as +$USER+.
*
- * == Example:
+ * *Example:*
*
* require 'etc'
*
@@ -1118,6 +1153,7 @@ Init_etc(void)
RB_EXT_RACTOR_SAFE(true);
#endif
mEtc = rb_define_module("Etc");
+ /* The version */
rb_define_const(mEtc, "VERSION", rb_str_new_cstr(RUBY_ETC_VERSION));
init_constants(mEtc);
diff --git a/ext/etc/mkconstants.rb b/ext/etc/mkconstants.rb
index a752d64519..a766560a8a 100644
--- a/ext/etc/mkconstants.rb
+++ b/ext/etc/mkconstants.rb
@@ -35,6 +35,12 @@ opt.def_option('-H FILE', 'specify output header file') {|filename|
opt.parse!
+CONST_PREFIXES = {
+ 'SC' => 'for Etc.sysconf; See <tt>man sysconf</tt>',
+ 'CS' => 'for Etc.confstr; See <tt>man constr</tt>',
+ 'PC' => 'for IO#pathconf; See <tt>man fpathconf</tt>',
+}
+
h = {}
COMMENTS = {}
@@ -49,6 +55,13 @@ DATA.each_line {|s|
next
end
h[name] = default_value
+ if additional = CONST_PREFIXES[name[/\A_([A-Z]+)_/, 1]]
+ if comment&.match(/\w\z/)
+ comment << " " << additional
+ else
+ (comment ||= String.new) << " " << additional.sub(/\A\w/) {$&.upcase}
+ end
+ end
COMMENTS[name] = comment if comment
}
DEFS = h.to_a
@@ -66,15 +79,11 @@ def each_name(pat)
}
end
-erb_new = lambda do |src, safe, trim|
- if ERB.instance_method(:initialize).parameters.assoc(:key) # Ruby 2.6+
- ERB.new(src, trim_mode: trim)
- else
- ERB.new(src, safe, trim)
- end
+erb_new = lambda do |src, trim|
+ ERB.new(src, trim_mode: trim)
end
-erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_const_decls")
+erb_new.call(<<'EOS', '%').def_method(Object, "gen_const_decls")
% each_const {|name, default_value|
#if !defined(<%=name%>)
# if defined(HAVE_CONST_<%=name.upcase%>)
@@ -88,7 +97,7 @@ erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_const_decls")
% }
EOS
-erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_const_defs")
+erb_new.call(<<'EOS', '%').def_method(Object, "gen_const_defs")
% each_const {|name, default_value|
#if defined(<%=name%>)
% if comment = COMMENTS[name]
@@ -99,13 +108,13 @@ erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_const_defs")
% }
EOS
-header_result = erb_new.call(<<'EOS', nil, '%').result(binding)
+header_result = erb_new.call(<<'EOS', '%').result(binding)
/* autogenerated file */
<%= gen_const_decls %>
EOS
-result = erb_new.call(<<'EOS', nil, '%').result(binding)
+result = erb_new.call(<<'EOS', '%').result(binding)
/* autogenerated file */
#ifdef HAVE_LONG_LONG
@@ -123,6 +132,9 @@ result = erb_new.call(<<'EOS', nil, '%').result(binding)
static void
init_constants(VALUE mod)
{
+#if 0
+ mod = rb_define_module("Etc");
+#endif
<%= gen_const_defs %>
}
EOS
diff --git a/ext/extmk.rb b/ext/extmk.rb
index 428ffc91a6..2f76e174d5 100755
--- a/ext/extmk.rb
+++ b/ext/extmk.rb
@@ -104,7 +104,7 @@ def extract_makefile(makefile, keep = true)
end
return false
end
- srcs = Dir[File.join($srcdir, "*.{#{SRC_EXT.join(%q{,})}}")].map {|fn| File.basename(fn)}.sort
+ srcs = Dir[*SRC_EXT.map {|e| "*.#{e}"}, base: $srcdir].map {|fn| File.basename(fn)}.sort
if !srcs.empty?
old_srcs = m[/^ORIG_SRCS[ \t]*=[ \t](.*)/, 1] or return false
(old_srcs.split - srcs).empty? or return false
@@ -132,6 +132,14 @@ def extract_makefile(makefile, keep = true)
true
end
+def create_makefile(target, srcprefix = nil)
+ if $static and target.include?("/")
+ base = File.basename(target)
+ $defs << "-DInit_#{base}=Init_#{target.tr('/', '_')}"
+ end
+ super
+end
+
def extmake(target, basedir = 'ext', maybestatic = true)
FileUtils.mkpath target unless File.directory?(target)
begin
@@ -472,12 +480,13 @@ if exts = ARGV.shift
$extension = [exts] if exts
if ext_prefix.start_with?('.')
@gemname = exts
- elsif exts
- $static_ext.delete_if {|t, *| !File.fnmatch(t, exts)}
+ exts = []
+ else
+ exts &&= $static_ext.select {|t, *| File.fnmatch(t, exts)}
end
end
-ext_prefix = "#{$top_srcdir}/#{ext_prefix || 'ext'}"
-exts = $static_ext.sort_by {|t, i| i}.collect {|t, i| t}
+ext_prefix ||= 'ext'
+exts = (exts || $static_ext).sort_by {|t, i| i}.collect {|t, i| t}
default_exclude_exts =
case
when $cygwin
@@ -490,28 +499,30 @@ default_exclude_exts =
mandatory_exts = {}
withes, withouts = [["--with", nil], ["--without", default_exclude_exts]].collect {|w, d|
if !(w = %w[-extensions -ext].collect {|o|arg_config(w+o)}).any?
- d ? proc {|c1| d.any?(&c1)} : proc {true}
+ d ? proc {|&c1| d.any?(&c1)} : proc {true}
elsif (w = w.grep(String)).empty?
proc {true}
else
w = w.collect {|o| o.split(/,/)}.flatten
w.collect! {|o| o == '+' ? d : o}.flatten!
- proc {|c1| w.any?(&c1)}
+ proc {|&c1| w.any?(&c1)}
end
}
cond = proc {|ext, *|
- withes.call(proc {|n|
- !n or (mandatory_exts[ext] = true if File.fnmatch(n, ext))
- }) and
- !withouts.call(proc {|n| File.fnmatch(n, ext)})
+ withes.call {|n| !n or (mandatory_exts[ext] = true if File.fnmatch(n, ext))} and
+ !withouts.call {|n| File.fnmatch(n, ext)}
}
($extension || %w[*]).each do |e|
e = e.sub(/\A(?:\.\/)+/, '')
- incl, excl = Dir.glob("#{ext_prefix}/#{e}/**/extconf.rb").collect {|d|
- d = File.dirname(d)
- d.slice!(0, ext_prefix.length + 1)
- d
+ incl, excl = Dir.glob("#{e}/**/extconf.rb", base: "#$top_srcdir/#{ext_prefix}").collect {|d|
+ File.dirname(d)
}.partition {|ext|
+ if @gemname
+ ext = ext[%r[\A[^/]+]] # extract gem name
+ Dir.glob("*.gemspec", base: "#$top_srcdir/#{ext_prefix}/#{ext}") do |g|
+ break ext = g if ext.start_with?("#{g.chomp!(".gemspec")}-")
+ end
+ end
with_config(ext, &cond)
}
incl.sort!
@@ -522,7 +533,7 @@ cond = proc {|ext, *|
exts.delete_if {|d| File.fnmatch?("-*", d)}
end
end
-ext_prefix = ext_prefix[$top_srcdir.size+1..-2]
+ext_prefix.chomp!("/")
@ext_prefix = ext_prefix
@inplace = inplace
@@ -545,7 +556,13 @@ extend Module.new {
end
def create_makefile(*args, &block)
- return super unless @gemname
+ unless @gemname
+ if $static and (target = args.first).include?("/")
+ base = File.basename(target)
+ $defs << "-DInit_#{base}=Init_#{target.tr('/', '_')}"
+ end
+ return super
+ end
super(*args) do |conf|
conf.find do |s|
s.sub!(%r(^(srcdir *= *)\$\(top_srcdir\)/\.bundle/gems/[^/]+(?=/))) {
@@ -628,7 +645,9 @@ $hdrdir = ($top_srcdir = relative_from(srcdir, $topdir = "..")) + "/include"
extso = []
fails = []
exts.each do |d|
- $static = $force_static ? true : $static_ext[d]
+ $static = $force_static ? true : $static_ext.fetch(d) do
+ $static_ext.any? {|t, | File.fnmatch?(t, d)}
+ end
if !$nodynamic or $static
result = extmake(d, ext_prefix, !@gemname) or abort
@@ -754,7 +773,6 @@ begin
end
submakeopts << 'EXTLDFLAGS="$(EXTLDFLAGS)"'
submakeopts << 'EXTINITS="$(EXTINITS)"'
- submakeopts << 'UPDATE_LIBRARIES="$(UPDATE_LIBRARIES)"'
submakeopts << 'SHOWFLAGS='
mf.macro "SUBMAKEOPTS", submakeopts
mf.macro "NOTE_MESG", %w[$(RUBY) $(top_srcdir)/tool/lib/colorize.rb skip]
@@ -810,7 +828,7 @@ begin
end
mf.puts "#{t}:#{pd}\n\t$(Q)#{submake} $(MFLAGS) V=$(V) $(@F)"
if clean and clean.begin(1)
- mf.puts "\t$(Q)$(RM) $(ext_build_dir)/exts.mk\n\t$(Q)$(RMDIRS) -p $(@D)"
+ mf.puts "\t$(Q)$(RM) $(ext_build_dir)/exts.mk\n\t$(Q)$(RMDIRS) $(@D)"
end
end
end
diff --git a/ext/fcntl/depend b/ext/fcntl/depend
index 9ce9fa30ef..5ed652563b 100644
--- a/ext/fcntl/depend
+++ b/ext/fcntl/depend
@@ -147,6 +147,7 @@ fcntl.o: $(hdrdir)/ruby/internal/special_consts.h
fcntl.o: $(hdrdir)/ruby/internal/static_assert.h
fcntl.o: $(hdrdir)/ruby/internal/stdalign.h
fcntl.o: $(hdrdir)/ruby/internal/stdbool.h
+fcntl.o: $(hdrdir)/ruby/internal/stdckdint.h
fcntl.o: $(hdrdir)/ruby/internal/symbol.h
fcntl.o: $(hdrdir)/ruby/internal/value.h
fcntl.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/fcntl/fcntl.c b/ext/fcntl/fcntl.c
index 4af2077a0a..e34a3aeae3 100644
--- a/ext/fcntl/fcntl.c
+++ b/ext/fcntl/fcntl.c
@@ -28,7 +28,10 @@ pack up your own arguments to pass as args for locking functions, etc.
#include "ruby.h"
#include <fcntl.h>
-/* Fcntl loads the constants defined in the system's <fcntl.h> C header
+/*
+ * Document-module: Fcntl
+ *
+ * Fcntl loads the constants defined in the system's <fcntl.h> C header
* file, and used with both the fcntl(2) and open(2) POSIX system calls.
*
* To perform a fcntl(2) operation, use IO::fcntl.
@@ -69,11 +72,11 @@ Init_fcntl(void)
{
VALUE mFcntl = rb_define_module("Fcntl");
+ /* The version string. */
rb_define_const(mFcntl, "VERSION", rb_str_new_cstr(FCNTL_VERSION));
#ifdef F_DUPFD
- /* Document-const: F_DUPFD
- *
+ /*
* Duplicate a file descriptor to the minimum unused file descriptor
* greater than or equal to the argument.
*
@@ -84,195 +87,164 @@ Init_fcntl(void)
rb_define_const(mFcntl, "F_DUPFD", INT2NUM(F_DUPFD));
#endif
#ifdef F_GETFD
- /* Document-const: F_GETFD
- *
+ /*
* Read the close-on-exec flag of a file descriptor.
*/
rb_define_const(mFcntl, "F_GETFD", INT2NUM(F_GETFD));
#endif
#ifdef F_GETLK
- /* Document-const: F_GETLK
- *
+ /*
* Determine whether a given region of a file is locked. This uses one of
* the F_*LK flags.
*/
rb_define_const(mFcntl, "F_GETLK", INT2NUM(F_GETLK));
#endif
#ifdef F_SETFD
- /* Document-const: F_SETFD
- *
+ /*
* Set the close-on-exec flag of a file descriptor.
*/
rb_define_const(mFcntl, "F_SETFD", INT2NUM(F_SETFD));
#endif
#ifdef F_GETFL
- /* Document-const: F_GETFL
- *
+ /*
* Get the file descriptor flags. This will be one or more of the O_*
* flags.
*/
rb_define_const(mFcntl, "F_GETFL", INT2NUM(F_GETFL));
#endif
#ifdef F_SETFL
- /* Document-const: F_SETFL
- *
+ /*
* Set the file descriptor flags. This will be one or more of the O_*
* flags.
*/
rb_define_const(mFcntl, "F_SETFL", INT2NUM(F_SETFL));
#endif
#ifdef F_SETLK
- /* Document-const: F_SETLK
- *
+ /*
* Acquire a lock on a region of a file. This uses one of the F_*LCK
* flags.
*/
rb_define_const(mFcntl, "F_SETLK", INT2NUM(F_SETLK));
#endif
#ifdef F_SETLKW
- /* Document-const: F_SETLKW
- *
+ /*
* Acquire a lock on a region of a file, waiting if necessary. This uses
* one of the F_*LCK flags
*/
rb_define_const(mFcntl, "F_SETLKW", INT2NUM(F_SETLKW));
#endif
#ifdef FD_CLOEXEC
- /* Document-const: FD_CLOEXEC
- *
+ /*
* the value of the close-on-exec flag.
*/
rb_define_const(mFcntl, "FD_CLOEXEC", INT2NUM(FD_CLOEXEC));
#endif
#ifdef F_RDLCK
- /* Document-const: F_RDLCK
- *
+ /*
* Read lock for a region of a file
*/
rb_define_const(mFcntl, "F_RDLCK", INT2NUM(F_RDLCK));
#endif
#ifdef F_UNLCK
- /* Document-const: F_UNLCK
- *
+ /*
* Remove lock for a region of a file
*/
rb_define_const(mFcntl, "F_UNLCK", INT2NUM(F_UNLCK));
#endif
#ifdef F_WRLCK
- /* Document-const: F_WRLCK
- *
+ /*
* Write lock for a region of a file
*/
rb_define_const(mFcntl, "F_WRLCK", INT2NUM(F_WRLCK));
#endif
#ifdef F_SETPIPE_SZ
- /* Document-const: F_SETPIPE_SZ
- *
+ /*
* Change the capacity of the pipe referred to by fd to be at least arg bytes.
*/
rb_define_const(mFcntl, "F_SETPIPE_SZ", INT2NUM(F_SETPIPE_SZ));
#endif
#ifdef F_GETPIPE_SZ
- /* Document-const: F_GETPIPE_SZ
- *
+ /*
* Return (as the function result) the capacity of the pipe referred to by fd.
*/
rb_define_const(mFcntl, "F_GETPIPE_SZ", INT2NUM(F_GETPIPE_SZ));
#endif
#ifdef O_CREAT
- /* Document-const: O_CREAT
- *
+ /*
* Create the file if it doesn't exist
*/
rb_define_const(mFcntl, "O_CREAT", INT2NUM(O_CREAT));
#endif
#ifdef O_EXCL
- /* Document-const: O_EXCL
- *
+ /*
* Used with O_CREAT, fail if the file exists
*/
rb_define_const(mFcntl, "O_EXCL", INT2NUM(O_EXCL));
#endif
#ifdef O_NOCTTY
- /* Document-const: O_NOCTTY
- *
+ /*
* Open TTY without it becoming the controlling TTY
*/
rb_define_const(mFcntl, "O_NOCTTY", INT2NUM(O_NOCTTY));
#endif
#ifdef O_TRUNC
- /* Document-const: O_TRUNC
- *
+ /*
* Truncate the file on open
*/
rb_define_const(mFcntl, "O_TRUNC", INT2NUM(O_TRUNC));
#endif
#ifdef O_APPEND
- /* Document-const: O_APPEND
- *
+ /*
* Open the file in append mode
*/
rb_define_const(mFcntl, "O_APPEND", INT2NUM(O_APPEND));
#endif
#ifdef O_NONBLOCK
- /* Document-const: O_NONBLOCK
- *
+ /*
* Open the file in non-blocking mode
*/
rb_define_const(mFcntl, "O_NONBLOCK", INT2NUM(O_NONBLOCK));
#endif
#ifdef O_NDELAY
- /* Document-const: O_NDELAY
- *
+ /*
* Open the file in non-blocking mode
*/
rb_define_const(mFcntl, "O_NDELAY", INT2NUM(O_NDELAY));
#endif
#ifdef O_RDONLY
- /* Document-const: O_RDONLY
- *
+ /*
* Open the file in read-only mode
*/
rb_define_const(mFcntl, "O_RDONLY", INT2NUM(O_RDONLY));
#endif
#ifdef O_RDWR
- /* Document-const: O_RDWR
- *
+ /*
* Open the file in read-write mode
*/
rb_define_const(mFcntl, "O_RDWR", INT2NUM(O_RDWR));
#endif
#ifdef O_WRONLY
- /* Document-const: O_WRONLY
- *
+ /*
* Open the file in write-only mode.
*/
rb_define_const(mFcntl, "O_WRONLY", INT2NUM(O_WRONLY));
#endif
-#ifdef O_ACCMODE
- /* Document-const: O_ACCMODE
- *
+#ifndef O_ACCMODE
+ int O_ACCMODE = (O_RDONLY | O_WRONLY | O_RDWR);
+#endif
+ /*
* Mask to extract the read/write flags
*/
rb_define_const(mFcntl, "O_ACCMODE", INT2FIX(O_ACCMODE));
-#else
- /* Document-const: O_ACCMODE
- *
- * Mask to extract the read/write flags
- */
- rb_define_const(mFcntl, "O_ACCMODE", INT2FIX(O_RDONLY | O_WRONLY | O_RDWR));
-#endif
#ifdef F_DUP2FD
- /* Document-const: F_DUP2FD
- *
+ /*
* It is a FreeBSD specific constant and equivalent
* to dup2 call.
*/
rb_define_const(mFcntl, "F_DUP2FD", INT2NUM(F_DUP2FD));
#endif
#ifdef F_DUP2FD_CLOEXEC
- /* Document-const: F_DUP2FD_CLOEXEC
- *
+ /*
* It is a FreeBSD specific constant and acts
* similarly as F_DUP2FD but set the FD_CLOEXEC
* flag in addition.
diff --git a/ext/fcntl/fcntl.gemspec b/ext/fcntl/fcntl.gemspec
index 54aadb4b81..d621bc0491 100644
--- a/ext/fcntl/fcntl.gemspec
+++ b/ext/fcntl/fcntl.gemspec
@@ -23,9 +23,10 @@ Gem::Specification.new do |spec|
spec.licenses = ["Ruby", "BSD-2-Clause"]
spec.files = ["ext/fcntl/extconf.rb", "ext/fcntl/fcntl.c"]
+ spec.extra_rdoc_files = [".document", ".rdoc_options", "LICENSE.txt", "README.md"]
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.extensions = "ext/fcntl/extconf.rb"
- spec.required_ruby_version = ">= 2.3.0"
+ spec.required_ruby_version = ">= 2.5.0"
end
diff --git a/ext/fiddle/depend b/ext/fiddle/depend
index 561785275e..43b11ca780 100644
--- a/ext/fiddle/depend
+++ b/ext/fiddle/depend
@@ -200,6 +200,7 @@ closure.o: $(hdrdir)/ruby/internal/special_consts.h
closure.o: $(hdrdir)/ruby/internal/static_assert.h
closure.o: $(hdrdir)/ruby/internal/stdalign.h
closure.o: $(hdrdir)/ruby/internal/stdbool.h
+closure.o: $(hdrdir)/ruby/internal/stdckdint.h
closure.o: $(hdrdir)/ruby/internal/symbol.h
closure.o: $(hdrdir)/ruby/internal/value.h
closure.o: $(hdrdir)/ruby/internal/value_type.h
@@ -364,6 +365,7 @@ conversions.o: $(hdrdir)/ruby/internal/special_consts.h
conversions.o: $(hdrdir)/ruby/internal/static_assert.h
conversions.o: $(hdrdir)/ruby/internal/stdalign.h
conversions.o: $(hdrdir)/ruby/internal/stdbool.h
+conversions.o: $(hdrdir)/ruby/internal/stdckdint.h
conversions.o: $(hdrdir)/ruby/internal/symbol.h
conversions.o: $(hdrdir)/ruby/internal/value.h
conversions.o: $(hdrdir)/ruby/internal/value_type.h
@@ -527,6 +529,7 @@ fiddle.o: $(hdrdir)/ruby/internal/special_consts.h
fiddle.o: $(hdrdir)/ruby/internal/static_assert.h
fiddle.o: $(hdrdir)/ruby/internal/stdalign.h
fiddle.o: $(hdrdir)/ruby/internal/stdbool.h
+fiddle.o: $(hdrdir)/ruby/internal/stdckdint.h
fiddle.o: $(hdrdir)/ruby/internal/symbol.h
fiddle.o: $(hdrdir)/ruby/internal/value.h
fiddle.o: $(hdrdir)/ruby/internal/value_type.h
@@ -690,6 +693,7 @@ function.o: $(hdrdir)/ruby/internal/special_consts.h
function.o: $(hdrdir)/ruby/internal/static_assert.h
function.o: $(hdrdir)/ruby/internal/stdalign.h
function.o: $(hdrdir)/ruby/internal/stdbool.h
+function.o: $(hdrdir)/ruby/internal/stdckdint.h
function.o: $(hdrdir)/ruby/internal/symbol.h
function.o: $(hdrdir)/ruby/internal/value.h
function.o: $(hdrdir)/ruby/internal/value_type.h
@@ -854,6 +858,7 @@ handle.o: $(hdrdir)/ruby/internal/special_consts.h
handle.o: $(hdrdir)/ruby/internal/static_assert.h
handle.o: $(hdrdir)/ruby/internal/stdalign.h
handle.o: $(hdrdir)/ruby/internal/stdbool.h
+handle.o: $(hdrdir)/ruby/internal/stdckdint.h
handle.o: $(hdrdir)/ruby/internal/symbol.h
handle.o: $(hdrdir)/ruby/internal/value.h
handle.o: $(hdrdir)/ruby/internal/value_type.h
@@ -1027,6 +1032,7 @@ memory_view.o: $(hdrdir)/ruby/internal/special_consts.h
memory_view.o: $(hdrdir)/ruby/internal/static_assert.h
memory_view.o: $(hdrdir)/ruby/internal/stdalign.h
memory_view.o: $(hdrdir)/ruby/internal/stdbool.h
+memory_view.o: $(hdrdir)/ruby/internal/stdckdint.h
memory_view.o: $(hdrdir)/ruby/internal/symbol.h
memory_view.o: $(hdrdir)/ruby/internal/value.h
memory_view.o: $(hdrdir)/ruby/internal/value_type.h
@@ -1193,6 +1199,7 @@ pinned.o: $(hdrdir)/ruby/internal/special_consts.h
pinned.o: $(hdrdir)/ruby/internal/static_assert.h
pinned.o: $(hdrdir)/ruby/internal/stdalign.h
pinned.o: $(hdrdir)/ruby/internal/stdbool.h
+pinned.o: $(hdrdir)/ruby/internal/stdckdint.h
pinned.o: $(hdrdir)/ruby/internal/symbol.h
pinned.o: $(hdrdir)/ruby/internal/value.h
pinned.o: $(hdrdir)/ruby/internal/value_type.h
@@ -1366,6 +1373,7 @@ pointer.o: $(hdrdir)/ruby/internal/special_consts.h
pointer.o: $(hdrdir)/ruby/internal/static_assert.h
pointer.o: $(hdrdir)/ruby/internal/stdalign.h
pointer.o: $(hdrdir)/ruby/internal/stdbool.h
+pointer.o: $(hdrdir)/ruby/internal/stdckdint.h
pointer.o: $(hdrdir)/ruby/internal/symbol.h
pointer.o: $(hdrdir)/ruby/internal/value.h
pointer.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/fiddle/fiddle.gemspec b/ext/fiddle/fiddle.gemspec
index 878109395b..3a1072dd49 100644
--- a/ext/fiddle/fiddle.gemspec
+++ b/ext/fiddle/fiddle.gemspec
@@ -56,4 +56,5 @@ Gem::Specification.new do |spec|
spec.required_ruby_version = ">= 2.5.0"
spec.metadata["msys2_mingw_dependencies"] = "libffi"
+ spec.metadata["changelog_uri"] = "https://github.com/ruby/fiddle/releases"
end
diff --git a/ext/fiddle/lib/fiddle/version.rb b/ext/fiddle/lib/fiddle/version.rb
index 706d98a7b5..6c5109dca8 100644
--- a/ext/fiddle/lib/fiddle/version.rb
+++ b/ext/fiddle/lib/fiddle/version.rb
@@ -1,3 +1,3 @@
module Fiddle
- VERSION = "1.1.2"
+ VERSION = "1.1.3"
end
diff --git a/ext/io/console/console.c b/ext/io/console/console.c
index 61b6e76327..7130c29a8b 100644
--- a/ext/io/console/console.c
+++ b/ext/io/console/console.c
@@ -2,6 +2,10 @@
/*
* console IO module
*/
+
+static const char *const
+IO_CONSOLE_VERSION = "0.7.2";
+
#include "ruby.h"
#include "ruby/io.h"
#include "ruby/thread.h"
@@ -75,6 +79,8 @@ getattr(int fd, conmode *t)
#define SET_LAST_ERROR (0)
#endif
+#define CSI "\x1b\x5b"
+
static ID id_getc, id_console, id_close;
static ID id_gets, id_flush, id_chomp_bang;
@@ -896,6 +902,16 @@ console_set_winsize(VALUE io, VALUE size)
#endif
#ifdef _WIN32
+/*
+ * call-seq:
+ * io.check_winsize_changed { ... } -> io
+ *
+ * Yields while console input events are queued.
+ *
+ * This method is Windows only.
+ *
+ * You must require 'io/console' to use this method.
+ */
static VALUE
console_check_winsize_changed(VALUE io)
{
@@ -982,6 +998,14 @@ console_ioflush(VALUE io)
return io;
}
+/*
+ * call-seq:
+ * io.beep
+ *
+ * Beeps on the output console.
+ *
+ * You must require 'io/console' to use this method.
+ */
static VALUE
console_beep(VALUE io)
{
@@ -1049,6 +1073,17 @@ console_scroll(VALUE io, int line)
#include "win32_vk.inc"
+/*
+ * call-seq:
+ * io.pressed?(key) -> bool
+ *
+ * Returns +true+ if +key+ is pressed. +key+ may be a virtual key
+ * code or its name (String or Symbol) with out "VK_" prefix.
+ *
+ * This method is Windows only.
+ *
+ * You must require 'io/console' to use this method.
+ */
static VALUE
console_key_pressed_p(VALUE io, VALUE k)
{
@@ -1142,7 +1177,7 @@ static VALUE
console_scroll(VALUE io, int line)
{
if (line) {
- VALUE s = rb_sprintf("\x1b[%d%c", line < 0 ? -line : line,
+ VALUE s = rb_sprintf(CSI "%d%c", line < 0 ? -line : line,
line < 0 ? 'T' : 'S');
rb_io_write(io, s);
}
@@ -1152,6 +1187,16 @@ console_scroll(VALUE io, int line)
# define console_key_pressed_p rb_f_notimplement
#endif
+/*
+ * call-seq:
+ * io.cursor -> [row, column]
+ *
+ * Returns the current cursor position as a two-element array of integers (row, column)
+ *
+ * io.cursor # => [3, 5]
+ *
+ * You must require 'io/console' to use this method.
+ */
static VALUE
console_cursor_pos(VALUE io)
{
@@ -1182,6 +1227,14 @@ console_cursor_pos(VALUE io)
#endif
}
+/*
+ * call-seq:
+ * io.goto(line, column) -> io
+ *
+ * Set the cursor position at +line+ and +column+.
+ *
+ * You must require 'io/console' to use this method.
+ */
static VALUE
console_goto(VALUE io, VALUE y, VALUE x)
{
@@ -1194,7 +1247,7 @@ console_goto(VALUE io, VALUE y, VALUE x)
rb_syserr_fail(LAST_ERROR, 0);
}
#else
- rb_io_write(io, rb_sprintf("\x1b[%d;%dH", NUM2UINT(y)+1, NUM2UINT(x)+1));
+ rb_io_write(io, rb_sprintf(CSI "%d;%dH", NUM2UINT(y)+1, NUM2UINT(x)+1));
#endif
return io;
}
@@ -1219,8 +1272,8 @@ console_move(VALUE io, int y, int x)
#else
if (x || y) {
VALUE s = rb_str_new_cstr("");
- if (y) rb_str_catf(s, "\x1b[%d%c", y < 0 ? -y : y, y < 0 ? 'A' : 'B');
- if (x) rb_str_catf(s, "\x1b[%d%c", x < 0 ? -x : x, x < 0 ? 'D' : 'C');
+ if (y) rb_str_catf(s, CSI "%d%c", y < 0 ? -y : y, y < 0 ? 'A' : 'B');
+ if (x) rb_str_catf(s, CSI "%d%c", x < 0 ? -x : x, x < 0 ? 'D' : 'C');
rb_io_write(io, s);
rb_io_flush(io);
}
@@ -1228,6 +1281,15 @@ console_move(VALUE io, int y, int x)
return io;
}
+/*
+ * call-seq:
+ * io.goto_column(column) -> io
+ *
+ * Set the cursor position at +column+ in the same line of the current
+ * position.
+ *
+ * You must require 'io/console' to use this method.
+ */
static VALUE
console_goto_column(VALUE io, VALUE val)
{
@@ -1245,11 +1307,23 @@ console_goto_column(VALUE io, VALUE val)
rb_syserr_fail(LAST_ERROR, 0);
}
#else
- rb_io_write(io, rb_sprintf("\x1b[%dG", NUM2UINT(val)+1));
+ rb_io_write(io, rb_sprintf(CSI "%dG", NUM2UINT(val)+1));
#endif
return io;
}
+/*
+ * call-seq:
+ * io.erase_line(mode) -> io
+ *
+ * Erases the line at the cursor corresponding to +mode+.
+ * +mode+ may be either:
+ * 0: after cursor
+ * 1: before and cursor
+ * 2: entire line
+ *
+ * You must require 'io/console' to use this method.
+ */
static VALUE
console_erase_line(VALUE io, VALUE val)
{
@@ -1280,11 +1354,23 @@ console_erase_line(VALUE io, VALUE val)
constat_clear(h, ws.wAttributes, w, *pos);
return io;
#else
- rb_io_write(io, rb_sprintf("\x1b[%dK", mode));
+ rb_io_write(io, rb_sprintf(CSI "%dK", mode));
#endif
return io;
}
+/*
+ * call-seq:
+ * io.erase_screen(mode) -> io
+ *
+ * Erases the screen at the cursor corresponding to +mode+.
+ * +mode+ may be either:
+ * 0: after cursor
+ * 1: before and cursor
+ * 2: entire screen
+ *
+ * You must require 'io/console' to use this method.
+ */
static VALUE
console_erase_screen(VALUE io, VALUE val)
{
@@ -1322,11 +1408,21 @@ console_erase_screen(VALUE io, VALUE val)
}
constat_clear(h, ws.wAttributes, w, *pos);
#else
- rb_io_write(io, rb_sprintf("\x1b[%dJ", mode));
+ rb_io_write(io, rb_sprintf(CSI "%dJ", mode));
#endif
return io;
}
+/*
+ * call-seq:
+ * io.cursor = [line, column] -> io
+ *
+ * Same as <tt>io.goto(line, column)</tt>
+ *
+ * See IO#goto.
+ *
+ * You must require 'io/console' to use this method.
+ */
static VALUE
console_cursor_set(VALUE io, VALUE cpos)
{
@@ -1335,42 +1431,98 @@ console_cursor_set(VALUE io, VALUE cpos)
return console_goto(io, RARRAY_AREF(cpos, 0), RARRAY_AREF(cpos, 1));
}
+/*
+ * call-seq:
+ * io.cursor_up(n) -> io
+ *
+ * Moves the cursor up +n+ lines.
+ *
+ * You must require 'io/console' to use this method.
+ */
static VALUE
console_cursor_up(VALUE io, VALUE val)
{
return console_move(io, -NUM2INT(val), 0);
}
+/*
+ * call-seq:
+ * io.cursor_down(n) -> io
+ *
+ * Moves the cursor down +n+ lines.
+ *
+ * You must require 'io/console' to use this method.
+ */
static VALUE
console_cursor_down(VALUE io, VALUE val)
{
return console_move(io, +NUM2INT(val), 0);
}
+/*
+ * call-seq:
+ * io.cursor_left(n) -> io
+ *
+ * Moves the cursor left +n+ columns.
+ *
+ * You must require 'io/console' to use this method.
+ */
static VALUE
console_cursor_left(VALUE io, VALUE val)
{
return console_move(io, 0, -NUM2INT(val));
}
+/*
+ * call-seq:
+ * io.cursor_right(n) -> io
+ *
+ * Moves the cursor right +n+ columns.
+ *
+ * You must require 'io/console' to use this method.
+ */
static VALUE
console_cursor_right(VALUE io, VALUE val)
{
return console_move(io, 0, +NUM2INT(val));
}
+/*
+ * call-seq:
+ * io.scroll_forward(n) -> io
+ *
+ * Scrolls the entire scrolls forward +n+ lines.
+ *
+ * You must require 'io/console' to use this method.
+ */
static VALUE
console_scroll_forward(VALUE io, VALUE val)
{
return console_scroll(io, +NUM2INT(val));
}
+/*
+ * call-seq:
+ * io.scroll_backward(n) -> io
+ *
+ * Scrolls the entire scrolls backward +n+ lines.
+ *
+ * You must require 'io/console' to use this method.
+ */
static VALUE
console_scroll_backward(VALUE io, VALUE val)
{
return console_scroll(io, -NUM2INT(val));
}
+/*
+ * call-seq:
+ * io.clear_screen -> io
+ *
+ * Clears the entire screen and moves the cursor top-left corner.
+ *
+ * You must require 'io/console' to use this method.
+ */
static VALUE
console_clear_screen(VALUE io)
{
@@ -1665,14 +1817,16 @@ InitVM_console(void)
rb_define_method(rb_cIO, "getpass", console_getpass, -1);
rb_define_singleton_method(rb_cIO, "console", console_dev, -1);
{
+ /* :stopdoc: */
VALUE mReadable = rb_define_module_under(rb_cIO, "generic_readable");
+ /* :startdoc: */
rb_define_method(mReadable, "getch", io_getch, -1);
rb_define_method(mReadable, "getpass", io_getpass, -1);
}
{
/* :stopdoc: */
cConmode = rb_define_class_under(rb_cIO, "ConsoleMode", rb_cObject);
- rb_define_const(cConmode, "VERSION", rb_str_new_cstr(STRINGIZE(IO_CONSOLE_VERSION)));
+ rb_define_const(cConmode, "VERSION", rb_str_new_cstr(IO_CONSOLE_VERSION));
rb_define_alloc_func(cConmode, conmode_alloc);
rb_undef_method(cConmode, "initialize");
rb_define_method(cConmode, "initialize_copy", conmode_init_copy, 1);
diff --git a/ext/io/console/depend b/ext/io/console/depend
index 59ca3442c2..5b91413f38 100644
--- a/ext/io/console/depend
+++ b/ext/io/console/depend
@@ -158,6 +158,7 @@ console.o: $(hdrdir)/ruby/internal/special_consts.h
console.o: $(hdrdir)/ruby/internal/static_assert.h
console.o: $(hdrdir)/ruby/internal/stdalign.h
console.o: $(hdrdir)/ruby/internal/stdbool.h
+console.o: $(hdrdir)/ruby/internal/stdckdint.h
console.o: $(hdrdir)/ruby/internal/symbol.h
console.o: $(hdrdir)/ruby/internal/value.h
console.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/io/console/extconf.rb b/ext/io/console/extconf.rb
index aa0b6c6cfb..a72403c7f9 100644
--- a/ext/io/console/extconf.rb
+++ b/ext/io/console/extconf.rb
@@ -1,11 +1,6 @@
# frozen_string_literal: false
require 'mkmf'
-version = ["../../..", "."].find do |dir|
- break File.read(File.join(__dir__, dir, "io-console.gemspec"))[/^_VERSION\s*=\s*"(.*?)"/, 1]
-rescue
-end
-
have_func("rb_io_path")
have_func("rb_io_descriptor")
have_func("rb_io_get_write_io")
@@ -40,7 +35,6 @@ when true
elsif have_func("rb_scheduler_timeout") # 3.0
have_func("rb_io_wait")
end
- $defs << "-D""IO_CONSOLE_VERSION=#{version}"
create_makefile("io/console") {|conf|
conf << "\n""VK_HEADER = #{vk_header}\n"
}
diff --git a/ext/io/console/io-console.gemspec b/ext/io/console/io-console.gemspec
index 32261e8c39..f9c1729cb7 100644
--- a/ext/io/console/io-console.gemspec
+++ b/ext/io/console/io-console.gemspec
@@ -1,5 +1,13 @@
# -*- ruby -*-
-_VERSION = "0.6.1.dev.1"
+_VERSION = ["", "ext/io/console/"].find do |dir|
+ begin
+ break File.open(File.join(__dir__, "#{dir}console.c")) {|f|
+ f.gets("\nIO_CONSOLE_VERSION ")
+ f.gets[/"(.+)"/, 1]
+ }
+ rescue Errno::ENOENT
+ end
+end
Gem::Specification.new do |s|
s.name = "io-console"
@@ -10,6 +18,7 @@ Gem::Specification.new do |s|
s.required_ruby_version = ">= 2.6.0"
s.homepage = "https://github.com/ruby/io-console"
s.metadata["source_code_url"] = s.homepage
+ s.metadata["changelog_uri"] = s.homepage + "/releases"
s.authors = ["Nobu Nakada"]
s.require_path = %[lib]
s.files = %w[
diff --git a/ext/io/nonblock/depend b/ext/io/nonblock/depend
index 48384fca62..20a96f1252 100644
--- a/ext/io/nonblock/depend
+++ b/ext/io/nonblock/depend
@@ -157,6 +157,7 @@ nonblock.o: $(hdrdir)/ruby/internal/special_consts.h
nonblock.o: $(hdrdir)/ruby/internal/static_assert.h
nonblock.o: $(hdrdir)/ruby/internal/stdalign.h
nonblock.o: $(hdrdir)/ruby/internal/stdbool.h
+nonblock.o: $(hdrdir)/ruby/internal/stdckdint.h
nonblock.o: $(hdrdir)/ruby/internal/symbol.h
nonblock.o: $(hdrdir)/ruby/internal/value.h
nonblock.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/io/nonblock/io-nonblock.gemspec b/ext/io/nonblock/io-nonblock.gemspec
index d6df21a84d..6a16c8b03b 100644
--- a/ext/io/nonblock/io-nonblock.gemspec
+++ b/ext/io/nonblock/io-nonblock.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "io-nonblock"
- spec.version = "0.2.0"
+ spec.version = "0.3.0"
spec.authors = ["Nobu Nakada"]
spec.email = ["nobu@ruby-lang.org"]
diff --git a/ext/io/wait/depend b/ext/io/wait/depend
index 83cf8f94c8..70317b1497 100644
--- a/ext/io/wait/depend
+++ b/ext/io/wait/depend
@@ -158,6 +158,7 @@ wait.o: $(hdrdir)/ruby/internal/special_consts.h
wait.o: $(hdrdir)/ruby/internal/static_assert.h
wait.o: $(hdrdir)/ruby/internal/stdalign.h
wait.o: $(hdrdir)/ruby/internal/stdbool.h
+wait.o: $(hdrdir)/ruby/internal/stdckdint.h
wait.o: $(hdrdir)/ruby/internal/symbol.h
wait.o: $(hdrdir)/ruby/internal/value.h
wait.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/io/wait/io-wait.gemspec b/ext/io/wait/io-wait.gemspec
index ebc1f6f5c7..e850e10bf9 100644
--- a/ext/io/wait/io-wait.gemspec
+++ b/ext/io/wait/io-wait.gemspec
@@ -1,4 +1,4 @@
-_VERSION = "0.3.0"
+_VERSION = "0.3.1"
Gem::Specification.new do |spec|
spec.name = "io-wait"
diff --git a/ext/json/VERSION b/ext/json/VERSION
deleted file mode 100644
index ec1cf33c3f..0000000000
--- a/ext/json/VERSION
+++ /dev/null
@@ -1 +0,0 @@
-2.6.3
diff --git a/ext/json/generator/depend b/ext/json/generator/depend
index 42752d1a35..f47e5f3a70 100644
--- a/ext/json/generator/depend
+++ b/ext/json/generator/depend
@@ -161,6 +161,7 @@ generator.o: $(hdrdir)/ruby/internal/special_consts.h
generator.o: $(hdrdir)/ruby/internal/static_assert.h
generator.o: $(hdrdir)/ruby/internal/stdalign.h
generator.o: $(hdrdir)/ruby/internal/stdbool.h
+generator.o: $(hdrdir)/ruby/internal/stdckdint.h
generator.o: $(hdrdir)/ruby/internal/symbol.h
generator.o: $(hdrdir)/ruby/internal/value.h
generator.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/json/generator/extconf.rb b/ext/json/generator/extconf.rb
index 8627c5f4bd..cf8d5f2bda 100644
--- a/ext/json/generator/extconf.rb
+++ b/ext/json/generator/extconf.rb
@@ -1,4 +1,9 @@
require 'mkmf'
-$defs << "-DJSON_GENERATOR"
-create_makefile 'json/ext/generator'
+if RUBY_ENGINE == 'truffleruby'
+ # The pure-Ruby generator is faster on TruffleRuby, so skip compiling the generator extension
+ File.write('Makefile', dummy_makefile("").join)
+else
+ $defs << "-DJSON_GENERATOR"
+ create_makefile 'json/ext/generator'
+end
diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c
index 8f7c57e042..e968619205 100644
--- a/ext/json/generator/generator.c
+++ b/ext/json/generator/generator.c
@@ -16,7 +16,7 @@ static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
i_object_nl, i_array_nl, i_max_nesting, i_allow_nan, i_ascii_only,
i_pack, i_unpack, i_create_id, i_extend, i_key_p,
i_aref, i_send, i_respond_to_p, i_match, i_keys, i_depth,
- i_buffer_initial_length, i_dup, i_escape_slash;
+ i_buffer_initial_length, i_dup, i_script_safe, i_escape_slash, i_strict;
/*
* Copyright 2001-2004 Unicode, Inc.
@@ -124,7 +124,7 @@ static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16
/* Converts string to a JSON string in FBuffer buffer, where all but the ASCII
* and control characters are JSON escaped. */
-static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char escape_slash)
+static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char script_safe)
{
const UTF8 *source = (UTF8 *) RSTRING_PTR(string);
const UTF8 *sourceEnd = source + RSTRING_LEN(string);
@@ -175,7 +175,7 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char escap
fbuffer_append(buffer, "\\\"", 2);
break;
case '/':
- if(escape_slash) {
+ if(script_safe) {
fbuffer_append(buffer, "\\/", 2);
break;
}
@@ -228,7 +228,7 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char escap
* characters required by the JSON standard are JSON escaped. The remaining
* characters (should be UTF8) are just passed through and appended to the
* result. */
-static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char escape_slash)
+static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char script_safe)
{
const char *ptr = RSTRING_PTR(string), *p;
unsigned long len = RSTRING_LEN(string), start = 0, end = 0;
@@ -280,7 +280,7 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char escape_slas
escape_len = 2;
break;
case '/':
- if(escape_slash) {
+ if(script_safe) {
escape = "\\/";
escape_len = 2;
break;
@@ -294,6 +294,22 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char escape_slas
rb_raise(rb_path2class("JSON::GeneratorError"),
"partial character in source, but hit end");
}
+
+ if (script_safe && c == 0xE2) {
+ unsigned char c2 = (unsigned char) *(p+1);
+ unsigned char c3 = (unsigned char) *(p+2);
+ if (c2 == 0x80 && (c3 == 0xA8 || c3 == 0xA9)) {
+ fbuffer_append(buffer, ptr + start, end - start);
+ start = end = (end + clen);
+ if (c3 == 0xA8) {
+ fbuffer_append(buffer, "\\u2028", 6);
+ } else {
+ fbuffer_append(buffer, "\\u2029", 6);
+ }
+ continue;
+ }
+ }
+
if (!isLegalUTF8((UTF8 *) p, clen)) {
rb_raise(rb_path2class("JSON::GeneratorError"),
"source sequence is illegal/malformed utf-8");
@@ -620,16 +636,12 @@ static size_t State_memsize(const void *ptr)
# define RUBY_TYPED_FROZEN_SHAREABLE 0
#endif
-#ifdef NEW_TYPEDDATA_WRAPPER
static const rb_data_type_t JSON_Generator_State_type = {
"JSON/Generator/State",
{NULL, State_free, State_memsize,},
-#ifdef RUBY_TYPED_FREE_IMMEDIATELY
0, 0,
- RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE,
-#endif
+ RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE,
};
-#endif
static VALUE cState_s_allocate(VALUE klass)
{
@@ -727,8 +739,14 @@ static VALUE cState_configure(VALUE self, VALUE opts)
state->allow_nan = RTEST(tmp);
tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
state->ascii_only = RTEST(tmp);
- tmp = rb_hash_aref(opts, ID2SYM(i_escape_slash));
- state->escape_slash = RTEST(tmp);
+ tmp = rb_hash_aref(opts, ID2SYM(i_script_safe));
+ state->script_safe = RTEST(tmp);
+ if (!state->script_safe) {
+ tmp = rb_hash_aref(opts, ID2SYM(i_escape_slash));
+ state->script_safe = RTEST(tmp);
+ }
+ tmp = rb_hash_aref(opts, ID2SYM(i_strict));
+ state->strict = RTEST(tmp);
return self;
}
@@ -763,7 +781,8 @@ static VALUE cState_to_h(VALUE self)
rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse);
rb_hash_aset(result, ID2SYM(i_ascii_only), state->ascii_only ? Qtrue : Qfalse);
rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
- rb_hash_aset(result, ID2SYM(i_escape_slash), state->escape_slash ? Qtrue : Qfalse);
+ rb_hash_aset(result, ID2SYM(i_script_safe), state->script_safe ? Qtrue : Qfalse);
+ rb_hash_aset(result, ID2SYM(i_strict), state->strict ? Qtrue : Qfalse);
rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth));
rb_hash_aset(result, ID2SYM(i_buffer_initial_length), LONG2FIX(state->buffer_initial_length));
return result;
@@ -844,7 +863,7 @@ json_object_i(VALUE key, VALUE val, VALUE _arg)
if (klass == rb_cString) {
key_to_s = key;
} else if (klass == rb_cSymbol) {
- key_to_s = rb_id2str(SYM2ID(key));
+ key_to_s = rb_sym2str(key);
} else {
key_to_s = rb_funcall(key, i_to_s, 0);
}
@@ -869,7 +888,6 @@ static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_S
struct hash_foreach_arg arg;
if (max_nesting != 0 && depth > max_nesting) {
- fbuffer_free(buffer);
rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
}
fbuffer_append_char(buffer, '{');
@@ -904,7 +922,6 @@ static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
long depth = ++state->depth;
int i, j;
if (max_nesting != 0 && depth > max_nesting) {
- fbuffer_free(buffer);
rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
}
fbuffer_append_char(buffer, '[');
@@ -948,9 +965,9 @@ static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_S
}
#endif
if (state->ascii_only) {
- convert_UTF8_to_JSON_ASCII(buffer, obj, state->escape_slash);
+ convert_UTF8_to_JSON_ASCII(buffer, obj, state->script_safe);
} else {
- convert_UTF8_to_JSON(buffer, obj, state->escape_slash);
+ convert_UTF8_to_JSON(buffer, obj, state->script_safe);
}
fbuffer_append_char(buffer, '"');
}
@@ -997,10 +1014,8 @@ static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
VALUE tmp = rb_funcall(obj, i_to_s, 0);
if (!allow_nan) {
if (isinf(value)) {
- fbuffer_free(buffer);
rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(tmp));
} else if (isnan(value)) {
- fbuffer_free(buffer);
rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(tmp));
}
}
@@ -1029,6 +1044,8 @@ static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *s
generate_json_bignum(buffer, Vstate, state, obj);
} else if (klass == rb_cFloat) {
generate_json_float(buffer, Vstate, state, obj);
+ } else if (state->strict) {
+ rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(CLASS_OF(obj)));
} else if (rb_respond_to(obj, i_to_json)) {
tmp = rb_funcall(obj, i_to_json, 1, Vstate);
Check_Type(tmp, T_STRING);
@@ -1071,11 +1088,45 @@ static FBuffer *cState_prepare_buffer(VALUE self)
return buffer;
}
+struct generate_json_data {
+ FBuffer *buffer;
+ VALUE vstate;
+ JSON_Generator_State *state;
+ VALUE obj;
+};
+
+static VALUE generate_json_try(VALUE d)
+{
+ struct generate_json_data *data = (struct generate_json_data *)d;
+
+ generate_json(data->buffer, data->vstate, data->state, data->obj);
+
+ return Qnil;
+}
+
+static VALUE generate_json_rescue(VALUE d, VALUE exc)
+{
+ struct generate_json_data *data = (struct generate_json_data *)d;
+ fbuffer_free(data->buffer);
+
+ rb_exc_raise(exc);
+
+ return Qundef;
+}
+
static VALUE cState_partial_generate(VALUE self, VALUE obj)
{
FBuffer *buffer = cState_prepare_buffer(self);
GET_STATE(self);
- generate_json(buffer, self, state, obj);
+
+ struct generate_json_data data = {
+ .buffer = buffer,
+ .vstate = self,
+ .state = state,
+ .obj = obj
+ };
+ rb_rescue(generate_json_try, (VALUE)&data, generate_json_rescue, (VALUE)&data);
+
return fbuffer_to_s(buffer);
}
@@ -1391,27 +1442,58 @@ static VALUE cState_max_nesting_set(VALUE self, VALUE depth)
}
/*
- * call-seq: escape_slash
+ * call-seq: script_safe
*
* If this boolean is true, the forward slashes will be escaped in
* the json output.
*/
-static VALUE cState_escape_slash(VALUE self)
+static VALUE cState_script_safe(VALUE self)
{
GET_STATE(self);
- return state->escape_slash ? Qtrue : Qfalse;
+ return state->script_safe ? Qtrue : Qfalse;
}
/*
- * call-seq: escape_slash=(depth)
+ * call-seq: script_safe=(enable)
*
* This sets whether or not the forward slashes will be escaped in
* the json output.
*/
-static VALUE cState_escape_slash_set(VALUE self, VALUE enable)
+static VALUE cState_script_safe_set(VALUE self, VALUE enable)
+{
+ GET_STATE(self);
+ state->script_safe = RTEST(enable);
+ return Qnil;
+}
+
+/*
+ * call-seq: strict
+ *
+ * If this boolean is false, types unsupported by the JSON format will
+ * be serialized as strings.
+ * If this boolean is true, types unsupported by the JSON format will
+ * raise a JSON::GeneratorError.
+ */
+static VALUE cState_strict(VALUE self)
+{
+ GET_STATE(self);
+ return state->strict ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq: strict=(enable)
+ *
+ * This sets whether or not to serialize types unsupported by the
+ * JSON format as strings.
+ * If this boolean is false, types unsupported by the JSON format will
+ * be serialized as strings.
+ * If this boolean is true, types unsupported by the JSON format will
+ * raise a JSON::GeneratorError.
+ */
+static VALUE cState_strict_set(VALUE self, VALUE enable)
{
GET_STATE(self);
- state->escape_slash = RTEST(enable);
+ state->strict = RTEST(enable);
return Qnil;
}
@@ -1531,9 +1613,15 @@ void Init_generator(void)
rb_define_method(cState, "array_nl=", cState_array_nl_set, 1);
rb_define_method(cState, "max_nesting", cState_max_nesting, 0);
rb_define_method(cState, "max_nesting=", cState_max_nesting_set, 1);
- rb_define_method(cState, "escape_slash", cState_escape_slash, 0);
- rb_define_method(cState, "escape_slash?", cState_escape_slash, 0);
- rb_define_method(cState, "escape_slash=", cState_escape_slash_set, 1);
+ rb_define_method(cState, "script_safe", cState_script_safe, 0);
+ rb_define_method(cState, "script_safe?", cState_script_safe, 0);
+ rb_define_method(cState, "script_safe=", cState_script_safe_set, 1);
+ rb_define_alias(cState, "escape_slash", "script_safe");
+ rb_define_alias(cState, "escape_slash?", "script_safe?");
+ rb_define_alias(cState, "escape_slash=", "script_safe=");
+ rb_define_method(cState, "strict", cState_strict, 0);
+ rb_define_method(cState, "strict?", cState_strict, 0);
+ rb_define_method(cState, "strict=", cState_strict_set, 1);
rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
@@ -1590,7 +1678,9 @@ void Init_generator(void)
i_object_nl = rb_intern("object_nl");
i_array_nl = rb_intern("array_nl");
i_max_nesting = rb_intern("max_nesting");
+ i_script_safe = rb_intern("script_safe");
i_escape_slash = rb_intern("escape_slash");
+ i_strict = rb_intern("strict");
i_allow_nan = rb_intern("allow_nan");
i_ascii_only = rb_intern("ascii_only");
i_depth = rb_intern("depth");
diff --git a/ext/json/generator/generator.h b/ext/json/generator/generator.h
index 3ebd622554..98b7d833f3 100644
--- a/ext/json/generator/generator.h
+++ b/ext/json/generator/generator.h
@@ -49,8 +49,8 @@ static const UTF32 halfMask = 0x3FFUL;
static unsigned char isLegalUTF8(const UTF8 *source, unsigned long length);
static void unicode_escape(char *buf, UTF16 character);
static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16 character);
-static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char escape_slash);
-static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char escape_slash);
+static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char script_safe);
+static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char script_safe);
static char *fstrndup(const char *ptr, unsigned long len);
/* ruby api and some helpers */
@@ -72,7 +72,8 @@ typedef struct JSON_Generator_StateStruct {
long max_nesting;
char allow_nan;
char ascii_only;
- char escape_slash;
+ char script_safe;
+ char strict;
long depth;
long buffer_initial_length;
} JSON_Generator_State;
@@ -151,8 +152,10 @@ static VALUE cState_allow_nan_p(VALUE self);
static VALUE cState_ascii_only_p(VALUE self);
static VALUE cState_depth(VALUE self);
static VALUE cState_depth_set(VALUE self, VALUE depth);
-static VALUE cState_escape_slash(VALUE self);
-static VALUE cState_escape_slash_set(VALUE self, VALUE depth);
+static VALUE cState_script_safe(VALUE self);
+static VALUE cState_script_safe_set(VALUE self, VALUE depth);
+static VALUE cState_strict(VALUE self);
+static VALUE cState_strict_set(VALUE self, VALUE strict);
static FBuffer *cState_prepare_buffer(VALUE self);
#ifndef ZALLOC
#define ZALLOC(type) ((type *)ruby_zalloc(sizeof(type)))
@@ -163,12 +166,7 @@ static inline void *ruby_zalloc(size_t n)
return p;
}
#endif
-#ifdef TypedData_Make_Struct
+
static const rb_data_type_t JSON_Generator_State_type;
-#define NEW_TYPEDDATA_WRAPPER 1
-#else
-#define TypedData_Make_Struct(klass, type, ignore, json) Data_Make_Struct(klass, type, NULL, State_free, json)
-#define TypedData_Get_Struct(self, JSON_Generator_State, ignore, json) Data_Get_Struct(self, JSON_Generator_State, json)
-#endif
#endif
diff --git a/ext/json/json.gemspec b/ext/json/json.gemspec
index f4b2ae791d..64d0c81391 100644
--- a/ext/json/json.gemspec
+++ b/ext/json/json.gemspec
@@ -1,8 +1,10 @@
-# -*- encoding: utf-8 -*-
+version = File.foreach(File.join(__dir__, "lib/json/version.rb")) do |line|
+ /^\s*VERSION\s*=\s*'(.*)'/ =~ line and break $1
+end rescue nil
Gem::Specification.new do |s|
s.name = "json"
- s.version = File.read(File.expand_path('../VERSION', __FILE__)).chomp
+ s.version = version
s.summary = "JSON Implementation for Ruby"
s.description = "This is a JSON implementation as a Ruby extension in C."
@@ -17,7 +19,6 @@ Gem::Specification.new do |s|
"CHANGES.md",
"LICENSE",
"README.md",
- "VERSION",
"ext/json/ext/fbuffer/fbuffer.h",
"ext/json/ext/generator/depend",
"ext/json/ext/generator/extconf.rb",
diff --git a/ext/json/lib/json.rb b/ext/json/lib/json.rb
index 1e64bfcb1a..807488ffef 100644
--- a/ext/json/lib/json.rb
+++ b/ext/json/lib/json.rb
@@ -285,6 +285,15 @@ require 'json/common'
# # Raises JSON::NestingError (nesting of 2 is too deep):
# JSON.generate(obj, max_nesting: 2)
#
+# ====== Escaping Options
+#
+# Options +script_safe+ (boolean) specifies wether <tt>'\u2028'</tt>, <tt>'\u2029'</tt>
+# and <tt>'/'</tt> should be escaped as to make the JSON object safe to interpolate in script
+# tags.
+#
+# Options +ascii_only+ (boolean) specifies wether all characters outside the ASCII range
+# should be escaped.
+#
# ====== Output Options
#
# The default formatting options generate the most compact
diff --git a/ext/json/lib/json/add/bigdecimal.rb b/ext/json/lib/json/add/bigdecimal.rb
index 25383f28ed..b1d0cfa043 100644
--- a/ext/json/lib/json/add/bigdecimal.rb
+++ b/ext/json/lib/json/add/bigdecimal.rb
@@ -8,16 +8,30 @@ rescue LoadError
end
class BigDecimal
- # Import a JSON Marshalled object.
- #
- # method used for JSON marshalling support.
+
+ # See #as_json.
def self.json_create(object)
BigDecimal._load object['b']
end
- # Marshal the object to JSON.
+ # Methods <tt>BigDecimal#as_json</tt> and +BigDecimal.json_create+ may be used
+ # to serialize and deserialize a \BigDecimal object;
+ # see Marshal[rdoc-ref:Marshal].
+ #
+ # \Method <tt>BigDecimal#as_json</tt> serializes +self+,
+ # returning a 2-element hash representing +self+:
+ #
+ # require 'json/add/bigdecimal'
+ # x = BigDecimal(2).as_json # => {"json_class"=>"BigDecimal", "b"=>"27:0.2e1"}
+ # y = BigDecimal(2.0, 4).as_json # => {"json_class"=>"BigDecimal", "b"=>"36:0.2e1"}
+ # z = BigDecimal(Complex(2, 0)).as_json # => {"json_class"=>"BigDecimal", "b"=>"27:0.2e1"}
+ #
+ # \Method +JSON.create+ deserializes such a hash, returning a \BigDecimal object:
+ #
+ # BigDecimal.json_create(x) # => 0.2e1
+ # BigDecimal.json_create(y) # => 0.2e1
+ # BigDecimal.json_create(z) # => 0.2e1
#
- # method used for JSON marshalling support.
def as_json(*)
{
JSON.create_id => self.class.name,
@@ -25,7 +39,19 @@ class BigDecimal
}
end
- # return the JSON value
+ # Returns a JSON string representing +self+:
+ #
+ # require 'json/add/bigdecimal'
+ # puts BigDecimal(2).to_json
+ # puts BigDecimal(2.0, 4).to_json
+ # puts BigDecimal(Complex(2, 0)).to_json
+ #
+ # Output:
+ #
+ # {"json_class":"BigDecimal","b":"27:0.2e1"}
+ # {"json_class":"BigDecimal","b":"36:0.2e1"}
+ # {"json_class":"BigDecimal","b":"27:0.2e1"}
+ #
def to_json(*args)
as_json.to_json(*args)
end
diff --git a/ext/json/lib/json/add/complex.rb b/ext/json/lib/json/add/complex.rb
index e63e29fd22..ef48c554c6 100644
--- a/ext/json/lib/json/add/complex.rb
+++ b/ext/json/lib/json/add/complex.rb
@@ -5,14 +5,27 @@ end
class Complex
- # Deserializes JSON string by converting Real value <tt>r</tt>, imaginary
- # value <tt>i</tt>, to a Complex object.
+ # See #as_json.
def self.json_create(object)
Complex(object['r'], object['i'])
end
- # Returns a hash, that will be turned into a JSON object and represent this
- # object.
+ # Methods <tt>Complex#as_json</tt> and +Complex.json_create+ may be used
+ # to serialize and deserialize a \Complex object;
+ # see Marshal[rdoc-ref:Marshal].
+ #
+ # \Method <tt>Complex#as_json</tt> serializes +self+,
+ # returning a 2-element hash representing +self+:
+ #
+ # require 'json/add/complex'
+ # x = Complex(2).as_json # => {"json_class"=>"Complex", "r"=>2, "i"=>0}
+ # y = Complex(2.0, 4).as_json # => {"json_class"=>"Complex", "r"=>2.0, "i"=>4}
+ #
+ # \Method +JSON.create+ deserializes such a hash, returning a \Complex object:
+ #
+ # Complex.json_create(x) # => (2+0i)
+ # Complex.json_create(y) # => (2.0+4i)
+ #
def as_json(*)
{
JSON.create_id => self.class.name,
@@ -21,7 +34,17 @@ class Complex
}
end
- # Stores class name (Complex) along with real value <tt>r</tt> and imaginary value <tt>i</tt> as JSON string
+ # Returns a JSON string representing +self+:
+ #
+ # require 'json/add/complex'
+ # puts Complex(2).to_json
+ # puts Complex(2.0, 4).to_json
+ #
+ # Output:
+ #
+ # {"json_class":"Complex","r":2,"i":0}
+ # {"json_class":"Complex","r":2.0,"i":4}
+ #
def to_json(*args)
as_json.to_json(*args)
end
diff --git a/ext/json/lib/json/add/date.rb b/ext/json/lib/json/add/date.rb
index 25523561a5..19688f751b 100644
--- a/ext/json/lib/json/add/date.rb
+++ b/ext/json/lib/json/add/date.rb
@@ -6,16 +6,29 @@ require 'date'
class Date
- # Deserializes JSON string by converting Julian year <tt>y</tt>, month
- # <tt>m</tt>, day <tt>d</tt> and Day of Calendar Reform <tt>sg</tt> to Date.
+ # See #as_json.
def self.json_create(object)
civil(*object.values_at('y', 'm', 'd', 'sg'))
end
alias start sg unless method_defined?(:start)
- # Returns a hash, that will be turned into a JSON object and represent this
- # object.
+ # Methods <tt>Date#as_json</tt> and +Date.json_create+ may be used
+ # to serialize and deserialize a \Date object;
+ # see Marshal[rdoc-ref:Marshal].
+ #
+ # \Method <tt>Date#as_json</tt> serializes +self+,
+ # returning a 2-element hash representing +self+:
+ #
+ # require 'json/add/date'
+ # x = Date.today.as_json
+ # # => {"json_class"=>"Date", "y"=>2023, "m"=>11, "d"=>21, "sg"=>2299161.0}
+ #
+ # \Method +JSON.create+ deserializes such a hash, returning a \Date object:
+ #
+ # Date.json_create(x)
+ # # => #<Date: 2023-11-21 ((2460270j,0s,0n),+0s,2299161j)>
+ #
def as_json(*)
{
JSON.create_id => self.class.name,
@@ -26,8 +39,15 @@ class Date
}
end
- # Stores class name (Date) with Julian year <tt>y</tt>, month <tt>m</tt>, day
- # <tt>d</tt> and Day of Calendar Reform <tt>sg</tt> as JSON string
+ # Returns a JSON string representing +self+:
+ #
+ # require 'json/add/date'
+ # puts Date.today.to_json
+ #
+ # Output:
+ #
+ # {"json_class":"Date","y":2023,"m":11,"d":21,"sg":2299161.0}
+ #
def to_json(*args)
as_json.to_json(*args)
end
diff --git a/ext/json/lib/json/add/date_time.rb b/ext/json/lib/json/add/date_time.rb
index 38b0e86ab8..d7d42591cf 100644
--- a/ext/json/lib/json/add/date_time.rb
+++ b/ext/json/lib/json/add/date_time.rb
@@ -6,9 +6,7 @@ require 'date'
class DateTime
- # Deserializes JSON string by converting year <tt>y</tt>, month <tt>m</tt>,
- # day <tt>d</tt>, hour <tt>H</tt>, minute <tt>M</tt>, second <tt>S</tt>,
- # offset <tt>of</tt> and Day of Calendar Reform <tt>sg</tt> to DateTime.
+ # See #as_json.
def self.json_create(object)
args = object.values_at('y', 'm', 'd', 'H', 'M', 'S')
of_a, of_b = object['of'].split('/')
@@ -23,8 +21,21 @@ class DateTime
alias start sg unless method_defined?(:start)
- # Returns a hash, that will be turned into a JSON object and represent this
- # object.
+ # Methods <tt>DateTime#as_json</tt> and +DateTime.json_create+ may be used
+ # to serialize and deserialize a \DateTime object;
+ # see Marshal[rdoc-ref:Marshal].
+ #
+ # \Method <tt>DateTime#as_json</tt> serializes +self+,
+ # returning a 2-element hash representing +self+:
+ #
+ # require 'json/add/datetime'
+ # x = DateTime.now.as_json
+ # # => {"json_class"=>"DateTime", "y"=>2023, "m"=>11, "d"=>21, "sg"=>2299161.0}
+ #
+ # \Method +JSON.create+ deserializes such a hash, returning a \DateTime object:
+ #
+ # DateTime.json_create(x) # BUG? Raises Date::Error "invalid date"
+ #
def as_json(*)
{
JSON.create_id => self.class.name,
@@ -39,9 +50,15 @@ class DateTime
}
end
- # Stores class name (DateTime) with Julian year <tt>y</tt>, month <tt>m</tt>,
- # day <tt>d</tt>, hour <tt>H</tt>, minute <tt>M</tt>, second <tt>S</tt>,
- # offset <tt>of</tt> and Day of Calendar Reform <tt>sg</tt> as JSON string
+ # Returns a JSON string representing +self+:
+ #
+ # require 'json/add/datetime'
+ # puts DateTime.now.to_json
+ #
+ # Output:
+ #
+ # {"json_class":"DateTime","y":2023,"m":11,"d":21,"sg":2299161.0}
+ #
def to_json(*args)
as_json.to_json(*args)
end
diff --git a/ext/json/lib/json/add/exception.rb b/ext/json/lib/json/add/exception.rb
index a107e5b3c4..71d8deb0ea 100644
--- a/ext/json/lib/json/add/exception.rb
+++ b/ext/json/lib/json/add/exception.rb
@@ -5,16 +5,27 @@ end
class Exception
- # Deserializes JSON string by constructing new Exception object with message
- # <tt>m</tt> and backtrace <tt>b</tt> serialized with <tt>to_json</tt>
+ # See #as_json.
def self.json_create(object)
result = new(object['m'])
result.set_backtrace object['b']
result
end
- # Returns a hash, that will be turned into a JSON object and represent this
- # object.
+ # Methods <tt>Exception#as_json</tt> and +Exception.json_create+ may be used
+ # to serialize and deserialize a \Exception object;
+ # see Marshal[rdoc-ref:Marshal].
+ #
+ # \Method <tt>Exception#as_json</tt> serializes +self+,
+ # returning a 2-element hash representing +self+:
+ #
+ # require 'json/add/exception'
+ # x = Exception.new('Foo').as_json # => {"json_class"=>"Exception", "m"=>"Foo", "b"=>nil}
+ #
+ # \Method +JSON.create+ deserializes such a hash, returning a \Exception object:
+ #
+ # Exception.json_create(x) # => #<Exception: Foo>
+ #
def as_json(*)
{
JSON.create_id => self.class.name,
@@ -23,8 +34,15 @@ class Exception
}
end
- # Stores class name (Exception) with message <tt>m</tt> and backtrace array
- # <tt>b</tt> as JSON string
+ # Returns a JSON string representing +self+:
+ #
+ # require 'json/add/exception'
+ # puts Exception.new('Foo').to_json
+ #
+ # Output:
+ #
+ # {"json_class":"Exception","m":"Foo","b":null}
+ #
def to_json(*args)
as_json.to_json(*args)
end
diff --git a/ext/json/lib/json/add/ostruct.rb b/ext/json/lib/json/add/ostruct.rb
index 686cf0025d..1e6f408248 100644
--- a/ext/json/lib/json/add/ostruct.rb
+++ b/ext/json/lib/json/add/ostruct.rb
@@ -2,18 +2,34 @@
unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
require 'json'
end
-require 'ostruct'
+begin
+ require 'ostruct'
+rescue LoadError
+end
class OpenStruct
- # Deserializes JSON string by constructing new Struct object with values
- # <tt>t</tt> serialized by <tt>to_json</tt>.
+ # See #as_json.
def self.json_create(object)
new(object['t'] || object[:t])
end
- # Returns a hash, that will be turned into a JSON object and represent this
- # object.
+ # Methods <tt>OpenStruct#as_json</tt> and +OpenStruct.json_create+ may be used
+ # to serialize and deserialize a \OpenStruct object;
+ # see Marshal[rdoc-ref:Marshal].
+ #
+ # \Method <tt>OpenStruct#as_json</tt> serializes +self+,
+ # returning a 2-element hash representing +self+:
+ #
+ # require 'json/add/ostruct'
+ # x = OpenStruct.new('name' => 'Rowdy', :age => nil).as_json
+ # # => {"json_class"=>"OpenStruct", "t"=>{:name=>'Rowdy', :age=>nil}}
+ #
+ # \Method +JSON.create+ deserializes such a hash, returning a \OpenStruct object:
+ #
+ # OpenStruct.json_create(x)
+ # # => #<OpenStruct name='Rowdy', age=nil>
+ #
def as_json(*)
klass = self.class.name
klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!"
@@ -23,9 +39,16 @@ class OpenStruct
}
end
- # Stores class name (OpenStruct) with this struct's values <tt>t</tt> as a
- # JSON string.
+ # Returns a JSON string representing +self+:
+ #
+ # require 'json/add/ostruct'
+ # puts OpenStruct.new('name' => 'Rowdy', :age => nil).to_json
+ #
+ # Output:
+ #
+ # {"json_class":"OpenStruct","t":{'name':'Rowdy',"age":null}}
+ #
def to_json(*args)
as_json.to_json(*args)
end
-end
+end if defined?(::OpenStruct)
diff --git a/ext/json/lib/json/add/range.rb b/ext/json/lib/json/add/range.rb
index d1210c5625..53f54ac372 100644
--- a/ext/json/lib/json/add/range.rb
+++ b/ext/json/lib/json/add/range.rb
@@ -5,24 +5,28 @@ end
class Range
- # Returns a new \Range object constructed from <tt>object['a']</tt>,
- # which must be an array of values suitable for a call to Range.new:
- #
- # require 'json/add/range'
- # Range.json_create({"a"=>[1, 4]}) # => 1..4
- # Range.json_create({"a"=>[1, 4, true]}) # => 1...4
- # Range.json_create({"a" => ['a', 'd']}) # => "a".."d"
- #
+ # See #as_json.
def self.json_create(object)
new(*object['a'])
end
- # Returns a 2-element hash representing +self+:
+ # Methods <tt>Range#as_json</tt> and +Range.json_create+ may be used
+ # to serialize and deserialize a \Range object;
+ # see Marshal[rdoc-ref:Marshal].
+ #
+ # \Method <tt>Range#as_json</tt> serializes +self+,
+ # returning a 2-element hash representing +self+:
#
# require 'json/add/range'
- # (1..4).as_json # => {"json_class"=>"Range", "a"=>[1, 4, false]}
- # (1...4).as_json # => {"json_class"=>"Range", "a"=>[1, 4, true]}
- # ('a'..'d').as_json # => {"json_class"=>"Range", "a"=>["a", "d", false]}
+ # x = (1..4).as_json # => {"json_class"=>"Range", "a"=>[1, 4, false]}
+ # y = (1...4).as_json # => {"json_class"=>"Range", "a"=>[1, 4, true]}
+ # z = ('a'..'d').as_json # => {"json_class"=>"Range", "a"=>["a", "d", false]}
+ #
+ # \Method +JSON.create+ deserializes such a hash, returning a \Range object:
+ #
+ # Range.json_create(x) # => 1..4
+ # Range.json_create(y) # => 1...4
+ # Range.json_create(z) # => "a".."d"
#
def as_json(*)
{
@@ -34,9 +38,15 @@ class Range
# Returns a JSON string representing +self+:
#
# require 'json/add/range'
- # (1..4).to_json # => "{\"json_class\":\"Range\",\"a\":[1,4,false]}"
- # (1...4).to_json # => "{\"json_class\":\"Range\",\"a\":[1,4,true]}"
- # ('a'..'d').to_json # => "{\"json_class\":\"Range\",\"a\":[\"a\",\"d\",false]}"
+ # puts (1..4).to_json
+ # puts (1...4).to_json
+ # puts ('a'..'d').to_json
+ #
+ # Output:
+ #
+ # {"json_class":"Range","a":[1,4,false]}
+ # {"json_class":"Range","a":[1,4,true]}
+ # {"json_class":"Range","a":["a","d",false]}
#
def to_json(*args)
as_json.to_json(*args)
diff --git a/ext/json/lib/json/add/rational.rb b/ext/json/lib/json/add/rational.rb
index f776226046..8c39a7db55 100644
--- a/ext/json/lib/json/add/rational.rb
+++ b/ext/json/lib/json/add/rational.rb
@@ -4,14 +4,28 @@ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
end
class Rational
- # Deserializes JSON string by converting numerator value <tt>n</tt>,
- # denominator value <tt>d</tt>, to a Rational object.
+
+ # See #as_json.
def self.json_create(object)
Rational(object['n'], object['d'])
end
- # Returns a hash, that will be turned into a JSON object and represent this
- # object.
+ # Methods <tt>Rational#as_json</tt> and +Rational.json_create+ may be used
+ # to serialize and deserialize a \Rational object;
+ # see Marshal[rdoc-ref:Marshal].
+ #
+ # \Method <tt>Rational#as_json</tt> serializes +self+,
+ # returning a 2-element hash representing +self+:
+ #
+ # require 'json/add/rational'
+ # x = Rational(2, 3).as_json
+ # # => {"json_class"=>"Rational", "n"=>2, "d"=>3}
+ #
+ # \Method +JSON.create+ deserializes such a hash, returning a \Rational object:
+ #
+ # Rational.json_create(x)
+ # # => (2/3)
+ #
def as_json(*)
{
JSON.create_id => self.class.name,
@@ -20,7 +34,15 @@ class Rational
}
end
- # Stores class name (Rational) along with numerator value <tt>n</tt> and denominator value <tt>d</tt> as JSON string
+ # Returns a JSON string representing +self+:
+ #
+ # require 'json/add/rational'
+ # puts Rational(2, 3).to_json
+ #
+ # Output:
+ #
+ # {"json_class":"Rational","n":2,"d":3}
+ #
def to_json(*args)
as_json.to_json(*args)
end
diff --git a/ext/json/lib/json/add/regexp.rb b/ext/json/lib/json/add/regexp.rb
index 39d69fede7..b63f49608f 100644
--- a/ext/json/lib/json/add/regexp.rb
+++ b/ext/json/lib/json/add/regexp.rb
@@ -5,15 +5,26 @@ end
class Regexp
- # Deserializes JSON string by constructing new Regexp object with source
- # <tt>s</tt> (Regexp or String) and options <tt>o</tt> serialized by
- # <tt>to_json</tt>
+ # See #as_json.
def self.json_create(object)
new(object['s'], object['o'])
end
- # Returns a hash, that will be turned into a JSON object and represent this
- # object.
+ # Methods <tt>Regexp#as_json</tt> and +Regexp.json_create+ may be used
+ # to serialize and deserialize a \Regexp object;
+ # see Marshal[rdoc-ref:Marshal].
+ #
+ # \Method <tt>Regexp#as_json</tt> serializes +self+,
+ # returning a 2-element hash representing +self+:
+ #
+ # require 'json/add/regexp'
+ # x = /foo/.as_json
+ # # => {"json_class"=>"Regexp", "o"=>0, "s"=>"foo"}
+ #
+ # \Method +JSON.create+ deserializes such a hash, returning a \Regexp object:
+ #
+ # Regexp.json_create(x) # => /foo/
+ #
def as_json(*)
{
JSON.create_id => self.class.name,
@@ -22,8 +33,15 @@ class Regexp
}
end
- # Stores class name (Regexp) with options <tt>o</tt> and source <tt>s</tt>
- # (Regexp or String) as JSON string
+ # Returns a JSON string representing +self+:
+ #
+ # require 'json/add/regexp'
+ # puts /foo/.to_json
+ #
+ # Output:
+ #
+ # {"json_class":"Regexp","o":0,"s":"foo"}
+ #
def to_json(*args)
as_json.to_json(*args)
end
diff --git a/ext/json/lib/json/add/set.rb b/ext/json/lib/json/add/set.rb
index 71e2a0ac8b..1918353187 100644
--- a/ext/json/lib/json/add/set.rb
+++ b/ext/json/lib/json/add/set.rb
@@ -4,16 +4,27 @@ end
defined?(::Set) or require 'set'
class Set
- # Import a JSON Marshalled object.
- #
- # method used for JSON marshalling support.
+
+ # See #as_json.
def self.json_create(object)
new object['a']
end
- # Marshal the object to JSON.
+ # Methods <tt>Set#as_json</tt> and +Set.json_create+ may be used
+ # to serialize and deserialize a \Set object;
+ # see Marshal[rdoc-ref:Marshal].
+ #
+ # \Method <tt>Set#as_json</tt> serializes +self+,
+ # returning a 2-element hash representing +self+:
+ #
+ # require 'json/add/set'
+ # x = Set.new(%w/foo bar baz/).as_json
+ # # => {"json_class"=>"Set", "a"=>["foo", "bar", "baz"]}
+ #
+ # \Method +JSON.create+ deserializes such a hash, returning a \Set object:
+ #
+ # Set.json_create(x) # => #<Set: {"foo", "bar", "baz"}>
#
- # method used for JSON marshalling support.
def as_json(*)
{
JSON.create_id => self.class.name,
@@ -21,7 +32,15 @@ class Set
}
end
- # return the JSON value
+ # Returns a JSON string representing +self+:
+ #
+ # require 'json/add/set'
+ # puts Set.new(%w/foo bar baz/).to_json
+ #
+ # Output:
+ #
+ # {"json_class":"Set","a":["foo","bar","baz"]}
+ #
def to_json(*args)
as_json.to_json(*args)
end
diff --git a/ext/json/lib/json/add/struct.rb b/ext/json/lib/json/add/struct.rb
index e8395ed42f..86847762ac 100644
--- a/ext/json/lib/json/add/struct.rb
+++ b/ext/json/lib/json/add/struct.rb
@@ -5,14 +5,28 @@ end
class Struct
- # Deserializes JSON string by constructing new Struct object with values
- # <tt>v</tt> serialized by <tt>to_json</tt>.
+ # See #as_json.
def self.json_create(object)
new(*object['v'])
end
- # Returns a hash, that will be turned into a JSON object and represent this
- # object.
+ # Methods <tt>Struct#as_json</tt> and +Struct.json_create+ may be used
+ # to serialize and deserialize a \Struct object;
+ # see Marshal[rdoc-ref:Marshal].
+ #
+ # \Method <tt>Struct#as_json</tt> serializes +self+,
+ # returning a 2-element hash representing +self+:
+ #
+ # require 'json/add/struct'
+ # Customer = Struct.new('Customer', :name, :address, :zip)
+ # x = Struct::Customer.new.as_json
+ # # => {"json_class"=>"Struct::Customer", "v"=>[nil, nil, nil]}
+ #
+ # \Method +JSON.create+ deserializes such a hash, returning a \Struct object:
+ #
+ # Struct::Customer.json_create(x)
+ # # => #<struct Struct::Customer name=nil, address=nil, zip=nil>
+ #
def as_json(*)
klass = self.class.name
klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!"
@@ -22,8 +36,16 @@ class Struct
}
end
- # Stores class name (Struct) with Struct values <tt>v</tt> as a JSON string.
- # Only named structs are supported.
+ # Returns a JSON string representing +self+:
+ #
+ # require 'json/add/struct'
+ # Customer = Struct.new('Customer', :name, :address, :zip)
+ # puts Struct::Customer.new.to_json
+ #
+ # Output:
+ #
+ # {"json_class":"Struct","t":{'name':'Rowdy',"age":null}}
+ #
def to_json(*args)
as_json.to_json(*args)
end
diff --git a/ext/json/lib/json/add/symbol.rb b/ext/json/lib/json/add/symbol.rb
index 74b13a423f..b5f3623158 100644
--- a/ext/json/lib/json/add/symbol.rb
+++ b/ext/json/lib/json/add/symbol.rb
@@ -1,11 +1,26 @@
+
#frozen_string_literal: false
unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
require 'json'
end
class Symbol
- # Returns a hash, that will be turned into a JSON object and represent this
- # object.
+
+ # Methods <tt>Symbol#as_json</tt> and +Symbol.json_create+ may be used
+ # to serialize and deserialize a \Symbol object;
+ # see Marshal[rdoc-ref:Marshal].
+ #
+ # \Method <tt>Symbol#as_json</tt> serializes +self+,
+ # returning a 2-element hash representing +self+:
+ #
+ # require 'json/add/symbol'
+ # x = :foo.as_json
+ # # => {"json_class"=>"Symbol", "s"=>"foo"}
+ #
+ # \Method +JSON.create+ deserializes such a hash, returning a \Symbol object:
+ #
+ # Symbol.json_create(x) # => :foo
+ #
def as_json(*)
{
JSON.create_id => self.class.name,
@@ -13,12 +28,20 @@ class Symbol
}
end
- # Stores class name (Symbol) with String representation of Symbol as a JSON string.
+ # Returns a JSON string representing +self+:
+ #
+ # require 'json/add/symbol'
+ # puts :foo.to_json
+ #
+ # Output:
+ #
+ # # {"json_class":"Symbol","s":"foo"}
+ #
def to_json(*a)
as_json.to_json(*a)
end
- # Deserializes JSON string by converting the <tt>string</tt> value stored in the object to a Symbol
+ # See #as_json.
def self.json_create(o)
o['s'].to_sym
end
diff --git a/ext/json/lib/json/add/time.rb b/ext/json/lib/json/add/time.rb
index b73acc4086..599ed9e24b 100644
--- a/ext/json/lib/json/add/time.rb
+++ b/ext/json/lib/json/add/time.rb
@@ -5,7 +5,7 @@ end
class Time
- # Deserializes JSON string by converting time since epoch to Time
+ # See #as_json.
def self.json_create(object)
if usec = object.delete('u') # used to be tv_usec -> tv_nsec
object['n'] = usec * 1000
@@ -17,8 +17,22 @@ class Time
end
end
- # Returns a hash, that will be turned into a JSON object and represent this
- # object.
+ # Methods <tt>Time#as_json</tt> and +Time.json_create+ may be used
+ # to serialize and deserialize a \Time object;
+ # see Marshal[rdoc-ref:Marshal].
+ #
+ # \Method <tt>Time#as_json</tt> serializes +self+,
+ # returning a 2-element hash representing +self+:
+ #
+ # require 'json/add/time'
+ # x = Time.now.as_json
+ # # => {"json_class"=>"Time", "s"=>1700931656, "n"=>472846644}
+ #
+ # \Method +JSON.create+ deserializes such a hash, returning a \Time object:
+ #
+ # Time.json_create(x)
+ # # => 2023-11-25 11:00:56.472846644 -0600
+ #
def as_json(*)
nanoseconds = [ tv_usec * 1000 ]
respond_to?(:tv_nsec) and nanoseconds << tv_nsec
@@ -30,8 +44,15 @@ class Time
}
end
- # Stores class name (Time) with number of seconds since epoch and number of
- # microseconds for Time as JSON string
+ # Returns a JSON string representing +self+:
+ #
+ # require 'json/add/time'
+ # puts Time.now.to_json
+ #
+ # Output:
+ #
+ # {"json_class":"Time","s":1700931678,"n":980650786}
+ #
def to_json(*args)
as_json.to_json(*args)
end
diff --git a/ext/json/lib/json/common.rb b/ext/json/lib/json/common.rb
index 173af04be0..95098d3bb4 100644
--- a/ext/json/lib/json/common.rb
+++ b/ext/json/lib/json/common.rb
@@ -1,8 +1,12 @@
#frozen_string_literal: false
require 'json/version'
-require 'json/generic_object'
module JSON
+ autoload :GenericObject, 'json/generic_object'
+
+ NOT_SET = Object.new.freeze
+ private_constant :NOT_SET
+
class << self
# :call-seq:
# JSON[object] -> new_array or new_string
@@ -572,13 +576,13 @@ module JSON
# Sets or returns the default options for the JSON.dump method.
# Initially:
# opts = JSON.dump_default_options
- # opts # => {:max_nesting=>false, :allow_nan=>true, :escape_slash=>false}
+ # opts # => {:max_nesting=>false, :allow_nan=>true, :script_safe=>false}
attr_accessor :dump_default_options
end
self.dump_default_options = {
:max_nesting => false,
:allow_nan => true,
- :escape_slash => false,
+ :script_safe => false,
}
# :call-seq:
@@ -608,16 +612,18 @@ module JSON
# puts File.read(path)
# Output:
# {"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"}
- def dump(obj, anIO = nil, limit = nil)
- if anIO and limit.nil?
- anIO = anIO.to_io if anIO.respond_to?(:to_io)
- unless anIO.respond_to?(:write)
- limit = anIO
- anIO = nil
- end
+ def dump(obj, anIO = nil, limit = nil, kwargs = nil)
+ io_limit_opt = [anIO, limit, kwargs].compact
+ kwargs = io_limit_opt.pop if io_limit_opt.last.is_a?(Hash)
+ anIO, limit = io_limit_opt
+ if anIO.respond_to?(:to_io)
+ anIO = anIO.to_io
+ elsif limit.nil? && !anIO.respond_to?(:write)
+ anIO, limit = nil, anIO
end
opts = JSON.dump_default_options
opts = opts.merge(:max_nesting => limit) if limit
+ opts = merge_dump_options(opts, **kwargs) if kwargs
result = generate(obj, opts)
if anIO
anIO.write result
@@ -633,6 +639,15 @@ module JSON
def self.iconv(to, from, string)
string.encode(to, from)
end
+
+ def merge_dump_options(opts, strict: NOT_SET)
+ opts = opts.merge(strict: strict) if NOT_SET != strict
+ opts
+ end
+
+ class << self
+ private :merge_dump_options
+ end
end
module ::Kernel
diff --git a/ext/json/lib/json/ext.rb b/ext/json/lib/json/ext.rb
index 7264a857fa..b62e231712 100644
--- a/ext/json/lib/json/ext.rb
+++ b/ext/json/lib/json/ext.rb
@@ -4,11 +4,19 @@ module JSON
# This module holds all the modules/classes that implement JSON's
# functionality as C extensions.
module Ext
- require 'json/ext/parser'
- require 'json/ext/generator'
- $DEBUG and warn "Using Ext extension for JSON."
- JSON.parser = Parser
- JSON.generator = Generator
+ if RUBY_ENGINE == 'truffleruby'
+ require 'json/ext/parser'
+ require 'json/pure'
+ $DEBUG and warn "Using Ext extension for JSON parser and Pure library for JSON generator."
+ JSON.parser = Parser
+ JSON.generator = JSON::Pure::Generator
+ else
+ require 'json/ext/parser'
+ require 'json/ext/generator'
+ $DEBUG and warn "Using Ext extension for JSON."
+ JSON.parser = Parser
+ JSON.generator = Generator
+ end
end
JSON_LOADED = true unless defined?(::JSON::JSON_LOADED)
diff --git a/ext/json/lib/json/generic_object.rb b/ext/json/lib/json/generic_object.rb
index 108309db26..56efda6495 100644
--- a/ext/json/lib/json/generic_object.rb
+++ b/ext/json/lib/json/generic_object.rb
@@ -1,5 +1,9 @@
#frozen_string_literal: false
-require 'ostruct'
+begin
+ require 'ostruct'
+rescue LoadError
+ warn "JSON::GenericObject requires 'ostruct'. Please install it with `gem install ostruct`."
+end
module JSON
class GenericObject < OpenStruct
@@ -67,5 +71,5 @@ module JSON
def to_json(*a)
as_json.to_json(*a)
end
- end
+ end if defined?(::OpenStruct)
end
diff --git a/ext/json/lib/json/version.rb b/ext/json/lib/json/version.rb
index 3d4326d836..836f47edf4 100644
--- a/ext/json/lib/json/version.rb
+++ b/ext/json/lib/json/version.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
module JSON
# JSON version
- VERSION = '2.6.3'
+ VERSION = '2.7.2'
VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
diff --git a/ext/json/parser/depend b/ext/json/parser/depend
index cb6e547d29..f3422b4f84 100644
--- a/ext/json/parser/depend
+++ b/ext/json/parser/depend
@@ -160,6 +160,7 @@ parser.o: $(hdrdir)/ruby/internal/special_consts.h
parser.o: $(hdrdir)/ruby/internal/static_assert.h
parser.o: $(hdrdir)/ruby/internal/stdalign.h
parser.o: $(hdrdir)/ruby/internal/stdbool.h
+parser.o: $(hdrdir)/ruby/internal/stdckdint.h
parser.o: $(hdrdir)/ruby/internal/symbol.h
parser.o: $(hdrdir)/ruby/internal/value.h
parser.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/json/parser/parser.c b/ext/json/parser/parser.c
index 876bec5769..7e44d469f8 100644
--- a/ext/json/parser/parser.c
+++ b/ext/json/parser/parser.c
@@ -587,7 +587,7 @@ tr25:
if (json->allow_nan) {
*result = CInfinity;
} else {
- rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p - 8);
+ rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p - 7);
}
}
goto st29;
@@ -1497,7 +1497,7 @@ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int
case 'u':
if (pe > stringEnd - 4) {
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
- free(bufferStart);
+ ruby_xfree(bufferStart);
}
rb_enc_raise(
EXC_ENCODING eParserError,
@@ -1510,7 +1510,7 @@ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int
pe++;
if (pe > stringEnd - 6) {
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
- free(bufferStart);
+ ruby_xfree(bufferStart);
}
rb_enc_raise(
EXC_ENCODING eParserError,
@@ -1555,13 +1555,13 @@ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int
result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
}
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
- free(bufferStart);
+ ruby_xfree(bufferStart);
}
# else
result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
- free(bufferStart);
+ ruby_xfree(bufferStart);
}
if (intern) {
@@ -1902,7 +1902,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
json->max_nesting = 100;
json->allow_nan = 0;
json->create_additions = 0;
- json->create_id = rb_funcall(mJSON, i_create_id, 0);
+ json->create_id = Qnil;
json->object_class = Qnil;
json->array_class = Qnil;
json->decimal_class = Qnil;
@@ -2097,12 +2097,12 @@ case 9:
static void JSON_mark(void *ptr)
{
JSON_Parser *json = ptr;
- rb_gc_mark_maybe(json->Vsource);
- rb_gc_mark_maybe(json->create_id);
- rb_gc_mark_maybe(json->object_class);
- rb_gc_mark_maybe(json->array_class);
- rb_gc_mark_maybe(json->decimal_class);
- rb_gc_mark_maybe(json->match_string);
+ rb_gc_mark(json->Vsource);
+ rb_gc_mark(json->create_id);
+ rb_gc_mark(json->object_class);
+ rb_gc_mark(json->array_class);
+ rb_gc_mark(json->decimal_class);
+ rb_gc_mark(json->match_string);
}
static void JSON_free(void *ptr)
@@ -2118,16 +2118,12 @@ static size_t JSON_memsize(const void *ptr)
return sizeof(*json) + FBUFFER_CAPA(json->fbuffer);
}
-#ifdef NEW_TYPEDDATA_WRAPPER
static const rb_data_type_t JSON_Parser_type = {
"JSON/Parser",
{JSON_mark, JSON_free, JSON_memsize,},
-#ifdef RUBY_TYPED_FREE_IMMEDIATELY
0, 0,
RUBY_TYPED_FREE_IMMEDIATELY,
-#endif
};
-#endif
static VALUE cJSON_parser_s_allocate(VALUE klass)
{
diff --git a/ext/json/parser/parser.h b/ext/json/parser/parser.h
index 92ed3fdc5d..651d40c074 100644
--- a/ext/json/parser/parser.h
+++ b/ext/json/parser/parser.h
@@ -85,12 +85,7 @@ static inline void *ruby_zalloc(size_t n)
return p;
}
#endif
-#ifdef TypedData_Make_Struct
+
static const rb_data_type_t JSON_Parser_type;
-#define NEW_TYPEDDATA_WRAPPER 1
-#else
-#define TypedData_Make_Struct(klass, type, ignore, json) Data_Make_Struct(klass, type, NULL, JSON_free, json)
-#define TypedData_Get_Struct(self, JSON_Parser, ignore, json) Data_Get_Struct(self, JSON_Parser, json)
-#endif
#endif
diff --git a/ext/json/parser/parser.rl b/ext/json/parser/parser.rl
index 1ecf3317c7..e2522918dc 100644
--- a/ext/json/parser/parser.rl
+++ b/ext/json/parser/parser.rl
@@ -229,7 +229,7 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
if (json->allow_nan) {
*result = CInfinity;
} else {
- rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p - 8);
+ rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p - 7);
}
}
action parse_string {
@@ -508,7 +508,7 @@ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int
case 'u':
if (pe > stringEnd - 4) {
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
- free(bufferStart);
+ ruby_xfree(bufferStart);
}
rb_enc_raise(
EXC_ENCODING eParserError,
@@ -521,7 +521,7 @@ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int
pe++;
if (pe > stringEnd - 6) {
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
- free(bufferStart);
+ ruby_xfree(bufferStart);
}
rb_enc_raise(
EXC_ENCODING eParserError,
@@ -566,13 +566,13 @@ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int
result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
}
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
- free(bufferStart);
+ ruby_xfree(bufferStart);
}
# else
result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
- free(bufferStart);
+ ruby_xfree(bufferStart);
}
if (intern) {
@@ -797,7 +797,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
json->max_nesting = 100;
json->allow_nan = 0;
json->create_additions = 0;
- json->create_id = rb_funcall(mJSON, i_create_id, 0);
+ json->create_id = Qnil;
json->object_class = Qnil;
json->array_class = Qnil;
json->decimal_class = Qnil;
@@ -857,12 +857,12 @@ static VALUE cParser_parse(VALUE self)
static void JSON_mark(void *ptr)
{
JSON_Parser *json = ptr;
- rb_gc_mark_maybe(json->Vsource);
- rb_gc_mark_maybe(json->create_id);
- rb_gc_mark_maybe(json->object_class);
- rb_gc_mark_maybe(json->array_class);
- rb_gc_mark_maybe(json->decimal_class);
- rb_gc_mark_maybe(json->match_string);
+ rb_gc_mark(json->Vsource);
+ rb_gc_mark(json->create_id);
+ rb_gc_mark(json->object_class);
+ rb_gc_mark(json->array_class);
+ rb_gc_mark(json->decimal_class);
+ rb_gc_mark(json->match_string);
}
static void JSON_free(void *ptr)
@@ -878,16 +878,12 @@ static size_t JSON_memsize(const void *ptr)
return sizeof(*json) + FBUFFER_CAPA(json->fbuffer);
}
-#ifdef NEW_TYPEDDATA_WRAPPER
static const rb_data_type_t JSON_Parser_type = {
"JSON/Parser",
{JSON_mark, JSON_free, JSON_memsize,},
-#ifdef RUBY_TYPED_FREE_IMMEDIATELY
0, 0,
RUBY_TYPED_FREE_IMMEDIATELY,
-#endif
};
-#endif
static VALUE cJSON_parser_s_allocate(VALUE klass)
{
diff --git a/ext/monitor/depend b/ext/monitor/depend
index 38e21b3f66..bc7ead0d32 100644
--- a/ext/monitor/depend
+++ b/ext/monitor/depend
@@ -146,6 +146,7 @@ monitor.o: $(hdrdir)/ruby/internal/special_consts.h
monitor.o: $(hdrdir)/ruby/internal/static_assert.h
monitor.o: $(hdrdir)/ruby/internal/stdalign.h
monitor.o: $(hdrdir)/ruby/internal/stdbool.h
+monitor.o: $(hdrdir)/ruby/internal/stdckdint.h
monitor.o: $(hdrdir)/ruby/internal/symbol.h
monitor.o: $(hdrdir)/ruby/internal/value.h
monitor.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/nkf/depend b/ext/nkf/depend
deleted file mode 100644
index 98afc5f201..0000000000
--- a/ext/nkf/depend
+++ /dev/null
@@ -1,181 +0,0 @@
-# BSD make needs "nkf.o: nkf.c" dependency BEFORE "nkf.o: nkf-utf8/nkf.c".
-# It seems BSD make searches the target for implicit rule in dependencies at first.
-nkf.o: nkf.c
-
-# AUTOGENERATED DEPENDENCIES START
-nkf.o: $(RUBY_EXTCONF_H)
-nkf.o: $(arch_hdrdir)/ruby/config.h
-nkf.o: $(hdrdir)/ruby/assert.h
-nkf.o: $(hdrdir)/ruby/backward.h
-nkf.o: $(hdrdir)/ruby/backward/2/assume.h
-nkf.o: $(hdrdir)/ruby/backward/2/attributes.h
-nkf.o: $(hdrdir)/ruby/backward/2/bool.h
-nkf.o: $(hdrdir)/ruby/backward/2/inttypes.h
-nkf.o: $(hdrdir)/ruby/backward/2/limits.h
-nkf.o: $(hdrdir)/ruby/backward/2/long_long.h
-nkf.o: $(hdrdir)/ruby/backward/2/stdalign.h
-nkf.o: $(hdrdir)/ruby/backward/2/stdarg.h
-nkf.o: $(hdrdir)/ruby/defines.h
-nkf.o: $(hdrdir)/ruby/encoding.h
-nkf.o: $(hdrdir)/ruby/intern.h
-nkf.o: $(hdrdir)/ruby/internal/abi.h
-nkf.o: $(hdrdir)/ruby/internal/anyargs.h
-nkf.o: $(hdrdir)/ruby/internal/arithmetic.h
-nkf.o: $(hdrdir)/ruby/internal/arithmetic/char.h
-nkf.o: $(hdrdir)/ruby/internal/arithmetic/double.h
-nkf.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
-nkf.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
-nkf.o: $(hdrdir)/ruby/internal/arithmetic/int.h
-nkf.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
-nkf.o: $(hdrdir)/ruby/internal/arithmetic/long.h
-nkf.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
-nkf.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
-nkf.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
-nkf.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
-nkf.o: $(hdrdir)/ruby/internal/arithmetic/short.h
-nkf.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
-nkf.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
-nkf.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
-nkf.o: $(hdrdir)/ruby/internal/assume.h
-nkf.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
-nkf.o: $(hdrdir)/ruby/internal/attr/artificial.h
-nkf.o: $(hdrdir)/ruby/internal/attr/cold.h
-nkf.o: $(hdrdir)/ruby/internal/attr/const.h
-nkf.o: $(hdrdir)/ruby/internal/attr/constexpr.h
-nkf.o: $(hdrdir)/ruby/internal/attr/deprecated.h
-nkf.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
-nkf.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
-nkf.o: $(hdrdir)/ruby/internal/attr/error.h
-nkf.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
-nkf.o: $(hdrdir)/ruby/internal/attr/forceinline.h
-nkf.o: $(hdrdir)/ruby/internal/attr/format.h
-nkf.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
-nkf.o: $(hdrdir)/ruby/internal/attr/noalias.h
-nkf.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
-nkf.o: $(hdrdir)/ruby/internal/attr/noexcept.h
-nkf.o: $(hdrdir)/ruby/internal/attr/noinline.h
-nkf.o: $(hdrdir)/ruby/internal/attr/nonnull.h
-nkf.o: $(hdrdir)/ruby/internal/attr/noreturn.h
-nkf.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
-nkf.o: $(hdrdir)/ruby/internal/attr/pure.h
-nkf.o: $(hdrdir)/ruby/internal/attr/restrict.h
-nkf.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
-nkf.o: $(hdrdir)/ruby/internal/attr/warning.h
-nkf.o: $(hdrdir)/ruby/internal/attr/weakref.h
-nkf.o: $(hdrdir)/ruby/internal/cast.h
-nkf.o: $(hdrdir)/ruby/internal/compiler_is.h
-nkf.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
-nkf.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
-nkf.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
-nkf.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
-nkf.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
-nkf.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
-nkf.o: $(hdrdir)/ruby/internal/compiler_since.h
-nkf.o: $(hdrdir)/ruby/internal/config.h
-nkf.o: $(hdrdir)/ruby/internal/constant_p.h
-nkf.o: $(hdrdir)/ruby/internal/core.h
-nkf.o: $(hdrdir)/ruby/internal/core/rarray.h
-nkf.o: $(hdrdir)/ruby/internal/core/rbasic.h
-nkf.o: $(hdrdir)/ruby/internal/core/rbignum.h
-nkf.o: $(hdrdir)/ruby/internal/core/rclass.h
-nkf.o: $(hdrdir)/ruby/internal/core/rdata.h
-nkf.o: $(hdrdir)/ruby/internal/core/rfile.h
-nkf.o: $(hdrdir)/ruby/internal/core/rhash.h
-nkf.o: $(hdrdir)/ruby/internal/core/robject.h
-nkf.o: $(hdrdir)/ruby/internal/core/rregexp.h
-nkf.o: $(hdrdir)/ruby/internal/core/rstring.h
-nkf.o: $(hdrdir)/ruby/internal/core/rstruct.h
-nkf.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
-nkf.o: $(hdrdir)/ruby/internal/ctype.h
-nkf.o: $(hdrdir)/ruby/internal/dllexport.h
-nkf.o: $(hdrdir)/ruby/internal/dosish.h
-nkf.o: $(hdrdir)/ruby/internal/encoding/coderange.h
-nkf.o: $(hdrdir)/ruby/internal/encoding/ctype.h
-nkf.o: $(hdrdir)/ruby/internal/encoding/encoding.h
-nkf.o: $(hdrdir)/ruby/internal/encoding/pathname.h
-nkf.o: $(hdrdir)/ruby/internal/encoding/re.h
-nkf.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
-nkf.o: $(hdrdir)/ruby/internal/encoding/string.h
-nkf.o: $(hdrdir)/ruby/internal/encoding/symbol.h
-nkf.o: $(hdrdir)/ruby/internal/encoding/transcode.h
-nkf.o: $(hdrdir)/ruby/internal/error.h
-nkf.o: $(hdrdir)/ruby/internal/eval.h
-nkf.o: $(hdrdir)/ruby/internal/event.h
-nkf.o: $(hdrdir)/ruby/internal/fl_type.h
-nkf.o: $(hdrdir)/ruby/internal/gc.h
-nkf.o: $(hdrdir)/ruby/internal/glob.h
-nkf.o: $(hdrdir)/ruby/internal/globals.h
-nkf.o: $(hdrdir)/ruby/internal/has/attribute.h
-nkf.o: $(hdrdir)/ruby/internal/has/builtin.h
-nkf.o: $(hdrdir)/ruby/internal/has/c_attribute.h
-nkf.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
-nkf.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
-nkf.o: $(hdrdir)/ruby/internal/has/extension.h
-nkf.o: $(hdrdir)/ruby/internal/has/feature.h
-nkf.o: $(hdrdir)/ruby/internal/has/warning.h
-nkf.o: $(hdrdir)/ruby/internal/intern/array.h
-nkf.o: $(hdrdir)/ruby/internal/intern/bignum.h
-nkf.o: $(hdrdir)/ruby/internal/intern/class.h
-nkf.o: $(hdrdir)/ruby/internal/intern/compar.h
-nkf.o: $(hdrdir)/ruby/internal/intern/complex.h
-nkf.o: $(hdrdir)/ruby/internal/intern/cont.h
-nkf.o: $(hdrdir)/ruby/internal/intern/dir.h
-nkf.o: $(hdrdir)/ruby/internal/intern/enum.h
-nkf.o: $(hdrdir)/ruby/internal/intern/enumerator.h
-nkf.o: $(hdrdir)/ruby/internal/intern/error.h
-nkf.o: $(hdrdir)/ruby/internal/intern/eval.h
-nkf.o: $(hdrdir)/ruby/internal/intern/file.h
-nkf.o: $(hdrdir)/ruby/internal/intern/hash.h
-nkf.o: $(hdrdir)/ruby/internal/intern/io.h
-nkf.o: $(hdrdir)/ruby/internal/intern/load.h
-nkf.o: $(hdrdir)/ruby/internal/intern/marshal.h
-nkf.o: $(hdrdir)/ruby/internal/intern/numeric.h
-nkf.o: $(hdrdir)/ruby/internal/intern/object.h
-nkf.o: $(hdrdir)/ruby/internal/intern/parse.h
-nkf.o: $(hdrdir)/ruby/internal/intern/proc.h
-nkf.o: $(hdrdir)/ruby/internal/intern/process.h
-nkf.o: $(hdrdir)/ruby/internal/intern/random.h
-nkf.o: $(hdrdir)/ruby/internal/intern/range.h
-nkf.o: $(hdrdir)/ruby/internal/intern/rational.h
-nkf.o: $(hdrdir)/ruby/internal/intern/re.h
-nkf.o: $(hdrdir)/ruby/internal/intern/ruby.h
-nkf.o: $(hdrdir)/ruby/internal/intern/select.h
-nkf.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
-nkf.o: $(hdrdir)/ruby/internal/intern/signal.h
-nkf.o: $(hdrdir)/ruby/internal/intern/sprintf.h
-nkf.o: $(hdrdir)/ruby/internal/intern/string.h
-nkf.o: $(hdrdir)/ruby/internal/intern/struct.h
-nkf.o: $(hdrdir)/ruby/internal/intern/thread.h
-nkf.o: $(hdrdir)/ruby/internal/intern/time.h
-nkf.o: $(hdrdir)/ruby/internal/intern/variable.h
-nkf.o: $(hdrdir)/ruby/internal/intern/vm.h
-nkf.o: $(hdrdir)/ruby/internal/interpreter.h
-nkf.o: $(hdrdir)/ruby/internal/iterator.h
-nkf.o: $(hdrdir)/ruby/internal/memory.h
-nkf.o: $(hdrdir)/ruby/internal/method.h
-nkf.o: $(hdrdir)/ruby/internal/module.h
-nkf.o: $(hdrdir)/ruby/internal/newobj.h
-nkf.o: $(hdrdir)/ruby/internal/scan_args.h
-nkf.o: $(hdrdir)/ruby/internal/special_consts.h
-nkf.o: $(hdrdir)/ruby/internal/static_assert.h
-nkf.o: $(hdrdir)/ruby/internal/stdalign.h
-nkf.o: $(hdrdir)/ruby/internal/stdbool.h
-nkf.o: $(hdrdir)/ruby/internal/symbol.h
-nkf.o: $(hdrdir)/ruby/internal/value.h
-nkf.o: $(hdrdir)/ruby/internal/value_type.h
-nkf.o: $(hdrdir)/ruby/internal/variable.h
-nkf.o: $(hdrdir)/ruby/internal/warning_push.h
-nkf.o: $(hdrdir)/ruby/internal/xmalloc.h
-nkf.o: $(hdrdir)/ruby/missing.h
-nkf.o: $(hdrdir)/ruby/onigmo.h
-nkf.o: $(hdrdir)/ruby/oniguruma.h
-nkf.o: $(hdrdir)/ruby/ruby.h
-nkf.o: $(hdrdir)/ruby/st.h
-nkf.o: $(hdrdir)/ruby/subst.h
-nkf.o: nkf-utf8/config.h
-nkf.o: nkf-utf8/nkf.c
-nkf.o: nkf-utf8/nkf.h
-nkf.o: nkf-utf8/utf8tbl.c
-nkf.o: nkf-utf8/utf8tbl.h
-nkf.o: nkf.c
-# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/nkf/extconf.rb b/ext/nkf/extconf.rb
deleted file mode 100644
index f41f6b11dc..0000000000
--- a/ext/nkf/extconf.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-# frozen_string_literal: false
-require 'mkmf'
-create_makefile('nkf')
diff --git a/ext/nkf/lib/kconv.rb b/ext/nkf/lib/kconv.rb
deleted file mode 100644
index f52b755288..0000000000
--- a/ext/nkf/lib/kconv.rb
+++ /dev/null
@@ -1,283 +0,0 @@
-# frozen_string_literal: false
-#
-# kconv.rb - Kanji Converter.
-#
-# $Id$
-#
-# ----
-#
-# kconv.rb implements the Kconv class for Kanji Converter. Additionally,
-# some methods in String classes are added to allow easy conversion.
-#
-
-require 'nkf'
-
-#
-# Kanji Converter for Ruby.
-#
-module Kconv
- #
- # Public Constants
- #
-
- #Constant of Encoding
-
- # Auto-Detect
- AUTO = NKF::AUTO
- # ISO-2022-JP
- JIS = NKF::JIS
- # EUC-JP
- EUC = NKF::EUC
- # Shift_JIS
- SJIS = NKF::SJIS
- # BINARY
- BINARY = NKF::BINARY
- # NOCONV
- NOCONV = NKF::NOCONV
- # ASCII
- ASCII = NKF::ASCII
- # UTF-8
- UTF8 = NKF::UTF8
- # UTF-16
- UTF16 = NKF::UTF16
- # UTF-32
- UTF32 = NKF::UTF32
- # UNKNOWN
- UNKNOWN = NKF::UNKNOWN
-
- #
- # Public Methods
- #
-
- # call-seq:
- # Kconv.kconv(str, to_enc, from_enc=nil)
- #
- # Convert <code>str</code> to <code>to_enc</code>.
- # <code>to_enc</code> and <code>from_enc</code> are given as constants of Kconv or Encoding objects.
- def kconv(str, to_enc, from_enc=nil)
- opt = ''
- opt += ' --ic=' + from_enc.to_s if from_enc
- opt += ' --oc=' + to_enc.to_s if to_enc
-
- ::NKF::nkf(opt, str)
- end
- module_function :kconv
-
- #
- # Encode to
- #
-
- # call-seq:
- # Kconv.tojis(str) => string
- #
- # Convert <code>str</code> to ISO-2022-JP
- def tojis(str)
- kconv(str, JIS)
- end
- module_function :tojis
-
- # call-seq:
- # Kconv.toeuc(str) => string
- #
- # Convert <code>str</code> to EUC-JP
- def toeuc(str)
- kconv(str, EUC)
- end
- module_function :toeuc
-
- # call-seq:
- # Kconv.tosjis(str) => string
- #
- # Convert <code>str</code> to Shift_JIS
- def tosjis(str)
- kconv(str, SJIS)
- end
- module_function :tosjis
-
- # call-seq:
- # Kconv.toutf8(str) => string
- #
- # Convert <code>str</code> to UTF-8
- def toutf8(str)
- kconv(str, UTF8)
- end
- module_function :toutf8
-
- # call-seq:
- # Kconv.toutf16(str) => string
- #
- # Convert <code>str</code> to UTF-16
- def toutf16(str)
- kconv(str, UTF16)
- end
- module_function :toutf16
-
- # call-seq:
- # Kconv.toutf32(str) => string
- #
- # Convert <code>str</code> to UTF-32
- def toutf32(str)
- kconv(str, UTF32)
- end
- module_function :toutf32
-
- # call-seq:
- # Kconv.tolocale => string
- #
- # Convert <code>self</code> to locale encoding
- def tolocale(str)
- kconv(str, Encoding.locale_charmap)
- end
- module_function :tolocale
-
- #
- # guess
- #
-
- # call-seq:
- # Kconv.guess(str) => encoding
- #
- # Guess input encoding by NKF.guess
- def guess(str)
- ::NKF::guess(str)
- end
- module_function :guess
-
- #
- # isEncoding
- #
-
- # call-seq:
- # Kconv.iseuc(str) => true or false
- #
- # Returns whether input encoding is EUC-JP or not.
- #
- # *Note* don't expect this return value is MatchData.
- def iseuc(str)
- str.dup.force_encoding(EUC).valid_encoding?
- end
- module_function :iseuc
-
- # call-seq:
- # Kconv.issjis(str) => true or false
- #
- # Returns whether input encoding is Shift_JIS or not.
- def issjis(str)
- str.dup.force_encoding(SJIS).valid_encoding?
- end
- module_function :issjis
-
- # call-seq:
- # Kconv.isjis(str) => true or false
- #
- # Returns whether input encoding is ISO-2022-JP or not.
- def isjis(str)
- /\A [\t\n\r\x20-\x7E]*
- (?:
- (?:\x1b \x28 I [\x21-\x7E]*
- |\x1b \x28 J [\x21-\x7E]*
- |\x1b \x24 @ (?:[\x21-\x7E]{2})*
- |\x1b \x24 B (?:[\x21-\x7E]{2})*
- |\x1b \x24 \x28 D (?:[\x21-\x7E]{2})*
- )*
- \x1b \x28 B [\t\n\r\x20-\x7E]*
- )*
- \z/nox =~ str.dup.force_encoding('BINARY') ? true : false
- end
- module_function :isjis
-
- # call-seq:
- # Kconv.isutf8(str) => true or false
- #
- # Returns whether input encoding is UTF-8 or not.
- def isutf8(str)
- str.dup.force_encoding(UTF8).valid_encoding?
- end
- module_function :isutf8
-end
-
-class String
- # call-seq:
- # String#kconv(to_enc, from_enc)
- #
- # Convert <code>self</code> to <code>to_enc</code>.
- # <code>to_enc</code> and <code>from_enc</code> are given as constants of Kconv or Encoding objects.
- def kconv(to_enc, from_enc=nil)
- from_enc = self.encoding if !from_enc && self.encoding != Encoding.list[0]
- Kconv::kconv(self, to_enc, from_enc)
- end
-
- #
- # to Encoding
- #
-
- # call-seq:
- # String#tojis => string
- #
- # Convert <code>self</code> to ISO-2022-JP
- def tojis; Kconv.tojis(self) end
-
- # call-seq:
- # String#toeuc => string
- #
- # Convert <code>self</code> to EUC-JP
- def toeuc; Kconv.toeuc(self) end
-
- # call-seq:
- # String#tosjis => string
- #
- # Convert <code>self</code> to Shift_JIS
- def tosjis; Kconv.tosjis(self) end
-
- # call-seq:
- # String#toutf8 => string
- #
- # Convert <code>self</code> to UTF-8
- def toutf8; Kconv.toutf8(self) end
-
- # call-seq:
- # String#toutf16 => string
- #
- # Convert <code>self</code> to UTF-16
- def toutf16; Kconv.toutf16(self) end
-
- # call-seq:
- # String#toutf32 => string
- #
- # Convert <code>self</code> to UTF-32
- def toutf32; Kconv.toutf32(self) end
-
- # call-seq:
- # String#tolocale => string
- #
- # Convert <code>self</code> to locale encoding
- def tolocale; Kconv.tolocale(self) end
-
- #
- # is Encoding
- #
-
- # call-seq:
- # String#iseuc => true or false
- #
- # Returns whether <code>self</code>'s encoding is EUC-JP or not.
- def iseuc; Kconv.iseuc(self) end
-
- # call-seq:
- # String#issjis => true or false
- #
- # Returns whether <code>self</code>'s encoding is Shift_JIS or not.
- def issjis; Kconv.issjis(self) end
-
- # call-seq:
- # String#isjis => true or false
- #
- # Returns whether <code>self</code>'s encoding is ISO-2022-JP or not.
- def isjis; Kconv.isjis(self) end
-
- # call-seq:
- # String#isutf8 => true or false
- #
- # Returns whether <code>self</code>'s encoding is UTF-8 or not.
- def isutf8; Kconv.isutf8(self) end
-end
diff --git a/ext/nkf/nkf-utf8/config.h b/ext/nkf/nkf-utf8/config.h
deleted file mode 100644
index 36898c0b4b..0000000000
--- a/ext/nkf/nkf-utf8/config.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#ifndef _CONFIG_H_
-#define _CONFIG_H_
-
-/* UTF8 input and output */
-#define UTF8_INPUT_ENABLE
-#define UTF8_OUTPUT_ENABLE
-
-/* invert characters invalid in Shift_JIS to CP932 */
-#define SHIFTJIS_CP932
-
-/* fix input encoding when given by option */
-#define INPUT_CODE_FIX
-
-/* --overwrite option */
-/* by Satoru Takabayashi <ccsatoru@vega.aichi-u.ac.jp> */
-#define OVERWRITE
-
-/* --cap-input, --url-input option */
-#define INPUT_OPTION
-
-/* --numchar-input option */
-#define NUMCHAR_OPTION
-
-/* --debug, --no-output option */
-#define CHECK_OPTION
-
-/* JIS X0212 */
-#define X0212_ENABLE
-
-/* --exec-in, --exec-out option
- * require pipe, fork, execvp and so on.
- * please undef this on MS-DOS, MinGW
- * this is still buggy around child process
- */
-/* #define EXEC_IO */
-
-/* Unicode Normalization */
-#define UNICODE_NORMALIZATION
-
-/*
- * Select Default Output Encoding
- *
- */
-
-/* #define DEFAULT_CODE_JIS */
-/* #define DEFAULT_CODE_SJIS */
-/* #define DEFAULT_CODE_WINDOWS_31J */
-/* #define DEFAULT_CODE_EUC */
-/* #define DEFAULT_CODE_UTF8 */
-
-#endif /* _CONFIG_H_ */
diff --git a/ext/nkf/nkf-utf8/nkf.c b/ext/nkf/nkf-utf8/nkf.c
deleted file mode 100644
index 6888a43918..0000000000
--- a/ext/nkf/nkf-utf8/nkf.c
+++ /dev/null
@@ -1,7205 +0,0 @@
-/*
- * Copyright (c) 1987, Fujitsu LTD. (Itaru ICHIKAWA).
- * Copyright (c) 1996-2018, The nkf Project.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- *
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- *
- * 3. This notice may not be removed or altered from any source distribution.
- */
-#define NKF_VERSION "2.1.5"
-#define NKF_RELEASE_DATE "2018-12-15"
-#define COPY_RIGHT \
- "Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa).\n" \
- "Copyright (C) 1996-2018, The nkf Project."
-
-#include "config.h"
-#include "nkf.h"
-#include "utf8tbl.h"
-#ifdef __WIN32__
-#include <windows.h>
-#include <locale.h>
-#endif
-#if defined(__OS2__)
-# define INCL_DOS
-# define INCL_DOSERRORS
-# include <os2.h>
-#endif
-#include <assert.h>
-
-
-/* state of output_mode and input_mode
-
- c2 0 means ASCII
- JIS_X_0201_1976_K
- ISO_8859_1
- JIS_X_0208
- EOF all termination
- c1 32bit data
-
- */
-
-/* MIME ENCODE */
-
-#define FIXED_MIME 7
-#define STRICT_MIME 8
-
-/* byte order */
-enum byte_order {
- ENDIAN_BIG = 1,
- ENDIAN_LITTLE = 2,
- ENDIAN_2143 = 3,
- ENDIAN_3412 = 4
-};
-
-/* ASCII CODE */
-
-#define BS 0x08
-#define TAB 0x09
-#define LF 0x0a
-#define CR 0x0d
-#define ESC 0x1b
-#define SP 0x20
-#define DEL 0x7f
-#define SI 0x0f
-#define SO 0x0e
-#define SS2 0x8e
-#define SS3 0x8f
-#define CRLF 0x0D0A
-
-
-/* encodings */
-
-enum nkf_encodings {
- ASCII,
- ISO_8859_1,
- ISO_2022_JP,
- CP50220,
- CP50221,
- CP50222,
- ISO_2022_JP_1,
- ISO_2022_JP_3,
- ISO_2022_JP_2004,
- SHIFT_JIS,
- WINDOWS_31J,
- CP10001,
- EUC_JP,
- EUCJP_NKF,
- CP51932,
- EUCJP_MS,
- EUCJP_ASCII,
- SHIFT_JISX0213,
- SHIFT_JIS_2004,
- EUC_JISX0213,
- EUC_JIS_2004,
- UTF_8,
- UTF_8N,
- UTF_8_BOM,
- UTF8_MAC,
- UTF_16,
- UTF_16BE,
- UTF_16BE_BOM,
- UTF_16LE,
- UTF_16LE_BOM,
- UTF_32,
- UTF_32BE,
- UTF_32BE_BOM,
- UTF_32LE,
- UTF_32LE_BOM,
- BINARY,
- NKF_ENCODING_TABLE_SIZE,
- JIS_X_0201_1976_K = 0x1013, /* I */ /* JIS C 6220-1969 */
- /* JIS_X_0201_1976_R = 0x1014, */ /* J */ /* JIS C 6220-1969 */
- /* JIS_X_0208_1978 = 0x1040, */ /* @ */ /* JIS C 6226-1978 */
- /* JIS_X_0208_1983 = 0x1087, */ /* B */ /* JIS C 6226-1983 */
- JIS_X_0208 = 0x1168, /* @B */
- JIS_X_0212 = 0x1159, /* D */
- /* JIS_X_0213_2000_1 = 0x1228, */ /* O */
- JIS_X_0213_2 = 0x1229, /* P */
- JIS_X_0213_1 = 0x1233 /* Q */
-};
-
-static nkf_char s_iconv(nkf_char c2, nkf_char c1, nkf_char c0);
-static nkf_char e_iconv(nkf_char c2, nkf_char c1, nkf_char c0);
-static nkf_char w_iconv(nkf_char c2, nkf_char c1, nkf_char c0);
-static nkf_char w_iconv16(nkf_char c2, nkf_char c1, nkf_char c0);
-static nkf_char w_iconv32(nkf_char c2, nkf_char c1, nkf_char c0);
-static void j_oconv(nkf_char c2, nkf_char c1);
-static void s_oconv(nkf_char c2, nkf_char c1);
-static void e_oconv(nkf_char c2, nkf_char c1);
-static void w_oconv(nkf_char c2, nkf_char c1);
-static void w_oconv16(nkf_char c2, nkf_char c1);
-static void w_oconv32(nkf_char c2, nkf_char c1);
-
-typedef const struct {
- const char *name;
- nkf_char (*iconv)(nkf_char c2, nkf_char c1, nkf_char c0);
- void (*oconv)(nkf_char c2, nkf_char c1);
-} nkf_native_encoding;
-
-nkf_native_encoding NkfEncodingASCII = { "ASCII", e_iconv, e_oconv };
-nkf_native_encoding NkfEncodingISO_2022_JP = { "ISO-2022-JP", e_iconv, j_oconv };
-nkf_native_encoding NkfEncodingShift_JIS = { "Shift_JIS", s_iconv, s_oconv };
-nkf_native_encoding NkfEncodingEUC_JP = { "EUC-JP", e_iconv, e_oconv };
-nkf_native_encoding NkfEncodingUTF_8 = { "UTF-8", w_iconv, w_oconv };
-nkf_native_encoding NkfEncodingUTF_16 = { "UTF-16", w_iconv16, w_oconv16 };
-nkf_native_encoding NkfEncodingUTF_32 = { "UTF-32", w_iconv32, w_oconv32 };
-
-typedef const struct {
- int id;
- const char *name;
- nkf_native_encoding *base_encoding;
-} nkf_encoding;
-
-nkf_encoding nkf_encoding_table[] = {
- {ASCII, "US-ASCII", &NkfEncodingASCII},
- {ISO_8859_1, "ISO-8859-1", &NkfEncodingASCII},
- {ISO_2022_JP, "ISO-2022-JP", &NkfEncodingISO_2022_JP},
- {CP50220, "CP50220", &NkfEncodingISO_2022_JP},
- {CP50221, "CP50221", &NkfEncodingISO_2022_JP},
- {CP50222, "CP50222", &NkfEncodingISO_2022_JP},
- {ISO_2022_JP_1, "ISO-2022-JP-1", &NkfEncodingISO_2022_JP},
- {ISO_2022_JP_3, "ISO-2022-JP-3", &NkfEncodingISO_2022_JP},
- {ISO_2022_JP_2004, "ISO-2022-JP-2004", &NkfEncodingISO_2022_JP},
- {SHIFT_JIS, "Shift_JIS", &NkfEncodingShift_JIS},
- {WINDOWS_31J, "Windows-31J", &NkfEncodingShift_JIS},
- {CP10001, "CP10001", &NkfEncodingShift_JIS},
- {EUC_JP, "EUC-JP", &NkfEncodingEUC_JP},
- {EUCJP_NKF, "eucJP-nkf", &NkfEncodingEUC_JP},
- {CP51932, "CP51932", &NkfEncodingEUC_JP},
- {EUCJP_MS, "eucJP-MS", &NkfEncodingEUC_JP},
- {EUCJP_ASCII, "eucJP-ASCII", &NkfEncodingEUC_JP},
- {SHIFT_JISX0213, "Shift_JISX0213", &NkfEncodingShift_JIS},
- {SHIFT_JIS_2004, "Shift_JIS-2004", &NkfEncodingShift_JIS},
- {EUC_JISX0213, "EUC-JISX0213", &NkfEncodingEUC_JP},
- {EUC_JIS_2004, "EUC-JIS-2004", &NkfEncodingEUC_JP},
- {UTF_8, "UTF-8", &NkfEncodingUTF_8},
- {UTF_8N, "UTF-8N", &NkfEncodingUTF_8},
- {UTF_8_BOM, "UTF-8-BOM", &NkfEncodingUTF_8},
- {UTF8_MAC, "UTF8-MAC", &NkfEncodingUTF_8},
- {UTF_16, "UTF-16", &NkfEncodingUTF_16},
- {UTF_16BE, "UTF-16BE", &NkfEncodingUTF_16},
- {UTF_16BE_BOM, "UTF-16BE-BOM", &NkfEncodingUTF_16},
- {UTF_16LE, "UTF-16LE", &NkfEncodingUTF_16},
- {UTF_16LE_BOM, "UTF-16LE-BOM", &NkfEncodingUTF_16},
- {UTF_32, "UTF-32", &NkfEncodingUTF_32},
- {UTF_32BE, "UTF-32BE", &NkfEncodingUTF_32},
- {UTF_32BE_BOM, "UTF-32BE-BOM", &NkfEncodingUTF_32},
- {UTF_32LE, "UTF-32LE", &NkfEncodingUTF_32},
- {UTF_32LE_BOM, "UTF-32LE-BOM", &NkfEncodingUTF_32},
- {BINARY, "BINARY", &NkfEncodingASCII},
- {-1, NULL, NULL}
-};
-
-static const struct {
- const char *name;
- int id;
-} encoding_name_to_id_table[] = {
- {"US-ASCII", ASCII},
- {"ASCII", ASCII},
- {"646", ASCII},
- {"ROMAN8", ASCII},
- {"ISO-2022-JP", ISO_2022_JP},
- {"ISO2022JP-CP932", CP50220},
- {"CP50220", CP50220},
- {"CP50221", CP50221},
- {"CSISO2022JP", CP50221},
- {"CP50222", CP50222},
- {"ISO-2022-JP-1", ISO_2022_JP_1},
- {"ISO-2022-JP-3", ISO_2022_JP_3},
- {"ISO-2022-JP-2004", ISO_2022_JP_2004},
- {"SHIFT_JIS", SHIFT_JIS},
- {"SJIS", SHIFT_JIS},
- {"MS_Kanji", SHIFT_JIS},
- {"PCK", SHIFT_JIS},
- {"WINDOWS-31J", WINDOWS_31J},
- {"CSWINDOWS31J", WINDOWS_31J},
- {"CP932", WINDOWS_31J},
- {"MS932", WINDOWS_31J},
- {"CP10001", CP10001},
- {"EUCJP", EUC_JP},
- {"EUC-JP", EUC_JP},
- {"EUCJP-NKF", EUCJP_NKF},
- {"CP51932", CP51932},
- {"EUC-JP-MS", EUCJP_MS},
- {"EUCJP-MS", EUCJP_MS},
- {"EUCJPMS", EUCJP_MS},
- {"EUC-JP-ASCII", EUCJP_ASCII},
- {"EUCJP-ASCII", EUCJP_ASCII},
- {"SHIFT_JISX0213", SHIFT_JISX0213},
- {"SHIFT_JIS-2004", SHIFT_JIS_2004},
- {"EUC-JISX0213", EUC_JISX0213},
- {"EUC-JIS-2004", EUC_JIS_2004},
- {"UTF-8", UTF_8},
- {"UTF-8N", UTF_8N},
- {"UTF-8-BOM", UTF_8_BOM},
- {"UTF8-MAC", UTF8_MAC},
- {"UTF-8-MAC", UTF8_MAC},
- {"UTF-16", UTF_16},
- {"UTF-16BE", UTF_16BE},
- {"UTF-16BE-BOM", UTF_16BE_BOM},
- {"UTF-16LE", UTF_16LE},
- {"UTF-16LE-BOM", UTF_16LE_BOM},
- {"UTF-32", UTF_32},
- {"UTF-32BE", UTF_32BE},
- {"UTF-32BE-BOM", UTF_32BE_BOM},
- {"UTF-32LE", UTF_32LE},
- {"UTF-32LE-BOM", UTF_32LE_BOM},
- {"BINARY", BINARY},
- {NULL, -1}
-};
-
-#if defined(DEFAULT_CODE_JIS)
-#define DEFAULT_ENCIDX ISO_2022_JP
-#elif defined(DEFAULT_CODE_SJIS)
-#define DEFAULT_ENCIDX SHIFT_JIS
-#elif defined(DEFAULT_CODE_WINDOWS_31J)
-#define DEFAULT_ENCIDX WINDOWS_31J
-#elif defined(DEFAULT_CODE_EUC)
-#define DEFAULT_ENCIDX EUC_JP
-#elif defined(DEFAULT_CODE_UTF8)
-#define DEFAULT_ENCIDX UTF_8
-#endif
-
-
-#define is_alnum(c) \
- (('a'<=c && c<='z')||('A'<= c && c<='Z')||('0'<=c && c<='9'))
-
-/* I don't trust portablity of toupper */
-#define nkf_toupper(c) (('a'<=c && c<='z')?(c-('a'-'A')):c)
-#define nkf_isoctal(c) ('0'<=c && c<='7')
-#define nkf_isdigit(c) ('0'<=c && c<='9')
-#define nkf_isxdigit(c) (nkf_isdigit(c) || ('a'<=c && c<='f') || ('A'<=c && c <= 'F'))
-#define nkf_isblank(c) (c == SP || c == TAB)
-#define nkf_isspace(c) (nkf_isblank(c) || c == CR || c == LF)
-#define nkf_isalpha(c) (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))
-#define nkf_isalnum(c) (nkf_isdigit(c) || nkf_isalpha(c))
-#define nkf_isprint(c) (SP<=c && c<='~')
-#define nkf_isgraph(c) ('!'<=c && c<='~')
-#define hex2bin(c) (('0'<=c&&c<='9') ? (c-'0') : \
- ('A'<=c&&c<='F') ? (c-'A'+10) : \
- ('a'<=c&&c<='f') ? (c-'a'+10) : 0)
-#define bin2hex(c) ("0123456789ABCDEF"[c&15])
-#define is_eucg3(c2) (((unsigned short)c2 >> 8) == SS3)
-#define nkf_noescape_mime(c) ((c == CR) || (c == LF) || \
- ((c > SP) && (c < DEL) && (c != '?') && (c != '=') && (c != '_') \
- && (c != '(') && (c != ')') && (c != '.') && (c != 0x22)))
-
-#define is_ibmext_in_sjis(c2) (CP932_TABLE_BEGIN <= c2 && c2 <= CP932_TABLE_END)
-#define nkf_byte_jisx0201_katakana_p(c) (SP <= c && c <= 0x5F)
-
-#define HOLD_SIZE 1024
-#if defined(INT_IS_SHORT)
-#define IOBUF_SIZE 2048
-#else
-#define IOBUF_SIZE 16384
-#endif
-
-#define DEFAULT_J 'B'
-#define DEFAULT_R 'B'
-
-
-#define GETA1 0x22
-#define GETA2 0x2e
-
-
-/* MIME preprocessor */
-
-#ifdef EASYWIN /*Easy Win */
-extern POINT _BufferSize;
-#endif
-
-struct input_code{
- const char *name;
- nkf_char stat;
- nkf_char score;
- nkf_char index;
- nkf_char buf[3];
- void (*status_func)(struct input_code *, nkf_char);
- nkf_char (*iconv_func)(nkf_char c2, nkf_char c1, nkf_char c0);
- int _file_stat;
-};
-
-static const char *input_codename = NULL; /* NULL: unestablished, "": BINARY */
-static nkf_encoding *input_encoding = NULL;
-static nkf_encoding *output_encoding = NULL;
-
-#if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
-/* UCS Mapping
- * 0: Shift_JIS, eucJP-ascii
- * 1: eucJP-ms
- * 2: CP932, CP51932
- * 3: CP10001
- */
-#define UCS_MAP_ASCII 0
-#define UCS_MAP_MS 1
-#define UCS_MAP_CP932 2
-#define UCS_MAP_CP10001 3
-static int ms_ucs_map_f = UCS_MAP_ASCII;
-#endif
-#ifdef UTF8_INPUT_ENABLE
-/* no NEC special, NEC-selected IBM extended and IBM extended characters */
-static int no_cp932ext_f = FALSE;
-/* ignore ZERO WIDTH NO-BREAK SPACE */
-static int no_best_fit_chars_f = FALSE;
-static int input_endian = ENDIAN_BIG;
-static int input_bom_f = FALSE;
-static nkf_char unicode_subchar = '?'; /* the regular substitution character */
-static void (*encode_fallback)(nkf_char c) = NULL;
-static void w_status(struct input_code *, nkf_char);
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
-static int output_bom_f = FALSE;
-static int output_endian = ENDIAN_BIG;
-#endif
-
-static void std_putc(nkf_char c);
-static nkf_char std_getc(FILE *f);
-static nkf_char std_ungetc(nkf_char c,FILE *f);
-
-static nkf_char broken_getc(FILE *f);
-static nkf_char broken_ungetc(nkf_char c,FILE *f);
-
-static nkf_char mime_getc(FILE *f);
-
-static void mime_putc(nkf_char c);
-
-/* buffers */
-
-#if !defined(PERL_XS) && !defined(WIN32DLL)
-static unsigned char stdibuf[IOBUF_SIZE];
-static unsigned char stdobuf[IOBUF_SIZE];
-#endif
-
-#define NKF_UNSPECIFIED (-TRUE)
-
-/* flags */
-static int unbuf_f = FALSE;
-static int estab_f = FALSE;
-static int nop_f = FALSE;
-static int binmode_f = TRUE; /* binary mode */
-static int rot_f = FALSE; /* rot14/43 mode */
-static int hira_f = FALSE; /* hira/kata henkan */
-static int alpha_f = FALSE; /* convert JIx0208 alphbet to ASCII */
-static int mime_f = MIME_DECODE_DEFAULT; /* convert MIME B base64 or Q */
-static int mime_decode_f = FALSE; /* mime decode is explicitly on */
-static int mimebuf_f = FALSE; /* MIME buffered input */
-static int broken_f = FALSE; /* convert ESC-less broken JIS */
-static int iso8859_f = FALSE; /* ISO8859 through */
-static int mimeout_f = FALSE; /* base64 mode */
-static int x0201_f = NKF_UNSPECIFIED; /* convert JIS X 0201 */
-static int iso2022jp_f = FALSE; /* replace non ISO-2022-JP with GETA */
-
-#ifdef UNICODE_NORMALIZATION
-static int nfc_f = FALSE;
-static nkf_char (*i_nfc_getc)(FILE *) = std_getc; /* input of ugetc */
-static nkf_char (*i_nfc_ungetc)(nkf_char c ,FILE *f) = std_ungetc;
-#endif
-
-#ifdef INPUT_OPTION
-static int cap_f = FALSE;
-static nkf_char (*i_cgetc)(FILE *) = std_getc; /* input of cgetc */
-static nkf_char (*i_cungetc)(nkf_char c ,FILE *f) = std_ungetc;
-
-static int url_f = FALSE;
-static nkf_char (*i_ugetc)(FILE *) = std_getc; /* input of ugetc */
-static nkf_char (*i_uungetc)(nkf_char c ,FILE *f) = std_ungetc;
-#endif
-
-#define PREFIX_EUCG3 NKF_INT32_C(0x8F00)
-#define CLASS_MASK NKF_INT32_C(0xFF000000)
-#define CLASS_UNICODE NKF_INT32_C(0x01000000)
-#define VALUE_MASK NKF_INT32_C(0x00FFFFFF)
-#define UNICODE_BMP_MAX NKF_INT32_C(0x0000FFFF)
-#define UNICODE_MAX NKF_INT32_C(0x0010FFFF)
-#define nkf_char_euc3_new(c) ((c) | PREFIX_EUCG3)
-#define nkf_char_unicode_new(c) ((c) | CLASS_UNICODE)
-#define nkf_char_unicode_p(c) ((c & CLASS_MASK) == CLASS_UNICODE)
-#define nkf_char_unicode_bmp_p(c) ((c & VALUE_MASK) <= UNICODE_BMP_MAX)
-#define nkf_char_unicode_value_p(c) ((c & VALUE_MASK) <= UNICODE_MAX)
-
-#define UTF16_TO_UTF32(lead, trail) (((lead) << 10) + (trail) - NKF_INT32_C(0x35FDC00))
-
-#ifdef NUMCHAR_OPTION
-static int numchar_f = FALSE;
-static nkf_char (*i_ngetc)(FILE *) = std_getc; /* input of ugetc */
-static nkf_char (*i_nungetc)(nkf_char c ,FILE *f) = std_ungetc;
-#endif
-
-#ifdef CHECK_OPTION
-static int noout_f = FALSE;
-static void no_putc(nkf_char c);
-static int debug_f = FALSE;
-static void debug(const char *str);
-static nkf_char (*iconv_for_check)(nkf_char c2,nkf_char c1,nkf_char c0) = 0;
-#endif
-
-static int guess_f = 0; /* 0: OFF, 1: ON, 2: VERBOSE */
-static void set_input_codename(const char *codename);
-
-#ifdef EXEC_IO
-static int exec_f = 0;
-#endif
-
-#ifdef SHIFTJIS_CP932
-/* invert IBM extended characters to others */
-static int cp51932_f = FALSE;
-
-/* invert NEC-selected IBM extended characters to IBM extended characters */
-static int cp932inv_f = TRUE;
-
-/* static nkf_char cp932_conv(nkf_char c2, nkf_char c1); */
-#endif /* SHIFTJIS_CP932 */
-
-static int x0212_f = FALSE;
-static int x0213_f = FALSE;
-
-static unsigned char prefix_table[256];
-
-static void e_status(struct input_code *, nkf_char);
-static void s_status(struct input_code *, nkf_char);
-
-struct input_code input_code_list[] = {
- {"EUC-JP", 0, 0, 0, {0, 0, 0}, e_status, e_iconv, 0},
- {"Shift_JIS", 0, 0, 0, {0, 0, 0}, s_status, s_iconv, 0},
-#ifdef UTF8_INPUT_ENABLE
- {"UTF-8", 0, 0, 0, {0, 0, 0}, w_status, w_iconv, 0},
- {"UTF-16", 0, 0, 0, {0, 0, 0}, NULL, w_iconv16, 0},
- {"UTF-32", 0, 0, 0, {0, 0, 0}, NULL, w_iconv32, 0},
-#endif
- {NULL, 0, 0, 0, {0, 0, 0}, NULL, NULL, 0}
-};
-
-static int mimeout_mode = 0; /* 0, -1, 'Q', 'B', 1, 2 */
-static int base64_count = 0;
-
-/* X0208 -> ASCII converter */
-
-/* fold parameter */
-static int f_line = 0; /* chars in line */
-static int f_prev = 0;
-static int fold_preserve_f = FALSE; /* preserve new lines */
-static int fold_f = FALSE;
-static int fold_len = 0;
-
-/* options */
-static unsigned char kanji_intro = DEFAULT_J;
-static unsigned char ascii_intro = DEFAULT_R;
-
-/* Folding */
-
-#define FOLD_MARGIN 10
-#define DEFAULT_FOLD 60
-
-static int fold_margin = FOLD_MARGIN;
-
-/* process default */
-
-static nkf_char
-no_connection2(ARG_UNUSED nkf_char c2, ARG_UNUSED nkf_char c1, ARG_UNUSED nkf_char c0)
-{
- fprintf(stderr,"nkf internal module connection failure.\n");
- exit(EXIT_FAILURE);
- return 0; /* LINT */
-}
-
-static void
-no_connection(nkf_char c2, nkf_char c1)
-{
- no_connection2(c2,c1,0);
-}
-
-static nkf_char (*iconv)(nkf_char c2,nkf_char c1,nkf_char c0) = no_connection2;
-static void (*oconv)(nkf_char c2,nkf_char c1) = no_connection;
-
-static void (*o_zconv)(nkf_char c2,nkf_char c1) = no_connection;
-static void (*o_fconv)(nkf_char c2,nkf_char c1) = no_connection;
-static void (*o_eol_conv)(nkf_char c2,nkf_char c1) = no_connection;
-static void (*o_rot_conv)(nkf_char c2,nkf_char c1) = no_connection;
-static void (*o_hira_conv)(nkf_char c2,nkf_char c1) = no_connection;
-static void (*o_base64conv)(nkf_char c2,nkf_char c1) = no_connection;
-static void (*o_iso2022jp_check_conv)(nkf_char c2,nkf_char c1) = no_connection;
-
-/* static redirections */
-
-static void (*o_putc)(nkf_char c) = std_putc;
-
-static nkf_char (*i_getc)(FILE *f) = std_getc; /* general input */
-static nkf_char (*i_ungetc)(nkf_char c,FILE *f) =std_ungetc;
-
-static nkf_char (*i_bgetc)(FILE *) = std_getc; /* input of mgetc */
-static nkf_char (*i_bungetc)(nkf_char c ,FILE *f) = std_ungetc;
-
-static void (*o_mputc)(nkf_char c) = std_putc ; /* output of mputc */
-
-static nkf_char (*i_mgetc)(FILE *) = std_getc; /* input of mgetc */
-static nkf_char (*i_mungetc)(nkf_char c ,FILE *f) = std_ungetc;
-
-/* for strict mime */
-static nkf_char (*i_mgetc_buf)(FILE *) = std_getc; /* input of mgetc_buf */
-static nkf_char (*i_mungetc_buf)(nkf_char c,FILE *f) = std_ungetc;
-
-/* Global states */
-static int output_mode = ASCII; /* output kanji mode */
-static int input_mode = ASCII; /* input kanji mode */
-static int mime_decode_mode = FALSE; /* MIME mode B base64, Q hex */
-
-/* X0201 / X0208 conversion tables */
-
-/* X0201 kana conversion table */
-/* 90-9F A0-DF */
-static const unsigned char cv[]= {
- 0x21,0x21,0x21,0x23,0x21,0x56,0x21,0x57,
- 0x21,0x22,0x21,0x26,0x25,0x72,0x25,0x21,
- 0x25,0x23,0x25,0x25,0x25,0x27,0x25,0x29,
- 0x25,0x63,0x25,0x65,0x25,0x67,0x25,0x43,
- 0x21,0x3c,0x25,0x22,0x25,0x24,0x25,0x26,
- 0x25,0x28,0x25,0x2a,0x25,0x2b,0x25,0x2d,
- 0x25,0x2f,0x25,0x31,0x25,0x33,0x25,0x35,
- 0x25,0x37,0x25,0x39,0x25,0x3b,0x25,0x3d,
- 0x25,0x3f,0x25,0x41,0x25,0x44,0x25,0x46,
- 0x25,0x48,0x25,0x4a,0x25,0x4b,0x25,0x4c,
- 0x25,0x4d,0x25,0x4e,0x25,0x4f,0x25,0x52,
- 0x25,0x55,0x25,0x58,0x25,0x5b,0x25,0x5e,
- 0x25,0x5f,0x25,0x60,0x25,0x61,0x25,0x62,
- 0x25,0x64,0x25,0x66,0x25,0x68,0x25,0x69,
- 0x25,0x6a,0x25,0x6b,0x25,0x6c,0x25,0x6d,
- 0x25,0x6f,0x25,0x73,0x21,0x2b,0x21,0x2c,
- 0x00,0x00};
-
-
-/* X0201 kana conversion table for dakuten */
-/* 90-9F A0-DF */
-static const unsigned char dv[]= {
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x74,
- 0x00,0x00,0x00,0x00,0x25,0x2c,0x25,0x2e,
- 0x25,0x30,0x25,0x32,0x25,0x34,0x25,0x36,
- 0x25,0x38,0x25,0x3a,0x25,0x3c,0x25,0x3e,
- 0x25,0x40,0x25,0x42,0x25,0x45,0x25,0x47,
- 0x25,0x49,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x25,0x50,0x25,0x53,
- 0x25,0x56,0x25,0x59,0x25,0x5c,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00};
-
-/* X0201 kana conversion table for han-dakuten */
-/* 90-9F A0-DF */
-static const unsigned char ev[]= {
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x25,0x51,0x25,0x54,
- 0x25,0x57,0x25,0x5a,0x25,0x5d,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00};
-
-/* X0201 kana to X0213 conversion table for han-dakuten */
-/* 90-9F A0-DF */
-static const unsigned char ev_x0213[]= {
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x25,0x77,0x25,0x78,
- 0x25,0x79,0x25,0x7a,0x25,0x7b,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x25,0x7c,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x25,0x7d,0x00,0x00,
- 0x25,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00};
-
-
-/* X0208 kigou conversion table */
-/* 0x8140 - 0x819e */
-static const unsigned char fv[] = {
-
- 0x00,0x00,0x00,0x00,0x2c,0x2e,0x00,0x3a,
- 0x3b,0x3f,0x21,0x00,0x00,0x27,0x60,0x00,
- 0x5e,0x00,0x5f,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x2d,0x00,0x2f,
- 0x5c,0x00,0x00,0x7c,0x00,0x00,0x60,0x27,
- 0x22,0x22,0x28,0x29,0x00,0x00,0x5b,0x5d,
- 0x7b,0x7d,0x3c,0x3e,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x2b,0x2d,0x00,0x00,
- 0x00,0x3d,0x00,0x3c,0x3e,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x24,0x00,0x00,0x25,0x23,0x26,0x2a,0x40,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
-} ;
-
-
-
-static int option_mode = 0;
-static int file_out_f = FALSE;
-#ifdef OVERWRITE
-static int overwrite_f = FALSE;
-static int preserve_time_f = FALSE;
-static int backup_f = FALSE;
-static char *backup_suffix = "";
-#endif
-
-static int eolmode_f = 0; /* CR, LF, CRLF */
-static int input_eol = 0; /* 0: unestablished, EOF: MIXED */
-static nkf_char prev_cr = 0; /* CR or 0 */
-#ifdef EASYWIN /*Easy Win */
-static int end_check;
-#endif /*Easy Win */
-
-static void *
-nkf_xmalloc(size_t size)
-{
- void *ptr;
-
- if (size == 0) size = 1;
-
- ptr = malloc(size);
- if (ptr == NULL) {
- perror("can't malloc");
- exit(EXIT_FAILURE);
- }
-
- return ptr;
-}
-
-static void *
-nkf_xrealloc(void *ptr, size_t size)
-{
- if (size == 0) size = 1;
-
- ptr = realloc(ptr, size);
- if (ptr == NULL) {
- perror("can't realloc");
- exit(EXIT_FAILURE);
- }
-
- return ptr;
-}
-
-#define nkf_xfree(ptr) free(ptr)
-
-static int
-nkf_str_caseeql(const char *src, const char *target)
-{
- int i;
- for (i = 0; src[i] && target[i]; i++) {
- if (nkf_toupper(src[i]) != nkf_toupper(target[i])) return FALSE;
- }
- if (src[i] || target[i]) return FALSE;
- else return TRUE;
-}
-
-static nkf_encoding*
-nkf_enc_from_index(int idx)
-{
- if (idx < 0 || NKF_ENCODING_TABLE_SIZE <= idx) {
- return 0;
- }
- return &nkf_encoding_table[idx];
-}
-
-static int
-nkf_enc_find_index(const char *name)
-{
- int i;
- if (name[0] == 'X' && *(name+1) == '-') name += 2;
- for (i = 0; encoding_name_to_id_table[i].id >= 0; i++) {
- if (nkf_str_caseeql(encoding_name_to_id_table[i].name, name)) {
- return encoding_name_to_id_table[i].id;
- }
- }
- return -1;
-}
-
-static nkf_encoding*
-nkf_enc_find(const char *name)
-{
- int idx = -1;
- idx = nkf_enc_find_index(name);
- if (idx < 0) return 0;
- return nkf_enc_from_index(idx);
-}
-
-#define nkf_enc_name(enc) (enc)->name
-#define nkf_enc_to_index(enc) (enc)->id
-#define nkf_enc_to_base_encoding(enc) (enc)->base_encoding
-#define nkf_enc_to_iconv(enc) nkf_enc_to_base_encoding(enc)->iconv
-#define nkf_enc_to_oconv(enc) nkf_enc_to_base_encoding(enc)->oconv
-#define nkf_enc_asciicompat(enc) (\
- nkf_enc_to_base_encoding(enc) == &NkfEncodingASCII ||\
- nkf_enc_to_base_encoding(enc) == &NkfEncodingISO_2022_JP)
-#define nkf_enc_unicode_p(enc) (\
- nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_8 ||\
- nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_16 ||\
- nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_32)
-#define nkf_enc_cp5022x_p(enc) (\
- nkf_enc_to_index(enc) == CP50220 ||\
- nkf_enc_to_index(enc) == CP50221 ||\
- nkf_enc_to_index(enc) == CP50222)
-
-#ifdef DEFAULT_CODE_LOCALE
-static const char*
-nkf_locale_charmap(void)
-{
-#ifdef HAVE_LANGINFO_H
- return nl_langinfo(CODESET);
-#elif defined(__WIN32__)
- static char buf[16];
- sprintf(buf, "CP%d", GetACP());
- return buf;
-#elif defined(__OS2__)
-# if defined(INT_IS_SHORT)
- /* OS/2 1.x */
- return NULL;
-# else
- /* OS/2 32bit */
- static char buf[16];
- ULONG ulCP[1], ulncp;
- DosQueryCp(sizeof(ulCP), ulCP, &ulncp);
- if (ulCP[0] == 932 || ulCP[0] == 943)
- strcpy(buf, "Shift_JIS");
- else
- sprintf(buf, "CP%lu", ulCP[0]);
- return buf;
-# endif
-#endif
- return NULL;
-}
-
-static nkf_encoding*
-nkf_locale_encoding(void)
-{
- nkf_encoding *enc = 0;
- const char *encname = nkf_locale_charmap();
- if (encname)
- enc = nkf_enc_find(encname);
- return enc;
-}
-#endif /* DEFAULT_CODE_LOCALE */
-
-static nkf_encoding*
-nkf_utf8_encoding(void)
-{
- return &nkf_encoding_table[UTF_8];
-}
-
-static nkf_encoding*
-nkf_default_encoding(void)
-{
- nkf_encoding *enc = 0;
-#ifdef DEFAULT_CODE_LOCALE
- enc = nkf_locale_encoding();
-#elif defined(DEFAULT_ENCIDX)
- enc = nkf_enc_from_index(DEFAULT_ENCIDX);
-#endif
- if (!enc) enc = nkf_utf8_encoding();
- return enc;
-}
-
-typedef struct {
- long capa;
- long len;
- nkf_char *ptr;
-} nkf_buf_t;
-
-static nkf_buf_t *
-nkf_buf_new(int length)
-{
- nkf_buf_t *buf = nkf_xmalloc(sizeof(nkf_buf_t));
- buf->ptr = nkf_xmalloc(sizeof(nkf_char) * length);
- buf->capa = length;
- buf->len = 0;
- return buf;
-}
-
-#if 0
-static void
-nkf_buf_dispose(nkf_buf_t *buf)
-{
- nkf_xfree(buf->ptr);
- nkf_xfree(buf);
-}
-#endif
-
-#define nkf_buf_length(buf) ((buf)->len)
-#define nkf_buf_empty_p(buf) ((buf)->len == 0)
-
-static nkf_char
-nkf_buf_at(nkf_buf_t *buf, int index)
-{
- assert(index <= buf->len);
- return buf->ptr[index];
-}
-
-static void
-nkf_buf_clear(nkf_buf_t *buf)
-{
- buf->len = 0;
-}
-
-static void
-nkf_buf_push(nkf_buf_t *buf, nkf_char c)
-{
- if (buf->capa <= buf->len) {
- exit(EXIT_FAILURE);
- }
- buf->ptr[buf->len++] = c;
-}
-
-static nkf_char
-nkf_buf_pop(nkf_buf_t *buf)
-{
- assert(!nkf_buf_empty_p(buf));
- return buf->ptr[--buf->len];
-}
-
-/* Normalization Form C */
-#ifndef PERL_XS
-#ifdef WIN32DLL
-#define fprintf dllprintf
-#endif
-
-static void
-version(void)
-{
- fprintf(HELP_OUTPUT,"Network Kanji Filter Version " NKF_VERSION " (" NKF_RELEASE_DATE ") \n" COPY_RIGHT "\n");
-}
-
-static void
-usage(void)
-{
- fprintf(HELP_OUTPUT,
- "Usage: nkf -[flags] [--] [in file] .. [out file for -O flag]\n"
-#ifdef UTF8_OUTPUT_ENABLE
- " j/s/e/w Specify output encoding ISO-2022-JP, Shift_JIS, EUC-JP\n"
- " UTF options is -w[8[0],{16,32}[{B,L}[0]]]\n"
-#else
-#endif
-#ifdef UTF8_INPUT_ENABLE
- " J/S/E/W Specify input encoding ISO-2022-JP, Shift_JIS, EUC-JP\n"
- " UTF option is -W[8,[16,32][B,L]]\n"
-#else
- " J/S/E Specify output encoding ISO-2022-JP, Shift_JIS, EUC-JP\n"
-#endif
- );
- fprintf(HELP_OUTPUT,
- " m[BQSN0] MIME decode [B:base64,Q:quoted,S:strict,N:nonstrict,0:no decode]\n"
- " M[BQ] MIME encode [B:base64 Q:quoted]\n"
- " f/F Folding: -f60 or -f or -f60-10 (fold margin 10) F preserve nl\n"
- );
- fprintf(HELP_OUTPUT,
- " Z[0-4] Default/0: Convert JISX0208 Alphabet to ASCII\n"
- " 1: Kankaku to one space 2: to two spaces 3: HTML Entity\n"
- " 4: JISX0208 Katakana to JISX0201 Katakana\n"
- " X,x Convert Halfwidth Katakana to Fullwidth or preserve it\n"
- );
- fprintf(HELP_OUTPUT,
- " O Output to File (DEFAULT 'nkf.out')\n"
- " L[uwm] Line mode u:LF w:CRLF m:CR (DEFAULT noconversion)\n"
- );
- fprintf(HELP_OUTPUT,
- " --ic=<encoding> Specify the input encoding\n"
- " --oc=<encoding> Specify the output encoding\n"
- " --hiragana --katakana Hiragana/Katakana Conversion\n"
- " --katakana-hiragana Converts each other\n"
- );
- fprintf(HELP_OUTPUT,
-#ifdef INPUT_OPTION
- " --{cap, url}-input Convert hex after ':' or '%%'\n"
-#endif
-#ifdef NUMCHAR_OPTION
- " --numchar-input Convert Unicode Character Reference\n"
-#endif
-#ifdef UTF8_INPUT_ENABLE
- " --fb-{skip, html, xml, perl, java, subchar}\n"
- " Specify unassigned character's replacement\n"
-#endif
- );
- fprintf(HELP_OUTPUT,
-#ifdef OVERWRITE
- " --in-place[=SUF] Overwrite original files\n"
- " --overwrite[=SUF] Preserve timestamp of original files\n"
-#endif
- " -g --guess Guess the input code\n"
- " -v --version Print the version\n"
- " --help/-V Print this help / configuration\n"
- );
- version();
-}
-
-static void
-show_configuration(void)
-{
- fprintf(HELP_OUTPUT,
- "Summary of my nkf " NKF_VERSION " (" NKF_RELEASE_DATE ") configuration:\n"
- " Compile-time options:\n"
- " Compiled at: " __DATE__ " " __TIME__ "\n"
- );
- fprintf(HELP_OUTPUT,
- " Default output encoding: "
-#ifdef DEFAULT_CODE_LOCALE
- "LOCALE (%s)\n", nkf_enc_name(nkf_default_encoding())
-#elif defined(DEFAULT_ENCIDX)
- "CONFIG (%s)\n", nkf_enc_name(nkf_default_encoding())
-#else
- "NONE\n"
-#endif
- );
- fprintf(HELP_OUTPUT,
- " Default output end of line: "
-#if DEFAULT_NEWLINE == CR
- "CR"
-#elif DEFAULT_NEWLINE == CRLF
- "CRLF"
-#else
- "LF"
-#endif
- "\n"
- " Decode MIME encoded string: "
-#if MIME_DECODE_DEFAULT
- "ON"
-#else
- "OFF"
-#endif
- "\n"
- " Convert JIS X 0201 Katakana: "
-#if X0201_DEFAULT
- "ON"
-#else
- "OFF"
-#endif
- "\n"
- " --help, --version output: "
-#if HELP_OUTPUT_HELP_OUTPUT
- "HELP_OUTPUT"
-#else
- "STDOUT"
-#endif
- "\n");
-}
-#endif /*PERL_XS*/
-
-#ifdef OVERWRITE
-static char*
-get_backup_filename(const char *suffix, const char *filename)
-{
- char *backup_filename;
- int asterisk_count = 0;
- int i, j;
- int filename_length = strlen(filename);
-
- for(i = 0; suffix[i]; i++){
- if(suffix[i] == '*') asterisk_count++;
- }
-
- if(asterisk_count){
- backup_filename = nkf_xmalloc(strlen(suffix) + (asterisk_count * (filename_length - 1)) + 1);
- for(i = 0, j = 0; suffix[i];){
- if(suffix[i] == '*'){
- backup_filename[j] = '\0';
- strncat(backup_filename, filename, filename_length);
- i++;
- j += filename_length;
- }else{
- backup_filename[j++] = suffix[i++];
- }
- }
- backup_filename[j] = '\0';
- }else{
- j = filename_length + strlen(suffix);
- backup_filename = nkf_xmalloc(j + 1);
- strcpy(backup_filename, filename);
- strcat(backup_filename, suffix);
- backup_filename[j] = '\0';
- }
- return backup_filename;
-}
-#endif
-
-#ifdef UTF8_INPUT_ENABLE
-static void
-nkf_each_char_to_hex(void (*f)(nkf_char c2,nkf_char c1), nkf_char c)
-{
- int shift = 20;
- c &= VALUE_MASK;
- while(shift >= 0){
- if(c >= NKF_INT32_C(1)<<shift){
- while(shift >= 0){
- (*f)(0, bin2hex(c>>shift));
- shift -= 4;
- }
- }else{
- shift -= 4;
- }
- }
- return;
-}
-
-static void
-encode_fallback_html(nkf_char c)
-{
- (*oconv)(0, '&');
- (*oconv)(0, '#');
- c &= VALUE_MASK;
- if(c >= NKF_INT32_C(1000000))
- (*oconv)(0, 0x30+(c/NKF_INT32_C(1000000))%10);
- if(c >= NKF_INT32_C(100000))
- (*oconv)(0, 0x30+(c/NKF_INT32_C(100000) )%10);
- if(c >= 10000)
- (*oconv)(0, 0x30+(c/10000 )%10);
- if(c >= 1000)
- (*oconv)(0, 0x30+(c/1000 )%10);
- if(c >= 100)
- (*oconv)(0, 0x30+(c/100 )%10);
- if(c >= 10)
- (*oconv)(0, 0x30+(c/10 )%10);
- if(c >= 0)
- (*oconv)(0, 0x30+ c %10);
- (*oconv)(0, ';');
- return;
-}
-
-static void
-encode_fallback_xml(nkf_char c)
-{
- (*oconv)(0, '&');
- (*oconv)(0, '#');
- (*oconv)(0, 'x');
- nkf_each_char_to_hex(oconv, c);
- (*oconv)(0, ';');
- return;
-}
-
-static void
-encode_fallback_java(nkf_char c)
-{
- (*oconv)(0, '\\');
- c &= VALUE_MASK;
- if(!nkf_char_unicode_bmp_p(c)){
- int high = (c >> 10) + NKF_INT32_C(0xD7C0); /* high surrogate */
- int low = (c & 0x3FF) + NKF_INT32_C(0xDC00); /* low surrogate */
- (*oconv)(0, 'u');
- (*oconv)(0, bin2hex(high>>12));
- (*oconv)(0, bin2hex(high>> 8));
- (*oconv)(0, bin2hex(high>> 4));
- (*oconv)(0, bin2hex(high ));
- (*oconv)(0, '\\');
- (*oconv)(0, 'u');
- (*oconv)(0, bin2hex(low>>12));
- (*oconv)(0, bin2hex(low>> 8));
- (*oconv)(0, bin2hex(low>> 4));
- (*oconv)(0, bin2hex(low ));
- }else{
- (*oconv)(0, 'u');
- (*oconv)(0, bin2hex(c>>12));
- (*oconv)(0, bin2hex(c>> 8));
- (*oconv)(0, bin2hex(c>> 4));
- (*oconv)(0, bin2hex(c ));
- }
- return;
-}
-
-static void
-encode_fallback_perl(nkf_char c)
-{
- (*oconv)(0, '\\');
- (*oconv)(0, 'x');
- (*oconv)(0, '{');
- nkf_each_char_to_hex(oconv, c);
- (*oconv)(0, '}');
- return;
-}
-
-static void
-encode_fallback_subchar(nkf_char c)
-{
- c = unicode_subchar;
- (*oconv)((c>>8)&0xFF, c&0xFF);
- return;
-}
-#endif
-
-static const struct {
- const char *name;
- const char *alias;
-} long_option[] = {
- {"ic=", ""},
- {"oc=", ""},
- {"base64","jMB"},
- {"euc","e"},
- {"euc-input","E"},
- {"fj","jm"},
- {"help",""},
- {"jis","j"},
- {"jis-input","J"},
- {"mac","sLm"},
- {"mime","jM"},
- {"mime-input","m"},
- {"msdos","sLw"},
- {"sjis","s"},
- {"sjis-input","S"},
- {"unix","eLu"},
- {"version","v"},
- {"windows","sLw"},
- {"hiragana","h1"},
- {"katakana","h2"},
- {"katakana-hiragana","h3"},
- {"guess=", ""},
- {"guess", "g2"},
- {"cp932", ""},
- {"no-cp932", ""},
-#ifdef X0212_ENABLE
- {"x0212", ""},
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- {"utf8", "w"},
- {"utf16", "w16"},
- {"ms-ucs-map", ""},
- {"fb-skip", ""},
- {"fb-html", ""},
- {"fb-xml", ""},
- {"fb-perl", ""},
- {"fb-java", ""},
- {"fb-subchar", ""},
- {"fb-subchar=", ""},
-#endif
-#ifdef UTF8_INPUT_ENABLE
- {"utf8-input", "W"},
- {"utf16-input", "W16"},
- {"no-cp932ext", ""},
- {"no-best-fit-chars",""},
-#endif
-#ifdef UNICODE_NORMALIZATION
- {"utf8mac-input", ""},
-#endif
-#ifdef OVERWRITE
- {"overwrite", ""},
- {"overwrite=", ""},
- {"in-place", ""},
- {"in-place=", ""},
-#endif
-#ifdef INPUT_OPTION
- {"cap-input", ""},
- {"url-input", ""},
-#endif
-#ifdef NUMCHAR_OPTION
- {"numchar-input", ""},
-#endif
-#ifdef CHECK_OPTION
- {"no-output", ""},
- {"debug", ""},
-#endif
-#ifdef SHIFTJIS_CP932
- {"cp932inv", ""},
-#endif
-#ifdef EXEC_IO
- {"exec-in", ""},
- {"exec-out", ""},
-#endif
- {"prefix=", ""},
-};
-
-static void
-set_input_encoding(nkf_encoding *enc)
-{
- switch (nkf_enc_to_index(enc)) {
- case ISO_8859_1:
- iso8859_f = TRUE;
- break;
- case CP50221:
- case CP50222:
- if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */
- case CP50220:
-#ifdef SHIFTJIS_CP932
- cp51932_f = TRUE;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_CP932;
-#endif
- break;
- case ISO_2022_JP_1:
- x0212_f = TRUE;
- break;
- case ISO_2022_JP_3:
- x0212_f = TRUE;
- x0213_f = TRUE;
- break;
- case ISO_2022_JP_2004:
- x0212_f = TRUE;
- x0213_f = TRUE;
- break;
- case SHIFT_JIS:
- break;
- case WINDOWS_31J:
- if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */
-#ifdef SHIFTJIS_CP932
- cp51932_f = TRUE;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_CP932;
-#endif
- break;
- break;
- case CP10001:
-#ifdef SHIFTJIS_CP932
- cp51932_f = TRUE;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_CP10001;
-#endif
- break;
- case EUC_JP:
- break;
- case EUCJP_NKF:
- break;
- case CP51932:
- if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */
-#ifdef SHIFTJIS_CP932
- cp51932_f = TRUE;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_CP932;
-#endif
- break;
- case EUCJP_MS:
- if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */
-#ifdef SHIFTJIS_CP932
- cp51932_f = FALSE;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_MS;
-#endif
- break;
- case EUCJP_ASCII:
- if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */
-#ifdef SHIFTJIS_CP932
- cp51932_f = FALSE;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_ASCII;
-#endif
- break;
- case SHIFT_JISX0213:
- case SHIFT_JIS_2004:
- x0213_f = TRUE;
-#ifdef SHIFTJIS_CP932
- cp51932_f = FALSE;
- if (cp932inv_f == TRUE) cp932inv_f = FALSE;
-#endif
- break;
- case EUC_JISX0213:
- case EUC_JIS_2004:
- x0213_f = TRUE;
-#ifdef SHIFTJIS_CP932
- cp51932_f = FALSE;
-#endif
- break;
-#ifdef UTF8_INPUT_ENABLE
-#ifdef UNICODE_NORMALIZATION
- case UTF8_MAC:
- nfc_f = TRUE;
- break;
-#endif
- case UTF_16:
- case UTF_16BE:
- case UTF_16BE_BOM:
- input_endian = ENDIAN_BIG;
- break;
- case UTF_16LE:
- case UTF_16LE_BOM:
- input_endian = ENDIAN_LITTLE;
- break;
- case UTF_32:
- case UTF_32BE:
- case UTF_32BE_BOM:
- input_endian = ENDIAN_BIG;
- break;
- case UTF_32LE:
- case UTF_32LE_BOM:
- input_endian = ENDIAN_LITTLE;
- break;
-#endif
- }
-}
-
-static void
-set_output_encoding(nkf_encoding *enc)
-{
- switch (nkf_enc_to_index(enc)) {
- case CP50220:
-#ifdef SHIFTJIS_CP932
- if (cp932inv_f == TRUE) cp932inv_f = FALSE;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_CP932;
-#endif
- break;
- case CP50221:
- if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */
-#ifdef SHIFTJIS_CP932
- if (cp932inv_f == TRUE) cp932inv_f = FALSE;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_CP932;
-#endif
- break;
- case ISO_2022_JP:
-#ifdef SHIFTJIS_CP932
- if (cp932inv_f == TRUE) cp932inv_f = FALSE;
-#endif
- break;
- case ISO_2022_JP_1:
- x0212_f = TRUE;
-#ifdef SHIFTJIS_CP932
- if (cp932inv_f == TRUE) cp932inv_f = FALSE;
-#endif
- break;
- case ISO_2022_JP_3:
- case ISO_2022_JP_2004:
- x0212_f = TRUE;
- x0213_f = TRUE;
-#ifdef SHIFTJIS_CP932
- if (cp932inv_f == TRUE) cp932inv_f = FALSE;
-#endif
- break;
- case SHIFT_JIS:
- break;
- case WINDOWS_31J:
- if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_CP932;
-#endif
- break;
- case CP10001:
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_CP10001;
-#endif
- break;
- case EUC_JP:
- x0212_f = TRUE;
-#ifdef SHIFTJIS_CP932
- if (cp932inv_f == TRUE) cp932inv_f = FALSE;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_ASCII;
-#endif
- break;
- case EUCJP_NKF:
- x0212_f = FALSE;
-#ifdef SHIFTJIS_CP932
- if (cp932inv_f == TRUE) cp932inv_f = FALSE;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_ASCII;
-#endif
- break;
- case CP51932:
- if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */
-#ifdef SHIFTJIS_CP932
- if (cp932inv_f == TRUE) cp932inv_f = FALSE;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_CP932;
-#endif
- break;
- case EUCJP_MS:
- if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */
- x0212_f = TRUE;
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_MS;
-#endif
- break;
- case EUCJP_ASCII:
- if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */
- x0212_f = TRUE;
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_ASCII;
-#endif
- break;
- case SHIFT_JISX0213:
- case SHIFT_JIS_2004:
- x0213_f = TRUE;
-#ifdef SHIFTJIS_CP932
- if (cp932inv_f == TRUE) cp932inv_f = FALSE;
-#endif
- break;
- case EUC_JISX0213:
- case EUC_JIS_2004:
- x0212_f = TRUE;
- x0213_f = TRUE;
-#ifdef SHIFTJIS_CP932
- if (cp932inv_f == TRUE) cp932inv_f = FALSE;
-#endif
- break;
-#ifdef UTF8_OUTPUT_ENABLE
- case UTF_8_BOM:
- output_bom_f = TRUE;
- break;
- case UTF_16:
- case UTF_16BE_BOM:
- output_bom_f = TRUE;
- break;
- case UTF_16LE:
- output_endian = ENDIAN_LITTLE;
- output_bom_f = FALSE;
- break;
- case UTF_16LE_BOM:
- output_endian = ENDIAN_LITTLE;
- output_bom_f = TRUE;
- break;
- case UTF_32:
- case UTF_32BE_BOM:
- output_bom_f = TRUE;
- break;
- case UTF_32LE:
- output_endian = ENDIAN_LITTLE;
- output_bom_f = FALSE;
- break;
- case UTF_32LE_BOM:
- output_endian = ENDIAN_LITTLE;
- output_bom_f = TRUE;
- break;
-#endif
- }
-}
-
-static struct input_code*
-find_inputcode_byfunc(nkf_char (*iconv_func)(nkf_char c2,nkf_char c1,nkf_char c0))
-{
- if (iconv_func){
- struct input_code *p = input_code_list;
- while (p->name){
- if (iconv_func == p->iconv_func){
- return p;
- }
- p++;
- }
- }
- return 0;
-}
-
-static void
-set_iconv(nkf_char f, nkf_char (*iconv_func)(nkf_char c2,nkf_char c1,nkf_char c0))
-{
-#ifdef INPUT_CODE_FIX
- if (f || !input_encoding)
-#endif
- if (estab_f != f){
- estab_f = f;
- }
-
- if (iconv_func
-#ifdef INPUT_CODE_FIX
- && (f == -TRUE || !input_encoding) /* -TRUE means "FORCE" */
-#endif
- ){
- iconv = iconv_func;
- }
-#ifdef CHECK_OPTION
- if (estab_f && iconv_for_check != iconv){
- struct input_code *p = find_inputcode_byfunc(iconv);
- if (p){
- set_input_codename(p->name);
- debug(p->name);
- }
- iconv_for_check = iconv;
- }
-#endif
-}
-
-#ifdef X0212_ENABLE
-static nkf_char
-x0212_shift(nkf_char c)
-{
- nkf_char ret = c;
- c &= 0x7f;
- if (is_eucg3(ret)){
- if (0x75 <= c && c <= 0x7f){
- ret = c + (0x109 - 0x75);
- }
- }else{
- if (0x75 <= c && c <= 0x7f){
- ret = c + (0x113 - 0x75);
- }
- }
- return ret;
-}
-
-
-static nkf_char
-x0212_unshift(nkf_char c)
-{
- nkf_char ret = c;
- if (0x7f <= c && c <= 0x88){
- ret = c + (0x75 - 0x7f);
- }else if (0x89 <= c && c <= 0x92){
- ret = PREFIX_EUCG3 | 0x80 | (c + (0x75 - 0x89));
- }
- return ret;
-}
-#endif /* X0212_ENABLE */
-
-static int
-is_x0213_2_in_x0212(nkf_char c1)
-{
- static const char x0213_2_table[] =
- {0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1};
- int ku = c1 - 0x20;
- if (ku <= 15)
- return x0213_2_table[ku]; /* 1, 3-5, 8, 12-15 */
- if (78 <= ku && ku <= 94)
- return 1;
- return 0;
-}
-
-static nkf_char
-e2s_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
-{
- nkf_char ndx;
- if (is_eucg3(c2)){
- ndx = c2 & 0x7f;
- if (x0213_f && is_x0213_2_in_x0212(ndx)){
- if((0x21 <= ndx && ndx <= 0x2F)){
- if (p2) *p2 = ((ndx - 1) >> 1) + 0xec - ndx / 8 * 3;
- if (p1) *p1 = c1 + ((ndx & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e);
- return 0;
- }else if(0x6E <= ndx && ndx <= 0x7E){
- if (p2) *p2 = ((ndx - 1) >> 1) + 0xbe;
- if (p1) *p1 = c1 + ((ndx & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e);
- return 0;
- }
- return 1;
- }
-#ifdef X0212_ENABLE
- else if(nkf_isgraph(ndx)){
- nkf_char val = 0;
- const unsigned short *ptr;
- ptr = x0212_shiftjis[ndx - 0x21];
- if (ptr){
- val = ptr[(c1 & 0x7f) - 0x21];
- }
- if (val){
- c2 = val >> 8;
- c1 = val & 0xff;
- if (p2) *p2 = c2;
- if (p1) *p1 = c1;
- return 0;
- }
- c2 = x0212_shift(c2);
- }
-#endif /* X0212_ENABLE */
- }
- if(0x7F < c2) return 1;
- if (p2) *p2 = ((c2 - 1) >> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1);
- if (p1) *p1 = c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e);
- return 0;
-}
-
-static nkf_char
-s2e_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
-{
-#if defined(SHIFTJIS_CP932) || defined(X0212_ENABLE)
- nkf_char val;
-#endif
- static const char shift_jisx0213_s1a3_table[5][2] ={ { 1, 8}, { 3, 4}, { 5,12}, {13,14}, {15, 0} };
- if (0xFC < c1) return 1;
-#ifdef SHIFTJIS_CP932
- if (!cp932inv_f && !x0213_f && is_ibmext_in_sjis(c2)){
- val = shiftjis_cp932[c2 - CP932_TABLE_BEGIN][c1 - 0x40];
- if (val){
- c2 = val >> 8;
- c1 = val & 0xff;
- }
- }
- if (cp932inv_f
- && CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){
- val = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40];
- if (val){
- c2 = val >> 8;
- c1 = val & 0xff;
- }
- }
-#endif /* SHIFTJIS_CP932 */
-#ifdef X0212_ENABLE
- if (!x0213_f && is_ibmext_in_sjis(c2)){
- val = shiftjis_x0212[c2 - 0xfa][c1 - 0x40];
- if (val){
- if (val > 0x7FFF){
- c2 = PREFIX_EUCG3 | ((val >> 8) & 0x7f);
- c1 = val & 0xff;
- }else{
- c2 = val >> 8;
- c1 = val & 0xff;
- }
- if (p2) *p2 = c2;
- if (p1) *p1 = c1;
- return 0;
- }
- }
-#endif
- if(c2 >= 0x80){
- if(x0213_f && c2 >= 0xF0){
- if(c2 <= 0xF3 || (c2 == 0xF4 && c1 < 0x9F)){ /* k=1, 3<=k<=5, k=8, 12<=k<=15 */
- c2 = PREFIX_EUCG3 | 0x20 | shift_jisx0213_s1a3_table[c2 - 0xF0][0x9E < c1];
- }else{ /* 78<=k<=94 */
- c2 = PREFIX_EUCG3 | (c2 * 2 - 0x17B);
- if (0x9E < c1) c2++;
- }
- }else{
-#define SJ0162 0x00e1 /* 01 - 62 ku offset */
-#define SJ6394 0x0161 /* 63 - 94 ku offset */
- c2 = c2 + c2 - ((c2 <= 0x9F) ? SJ0162 : SJ6394);
- if (0x9E < c1) c2++;
- }
- if (c1 < 0x9F)
- c1 = c1 - ((c1 > DEL) ? SP : 0x1F);
- else {
- c1 = c1 - 0x7E;
- }
- }
-
-#ifdef X0212_ENABLE
- c2 = x0212_unshift(c2);
-#endif
- if (p2) *p2 = c2;
- if (p1) *p1 = c1;
- return 0;
-}
-
-#if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
-static void
-nkf_unicode_to_utf8(nkf_char val, nkf_char *p1, nkf_char *p2, nkf_char *p3, nkf_char *p4)
-{
- val &= VALUE_MASK;
- if (val < 0x80){
- *p1 = val;
- *p2 = 0;
- *p3 = 0;
- *p4 = 0;
- }else if (val < 0x800){
- *p1 = 0xc0 | (val >> 6);
- *p2 = 0x80 | (val & 0x3f);
- *p3 = 0;
- *p4 = 0;
- } else if (nkf_char_unicode_bmp_p(val)) {
- *p1 = 0xe0 | (val >> 12);
- *p2 = 0x80 | ((val >> 6) & 0x3f);
- *p3 = 0x80 | ( val & 0x3f);
- *p4 = 0;
- } else if (nkf_char_unicode_value_p(val)) {
- *p1 = 0xf0 | (val >> 18);
- *p2 = 0x80 | ((val >> 12) & 0x3f);
- *p3 = 0x80 | ((val >> 6) & 0x3f);
- *p4 = 0x80 | ( val & 0x3f);
- } else {
- *p1 = 0;
- *p2 = 0;
- *p3 = 0;
- *p4 = 0;
- }
-}
-
-static nkf_char
-nkf_utf8_to_unicode(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4)
-{
- nkf_char wc;
- if (c1 <= 0x7F) {
- /* single byte */
- wc = c1;
- }
- else if (c1 <= 0xC1) {
- /* trail byte or invalid */
- return -1;
- }
- else if (c1 <= 0xDF) {
- /* 2 bytes */
- wc = (c1 & 0x1F) << 6;
- wc |= (c2 & 0x3F);
- }
- else if (c1 <= 0xEF) {
- /* 3 bytes */
- wc = (c1 & 0x0F) << 12;
- wc |= (c2 & 0x3F) << 6;
- wc |= (c3 & 0x3F);
- }
- else if (c2 <= 0xF4) {
- /* 4 bytes */
- wc = (c1 & 0x0F) << 18;
- wc |= (c2 & 0x3F) << 12;
- wc |= (c3 & 0x3F) << 6;
- wc |= (c4 & 0x3F);
- }
- else {
- return -1;
- }
- return wc;
-}
-#endif
-
-#ifdef UTF8_INPUT_ENABLE
-static int
-unicode_to_jis_common2(nkf_char c1, nkf_char c0,
- const unsigned short *const *pp, nkf_char psize,
- nkf_char *p2, nkf_char *p1)
-{
- nkf_char c2;
- const unsigned short *p;
- unsigned short val;
-
- if (pp == 0) return 1;
-
- c1 -= 0x80;
- if (c1 < 0 || psize <= c1) return 1;
- p = pp[c1];
- if (p == 0) return 1;
-
- c0 -= 0x80;
- if (c0 < 0 || sizeof_utf8_to_euc_C2 <= c0) return 1;
- val = p[c0];
- if (val == 0) return 1;
- if (no_cp932ext_f && (
- (val>>8) == 0x2D || /* NEC special characters */
- val > NKF_INT32_C(0xF300) /* IBM extended characters */
- )) return 1;
-
- c2 = val >> 8;
- if (val > 0x7FFF){
- c2 &= 0x7f;
- c2 |= PREFIX_EUCG3;
- }
- if (c2 == SO) c2 = JIS_X_0201_1976_K;
- c1 = val & 0xFF;
- if (p2) *p2 = c2;
- if (p1) *p1 = c1;
- return 0;
-}
-
-static int
-unicode_to_jis_common(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *p2, nkf_char *p1)
-{
- const unsigned short *const *pp;
- const unsigned short *const *const *ppp;
- static const char no_best_fit_chars_table_C2[] =
- {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 2, 1, 1, 2,
- 0, 0, 1, 1, 0, 1, 0, 1, 2, 1, 1, 1, 1, 1, 1, 1};
- static const char no_best_fit_chars_table_C2_ms[] =
- {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0,
- 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0};
- static const char no_best_fit_chars_table_932_C2[] =
- {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1,
- 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0};
- static const char no_best_fit_chars_table_932_C3[] =
- {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1};
- nkf_char ret = 0;
-
- if(c2 < 0x80){
- *p2 = 0;
- *p1 = c2;
- }else if(c2 < 0xe0){
- if(no_best_fit_chars_f){
- if(ms_ucs_map_f == UCS_MAP_CP932){
- switch(c2){
- case 0xC2:
- if(no_best_fit_chars_table_932_C2[c1&0x3F]) return 1;
- break;
- case 0xC3:
- if(no_best_fit_chars_table_932_C3[c1&0x3F]) return 1;
- break;
- }
- }else if(!cp932inv_f){
- switch(c2){
- case 0xC2:
- if(no_best_fit_chars_table_C2[c1&0x3F]) return 1;
- break;
- case 0xC3:
- if(no_best_fit_chars_table_932_C3[c1&0x3F]) return 1;
- break;
- }
- }else if(ms_ucs_map_f == UCS_MAP_MS){
- if(c2 == 0xC2 && no_best_fit_chars_table_C2_ms[c1&0x3F]) return 1;
- }else if(ms_ucs_map_f == UCS_MAP_CP10001){
- switch(c2){
- case 0xC2:
- switch(c1){
- case 0xA2:
- case 0xA3:
- case 0xA5:
- case 0xA6:
- case 0xAC:
- case 0xAF:
- case 0xB8:
- return 1;
- }
- break;
- }
- }
- }
- pp =
- ms_ucs_map_f == UCS_MAP_CP932 ? utf8_to_euc_2bytes_932 :
- ms_ucs_map_f == UCS_MAP_MS ? utf8_to_euc_2bytes_ms :
- ms_ucs_map_f == UCS_MAP_CP10001 ? utf8_to_euc_2bytes_mac :
- x0213_f ? utf8_to_euc_2bytes_x0213 :
- utf8_to_euc_2bytes;
- ret = unicode_to_jis_common2(c2, c1, pp, sizeof_utf8_to_euc_2bytes, p2, p1);
- }else if(c0 < 0xF0){
- if(no_best_fit_chars_f){
- if(ms_ucs_map_f == UCS_MAP_CP932){
- if(c2 == 0xE3 && c1 == 0x82 && c0 == 0x94) return 1;
- }else if(ms_ucs_map_f == UCS_MAP_MS){
- switch(c2){
- case 0xE2:
- switch(c1){
- case 0x80:
- if(c0 == 0x94 || c0 == 0x96 || c0 == 0xBE) return 1;
- break;
- case 0x88:
- if(c0 == 0x92) return 1;
- break;
- }
- break;
- case 0xE3:
- if(c1 == 0x80 || c0 == 0x9C) return 1;
- break;
- }
- }else if(ms_ucs_map_f == UCS_MAP_CP10001){
- switch(c2){
- case 0xE3:
- switch(c1){
- case 0x82:
- if(c0 == 0x94) return 1;
- break;
- case 0x83:
- if(c0 == 0xBB) return 1;
- break;
- }
- break;
- }
- }else{
- switch(c2){
- case 0xE2:
- switch(c1){
- case 0x80:
- if(c0 == 0x95) return 1;
- break;
- case 0x88:
- if(c0 == 0xA5) return 1;
- break;
- }
- break;
- case 0xEF:
- switch(c1){
- case 0xBC:
- if(c0 == 0x8D) return 1;
- break;
- case 0xBD:
- if(c0 == 0x9E && !cp932inv_f) return 1;
- break;
- case 0xBF:
- if(0xA0 <= c0 && c0 <= 0xA5) return 1;
- break;
- }
- break;
- }
- }
- }
- ppp =
- ms_ucs_map_f == UCS_MAP_CP932 ? utf8_to_euc_3bytes_932 :
- ms_ucs_map_f == UCS_MAP_MS ? utf8_to_euc_3bytes_ms :
- ms_ucs_map_f == UCS_MAP_CP10001 ? utf8_to_euc_3bytes_mac :
- x0213_f ? utf8_to_euc_3bytes_x0213 :
- utf8_to_euc_3bytes;
- ret = unicode_to_jis_common2(c1, c0, ppp[c2 - 0xE0], sizeof_utf8_to_euc_C2, p2, p1);
- }else return -1;
-#ifdef SHIFTJIS_CP932
- if (!ret&& is_eucg3(*p2)) {
- if (cp932inv_f) {
- if (encode_fallback) ret = 1;
- }
- else {
- nkf_char s2, s1;
- if (e2s_conv(*p2, *p1, &s2, &s1) == 0) {
- s2e_conv(s2, s1, p2, p1);
- }else{
- ret = 1;
- }
- }
- }
-#endif
- return ret;
-}
-
-#ifdef UTF8_OUTPUT_ENABLE
-#define X0213_SURROGATE_FIND(tbl, size, euc) do { \
- int i; \
- for (i = 0; i < size; i++) \
- if (tbl[i][0] == euc) { \
- low = tbl[i][2]; \
- break; \
- } \
- } while (0)
-
-static nkf_char
-e2w_conv(nkf_char c2, nkf_char c1)
-{
- const unsigned short *p;
-
- if (c2 == JIS_X_0201_1976_K) {
- if (ms_ucs_map_f == UCS_MAP_CP10001) {
- switch (c1) {
- case 0x20:
- return 0xA0;
- case 0x7D:
- return 0xA9;
- }
- }
- p = euc_to_utf8_1byte;
-#ifdef X0212_ENABLE
- } else if (is_eucg3(c2)){
- if(ms_ucs_map_f == UCS_MAP_ASCII&& c2 == NKF_INT32_C(0x8F22) && c1 == 0x43){
- return 0xA6;
- }
- c2 = (c2&0x7f) - 0x21;
- if (0<=c2 && c2<sizeof_euc_to_utf8_2bytes)
- p =
- x0213_f ? x0212_to_utf8_2bytes_x0213[c2] :
- x0212_to_utf8_2bytes[c2];
- else
- return 0;
-#endif
- } else {
- c2 &= 0x7f;
- c2 = (c2&0x7f) - 0x21;
- if (0<=c2 && c2<sizeof_euc_to_utf8_2bytes)
- p =
- x0213_f ? euc_to_utf8_2bytes_x0213[c2] :
- ms_ucs_map_f == UCS_MAP_ASCII ? euc_to_utf8_2bytes[c2] :
- ms_ucs_map_f == UCS_MAP_CP10001 ? euc_to_utf8_2bytes_mac[c2] :
- euc_to_utf8_2bytes_ms[c2];
- else
- return 0;
- }
- if (!p) return 0;
- c1 = (c1 & 0x7f) - 0x21;
- if (0<=c1 && c1<sizeof_euc_to_utf8_1byte) {
- nkf_char val = p[c1];
- if (x0213_f && 0xD800<=val && val<=0xDBFF) {
- nkf_char euc = (c2+0x21)<<8 | (c1+0x21);
- nkf_char low = 0;
- if (p==x0212_to_utf8_2bytes_x0213[c2]) {
- X0213_SURROGATE_FIND(x0213_2_surrogate_table, sizeof_x0213_2_surrogate_table, euc);
- } else {
- X0213_SURROGATE_FIND(x0213_1_surrogate_table, sizeof_x0213_1_surrogate_table, euc);
- }
- if (!low) return 0;
- return UTF16_TO_UTF32(val, low);
- } else {
- return val;
- }
- }
- return 0;
-}
-
-static nkf_char
-e2w_combining(nkf_char comb, nkf_char c2, nkf_char c1)
-{
- nkf_char euc;
- int i;
- for (i = 0; i < sizeof_x0213_combining_chars; i++)
- if (x0213_combining_chars[i] == comb)
- break;
- if (i >= sizeof_x0213_combining_chars)
- return 0;
- euc = (c2&0x7f)<<8 | (c1&0x7f);
- for (i = 0; i < sizeof_x0213_combining_table; i++)
- if (x0213_combining_table[i][0] == euc)
- return x0213_combining_table[i][1];
- return 0;
-}
-#endif
-
-static nkf_char
-w2e_conv(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *p2, nkf_char *p1)
-{
- nkf_char ret = 0;
-
- if (!c1){
- *p2 = 0;
- *p1 = c2;
- }else if (0xc0 <= c2 && c2 <= 0xef) {
- ret = unicode_to_jis_common(c2, c1, c0, p2, p1);
-#ifdef NUMCHAR_OPTION
- if (ret > 0){
- if (p2) *p2 = 0;
- if (p1) *p1 = nkf_char_unicode_new(nkf_utf8_to_unicode(c2, c1, c0, 0));
- ret = 0;
- }
-#endif
- }
- return ret;
-}
-
-#ifdef UTF8_INPUT_ENABLE
-static nkf_char
-w16e_conv(nkf_char val, nkf_char *p2, nkf_char *p1)
-{
- nkf_char c1, c2, c3, c4;
- nkf_char ret = 0;
- val &= VALUE_MASK;
- if (val < 0x80) {
- *p2 = 0;
- *p1 = val;
- }
- else if (nkf_char_unicode_bmp_p(val)){
- nkf_unicode_to_utf8(val, &c1, &c2, &c3, &c4);
- ret = unicode_to_jis_common(c1, c2, c3, p2, p1);
- if (ret > 0){
- *p2 = 0;
- *p1 = nkf_char_unicode_new(val);
- ret = 0;
- }
- }
- else {
- int i;
- if (x0213_f) {
- c1 = (val >> 10) + NKF_INT32_C(0xD7C0); /* high surrogate */
- c2 = (val & 0x3FF) + NKF_INT32_C(0xDC00); /* low surrogate */
- for (i = 0; i < sizeof_x0213_1_surrogate_table; i++)
- if (x0213_1_surrogate_table[i][1] == c1 && x0213_1_surrogate_table[i][2] == c2) {
- val = x0213_1_surrogate_table[i][0];
- *p2 = val >> 8;
- *p1 = val & 0xFF;
- return 0;
- }
- for (i = 0; i < sizeof_x0213_2_surrogate_table; i++)
- if (x0213_2_surrogate_table[i][1] == c1 && x0213_2_surrogate_table[i][2] == c2) {
- val = x0213_2_surrogate_table[i][0];
- *p2 = PREFIX_EUCG3 | (val >> 8);
- *p1 = val & 0xFF;
- return 0;
- }
- }
- *p2 = 0;
- *p1 = nkf_char_unicode_new(val);
- }
- return ret;
-}
-#endif
-
-static nkf_char
-e_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
-{
- if (c2 == JIS_X_0201_1976_K || c2 == SS2){
- if (iso2022jp_f && !x0201_f) {
- c2 = GETA1; c1 = GETA2;
- } else {
- c2 = JIS_X_0201_1976_K;
- c1 &= 0x7f;
- }
-#ifdef X0212_ENABLE
- }else if (c2 == 0x8f){
- if (c0 == 0){
- return -1;
- }
- if (!cp51932_f && !x0213_f && 0xF5 <= c1 && c1 <= 0xFE && 0xA1 <= c0 && c0 <= 0xFE) {
- /* encoding is eucJP-ms, so invert to Unicode Private User Area */
- c1 = nkf_char_unicode_new((c1 - 0xF5) * 94 + c0 - 0xA1 + 0xE3AC);
- c2 = 0;
- } else {
- c2 = (c2 << 8) | (c1 & 0x7f);
- c1 = c0 & 0x7f;
-#ifdef SHIFTJIS_CP932
- if (cp51932_f){
- nkf_char s2, s1;
- if (e2s_conv(c2, c1, &s2, &s1) == 0){
- s2e_conv(s2, s1, &c2, &c1);
- if (c2 < 0x100){
- c1 &= 0x7f;
- c2 &= 0x7f;
- }
- }
- }
-#endif /* SHIFTJIS_CP932 */
- }
-#endif /* X0212_ENABLE */
- } else if ((c2 == EOF) || (c2 == 0) || c2 < SP || c2 == ISO_8859_1) {
- /* NOP */
- } else {
- if (!cp51932_f && ms_ucs_map_f && 0xF5 <= c2 && c2 <= 0xFE && 0xA1 <= c1 && c1 <= 0xFE) {
- /* encoding is eucJP-ms, so invert to Unicode Private User Area */
- c1 = nkf_char_unicode_new((c2 - 0xF5) * 94 + c1 - 0xA1 + 0xE000);
- c2 = 0;
- } else {
- c1 &= 0x7f;
- c2 &= 0x7f;
-#ifdef SHIFTJIS_CP932
- if (cp51932_f && 0x79 <= c2 && c2 <= 0x7c){
- nkf_char s2, s1;
- if (e2s_conv(c2, c1, &s2, &s1) == 0){
- s2e_conv(s2, s1, &c2, &c1);
- if (c2 < 0x100){
- c1 &= 0x7f;
- c2 &= 0x7f;
- }
- }
- }
-#endif /* SHIFTJIS_CP932 */
- }
- }
- (*oconv)(c2, c1);
- return 0;
-}
-
-static nkf_char
-s_iconv(ARG_UNUSED nkf_char c2, nkf_char c1, ARG_UNUSED nkf_char c0)
-{
- if (c2 == JIS_X_0201_1976_K || (0xA1 <= c2 && c2 <= 0xDF)) {
- if (iso2022jp_f && !x0201_f) {
- c2 = GETA1; c1 = GETA2;
- } else {
- c1 &= 0x7f;
- }
- } else if ((c2 == EOF) || (c2 == 0) || c2 < SP) {
- /* NOP */
- } else if (!x0213_f && 0xF0 <= c2 && c2 <= 0xF9 && 0x40 <= c1 && c1 <= 0xFC) {
- /* CP932 UDC */
- if(c1 == 0x7F) return 0;
- c1 = nkf_char_unicode_new((c2 - 0xF0) * 188 + (c1 - 0x40 - (0x7E < c1)) + 0xE000);
- c2 = 0;
- } else {
- nkf_char ret = s2e_conv(c2, c1, &c2, &c1);
- if (ret) return ret;
- }
- (*oconv)(c2, c1);
- return 0;
-}
-
-static int
-x0213_wait_combining_p(nkf_char wc)
-{
- int i;
- for (i = 0; i < sizeof_x0213_combining_table; i++) {
- if (x0213_combining_table[i][1] == wc) {
- return TRUE;
- }
- }
- return FALSE;
-}
-
-static int
-x0213_combining_p(nkf_char wc)
-{
- int i;
- for (i = 0; i < sizeof_x0213_combining_chars; i++) {
- if (x0213_combining_chars[i] == wc) {
- return TRUE;
- }
- }
- return FALSE;
-}
-
-static nkf_char
-w_iconv(nkf_char c1, nkf_char c2, nkf_char c3)
-{
- nkf_char ret = 0, c4 = 0;
- static const char w_iconv_utf8_1st_byte[] =
- { /* 0xC0 - 0xFF */
- 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 33, 33,
- 40, 41, 41, 41, 42, 43, 43, 43, 50, 50, 50, 50, 60, 60, 70, 70};
-
- if (c3 > 0xFF) {
- c4 = c3 & 0xFF;
- c3 >>= 8;
- }
-
- if (c1 < 0 || 0xff < c1) {
- }else if (c1 == 0) { /* 0 : 1 byte*/
- c3 = 0;
- } else if ((c1 & 0xC0) == 0x80) { /* 0x80-0xbf : trail byte */
- return 0;
- } else{
- switch (w_iconv_utf8_1st_byte[c1 - 0xC0]) {
- case 21:
- if (c2 < 0x80 || 0xBF < c2) return 0;
- break;
- case 30:
- if (c3 == 0) return -1;
- if (c2 < 0xA0 || 0xBF < c2 || (c3 & 0xC0) != 0x80)
- return 0;
- break;
- case 31:
- case 33:
- if (c3 == 0) return -1;
- if ((c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80)
- return 0;
- break;
- case 32:
- if (c3 == 0) return -1;
- if (c2 < 0x80 || 0x9F < c2 || (c3 & 0xC0) != 0x80)
- return 0;
- break;
- case 40:
- if (c3 == 0) return -2;
- if (c2 < 0x90 || 0xBF < c2 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
- return 0;
- break;
- case 41:
- if (c3 == 0) return -2;
- if (c2 < 0x80 || 0xBF < c2 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
- return 0;
- break;
- case 42:
- if (c3 == 0) return -2;
- if (c2 < 0x80 || 0x8F < c2 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
- return 0;
- break;
- default:
- return 0;
- break;
- }
- }
- if (c1 == 0 || c1 == EOF){
- } else if ((c1 & 0xf8) == 0xf0) { /* 4 bytes */
- c2 = nkf_char_unicode_new(nkf_utf8_to_unicode(c1, c2, c3, c4));
- c1 = 0;
- } else {
- if (x0213_f && x0213_wait_combining_p(nkf_utf8_to_unicode(c1, c2, c3, c4)))
- return -3;
- ret = w2e_conv(c1, c2, c3, &c1, &c2);
- }
- if (ret == 0){
- (*oconv)(c1, c2);
- }
- return ret;
-}
-
-static nkf_char
-w_iconv_nocombine(nkf_char c1, nkf_char c2, nkf_char c3)
-{
- /* continue from the line below 'return -3;' in w_iconv() */
- nkf_char ret = w2e_conv(c1, c2, c3, &c1, &c2);
- if (ret == 0){
- (*oconv)(c1, c2);
- }
- return ret;
-}
-
-#define NKF_ICONV_INVALID_CODE_RANGE -13
-#define NKF_ICONV_WAIT_COMBINING_CHAR -14
-#define NKF_ICONV_NOT_COMBINED -15
-static size_t
-unicode_iconv(nkf_char wc, int nocombine)
-{
- nkf_char c1, c2;
- int ret = 0;
-
- if (wc < 0x80) {
- c2 = 0;
- c1 = wc;
- }else if ((wc>>11) == 27) {
- /* unpaired surrogate */
- return NKF_ICONV_INVALID_CODE_RANGE;
- }else if (wc < 0xFFFF) {
- if (!nocombine && x0213_f && x0213_wait_combining_p(wc))
- return NKF_ICONV_WAIT_COMBINING_CHAR;
- ret = w16e_conv(wc, &c2, &c1);
- if (ret) return ret;
- }else if (wc < 0x10FFFF) {
- c2 = 0;
- c1 = nkf_char_unicode_new(wc);
- } else {
- return NKF_ICONV_INVALID_CODE_RANGE;
- }
- (*oconv)(c2, c1);
- return 0;
-}
-
-static nkf_char
-unicode_iconv_combine(nkf_char wc, nkf_char wc2)
-{
- nkf_char c1, c2;
- int i;
-
- if (wc2 < 0x80) {
- return NKF_ICONV_NOT_COMBINED;
- }else if ((wc2>>11) == 27) {
- /* unpaired surrogate */
- return NKF_ICONV_INVALID_CODE_RANGE;
- }else if (wc2 < 0xFFFF) {
- if (!x0213_combining_p(wc2))
- return NKF_ICONV_NOT_COMBINED;
- for (i = 0; i < sizeof_x0213_combining_table; i++) {
- if (x0213_combining_table[i][1] == wc &&
- x0213_combining_table[i][2] == wc2) {
- c2 = x0213_combining_table[i][0] >> 8;
- c1 = x0213_combining_table[i][0] & 0x7f;
- (*oconv)(c2, c1);
- return 0;
- }
- }
- }else if (wc2 < 0x10FFFF) {
- return NKF_ICONV_NOT_COMBINED;
- } else {
- return NKF_ICONV_INVALID_CODE_RANGE;
- }
- return NKF_ICONV_NOT_COMBINED;
-}
-
-static nkf_char
-w_iconv_combine(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4, nkf_char c5, nkf_char c6)
-{
- nkf_char wc, wc2;
- wc = nkf_utf8_to_unicode(c1, c2, c3, 0);
- wc2 = nkf_utf8_to_unicode(c4, c5, c6, 0);
- if (wc2 < 0)
- return wc2;
- return unicode_iconv_combine(wc, wc2);
-}
-
-#define NKF_ICONV_NEED_ONE_MORE_BYTE (size_t)-1
-#define NKF_ICONV_NEED_TWO_MORE_BYTES (size_t)-2
-static size_t
-nkf_iconv_utf_16(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4)
-{
- nkf_char wc;
-
- if (c1 == EOF) {
- (*oconv)(EOF, 0);
- return 0;
- }
-
- if (input_endian == ENDIAN_BIG) {
- if (0xD8 <= c1 && c1 <= 0xDB) {
- if (0xDC <= c3 && c3 <= 0xDF) {
- wc = UTF16_TO_UTF32(c1 << 8 | c2, c3 << 8 | c4);
- } else return NKF_ICONV_NEED_TWO_MORE_BYTES;
- } else {
- wc = c1 << 8 | c2;
- }
- } else {
- if (0xD8 <= c2 && c2 <= 0xDB) {
- if (0xDC <= c4 && c4 <= 0xDF) {
- wc = UTF16_TO_UTF32(c2 << 8 | c1, c4 << 8 | c3);
- } else return NKF_ICONV_NEED_TWO_MORE_BYTES;
- } else {
- wc = c2 << 8 | c1;
- }
- }
-
- return (*unicode_iconv)(wc, FALSE);
-}
-
-static size_t
-nkf_iconv_utf_16_combine(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4)
-{
- nkf_char wc, wc2;
-
- if (input_endian == ENDIAN_BIG) {
- if (0xD8 <= c3 && c3 <= 0xDB) {
- return NKF_ICONV_NOT_COMBINED;
- } else {
- wc = c1 << 8 | c2;
- wc2 = c3 << 8 | c4;
- }
- } else {
- if (0xD8 <= c2 && c2 <= 0xDB) {
- return NKF_ICONV_NOT_COMBINED;
- } else {
- wc = c2 << 8 | c1;
- wc2 = c4 << 8 | c3;
- }
- }
-
- return unicode_iconv_combine(wc, wc2);
-}
-
-static size_t
-nkf_iconv_utf_16_nocombine(nkf_char c1, nkf_char c2)
-{
- nkf_char wc;
- if (input_endian == ENDIAN_BIG)
- wc = c1 << 8 | c2;
- else
- wc = c2 << 8 | c1;
- return (*unicode_iconv)(wc, TRUE);
-}
-
-static nkf_char
-w_iconv16(nkf_char c2, nkf_char c1, ARG_UNUSED nkf_char c0)
-{
- (*oconv)(c2, c1);
- return 16; /* different from w_iconv32 */
-}
-
-static nkf_char
-w_iconv32(nkf_char c2, nkf_char c1, ARG_UNUSED nkf_char c0)
-{
- (*oconv)(c2, c1);
- return 32; /* different from w_iconv16 */
-}
-
-static nkf_char
-utf32_to_nkf_char(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4)
-{
- nkf_char wc;
-
- switch(input_endian){
- case ENDIAN_BIG:
- wc = c2 << 16 | c3 << 8 | c4;
- break;
- case ENDIAN_LITTLE:
- wc = c3 << 16 | c2 << 8 | c1;
- break;
- case ENDIAN_2143:
- wc = c1 << 16 | c4 << 8 | c3;
- break;
- case ENDIAN_3412:
- wc = c4 << 16 | c1 << 8 | c2;
- break;
- default:
- return NKF_ICONV_INVALID_CODE_RANGE;
- }
- return wc;
-}
-
-static size_t
-nkf_iconv_utf_32(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4)
-{
- nkf_char wc;
-
- if (c1 == EOF) {
- (*oconv)(EOF, 0);
- return 0;
- }
-
- wc = utf32_to_nkf_char(c1, c2, c3, c4);
- if (wc < 0)
- return wc;
-
- return (*unicode_iconv)(wc, FALSE);
-}
-
-static nkf_char
-nkf_iconv_utf_32_combine(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4, nkf_char c5, nkf_char c6, nkf_char c7, nkf_char c8)
-{
- nkf_char wc, wc2;
-
- wc = utf32_to_nkf_char(c1, c2, c3, c4);
- if (wc < 0)
- return wc;
- wc2 = utf32_to_nkf_char(c5, c6, c7, c8);
- if (wc2 < 0)
- return wc2;
-
- return unicode_iconv_combine(wc, wc2);
-}
-
-static size_t
-nkf_iconv_utf_32_nocombine(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4)
-{
- nkf_char wc;
-
- wc = utf32_to_nkf_char(c1, c2, c3, c4);
- return (*unicode_iconv)(wc, TRUE);
-}
-#endif
-
-#define output_ascii_escape_sequence(mode) do { \
- if (output_mode != ASCII && output_mode != ISO_8859_1) { \
- (*o_putc)(ESC); \
- (*o_putc)('('); \
- (*o_putc)(ascii_intro); \
- output_mode = mode; \
- } \
- } while (0)
-
-static void
-output_escape_sequence(int mode)
-{
- if (output_mode == mode)
- return;
- switch(mode) {
- case ISO_8859_1:
- (*o_putc)(ESC);
- (*o_putc)('.');
- (*o_putc)('A');
- break;
- case JIS_X_0201_1976_K:
- (*o_putc)(ESC);
- (*o_putc)('(');
- (*o_putc)('I');
- break;
- case JIS_X_0208:
- (*o_putc)(ESC);
- (*o_putc)('$');
- (*o_putc)(kanji_intro);
- break;
- case JIS_X_0212:
- (*o_putc)(ESC);
- (*o_putc)('$');
- (*o_putc)('(');
- (*o_putc)('D');
- break;
- case JIS_X_0213_1:
- (*o_putc)(ESC);
- (*o_putc)('$');
- (*o_putc)('(');
- (*o_putc)('Q');
- break;
- case JIS_X_0213_2:
- (*o_putc)(ESC);
- (*o_putc)('$');
- (*o_putc)('(');
- (*o_putc)('P');
- break;
- }
- output_mode = mode;
-}
-
-static void
-j_oconv(nkf_char c2, nkf_char c1)
-{
-#ifdef NUMCHAR_OPTION
- if (c2 == 0 && nkf_char_unicode_p(c1)){
- w16e_conv(c1, &c2, &c1);
- if (c2 == 0 && nkf_char_unicode_p(c1)){
- c2 = c1 & VALUE_MASK;
- if (ms_ucs_map_f && 0xE000 <= c2 && c2 <= 0xE757) {
- /* CP5022x UDC */
- c1 &= 0xFFF;
- c2 = 0x7F + c1 / 94;
- c1 = 0x21 + c1 % 94;
- } else {
- if (encode_fallback) (*encode_fallback)(c1);
- return;
- }
- }
- }
-#endif
- if (c2 == 0) {
- output_ascii_escape_sequence(ASCII);
- (*o_putc)(c1);
- }
- else if (c2 == EOF) {
- output_ascii_escape_sequence(ASCII);
- (*o_putc)(EOF);
- }
- else if (c2 == ISO_8859_1) {
- output_ascii_escape_sequence(ISO_8859_1);
- (*o_putc)(c1|0x80);
- }
- else if (c2 == JIS_X_0201_1976_K) {
- output_escape_sequence(JIS_X_0201_1976_K);
- (*o_putc)(c1);
-#ifdef X0212_ENABLE
- } else if (is_eucg3(c2)){
- output_escape_sequence(x0213_f ? JIS_X_0213_2 : JIS_X_0212);
- (*o_putc)(c2 & 0x7f);
- (*o_putc)(c1);
-#endif
- } else {
- if(ms_ucs_map_f
- ? c2<0x20 || 0x92<c2 || c1<0x20 || 0x7e<c1
- : c2<0x20 || 0x7e<c2 || c1<0x20 || 0x7e<c1) return;
- output_escape_sequence(x0213_f ? JIS_X_0213_1 : JIS_X_0208);
- (*o_putc)(c2);
- (*o_putc)(c1);
- }
-}
-
-static void
-e_oconv(nkf_char c2, nkf_char c1)
-{
- if (c2 == 0 && nkf_char_unicode_p(c1)){
- w16e_conv(c1, &c2, &c1);
- if (c2 == 0 && nkf_char_unicode_p(c1)){
- c2 = c1 & VALUE_MASK;
- if (x0212_f && 0xE000 <= c2 && c2 <= 0xE757) {
- /* eucJP-ms UDC */
- c1 &= 0xFFF;
- c2 = c1 / 94;
- c2 += c2 < 10 ? 0x75 : 0x8FEB;
- c1 = 0x21 + c1 % 94;
- if (is_eucg3(c2)){
- (*o_putc)(0x8f);
- (*o_putc)((c2 & 0x7f) | 0x080);
- (*o_putc)(c1 | 0x080);
- }else{
- (*o_putc)((c2 & 0x7f) | 0x080);
- (*o_putc)(c1 | 0x080);
- }
- return;
- } else {
- if (encode_fallback) (*encode_fallback)(c1);
- return;
- }
- }
- }
-
- if (c2 == EOF) {
- (*o_putc)(EOF);
- } else if (c2 == 0) {
- output_mode = ASCII;
- (*o_putc)(c1);
- } else if (c2 == JIS_X_0201_1976_K) {
- output_mode = EUC_JP;
- (*o_putc)(SS2); (*o_putc)(c1|0x80);
- } else if (c2 == ISO_8859_1) {
- output_mode = ISO_8859_1;
- (*o_putc)(c1 | 0x080);
-#ifdef X0212_ENABLE
- } else if (is_eucg3(c2)){
- output_mode = EUC_JP;
-#ifdef SHIFTJIS_CP932
- if (!cp932inv_f){
- nkf_char s2, s1;
- if (e2s_conv(c2, c1, &s2, &s1) == 0){
- s2e_conv(s2, s1, &c2, &c1);
- }
- }
-#endif
- if (c2 == 0) {
- output_mode = ASCII;
- (*o_putc)(c1);
- }else if (is_eucg3(c2)){
- if (x0212_f){
- (*o_putc)(0x8f);
- (*o_putc)((c2 & 0x7f) | 0x080);
- (*o_putc)(c1 | 0x080);
- }
- }else{
- (*o_putc)((c2 & 0x7f) | 0x080);
- (*o_putc)(c1 | 0x080);
- }
-#endif
- } else {
- if (!nkf_isgraph(c1) || !nkf_isgraph(c2)) {
- set_iconv(FALSE, 0);
- return; /* too late to rescue this char */
- }
- output_mode = EUC_JP;
- (*o_putc)(c2 | 0x080);
- (*o_putc)(c1 | 0x080);
- }
-}
-
-static void
-s_oconv(nkf_char c2, nkf_char c1)
-{
-#ifdef NUMCHAR_OPTION
- if (c2 == 0 && nkf_char_unicode_p(c1)){
- w16e_conv(c1, &c2, &c1);
- if (c2 == 0 && nkf_char_unicode_p(c1)){
- c2 = c1 & VALUE_MASK;
- if (!x0213_f && 0xE000 <= c2 && c2 <= 0xE757) {
- /* CP932 UDC */
- c1 &= 0xFFF;
- c2 = c1 / 188 + (cp932inv_f ? 0xF0 : 0xEB);
- c1 = c1 % 188;
- c1 += 0x40 + (c1 > 0x3e);
- (*o_putc)(c2);
- (*o_putc)(c1);
- return;
- } else {
- if(encode_fallback)(*encode_fallback)(c1);
- return;
- }
- }
- }
-#endif
- if (c2 == EOF) {
- (*o_putc)(EOF);
- return;
- } else if (c2 == 0) {
- output_mode = ASCII;
- (*o_putc)(c1);
- } else if (c2 == JIS_X_0201_1976_K) {
- output_mode = SHIFT_JIS;
- (*o_putc)(c1|0x80);
- } else if (c2 == ISO_8859_1) {
- output_mode = ISO_8859_1;
- (*o_putc)(c1 | 0x080);
-#ifdef X0212_ENABLE
- } else if (is_eucg3(c2)){
- output_mode = SHIFT_JIS;
- if (e2s_conv(c2, c1, &c2, &c1) == 0){
- (*o_putc)(c2);
- (*o_putc)(c1);
- }
-#endif
- } else {
- if (!nkf_isprint(c1) || !nkf_isprint(c2)) {
- set_iconv(FALSE, 0);
- return; /* too late to rescue this char */
- }
- output_mode = SHIFT_JIS;
- e2s_conv(c2, c1, &c2, &c1);
-
-#ifdef SHIFTJIS_CP932
- if (cp932inv_f
- && CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){
- nkf_char c = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40];
- if (c){
- c2 = c >> 8;
- c1 = c & 0xff;
- }
- }
-#endif /* SHIFTJIS_CP932 */
-
- (*o_putc)(c2);
- if (prefix_table[(unsigned char)c1]){
- (*o_putc)(prefix_table[(unsigned char)c1]);
- }
- (*o_putc)(c1);
- }
-}
-
-#ifdef UTF8_OUTPUT_ENABLE
-#define OUTPUT_UTF8(val) do { \
- nkf_unicode_to_utf8(val, &c1, &c2, &c3, &c4); \
- (*o_putc)(c1); \
- if (c2) (*o_putc)(c2); \
- if (c3) (*o_putc)(c3); \
- if (c4) (*o_putc)(c4); \
- } while (0)
-
-static void
-w_oconv(nkf_char c2, nkf_char c1)
-{
- nkf_char c3, c4;
- nkf_char val, val2;
-
- if (output_bom_f) {
- output_bom_f = FALSE;
- (*o_putc)('\357');
- (*o_putc)('\273');
- (*o_putc)('\277');
- }
-
- if (c2 == EOF) {
- (*o_putc)(EOF);
- return;
- }
-
- if (c2 == 0 && nkf_char_unicode_p(c1)){
- val = c1 & VALUE_MASK;
- OUTPUT_UTF8(val);
- return;
- }
-
- if (c2 == 0) {
- (*o_putc)(c1);
- } else {
- val = e2w_conv(c2, c1);
- if (val){
- val2 = e2w_combining(val, c2, c1);
- if (val2)
- OUTPUT_UTF8(val2);
- OUTPUT_UTF8(val);
- }
- }
-}
-
-#define OUTPUT_UTF16_BYTES(c1, c2) do { \
- if (output_endian == ENDIAN_LITTLE){ \
- (*o_putc)(c1); \
- (*o_putc)(c2); \
- }else{ \
- (*o_putc)(c2); \
- (*o_putc)(c1); \
- } \
- } while (0)
-
-#define OUTPUT_UTF16(val) do { \
- if (nkf_char_unicode_bmp_p(val)) { \
- c2 = (val >> 8) & 0xff; \
- c1 = val & 0xff; \
- OUTPUT_UTF16_BYTES(c1, c2); \
- } else { \
- val &= VALUE_MASK; \
- if (val <= UNICODE_MAX) { \
- c2 = (val >> 10) + NKF_INT32_C(0xD7C0); /* high surrogate */ \
- c1 = (val & 0x3FF) + NKF_INT32_C(0xDC00); /* low surrogate */ \
- OUTPUT_UTF16_BYTES(c2 & 0xff, (c2 >> 8) & 0xff); \
- OUTPUT_UTF16_BYTES(c1 & 0xff, (c1 >> 8) & 0xff); \
- } \
- } \
- } while (0)
-
-static void
-w_oconv16(nkf_char c2, nkf_char c1)
-{
- if (output_bom_f) {
- output_bom_f = FALSE;
- OUTPUT_UTF16_BYTES(0xFF, 0xFE);
- }
-
- if (c2 == EOF) {
- (*o_putc)(EOF);
- return;
- }
-
- if (c2 == 0 && nkf_char_unicode_p(c1)) {
- OUTPUT_UTF16(c1);
- } else if (c2) {
- nkf_char val, val2;
- val = e2w_conv(c2, c1);
- if (!val) return;
- val2 = e2w_combining(val, c2, c1);
- if (val2)
- OUTPUT_UTF16(val2);
- OUTPUT_UTF16(val);
- } else {
- OUTPUT_UTF16_BYTES(c1, c2);
- }
-}
-
-#define OUTPUT_UTF32(c) do { \
- if (output_endian == ENDIAN_LITTLE){ \
- (*o_putc)( (c) & 0xFF); \
- (*o_putc)(((c) >> 8) & 0xFF); \
- (*o_putc)(((c) >> 16) & 0xFF); \
- (*o_putc)(0); \
- }else{ \
- (*o_putc)(0); \
- (*o_putc)(((c) >> 16) & 0xFF); \
- (*o_putc)(((c) >> 8) & 0xFF); \
- (*o_putc)( (c) & 0xFF); \
- } \
- } while (0)
-
-static void
-w_oconv32(nkf_char c2, nkf_char c1)
-{
- if (output_bom_f) {
- output_bom_f = FALSE;
- if (output_endian == ENDIAN_LITTLE){
- (*o_putc)(0xFF);
- (*o_putc)(0xFE);
- (*o_putc)(0);
- (*o_putc)(0);
- }else{
- (*o_putc)(0);
- (*o_putc)(0);
- (*o_putc)(0xFE);
- (*o_putc)(0xFF);
- }
- }
-
- if (c2 == EOF) {
- (*o_putc)(EOF);
- return;
- }
-
- if (c2 == ISO_8859_1) {
- c1 |= 0x80;
- } else if (c2 == 0 && nkf_char_unicode_p(c1)) {
- c1 &= VALUE_MASK;
- } else if (c2) {
- nkf_char val, val2;
- val = e2w_conv(c2, c1);
- if (!val) return;
- val2 = e2w_combining(val, c2, c1);
- if (val2)
- OUTPUT_UTF32(val2);
- c1 = val;
- }
- OUTPUT_UTF32(c1);
-}
-#endif
-
-#define SCORE_L2 (1) /* Kanji Level 2 */
-#define SCORE_KANA (SCORE_L2 << 1) /* Halfwidth Katakana */
-#define SCORE_DEPEND (SCORE_KANA << 1) /* MD Characters */
-#define SCORE_CP932 (SCORE_DEPEND << 1) /* IBM extended characters */
-#define SCORE_X0212 (SCORE_CP932 << 1) /* JIS X 0212 */
-#define SCORE_X0213 (SCORE_X0212 << 1) /* JIS X 0213 */
-#define SCORE_NO_EXIST (SCORE_X0213 << 1) /* Undefined Characters */
-#define SCORE_iMIME (SCORE_NO_EXIST << 1) /* MIME selected */
-#define SCORE_ERROR (SCORE_iMIME << 1) /* Error */
-
-#define SCORE_INIT (SCORE_iMIME)
-
-static const nkf_char score_table_A0[] = {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND,
- SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND, SCORE_X0213,
-};
-
-static const nkf_char score_table_F0[] = {
- SCORE_L2, SCORE_L2, SCORE_L2, SCORE_L2,
- SCORE_L2, SCORE_DEPEND, SCORE_X0213, SCORE_X0213,
- SCORE_DEPEND, SCORE_DEPEND, SCORE_CP932, SCORE_CP932,
- SCORE_CP932, SCORE_X0213, SCORE_X0213, SCORE_ERROR,
-};
-
-static const nkf_char score_table_8FA0[] = {
- 0, SCORE_X0213, SCORE_X0212, SCORE_X0213,
- SCORE_X0213, SCORE_X0213, SCORE_X0212, SCORE_X0212,
- SCORE_X0213, SCORE_X0212, SCORE_X0212, SCORE_X0212,
- SCORE_X0213, SCORE_X0213, SCORE_X0213, SCORE_X0213,
-};
-
-static const nkf_char score_table_8FE0[] = {
- SCORE_X0212, SCORE_X0212, SCORE_X0212, SCORE_X0212,
- SCORE_X0212, SCORE_X0212, SCORE_X0212, SCORE_X0212,
- SCORE_X0212, SCORE_X0212, SCORE_X0212, SCORE_X0212,
- SCORE_X0212, SCORE_X0212, SCORE_X0213, SCORE_X0213,
-};
-
-static const nkf_char score_table_8FF0[] = {
- SCORE_X0213, SCORE_X0213, SCORE_X0213, SCORE_X0212,
- SCORE_X0212, SCORE_X0213, SCORE_X0213, SCORE_X0213,
- SCORE_X0213, SCORE_X0213, SCORE_X0213, SCORE_X0213,
- SCORE_X0213, SCORE_X0213, SCORE_X0213, SCORE_X0213,
-};
-
-static void
-set_code_score(struct input_code *ptr, nkf_char score)
-{
- if (ptr){
- ptr->score |= score;
- }
-}
-
-static void
-clr_code_score(struct input_code *ptr, nkf_char score)
-{
- if (ptr){
- ptr->score &= ~score;
- }
-}
-
-static void
-code_score(struct input_code *ptr)
-{
- nkf_char c2 = ptr->buf[0];
- nkf_char c1 = ptr->buf[1];
- if (c2 < 0){
- set_code_score(ptr, SCORE_ERROR);
- }else if (c2 == SS2){
- set_code_score(ptr, SCORE_KANA);
- }else if (c2 == 0x8f){
- if ((c1 & 0x70) == 0x20){
- set_code_score(ptr, score_table_8FA0[c1 & 0x0f]);
- }else if ((c1 & 0x70) == 0x60){
- set_code_score(ptr, score_table_8FE0[c1 & 0x0f]);
- }else if ((c1 & 0x70) == 0x70){
- set_code_score(ptr, score_table_8FF0[c1 & 0x0f]);
- }else{
- set_code_score(ptr, SCORE_X0212);
- }
-#ifdef UTF8_OUTPUT_ENABLE
- }else if (!e2w_conv(c2, c1)){
- set_code_score(ptr, SCORE_NO_EXIST);
-#endif
- }else if ((c2 & 0x70) == 0x20){
- set_code_score(ptr, score_table_A0[c2 & 0x0f]);
- }else if ((c2 & 0x70) == 0x70){
- set_code_score(ptr, score_table_F0[c2 & 0x0f]);
- }else if ((c2 & 0x70) >= 0x50){
- set_code_score(ptr, SCORE_L2);
- }
-}
-
-static void
-status_disable(struct input_code *ptr)
-{
- ptr->stat = -1;
- ptr->buf[0] = -1;
- code_score(ptr);
- if (iconv == ptr->iconv_func) set_iconv(FALSE, 0);
-}
-
-static void
-status_push_ch(struct input_code *ptr, nkf_char c)
-{
- ptr->buf[ptr->index++] = c;
-}
-
-static void
-status_clear(struct input_code *ptr)
-{
- ptr->stat = 0;
- ptr->index = 0;
-}
-
-static void
-status_reset(struct input_code *ptr)
-{
- status_clear(ptr);
- ptr->score = SCORE_INIT;
-}
-
-static void
-status_reinit(struct input_code *ptr)
-{
- status_reset(ptr);
- ptr->_file_stat = 0;
-}
-
-static void
-status_check(struct input_code *ptr, nkf_char c)
-{
- if (c <= DEL && estab_f){
- status_reset(ptr);
- }
-}
-
-static void
-s_status(struct input_code *ptr, nkf_char c)
-{
- switch(ptr->stat){
- case -1:
- status_check(ptr, c);
- break;
- case 0:
- if (c <= DEL){
- break;
- }else if (nkf_char_unicode_p(c)){
- break;
- }else if (0xa1 <= c && c <= 0xdf){
- status_push_ch(ptr, SS2);
- status_push_ch(ptr, c);
- code_score(ptr);
- status_clear(ptr);
- }else if ((0x81 <= c && c < 0xa0) || (0xe0 <= c && c <= 0xea)){
- ptr->stat = 1;
- status_push_ch(ptr, c);
- }else if (0xed <= c && c <= 0xee){
- ptr->stat = 3;
- status_push_ch(ptr, c);
-#ifdef SHIFTJIS_CP932
- }else if (is_ibmext_in_sjis(c)){
- ptr->stat = 2;
- status_push_ch(ptr, c);
-#endif /* SHIFTJIS_CP932 */
-#ifdef X0212_ENABLE
- }else if (0xf0 <= c && c <= 0xfc){
- ptr->stat = 1;
- status_push_ch(ptr, c);
-#endif /* X0212_ENABLE */
- }else{
- status_disable(ptr);
- }
- break;
- case 1:
- if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){
- status_push_ch(ptr, c);
- s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]);
- code_score(ptr);
- status_clear(ptr);
- }else{
- status_disable(ptr);
- }
- break;
- case 2:
-#ifdef SHIFTJIS_CP932
- if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)) {
- status_push_ch(ptr, c);
- if (s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]) == 0) {
- set_code_score(ptr, SCORE_CP932);
- status_clear(ptr);
- break;
- }
- }
-#endif /* SHIFTJIS_CP932 */
- status_disable(ptr);
- break;
- case 3:
- if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){
- status_push_ch(ptr, c);
- s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]);
- set_code_score(ptr, SCORE_CP932);
- status_clear(ptr);
- }else{
- status_disable(ptr);
- }
- break;
- }
-}
-
-static void
-e_status(struct input_code *ptr, nkf_char c)
-{
- switch (ptr->stat){
- case -1:
- status_check(ptr, c);
- break;
- case 0:
- if (c <= DEL){
- break;
- }else if (nkf_char_unicode_p(c)){
- break;
- }else if (SS2 == c || (0xa1 <= c && c <= 0xfe)){
- ptr->stat = 1;
- status_push_ch(ptr, c);
-#ifdef X0212_ENABLE
- }else if (0x8f == c){
- ptr->stat = 2;
- status_push_ch(ptr, c);
-#endif /* X0212_ENABLE */
- }else{
- status_disable(ptr);
- }
- break;
- case 1:
- if (0xa1 <= c && c <= 0xfe){
- status_push_ch(ptr, c);
- code_score(ptr);
- status_clear(ptr);
- }else{
- status_disable(ptr);
- }
- break;
-#ifdef X0212_ENABLE
- case 2:
- if (0xa1 <= c && c <= 0xfe){
- ptr->stat = 1;
- status_push_ch(ptr, c);
- }else{
- status_disable(ptr);
- }
-#endif /* X0212_ENABLE */
- }
-}
-
-#ifdef UTF8_INPUT_ENABLE
-static void
-w_status(struct input_code *ptr, nkf_char c)
-{
- switch (ptr->stat){
- case -1:
- status_check(ptr, c);
- break;
- case 0:
- if (c <= DEL){
- break;
- }else if (nkf_char_unicode_p(c)){
- break;
- }else if (0xc0 <= c && c <= 0xdf){
- ptr->stat = 1;
- status_push_ch(ptr, c);
- }else if (0xe0 <= c && c <= 0xef){
- ptr->stat = 2;
- status_push_ch(ptr, c);
- }else if (0xf0 <= c && c <= 0xf4){
- ptr->stat = 3;
- status_push_ch(ptr, c);
- }else{
- status_disable(ptr);
- }
- break;
- case 1:
- case 2:
- if (0x80 <= c && c <= 0xbf){
- status_push_ch(ptr, c);
- if (ptr->index > ptr->stat){
- int bom = (ptr->buf[0] == 0xef && ptr->buf[1] == 0xbb
- && ptr->buf[2] == 0xbf);
- w2e_conv(ptr->buf[0], ptr->buf[1], ptr->buf[2],
- &ptr->buf[0], &ptr->buf[1]);
- if (!bom){
- code_score(ptr);
- }
- status_clear(ptr);
- }
- }else{
- status_disable(ptr);
- }
- break;
- case 3:
- if (0x80 <= c && c <= 0xbf){
- if (ptr->index < ptr->stat){
- status_push_ch(ptr, c);
- } else {
- status_clear(ptr);
- }
- }else{
- status_disable(ptr);
- }
- break;
- }
-}
-#endif
-
-static void
-code_status(nkf_char c)
-{
- int action_flag = 1;
- struct input_code *result = 0;
- struct input_code *p = input_code_list;
- while (p->name){
- if (!p->status_func) {
- ++p;
- continue;
- }
- if (!p->status_func)
- continue;
- (p->status_func)(p, c);
- if (p->stat > 0){
- action_flag = 0;
- }else if(p->stat == 0){
- if (result){
- action_flag = 0;
- }else{
- result = p;
- }
- }
- ++p;
- }
-
- if (action_flag){
- if (result && !estab_f){
- set_iconv(TRUE, result->iconv_func);
- }else if (c <= DEL){
- struct input_code *ptr = input_code_list;
- while (ptr->name){
- status_reset(ptr);
- ++ptr;
- }
- }
- }
-}
-
-typedef struct {
- nkf_buf_t *std_gc_buf;
- nkf_char broken_state;
- nkf_buf_t *broken_buf;
- nkf_char mimeout_state;
- nkf_buf_t *nfc_buf;
-} nkf_state_t;
-
-static nkf_state_t *nkf_state = NULL;
-
-#define STD_GC_BUFSIZE (256)
-
-static void
-nkf_state_init(void)
-{
- if (nkf_state) {
- nkf_buf_clear(nkf_state->std_gc_buf);
- nkf_buf_clear(nkf_state->broken_buf);
- nkf_buf_clear(nkf_state->nfc_buf);
- }
- else {
- nkf_state = nkf_xmalloc(sizeof(nkf_state_t));
- nkf_state->std_gc_buf = nkf_buf_new(STD_GC_BUFSIZE);
- nkf_state->broken_buf = nkf_buf_new(3);
- nkf_state->nfc_buf = nkf_buf_new(9);
- }
- nkf_state->broken_state = 0;
- nkf_state->mimeout_state = 0;
-}
-
-#ifndef WIN32DLL
-static nkf_char
-std_getc(FILE *f)
-{
- if (!nkf_buf_empty_p(nkf_state->std_gc_buf)){
- return nkf_buf_pop(nkf_state->std_gc_buf);
- }
- return getc(f);
-}
-#endif /*WIN32DLL*/
-
-static nkf_char
-std_ungetc(nkf_char c, ARG_UNUSED FILE *f)
-{
- nkf_buf_push(nkf_state->std_gc_buf, c);
- return c;
-}
-
-#ifndef WIN32DLL
-static void
-std_putc(nkf_char c)
-{
- if(c!=EOF)
- putchar(c);
-}
-#endif /*WIN32DLL*/
-
-static nkf_char hold_buf[HOLD_SIZE*2];
-static int hold_count = 0;
-static nkf_char
-push_hold_buf(nkf_char c2)
-{
- if (hold_count >= HOLD_SIZE*2)
- return (EOF);
- hold_buf[hold_count++] = c2;
- return ((hold_count >= HOLD_SIZE*2) ? EOF : hold_count);
-}
-
-static int
-h_conv(FILE *f, nkf_char c1, nkf_char c2)
-{
- int ret;
- int hold_index;
- int fromhold_count;
- nkf_char c3, c4;
-
- /** it must NOT be in the kanji shifte sequence */
- /** it must NOT be written in JIS7 */
- /** and it must be after 2 byte 8bit code */
-
- hold_count = 0;
- push_hold_buf(c1);
- push_hold_buf(c2);
-
- while ((c2 = (*i_getc)(f)) != EOF) {
- if (c2 == ESC){
- (*i_ungetc)(c2,f);
- break;
- }
- code_status(c2);
- if (push_hold_buf(c2) == EOF || estab_f) {
- break;
- }
- }
-
- if (!estab_f) {
- struct input_code *p = input_code_list;
- struct input_code *result = p;
- if (c2 == EOF) {
- code_status(c2);
- }
- while (p->name) {
- if (p->status_func && p->score < result->score) {
- result = p;
- }
- p++;
- }
- set_iconv(TRUE, result->iconv_func);
- }
-
-
- /** now,
- ** 1) EOF is detected, or
- ** 2) Code is established, or
- ** 3) Buffer is FULL (but last word is pushed)
- **
- ** in 1) and 3) cases, we continue to use
- ** Kanji codes by oconv and leave estab_f unchanged.
- **/
-
- ret = c2;
- hold_index = 0;
- while (hold_index < hold_count){
- c1 = hold_buf[hold_index++];
- if (nkf_char_unicode_p(c1)) {
- (*oconv)(0, c1);
- continue;
- }
- else if (c1 <= DEL){
- (*iconv)(0, c1, 0);
- continue;
- }else if (iconv == s_iconv && 0xa1 <= c1 && c1 <= 0xdf){
- (*iconv)(JIS_X_0201_1976_K, c1, 0);
- continue;
- }
- fromhold_count = 1;
- if (hold_index < hold_count){
- c2 = hold_buf[hold_index++];
- fromhold_count++;
- }else{
- c2 = (*i_getc)(f);
- if (c2 == EOF){
- c4 = EOF;
- break;
- }
- code_status(c2);
- }
- c3 = 0;
- switch ((*iconv)(c1, c2, 0)) { /* can be EUC/SJIS/UTF-8 */
- case -2:
- /* 4 bytes UTF-8 */
- if (hold_index < hold_count){
- c3 = hold_buf[hold_index++];
- } else if ((c3 = (*i_getc)(f)) == EOF) {
- ret = EOF;
- break;
- }
- code_status(c3);
- if (hold_index < hold_count){
- c4 = hold_buf[hold_index++];
- } else if ((c4 = (*i_getc)(f)) == EOF) {
- c3 = ret = EOF;
- break;
- }
- code_status(c4);
- (*iconv)(c1, c2, (c3<<8)|c4);
- break;
- case -3:
- /* 4 bytes UTF-8 (check combining character) */
- if (hold_index < hold_count){
- c3 = hold_buf[hold_index++];
- fromhold_count++;
- } else if ((c3 = (*i_getc)(f)) == EOF) {
- w_iconv_nocombine(c1, c2, 0);
- break;
- }
- if (hold_index < hold_count){
- c4 = hold_buf[hold_index++];
- fromhold_count++;
- } else if ((c4 = (*i_getc)(f)) == EOF) {
- w_iconv_nocombine(c1, c2, 0);
- if (fromhold_count <= 2)
- (*i_ungetc)(c3,f);
- else
- hold_index--;
- continue;
- }
- if (w_iconv_combine(c1, c2, 0, c3, c4, 0)) {
- w_iconv_nocombine(c1, c2, 0);
- if (fromhold_count <= 2) {
- (*i_ungetc)(c4,f);
- (*i_ungetc)(c3,f);
- } else if (fromhold_count == 3) {
- (*i_ungetc)(c4,f);
- hold_index--;
- } else {
- hold_index -= 2;
- }
- }
- break;
- case -1:
- /* 3 bytes EUC or UTF-8 */
- if (hold_index < hold_count){
- c3 = hold_buf[hold_index++];
- fromhold_count++;
- } else if ((c3 = (*i_getc)(f)) == EOF) {
- ret = EOF;
- break;
- } else {
- code_status(c3);
- }
- if ((*iconv)(c1, c2, c3) == -3) {
- /* 6 bytes UTF-8 (check combining character) */
- nkf_char c5, c6;
- if (hold_index < hold_count){
- c4 = hold_buf[hold_index++];
- fromhold_count++;
- } else if ((c4 = (*i_getc)(f)) == EOF) {
- w_iconv_nocombine(c1, c2, c3);
- continue;
- }
- if (hold_index < hold_count){
- c5 = hold_buf[hold_index++];
- fromhold_count++;
- } else if ((c5 = (*i_getc)(f)) == EOF) {
- w_iconv_nocombine(c1, c2, c3);
- if (fromhold_count == 4)
- hold_index--;
- else
- (*i_ungetc)(c4,f);
- continue;
- }
- if (hold_index < hold_count){
- c6 = hold_buf[hold_index++];
- fromhold_count++;
- } else if ((c6 = (*i_getc)(f)) == EOF) {
- w_iconv_nocombine(c1, c2, c3);
- if (fromhold_count == 5) {
- hold_index -= 2;
- } else if (fromhold_count == 4) {
- hold_index--;
- (*i_ungetc)(c5,f);
- } else {
- (*i_ungetc)(c5,f);
- (*i_ungetc)(c4,f);
- }
- continue;
- }
- if (w_iconv_combine(c1, c2, c3, c4, c5, c6)) {
- w_iconv_nocombine(c1, c2, c3);
- if (fromhold_count == 6) {
- hold_index -= 3;
- } else if (fromhold_count == 5) {
- hold_index -= 2;
- (*i_ungetc)(c6,f);
- } else if (fromhold_count == 4) {
- hold_index--;
- (*i_ungetc)(c6,f);
- (*i_ungetc)(c5,f);
- } else {
- (*i_ungetc)(c6,f);
- (*i_ungetc)(c5,f);
- (*i_ungetc)(c4,f);
- }
- }
- }
- break;
- }
- if (c3 == EOF) break;
- }
- return ret;
-}
-
-/*
- * Check and Ignore BOM
- */
-static void
-check_bom(FILE *f)
-{
- int c2;
- input_bom_f = FALSE;
- switch(c2 = (*i_getc)(f)){
- case 0x00:
- if((c2 = (*i_getc)(f)) == 0x00){
- if((c2 = (*i_getc)(f)) == 0xFE){
- if((c2 = (*i_getc)(f)) == 0xFF){
- if(!input_encoding){
- set_iconv(TRUE, w_iconv32);
- }
- if (iconv == w_iconv32) {
- input_bom_f = TRUE;
- input_endian = ENDIAN_BIG;
- return;
- }
- (*i_ungetc)(0xFF,f);
- }else (*i_ungetc)(c2,f);
- (*i_ungetc)(0xFE,f);
- }else if(c2 == 0xFF){
- if((c2 = (*i_getc)(f)) == 0xFE){
- if(!input_encoding){
- set_iconv(TRUE, w_iconv32);
- }
- if (iconv == w_iconv32) {
- input_endian = ENDIAN_2143;
- return;
- }
- (*i_ungetc)(0xFF,f);
- }else (*i_ungetc)(c2,f);
- (*i_ungetc)(0xFF,f);
- }else (*i_ungetc)(c2,f);
- (*i_ungetc)(0x00,f);
- }else (*i_ungetc)(c2,f);
- (*i_ungetc)(0x00,f);
- break;
- case 0xEF:
- if((c2 = (*i_getc)(f)) == 0xBB){
- if((c2 = (*i_getc)(f)) == 0xBF){
- if(!input_encoding){
- set_iconv(TRUE, w_iconv);
- }
- if (iconv == w_iconv) {
- input_bom_f = TRUE;
- return;
- }
- (*i_ungetc)(0xBF,f);
- }else (*i_ungetc)(c2,f);
- (*i_ungetc)(0xBB,f);
- }else (*i_ungetc)(c2,f);
- (*i_ungetc)(0xEF,f);
- break;
- case 0xFE:
- if((c2 = (*i_getc)(f)) == 0xFF){
- if((c2 = (*i_getc)(f)) == 0x00){
- if((c2 = (*i_getc)(f)) == 0x00){
- if(!input_encoding){
- set_iconv(TRUE, w_iconv32);
- }
- if (iconv == w_iconv32) {
- input_endian = ENDIAN_3412;
- return;
- }
- (*i_ungetc)(0x00,f);
- }else (*i_ungetc)(c2,f);
- (*i_ungetc)(0x00,f);
- }else (*i_ungetc)(c2,f);
- if(!input_encoding){
- set_iconv(TRUE, w_iconv16);
- }
- if (iconv == w_iconv16) {
- input_endian = ENDIAN_BIG;
- input_bom_f = TRUE;
- return;
- }
- (*i_ungetc)(0xFF,f);
- }else (*i_ungetc)(c2,f);
- (*i_ungetc)(0xFE,f);
- break;
- case 0xFF:
- if((c2 = (*i_getc)(f)) == 0xFE){
- if((c2 = (*i_getc)(f)) == 0x00){
- if((c2 = (*i_getc)(f)) == 0x00){
- if(!input_encoding){
- set_iconv(TRUE, w_iconv32);
- }
- if (iconv == w_iconv32) {
- input_endian = ENDIAN_LITTLE;
- input_bom_f = TRUE;
- return;
- }
- (*i_ungetc)(0x00,f);
- }else (*i_ungetc)(c2,f);
- (*i_ungetc)(0x00,f);
- }else (*i_ungetc)(c2,f);
- if(!input_encoding){
- set_iconv(TRUE, w_iconv16);
- }
- if (iconv == w_iconv16) {
- input_endian = ENDIAN_LITTLE;
- input_bom_f = TRUE;
- return;
- }
- (*i_ungetc)(0xFE,f);
- }else (*i_ungetc)(c2,f);
- (*i_ungetc)(0xFF,f);
- break;
- default:
- (*i_ungetc)(c2,f);
- break;
- }
-}
-
-static nkf_char
-broken_getc(FILE *f)
-{
- nkf_char c, c1;
-
- if (!nkf_buf_empty_p(nkf_state->broken_buf)) {
- return nkf_buf_pop(nkf_state->broken_buf);
- }
- c = (*i_bgetc)(f);
- if (c=='$' && nkf_state->broken_state != ESC
- && (input_mode == ASCII || input_mode == JIS_X_0201_1976_K)) {
- c1= (*i_bgetc)(f);
- nkf_state->broken_state = 0;
- if (c1=='@'|| c1=='B') {
- nkf_buf_push(nkf_state->broken_buf, c1);
- nkf_buf_push(nkf_state->broken_buf, c);
- return ESC;
- } else {
- (*i_bungetc)(c1,f);
- return c;
- }
- } else if (c=='(' && nkf_state->broken_state != ESC
- && (input_mode == JIS_X_0208 || input_mode == JIS_X_0201_1976_K)) {
- c1= (*i_bgetc)(f);
- nkf_state->broken_state = 0;
- if (c1=='J'|| c1=='B') {
- nkf_buf_push(nkf_state->broken_buf, c1);
- nkf_buf_push(nkf_state->broken_buf, c);
- return ESC;
- } else {
- (*i_bungetc)(c1,f);
- return c;
- }
- } else {
- nkf_state->broken_state = c;
- return c;
- }
-}
-
-static nkf_char
-broken_ungetc(nkf_char c, ARG_UNUSED FILE *f)
-{
- if (nkf_buf_length(nkf_state->broken_buf) < 2)
- nkf_buf_push(nkf_state->broken_buf, c);
- return c;
-}
-
-static void
-eol_conv(nkf_char c2, nkf_char c1)
-{
- if (guess_f && input_eol != EOF) {
- if (c2 == 0 && c1 == LF) {
- if (!input_eol) input_eol = prev_cr ? CRLF : LF;
- else if (input_eol != (prev_cr ? CRLF : LF)) input_eol = EOF;
- } else if (c2 == 0 && c1 == CR && input_eol == LF) input_eol = EOF;
- else if (!prev_cr);
- else if (!input_eol) input_eol = CR;
- else if (input_eol != CR) input_eol = EOF;
- }
- if (prev_cr || (c2 == 0 && c1 == LF)) {
- prev_cr = 0;
- if (eolmode_f != LF) (*o_eol_conv)(0, CR);
- if (eolmode_f != CR) (*o_eol_conv)(0, LF);
- }
- if (c2 == 0 && c1 == CR) prev_cr = CR;
- else if (c2 != 0 || c1 != LF) (*o_eol_conv)(c2, c1);
-}
-
-static void
-put_newline(void (*func)(nkf_char))
-{
- switch (eolmode_f ? eolmode_f : DEFAULT_NEWLINE) {
- case CRLF:
- (*func)(0x0D);
- (*func)(0x0A);
- break;
- case CR:
- (*func)(0x0D);
- break;
- case LF:
- (*func)(0x0A);
- break;
- }
-}
-
-static void
-oconv_newline(void (*func)(nkf_char, nkf_char))
-{
- switch (eolmode_f ? eolmode_f : DEFAULT_NEWLINE) {
- case CRLF:
- (*func)(0, 0x0D);
- (*func)(0, 0x0A);
- break;
- case CR:
- (*func)(0, 0x0D);
- break;
- case LF:
- (*func)(0, 0x0A);
- break;
- }
-}
-
-/*
- Return value of fold_conv()
-
- LF add newline and output char
- CR add newline and output nothing
- SP space
- 0 skip
- 1 (or else) normal output
-
- fold state in prev (previous character)
-
- >0x80 Japanese (X0208/X0201)
- <0x80 ASCII
- LF new line
- SP space
-
- This fold algorithm does not preserve heading space in a line.
- This is the main difference from fmt.
- */
-
-#define char_size(c2,c1) (c2?2:1)
-
-static void
-fold_conv(nkf_char c2, nkf_char c1)
-{
- nkf_char prev0;
- nkf_char fold_state;
-
- if (c1== CR && !fold_preserve_f) {
- fold_state=0; /* ignore cr */
- }else if (c1== LF&&f_prev==CR && fold_preserve_f) {
- f_prev = LF;
- fold_state=0; /* ignore cr */
- } else if (c1== BS) {
- if (f_line>0) f_line--;
- fold_state = 1;
- } else if (c2==EOF && f_line != 0) { /* close open last line */
- fold_state = LF;
- } else if ((c1==LF && !fold_preserve_f)
- || ((c1==CR||(c1==LF&&f_prev!=CR))
- && fold_preserve_f)) {
- /* new line */
- if (fold_preserve_f) {
- f_prev = c1;
- f_line = 0;
- fold_state = CR;
- } else if ((f_prev == c1)
- || (f_prev == LF)
- ) { /* duplicate newline */
- if (f_line) {
- f_line = 0;
- fold_state = LF; /* output two newline */
- } else {
- f_line = 0;
- fold_state = 1;
- }
- } else {
- if (f_prev&0x80) { /* Japanese? */
- f_prev = c1;
- fold_state = 0; /* ignore given single newline */
- } else if (f_prev==SP) {
- fold_state = 0;
- } else {
- f_prev = c1;
- if (++f_line<=fold_len)
- fold_state = SP;
- else {
- f_line = 0;
- fold_state = CR; /* fold and output nothing */
- }
- }
- }
- } else if (c1=='\f') {
- f_prev = LF;
- f_line = 0;
- fold_state = LF; /* output newline and clear */
- } else if ((c2==0 && nkf_isblank(c1)) || (c2 == '!' && c1 == '!')) {
- /* X0208 kankaku or ascii space */
- if (f_prev == SP) {
- fold_state = 0; /* remove duplicate spaces */
- } else {
- f_prev = SP;
- if (++f_line<=fold_len)
- fold_state = SP; /* output ASCII space only */
- else {
- f_prev = SP; f_line = 0;
- fold_state = CR; /* fold and output nothing */
- }
- }
- } else {
- prev0 = f_prev; /* we still need this one... , but almost done */
- f_prev = c1;
- if (c2 || c2 == JIS_X_0201_1976_K)
- f_prev |= 0x80; /* this is Japanese */
- f_line += c2 == JIS_X_0201_1976_K ? 1: char_size(c2,c1);
- if (f_line<=fold_len) { /* normal case */
- fold_state = 1;
- } else {
- if (f_line>fold_len+fold_margin) { /* too many kinsoku suspension */
- f_line = char_size(c2,c1);
- fold_state = LF; /* We can't wait, do fold now */
- } else if (c2 == JIS_X_0201_1976_K) {
- /* simple kinsoku rules return 1 means no folding */
- if (c1==(0xde&0x7f)) fold_state = 1; /* $B!+(B*/
- else if (c1==(0xdf&0x7f)) fold_state = 1; /* $B!,(B*/
- else if (c1==(0xa4&0x7f)) fold_state = 1; /* $B!#(B*/
- else if (c1==(0xa3&0x7f)) fold_state = 1; /* $B!$(B*/
- else if (c1==(0xa1&0x7f)) fold_state = 1; /* $B!W(B*/
- else if (c1==(0xb0&0x7f)) fold_state = 1; /* - */
- else if (SP<=c1 && c1<=(0xdf&0x7f)) { /* X0201 */
- f_line = 1;
- fold_state = LF;/* add one new f_line before this character */
- } else {
- f_line = 1;
- fold_state = LF;/* add one new f_line before this character */
- }
- } else if (c2==0) {
- /* kinsoku point in ASCII */
- if ( c1==')'|| /* { [ ( */
- c1==']'||
- c1=='}'||
- c1=='.'||
- c1==','||
- c1=='!'||
- c1=='?'||
- c1=='/'||
- c1==':'||
- c1==';') {
- fold_state = 1;
- /* just after special */
- } else if (!is_alnum(prev0)) {
- f_line = char_size(c2,c1);
- fold_state = LF;
- } else if ((prev0==SP) || /* ignored new f_line */
- (prev0==LF)|| /* ignored new f_line */
- (prev0&0x80)) { /* X0208 - ASCII */
- f_line = char_size(c2,c1);
- fold_state = LF;/* add one new f_line before this character */
- } else {
- fold_state = 1; /* default no fold in ASCII */
- }
- } else {
- if (c2=='!') {
- if (c1=='"') fold_state = 1; /* $B!"(B */
- else if (c1=='#') fold_state = 1; /* $B!#(B */
- else if (c1=='W') fold_state = 1; /* $B!W(B */
- else if (c1=='K') fold_state = 1; /* $B!K(B */
- else if (c1=='$') fold_state = 1; /* $B!$(B */
- else if (c1=='%') fold_state = 1; /* $B!%(B */
- else if (c1=='\'') fold_state = 1; /* $B!\(B */
- else if (c1=='(') fold_state = 1; /* $B!((B */
- else if (c1==')') fold_state = 1; /* $B!)(B */
- else if (c1=='*') fold_state = 1; /* $B!*(B */
- else if (c1=='+') fold_state = 1; /* $B!+(B */
- else if (c1==',') fold_state = 1; /* $B!,(B */
- /* default no fold in kinsoku */
- else {
- fold_state = LF;
- f_line = char_size(c2,c1);
- /* add one new f_line before this character */
- }
- } else {
- f_line = char_size(c2,c1);
- fold_state = LF;
- /* add one new f_line before this character */
- }
- }
- }
- }
- /* terminator process */
- switch(fold_state) {
- case LF:
- oconv_newline(o_fconv);
- (*o_fconv)(c2,c1);
- break;
- case 0:
- return;
- case CR:
- oconv_newline(o_fconv);
- break;
- case TAB:
- case SP:
- (*o_fconv)(0,SP);
- break;
- default:
- (*o_fconv)(c2,c1);
- }
-}
-
-static nkf_char z_prev2=0,z_prev1=0;
-
-static void
-z_conv(nkf_char c2, nkf_char c1)
-{
-
- /* if (c2) c1 &= 0x7f; assertion */
-
- if (c2 == JIS_X_0201_1976_K && (c1 == 0x20 || c1 == 0x7D || c1 == 0x7E)) {
- (*o_zconv)(c2,c1);
- return;
- }
-
- if (x0201_f) {
- if (z_prev2 == JIS_X_0201_1976_K) {
- if (c2 == JIS_X_0201_1976_K) {
- if (c1 == (0xde&0x7f)) { /* $BByE@(B */
- z_prev2 = 0;
- (*o_zconv)(dv[(z_prev1-SP)*2], dv[(z_prev1-SP)*2+1]);
- return;
- } else if (c1 == (0xdf&0x7f) && ev[(z_prev1-SP)*2]) { /* $BH>ByE@(B */
- z_prev2 = 0;
- (*o_zconv)(ev[(z_prev1-SP)*2], ev[(z_prev1-SP)*2+1]);
- return;
- } else if (x0213_f && c1 == (0xdf&0x7f) && ev_x0213[(z_prev1-SP)*2]) { /* $BH>ByE@(B */
- z_prev2 = 0;
- (*o_zconv)(ev_x0213[(z_prev1-SP)*2], ev_x0213[(z_prev1-SP)*2+1]);
- return;
- }
- }
- z_prev2 = 0;
- (*o_zconv)(cv[(z_prev1-SP)*2], cv[(z_prev1-SP)*2+1]);
- }
- if (c2 == JIS_X_0201_1976_K) {
- if (dv[(c1-SP)*2] || ev[(c1-SP)*2] || (x0213_f && ev_x0213[(c1-SP)*2])) {
- /* wait for $BByE@(B or $BH>ByE@(B */
- z_prev1 = c1;
- z_prev2 = c2;
- return;
- } else {
- (*o_zconv)(cv[(c1-SP)*2], cv[(c1-SP)*2+1]);
- return;
- }
- }
- }
-
- if (c2 == EOF) {
- (*o_zconv)(c2, c1);
- return;
- }
-
- if (alpha_f&1 && c2 == 0x23) {
- /* JISX0208 Alphabet */
- c2 = 0;
- } else if (c2 == 0x21) {
- /* JISX0208 Kigou */
- if (0x21==c1) {
- if (alpha_f&2) {
- c2 = 0;
- c1 = SP;
- } else if (alpha_f&4) {
- (*o_zconv)(0, SP);
- (*o_zconv)(0, SP);
- return;
- }
- } else if (alpha_f&1 && 0x20<c1 && c1<0x7f && fv[c1-0x20]) {
- c2 = 0;
- c1 = fv[c1-0x20];
- }
- }
-
- if (alpha_f&8 && c2 == 0) {
- /* HTML Entity */
- const char *entity = 0;
- switch (c1){
- case '>': entity = "&gt;"; break;
- case '<': entity = "&lt;"; break;
- case '\"': entity = "&quot;"; break;
- case '&': entity = "&amp;"; break;
- }
- if (entity){
- while (*entity) (*o_zconv)(0, *entity++);
- return;
- }
- }
-
- if (alpha_f & 16) {
- /* JIS X 0208 Katakana to JIS X 0201 Katakana */
- if (c2 == 0x21) {
- nkf_char c = 0;
- switch (c1) {
- case 0x23:
- /* U+3002 (0x8142) Ideographic Full Stop -> U+FF61 (0xA1) Halfwidth Ideographic Full Stop */
- c = 0xA1;
- break;
- case 0x56:
- /* U+300C (0x8175) Left Corner Bracket -> U+FF62 (0xA2) Halfwidth Left Corner Bracket */
- c = 0xA2;
- break;
- case 0x57:
- /* U+300D (0x8176) Right Corner Bracket -> U+FF63 (0xA3) Halfwidth Right Corner Bracket */
- c = 0xA3;
- break;
- case 0x22:
- /* U+3001 (0x8141) Ideographic Comma -> U+FF64 (0xA4) Halfwidth Ideographic Comma */
- c = 0xA4;
- break;
- case 0x26:
- /* U+30FB (0x8145) Katakana Middle Dot -> U+FF65 (0xA5) Halfwidth Katakana Middle Dot */
- c = 0xA5;
- break;
- case 0x3C:
- /* U+30FC (0x815B) Katakana-Hiragana Prolonged Sound Mark -> U+FF70 (0xB0) Halfwidth Katakana-Hiragana Prolonged Sound Mark */
- c = 0xB0;
- break;
- case 0x2B:
- /* U+309B (0x814A) Katakana-Hiragana Voiced Sound Mark -> U+FF9E (0xDE) Halfwidth Katakana Voiced Sound Mark */
- c = 0xDE;
- break;
- case 0x2C:
- /* U+309C (0x814B) Katakana-Hiragana Semi-Voiced Sound Mark -> U+FF9F (0xDF) Halfwidth Katakana Semi-Voiced Sound Mark */
- c = 0xDF;
- break;
- }
- if (c) {
- (*o_zconv)(JIS_X_0201_1976_K, c);
- return;
- }
- } else if (c2 == 0x25) {
- /* JISX0208 Katakana */
- static const int fullwidth_to_halfwidth[] =
- {
- 0x0000, 0x2700, 0x3100, 0x2800, 0x3200, 0x2900, 0x3300, 0x2A00,
- 0x3400, 0x2B00, 0x3500, 0x3600, 0x365E, 0x3700, 0x375E, 0x3800,
- 0x385E, 0x3900, 0x395E, 0x3A00, 0x3A5E, 0x3B00, 0x3B5E, 0x3C00,
- 0x3C5E, 0x3D00, 0x3D5E, 0x3E00, 0x3E5E, 0x3F00, 0x3F5E, 0x4000,
- 0x405E, 0x4100, 0x415E, 0x2F00, 0x4200, 0x425E, 0x4300, 0x435E,
- 0x4400, 0x445E, 0x4500, 0x4600, 0x4700, 0x4800, 0x4900, 0x4A00,
- 0x4A5E, 0x4A5F, 0x4B00, 0x4B5E, 0x4B5F, 0x4C00, 0x4C5E, 0x4C5F,
- 0x4D00, 0x4D5E, 0x4D5F, 0x4E00, 0x4E5E, 0x4E5F, 0x4F00, 0x5000,
- 0x5100, 0x5200, 0x5300, 0x2C00, 0x5400, 0x2D00, 0x5500, 0x2E00,
- 0x5600, 0x5700, 0x5800, 0x5900, 0x5A00, 0x5B00, 0x0000, 0x5C00,
- 0x0000, 0x0000, 0x2600, 0x5D00, 0x335E, 0x0000, 0x0000, 0x365F,
- 0x375F, 0x385F, 0x395F, 0x3A5F, 0x3E5F, 0x425F, 0x445F, 0x0000
- };
- if (fullwidth_to_halfwidth[c1-0x20]){
- c2 = fullwidth_to_halfwidth[c1-0x20];
- (*o_zconv)(JIS_X_0201_1976_K, c2>>8);
- if (c2 & 0xFF) {
- (*o_zconv)(JIS_X_0201_1976_K, c2&0xFF);
- }
- return;
- }
- } else if (c2 == 0 && nkf_char_unicode_p(c1) &&
- ((c1&VALUE_MASK) == 0x3099 || (c1&VALUE_MASK) == 0x309A)) { /* $B9g@.MQByE@!&H>ByE@(B */
- (*o_zconv)(JIS_X_0201_1976_K, 0x5E + (c1&VALUE_MASK) - 0x3099);
- return;
- }
- }
- (*o_zconv)(c2,c1);
-}
-
-
-#define rot13(c) ( \
- ( c < 'A') ? c: \
- (c <= 'M') ? (c + 13): \
- (c <= 'Z') ? (c - 13): \
- (c < 'a') ? (c): \
- (c <= 'm') ? (c + 13): \
- (c <= 'z') ? (c - 13): \
- (c) \
- )
-
-#define rot47(c) ( \
- ( c < '!') ? c: \
- ( c <= 'O') ? (c + 47) : \
- ( c <= '~') ? (c - 47) : \
- c \
- )
-
-static void
-rot_conv(nkf_char c2, nkf_char c1)
-{
- if (c2 == 0 || c2 == JIS_X_0201_1976_K || c2 == ISO_8859_1) {
- c1 = rot13(c1);
- } else if (c2) {
- c1 = rot47(c1);
- c2 = rot47(c2);
- }
- (*o_rot_conv)(c2,c1);
-}
-
-static void
-hira_conv(nkf_char c2, nkf_char c1)
-{
- if (hira_f & 1) {
- if (c2 == 0x25) {
- if (0x20 < c1 && c1 < 0x74) {
- c2 = 0x24;
- (*o_hira_conv)(c2,c1);
- return;
- } else if (c1 == 0x74 && nkf_enc_unicode_p(output_encoding)) {
- c2 = 0;
- c1 = nkf_char_unicode_new(0x3094);
- (*o_hira_conv)(c2,c1);
- return;
- }
- } else if (c2 == 0x21 && (c1 == 0x33 || c1 == 0x34)) {
- c1 += 2;
- (*o_hira_conv)(c2,c1);
- return;
- }
- }
- if (hira_f & 2) {
- if (c2 == 0 && c1 == nkf_char_unicode_new(0x3094)) {
- c2 = 0x25;
- c1 = 0x74;
- } else if (c2 == 0x24 && 0x20 < c1 && c1 < 0x74) {
- c2 = 0x25;
- } else if (c2 == 0x21 && (c1 == 0x35 || c1 == 0x36)) {
- c1 -= 2;
- }
- }
- (*o_hira_conv)(c2,c1);
-}
-
-
-static void
-iso2022jp_check_conv(nkf_char c2, nkf_char c1)
-{
-#define RANGE_NUM_MAX 18
- static const nkf_char range[RANGE_NUM_MAX][2] = {
- {0x222f, 0x2239,},
- {0x2242, 0x2249,},
- {0x2251, 0x225b,},
- {0x226b, 0x2271,},
- {0x227a, 0x227d,},
- {0x2321, 0x232f,},
- {0x233a, 0x2340,},
- {0x235b, 0x2360,},
- {0x237b, 0x237e,},
- {0x2474, 0x247e,},
- {0x2577, 0x257e,},
- {0x2639, 0x2640,},
- {0x2659, 0x267e,},
- {0x2742, 0x2750,},
- {0x2772, 0x277e,},
- {0x2841, 0x287e,},
- {0x4f54, 0x4f7e,},
- {0x7425, 0x747e},
- };
- nkf_char i;
- nkf_char start, end, c;
-
- if(c2 >= 0x00 && c2 <= 0x20 && c1 >= 0x7f && c1 <= 0xff) {
- c2 = GETA1;
- c1 = GETA2;
- }
- if((c2 >= 0x29 && c2 <= 0x2f) || (c2 >= 0x75 && c2 <= 0x7e)) {
- c2 = GETA1;
- c1 = GETA2;
- }
-
- for (i = 0; i < RANGE_NUM_MAX; i++) {
- start = range[i][0];
- end = range[i][1];
- c = (c2 << 8) + c1;
- if (c >= start && c <= end) {
- c2 = GETA1;
- c1 = GETA2;
- }
- }
- (*o_iso2022jp_check_conv)(c2,c1);
-}
-
-
-/* This converts =?ISO-2022-JP?B?HOGE HOGE?= */
-
-static const unsigned char *mime_pattern[] = {
- (const unsigned char *)"\075?EUC-JP?B?",
- (const unsigned char *)"\075?SHIFT_JIS?B?",
- (const unsigned char *)"\075?ISO-8859-1?Q?",
- (const unsigned char *)"\075?ISO-8859-1?B?",
- (const unsigned char *)"\075?ISO-2022-JP?B?",
- (const unsigned char *)"\075?ISO-2022-JP?B?",
- (const unsigned char *)"\075?ISO-2022-JP?Q?",
-#if defined(UTF8_INPUT_ENABLE)
- (const unsigned char *)"\075?UTF-8?B?",
- (const unsigned char *)"\075?UTF-8?Q?",
-#endif
- (const unsigned char *)"\075?US-ASCII?Q?",
- NULL
-};
-
-
-/* $B3:Ev$9$k%3!<%I$NM%@hEY$r>e$2$k$?$a$NL\0u(B */
-static nkf_char (*const mime_priority_func[])(nkf_char c2, nkf_char c1, nkf_char c0) = {
- e_iconv, s_iconv, 0, 0, 0, 0, 0,
-#if defined(UTF8_INPUT_ENABLE)
- w_iconv, w_iconv,
-#endif
- 0,
-};
-
-static const nkf_char mime_encode[] = {
- EUC_JP, SHIFT_JIS, ISO_8859_1, ISO_8859_1, JIS_X_0208, JIS_X_0201_1976_K, JIS_X_0201_1976_K,
-#if defined(UTF8_INPUT_ENABLE)
- UTF_8, UTF_8,
-#endif
- ASCII,
- 0
-};
-
-static const nkf_char mime_encode_method[] = {
- 'B', 'B','Q', 'B', 'B', 'B', 'Q',
-#if defined(UTF8_INPUT_ENABLE)
- 'B', 'Q',
-#endif
- 'Q',
- 0
-};
-
-
-/* MIME preprocessor fifo */
-
-#define MIME_BUF_SIZE (1024) /* 2^n ring buffer */
-#define MIME_BUF_MASK (MIME_BUF_SIZE-1)
-#define mime_input_buf(n) mime_input_state.buf[(n)&MIME_BUF_MASK]
-static struct {
- unsigned char buf[MIME_BUF_SIZE];
- unsigned int top;
- unsigned int last; /* decoded */
- unsigned int input; /* undecoded */
-} mime_input_state;
-static nkf_char (*mime_iconv_back)(nkf_char c2,nkf_char c1,nkf_char c0) = NULL;
-
-#define MAXRECOVER 20
-
-static void
-mime_input_buf_unshift(nkf_char c)
-{
- mime_input_buf(--mime_input_state.top) = (unsigned char)c;
-}
-
-static nkf_char
-mime_ungetc(nkf_char c, ARG_UNUSED FILE *f)
-{
- mime_input_buf_unshift(c);
- return c;
-}
-
-static nkf_char
-mime_ungetc_buf(nkf_char c, FILE *f)
-{
- if (mimebuf_f)
- (*i_mungetc_buf)(c,f);
- else
- mime_input_buf(--mime_input_state.input) = (unsigned char)c;
- return c;
-}
-
-static nkf_char
-mime_getc_buf(FILE *f)
-{
- /* we don't keep eof of mime_input_buf, because it contains ?= as
- a terminator. It was checked in mime_integrity. */
- return ((mimebuf_f)?
- (*i_mgetc_buf)(f):mime_input_buf(mime_input_state.input++));
-}
-
-static void
-switch_mime_getc(void)
-{
- if (i_getc!=mime_getc) {
- i_mgetc = i_getc; i_getc = mime_getc;
- i_mungetc = i_ungetc; i_ungetc = mime_ungetc;
- if(mime_f==STRICT_MIME) {
- i_mgetc_buf = i_mgetc; i_mgetc = mime_getc_buf;
- i_mungetc_buf = i_mungetc; i_mungetc = mime_ungetc_buf;
- }
- }
-}
-
-static void
-unswitch_mime_getc(void)
-{
- if(mime_f==STRICT_MIME) {
- i_mgetc = i_mgetc_buf;
- i_mungetc = i_mungetc_buf;
- }
- i_getc = i_mgetc;
- i_ungetc = i_mungetc;
- if(mime_iconv_back)set_iconv(FALSE, mime_iconv_back);
- mime_iconv_back = NULL;
-}
-
-static nkf_char
-mime_integrity(FILE *f, const unsigned char *p)
-{
- nkf_char c,d;
- unsigned int q;
- /* In buffered mode, read until =? or NL or buffer full
- */
- mime_input_state.input = mime_input_state.top;
- mime_input_state.last = mime_input_state.top;
-
- while(*p) mime_input_buf(mime_input_state.input++) = *p++;
- d = 0;
- q = mime_input_state.input;
- while((c=(*i_getc)(f))!=EOF) {
- if (((mime_input_state.input-mime_input_state.top)&MIME_BUF_MASK)==0) {
- break; /* buffer full */
- }
- if (c=='=' && d=='?') {
- /* checked. skip header, start decode */
- mime_input_buf(mime_input_state.input++) = (unsigned char)c;
- /* mime_last_input = mime_input_state.input; */
- mime_input_state.input = q;
- switch_mime_getc();
- return 1;
- }
- if (!( (c=='+'||c=='/'|| c=='=' || c=='?' || is_alnum(c))))
- break;
- /* Should we check length mod 4? */
- mime_input_buf(mime_input_state.input++) = (unsigned char)c;
- d=c;
- }
- /* In case of Incomplete MIME, no MIME decode */
- mime_input_buf(mime_input_state.input++) = (unsigned char)c;
- mime_input_state.last = mime_input_state.input; /* point undecoded buffer */
- mime_decode_mode = 1; /* no decode on mime_input_buf last in mime_getc */
- switch_mime_getc(); /* anyway we need buffered getc */
- return 1;
-}
-
-static nkf_char
-mime_begin_strict(FILE *f)
-{
- nkf_char c1 = 0;
- int i,j,k;
- const unsigned char *p,*q;
- nkf_char r[MAXRECOVER]; /* recovery buffer, max mime pattern length */
-
- mime_decode_mode = FALSE;
- /* =? has been checked */
- j = 0;
- p = mime_pattern[j];
- r[0]='='; r[1]='?';
-
- for(i=2;p[i]>SP;i++) { /* start at =? */
- if (((r[i] = c1 = (*i_getc)(f))==EOF) || nkf_toupper(c1) != p[i]) {
- /* pattern fails, try next one */
- q = p;
- while (mime_pattern[++j]) {
- p = mime_pattern[j];
- for(k=2;k<i;k++) /* assume length(p) > i */
- if (p[k]!=q[k]) break;
- if (k==i && nkf_toupper(c1)==p[k]) break;
- }
- p = mime_pattern[j];
- if (p) continue; /* found next one, continue */
- /* all fails, output from recovery buffer */
- (*i_ungetc)(c1,f);
- for(j=0;j<i;j++) {
- (*oconv)(0,r[j]);
- }
- return c1;
- }
- }
- mime_decode_mode = p[i-2];
-
- mime_iconv_back = iconv;
- set_iconv(FALSE, mime_priority_func[j]);
- clr_code_score(find_inputcode_byfunc(mime_priority_func[j]), SCORE_iMIME);
-
- if (mime_decode_mode=='B') {
- mimebuf_f = unbuf_f;
- if (!unbuf_f) {
- /* do MIME integrity check */
- return mime_integrity(f,mime_pattern[j]);
- }
- }
- switch_mime_getc();
- mimebuf_f = TRUE;
- return c1;
-}
-
-static nkf_char
-mime_begin(FILE *f)
-{
- nkf_char c1 = 0;
- int i,k;
-
- /* In NONSTRICT mode, only =? is checked. In case of failure, we */
- /* re-read and convert again from mime_buffer. */
-
- /* =? has been checked */
- k = mime_input_state.last;
- mime_input_buf(mime_input_state.last++)='='; mime_input_buf(mime_input_state.last++)='?';
- for(i=2;i<MAXRECOVER;i++) { /* start at =? */
- /* We accept any character type even if it is breaked by new lines */
- c1 = (*i_getc)(f); mime_input_buf(mime_input_state.last++) = (unsigned char)c1;
- if (c1==LF||c1==SP||c1==CR||
- c1=='-'||c1=='_'||is_alnum(c1)) continue;
- if (c1=='=') {
- /* Failed. But this could be another MIME preemble */
- (*i_ungetc)(c1,f);
- mime_input_state.last--;
- break;
- }
- if (c1!='?') break;
- else {
- /* c1=='?' */
- c1 = (*i_getc)(f); mime_input_buf(mime_input_state.last++) = (unsigned char)c1;
- if (!(++i<MAXRECOVER) || c1==EOF) break;
- if (c1=='b'||c1=='B') {
- mime_decode_mode = 'B';
- } else if (c1=='q'||c1=='Q') {
- mime_decode_mode = 'Q';
- } else {
- break;
- }
- c1 = (*i_getc)(f); mime_input_buf(mime_input_state.last++) = (unsigned char)c1;
- if (!(++i<MAXRECOVER) || c1==EOF) break;
- if (c1!='?') {
- mime_decode_mode = FALSE;
- }
- break;
- }
- }
- switch_mime_getc();
- if (!mime_decode_mode) {
- /* false MIME premble, restart from mime_buffer */
- mime_decode_mode = 1; /* no decode, but read from the mime_buffer */
- /* Since we are in MIME mode until buffer becomes empty, */
- /* we never go into mime_begin again for a while. */
- return c1;
- }
- /* discard mime preemble, and goto MIME mode */
- mime_input_state.last = k;
- /* do no MIME integrity check */
- return c1; /* used only for checking EOF */
-}
-
-#ifdef CHECK_OPTION
-static void
-no_putc(ARG_UNUSED nkf_char c)
-{
- ;
-}
-
-static void
-debug(const char *str)
-{
- if (debug_f){
- fprintf(stderr, "%s\n", str ? str : "NULL");
- }
-}
-#endif
-
-static void
-set_input_codename(const char *codename)
-{
- if (!input_codename) {
- input_codename = codename;
- } else if (strcmp(codename, input_codename) != 0) {
- input_codename = "";
- }
-}
-
-static const char*
-get_guessed_code(void)
-{
- if (input_codename && !*input_codename) {
- input_codename = "BINARY";
- } else {
- struct input_code *p = find_inputcode_byfunc(iconv);
- if (!input_codename) {
- input_codename = "ASCII";
- } else if (strcmp(input_codename, "Shift_JIS") == 0) {
- if (p->score & (SCORE_DEPEND|SCORE_CP932))
- input_codename = "CP932";
- } else if (strcmp(input_codename, "EUC-JP") == 0) {
- if (p->score & SCORE_X0213)
- input_codename = "EUC-JIS-2004";
- else if (p->score & (SCORE_X0212))
- input_codename = "EUCJP-MS";
- else if (p->score & (SCORE_DEPEND|SCORE_CP932))
- input_codename = "CP51932";
- } else if (strcmp(input_codename, "ISO-2022-JP") == 0) {
- if (p->score & (SCORE_KANA))
- input_codename = "CP50221";
- else if (p->score & (SCORE_DEPEND|SCORE_CP932))
- input_codename = "CP50220";
- }
- }
- return input_codename;
-}
-
-#if !defined(PERL_XS) && !defined(WIN32DLL)
-static void
-print_guessed_code(char *filename)
-{
- if (filename != NULL) printf("%s: ", filename);
- if (input_codename && !*input_codename) {
- printf("BINARY\n");
- } else {
- input_codename = get_guessed_code();
- if (guess_f == 1) {
- printf("%s\n", input_codename);
- } else {
- printf("%s%s%s%s\n",
- input_codename,
- iconv != w_iconv16 && iconv != w_iconv32 ? "" :
- input_endian == ENDIAN_LITTLE ? " LE" :
- input_endian == ENDIAN_BIG ? " BE" :
- "[BUG]",
- input_bom_f ? " (BOM)" : "",
- input_eol == CR ? " (CR)" :
- input_eol == LF ? " (LF)" :
- input_eol == CRLF ? " (CRLF)" :
- input_eol == EOF ? " (MIXED NL)" :
- "");
- }
- }
-}
-#endif /*WIN32DLL*/
-
-#ifdef INPUT_OPTION
-
-static nkf_char
-hex_getc(nkf_char ch, FILE *f, nkf_char (*g)(FILE *f), nkf_char (*u)(nkf_char c, FILE *f))
-{
- nkf_char c1, c2, c3;
- c1 = (*g)(f);
- if (c1 != ch){
- return c1;
- }
- c2 = (*g)(f);
- if (!nkf_isxdigit(c2)){
- (*u)(c2, f);
- return c1;
- }
- c3 = (*g)(f);
- if (!nkf_isxdigit(c3)){
- (*u)(c2, f);
- (*u)(c3, f);
- return c1;
- }
- return (hex2bin(c2) << 4) | hex2bin(c3);
-}
-
-static nkf_char
-cap_getc(FILE *f)
-{
- return hex_getc(':', f, i_cgetc, i_cungetc);
-}
-
-static nkf_char
-cap_ungetc(nkf_char c, FILE *f)
-{
- return (*i_cungetc)(c, f);
-}
-
-static nkf_char
-url_getc(FILE *f)
-{
- return hex_getc('%', f, i_ugetc, i_uungetc);
-}
-
-static nkf_char
-url_ungetc(nkf_char c, FILE *f)
-{
- return (*i_uungetc)(c, f);
-}
-#endif
-
-#ifdef NUMCHAR_OPTION
-static nkf_char
-numchar_getc(FILE *f)
-{
- nkf_char (*g)(FILE *) = i_ngetc;
- nkf_char (*u)(nkf_char c ,FILE *f) = i_nungetc;
- int i = 0, j;
- nkf_char buf[12];
- nkf_char c = -1;
-
- buf[i] = (*g)(f);
- if (buf[i] == '&'){
- buf[++i] = (*g)(f);
- if (buf[i] == '#'){
- c = 0;
- buf[++i] = (*g)(f);
- if (buf[i] == 'x' || buf[i] == 'X'){
- for (j = 0; j < 7; j++){
- buf[++i] = (*g)(f);
- if (!nkf_isxdigit(buf[i])){
- if (buf[i] != ';'){
- c = -1;
- }
- break;
- }
- c <<= 4;
- c |= hex2bin(buf[i]);
- }
- }else{
- for (j = 0; j < 8; j++){
- if (j){
- buf[++i] = (*g)(f);
- }
- if (!nkf_isdigit(buf[i])){
- if (buf[i] != ';'){
- c = -1;
- }
- break;
- }
- c *= 10;
- c += hex2bin(buf[i]);
- }
- }
- }
- }
- if (c != -1){
- return nkf_char_unicode_new(c);
- }
- while (i > 0){
- (*u)(buf[i], f);
- --i;
- }
- return buf[0];
-}
-
-static nkf_char
-numchar_ungetc(nkf_char c, FILE *f)
-{
- return (*i_nungetc)(c, f);
-}
-#endif
-
-#ifdef UNICODE_NORMALIZATION
-
-static nkf_char
-nfc_getc(FILE *f)
-{
- nkf_char (*g)(FILE *f) = i_nfc_getc;
- nkf_char (*u)(nkf_char c ,FILE *f) = i_nfc_ungetc;
- nkf_buf_t *buf = nkf_state->nfc_buf;
- const unsigned char *array;
- int lower=0, upper=NORMALIZATION_TABLE_LENGTH-1;
- nkf_char c = (*g)(f);
-
- if (c == EOF || c > 0xFF || (c & 0xc0) == 0x80) return c;
-
- nkf_buf_push(buf, c);
- do {
- while (lower <= upper) {
- int mid = (lower+upper) / 2;
- int len;
- array = normalization_table[mid].nfd;
- for (len=0; len < NORMALIZATION_TABLE_NFD_LENGTH && array[len]; len++) {
- if (len >= nkf_buf_length(buf)) {
- c = (*g)(f);
- if (c == EOF) {
- len = 0;
- lower = 1, upper = 0;
- break;
- }
- nkf_buf_push(buf, c);
- }
- if (array[len] != nkf_buf_at(buf, len)) {
- if (array[len] < nkf_buf_at(buf, len)) lower = mid + 1;
- else upper = mid - 1;
- len = 0;
- break;
- }
- }
- if (len > 0) {
- int i;
- array = normalization_table[mid].nfc;
- nkf_buf_clear(buf);
- for (i=0; i < NORMALIZATION_TABLE_NFC_LENGTH && array[i]; i++)
- nkf_buf_push(buf, array[i]);
- break;
- }
- }
- } while (lower <= upper);
-
- while (nkf_buf_length(buf) > 1) (*u)(nkf_buf_pop(buf), f);
- c = nkf_buf_pop(buf);
-
- return c;
-}
-
-static nkf_char
-nfc_ungetc(nkf_char c, FILE *f)
-{
- return (*i_nfc_ungetc)(c, f);
-}
-#endif /* UNICODE_NORMALIZATION */
-
-
-static nkf_char
-base64decode(nkf_char c)
-{
- int i;
- if (c > '@') {
- if (c < '[') {
- i = c - 'A'; /* A..Z 0-25 */
- } else if (c == '_') {
- i = '?' /* 63 */ ; /* _ 63 */
- } else {
- i = c - 'G' /* - 'a' + 26 */ ; /* a..z 26-51 */
- }
- } else if (c > '/') {
- i = c - '0' + '4' /* - '0' + 52 */ ; /* 0..9 52-61 */
- } else if (c == '+' || c == '-') {
- i = '>' /* 62 */ ; /* + and - 62 */
- } else {
- i = '?' /* 63 */ ; /* / 63 */
- }
- return (i);
-}
-
-static nkf_char
-mime_getc(FILE *f)
-{
- nkf_char c1, c2, c3, c4, cc;
- nkf_char t1, t2, t3, t4, mode, exit_mode;
- nkf_char lwsp_count;
- char *lwsp_buf;
- char *lwsp_buf_new;
- nkf_char lwsp_size = 128;
-
- if (mime_input_state.top != mime_input_state.last) { /* Something is in FIFO */
- return mime_input_buf(mime_input_state.top++);
- }
- if (mime_decode_mode==1 ||mime_decode_mode==FALSE) {
- mime_decode_mode=FALSE;
- unswitch_mime_getc();
- return (*i_getc)(f);
- }
-
- if (mimebuf_f == FIXED_MIME)
- exit_mode = mime_decode_mode;
- else
- exit_mode = FALSE;
- if (mime_decode_mode == 'Q') {
- if ((c1 = (*i_mgetc)(f)) == EOF) return (EOF);
- restart_mime_q:
- if (c1=='_' && mimebuf_f != FIXED_MIME) return SP;
- if (c1<=SP || DEL<=c1) {
- mime_decode_mode = exit_mode; /* prepare for quit */
- return c1;
- }
- if (c1!='=' && (c1!='?' || mimebuf_f == FIXED_MIME)) {
- return c1;
- }
-
- mime_decode_mode = exit_mode; /* prepare for quit */
- if ((c2 = (*i_mgetc)(f)) == EOF) return (EOF);
- if (c1=='?'&&c2=='=' && mimebuf_f != FIXED_MIME) {
- /* end Q encoding */
- input_mode = exit_mode;
- lwsp_count = 0;
- lwsp_buf = nkf_xmalloc((lwsp_size+5)*sizeof(char));
- while ((c1=(*i_getc)(f))!=EOF) {
- switch (c1) {
- case LF:
- case CR:
- if (c1==LF) {
- if ((c1=(*i_getc)(f))!=EOF && nkf_isblank(c1)) {
- i_ungetc(SP,f);
- continue;
- } else {
- i_ungetc(c1,f);
- }
- c1 = LF;
- } else {
- if ((c1=(*i_getc)(f))!=EOF && c1 == LF) {
- if ((c1=(*i_getc)(f))!=EOF && nkf_isblank(c1)) {
- i_ungetc(SP,f);
- continue;
- } else {
- i_ungetc(c1,f);
- }
- i_ungetc(LF,f);
- } else {
- i_ungetc(c1,f);
- }
- c1 = CR;
- }
- break;
- case SP:
- case TAB:
- lwsp_buf[lwsp_count] = (unsigned char)c1;
- if (lwsp_count++>lwsp_size){
- lwsp_size <<= 1;
- lwsp_buf_new = nkf_xrealloc(lwsp_buf, (lwsp_size+5)*sizeof(char));
- lwsp_buf = lwsp_buf_new;
- }
- continue;
- }
- break;
- }
- if (lwsp_count > 0 && (c1 != '=' || (lwsp_buf[lwsp_count-1] != SP && lwsp_buf[lwsp_count-1] != TAB))) {
- i_ungetc(c1,f);
- for(lwsp_count--;lwsp_count>0;lwsp_count--)
- i_ungetc(lwsp_buf[lwsp_count],f);
- c1 = lwsp_buf[0];
- }
- nkf_xfree(lwsp_buf);
- return c1;
- }
- if (c1=='='&&c2<SP) { /* this is soft wrap */
- while((c1 = (*i_mgetc)(f)) <=SP) {
- if (c1 == EOF) return (EOF);
- }
- mime_decode_mode = 'Q'; /* still in MIME */
- goto restart_mime_q;
- }
- if (c1=='?') {
- mime_decode_mode = 'Q'; /* still in MIME */
- (*i_mungetc)(c2,f);
- return c1;
- }
- if ((c3 = (*i_mgetc)(f)) == EOF) return (EOF);
- if (c2<=SP) return c2;
- mime_decode_mode = 'Q'; /* still in MIME */
- return ((hex2bin(c2)<<4) + hex2bin(c3));
- }
-
- if (mime_decode_mode != 'B') {
- mime_decode_mode = FALSE;
- return (*i_mgetc)(f);
- }
-
-
- /* Base64 encoding */
- /*
- MIME allows line break in the middle of
- Base64, but we are very pessimistic in decoding
- in unbuf mode because MIME encoded code may broken by
- less or editor's control sequence (such as ESC-[-K in unbuffered
- mode. ignore incomplete MIME.
- */
- mode = mime_decode_mode;
- mime_decode_mode = exit_mode; /* prepare for quit */
-
- while ((c1 = (*i_mgetc)(f))<=SP) {
- if (c1==EOF)
- return (EOF);
- }
- mime_c2_retry:
- if ((c2 = (*i_mgetc)(f))<=SP) {
- if (c2==EOF)
- return (EOF);
- if (mime_f != STRICT_MIME) goto mime_c2_retry;
- if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;
- return c2;
- }
- if ((c1 == '?') && (c2 == '=')) {
- input_mode = ASCII;
- lwsp_count = 0;
- lwsp_buf = nkf_xmalloc((lwsp_size+5)*sizeof(char));
- while ((c1=(*i_getc)(f))!=EOF) {
- switch (c1) {
- case LF:
- case CR:
- if (c1==LF) {
- if ((c1=(*i_getc)(f))!=EOF && nkf_isblank(c1)) {
- i_ungetc(SP,f);
- continue;
- } else {
- i_ungetc(c1,f);
- }
- c1 = LF;
- } else {
- if ((c1=(*i_getc)(f))!=EOF) {
- if (c1==SP) {
- i_ungetc(SP,f);
- continue;
- } else if ((c1=(*i_getc)(f))!=EOF && nkf_isblank(c1)) {
- i_ungetc(SP,f);
- continue;
- } else {
- i_ungetc(c1,f);
- }
- i_ungetc(LF,f);
- } else {
- i_ungetc(c1,f);
- }
- c1 = CR;
- }
- break;
- case SP:
- case TAB:
- lwsp_buf[lwsp_count] = (unsigned char)c1;
- if (lwsp_count++>lwsp_size){
- lwsp_size <<= 1;
- lwsp_buf_new = nkf_xrealloc(lwsp_buf, (lwsp_size+5)*sizeof(char));
- lwsp_buf = lwsp_buf_new;
- }
- continue;
- }
- break;
- }
- if (lwsp_count > 0 && (c1 != '=' || (lwsp_buf[lwsp_count-1] != SP && lwsp_buf[lwsp_count-1] != TAB))) {
- i_ungetc(c1,f);
- for(lwsp_count--;lwsp_count>0;lwsp_count--)
- i_ungetc(lwsp_buf[lwsp_count],f);
- c1 = lwsp_buf[0];
- }
- nkf_xfree(lwsp_buf);
- return c1;
- }
- mime_c3_retry:
- if ((c3 = (*i_mgetc)(f))<=SP) {
- if (c3==EOF)
- return (EOF);
- if (mime_f != STRICT_MIME) goto mime_c3_retry;
- if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;
- return c3;
- }
- mime_c4_retry:
- if ((c4 = (*i_mgetc)(f))<=SP) {
- if (c4==EOF)
- return (EOF);
- if (mime_f != STRICT_MIME) goto mime_c4_retry;
- if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;
- return c4;
- }
-
- mime_decode_mode = mode; /* still in MIME sigh... */
-
- /* BASE 64 decoding */
-
- t1 = 0x3f & base64decode(c1);
- t2 = 0x3f & base64decode(c2);
- t3 = 0x3f & base64decode(c3);
- t4 = 0x3f & base64decode(c4);
- cc = ((t1 << 2) & 0x0fc) | ((t2 >> 4) & 0x03);
- if (c2 != '=') {
- mime_input_buf(mime_input_state.last++) = (unsigned char)cc;
- cc = ((t2 << 4) & 0x0f0) | ((t3 >> 2) & 0x0f);
- if (c3 != '=') {
- mime_input_buf(mime_input_state.last++) = (unsigned char)cc;
- cc = ((t3 << 6) & 0x0c0) | (t4 & 0x3f);
- if (c4 != '=')
- mime_input_buf(mime_input_state.last++) = (unsigned char)cc;
- }
- } else {
- return c1;
- }
- return mime_input_buf(mime_input_state.top++);
-}
-
-static const char basis_64[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-#define MIMEOUT_BUF_LENGTH 74
-static struct {
- unsigned char buf[MIMEOUT_BUF_LENGTH+1];
- int count;
-} mimeout_state;
-
-/*nkf_char mime_lastchar2, mime_lastchar1;*/
-
-static void
-open_mime(nkf_char mode)
-{
- const unsigned char *p;
- int i;
- int j;
- p = mime_pattern[0];
- for(i=0;mime_pattern[i];i++) {
- if (mode == mime_encode[i]) {
- p = mime_pattern[i];
- break;
- }
- }
- mimeout_mode = mime_encode_method[i];
- i = 0;
- if (base64_count>45) {
- if (mimeout_state.count>0 && nkf_isblank(mimeout_state.buf[i])){
- (*o_mputc)(mimeout_state.buf[i]);
- i++;
- }
- put_newline(o_mputc);
- (*o_mputc)(SP);
- base64_count = 1;
- if (mimeout_state.count>0 && nkf_isspace(mimeout_state.buf[i])) {
- i++;
- }
- }
- for (;i<mimeout_state.count;i++) {
- if (nkf_isspace(mimeout_state.buf[i])) {
- (*o_mputc)(mimeout_state.buf[i]);
- base64_count ++;
- } else {
- break;
- }
- }
- while(*p) {
- (*o_mputc)(*p++);
- base64_count ++;
- }
- j = mimeout_state.count;
- mimeout_state.count = 0;
- for (;i<j;i++) {
- mime_putc(mimeout_state.buf[i]);
- }
-}
-
-static void
-mime_prechar(nkf_char c2, nkf_char c1)
-{
- if (mimeout_mode > 0){
- if (c2 == EOF){
- if (base64_count + mimeout_state.count/3*4> 73){
- (*o_base64conv)(EOF,0);
- oconv_newline(o_base64conv);
- (*o_base64conv)(0,SP);
- base64_count = 1;
- }
- } else {
- if ((c2 != 0 || c1 > DEL) && base64_count + mimeout_state.count/3*4> 66) {
- (*o_base64conv)(EOF,0);
- oconv_newline(o_base64conv);
- (*o_base64conv)(0,SP);
- base64_count = 1;
- mimeout_mode = -1;
- }
- }
- } else if (c2) {
- if (c2 != EOF && base64_count + mimeout_state.count/3*4> 60) {
- mimeout_mode = (output_mode==ASCII ||output_mode == ISO_8859_1) ? 'Q' : 'B';
- open_mime(output_mode);
- (*o_base64conv)(EOF,0);
- oconv_newline(o_base64conv);
- (*o_base64conv)(0,SP);
- base64_count = 1;
- mimeout_mode = -1;
- }
- }
-}
-
-static void
-close_mime(void)
-{
- (*o_mputc)('?');
- (*o_mputc)('=');
- base64_count += 2;
- mimeout_mode = 0;
-}
-
-static void
-eof_mime(void)
-{
- switch(mimeout_mode) {
- case 'Q':
- case 'B':
- break;
- case 2:
- (*o_mputc)(basis_64[((nkf_state->mimeout_state & 0x3)<< 4)]);
- (*o_mputc)('=');
- (*o_mputc)('=');
- base64_count += 3;
- break;
- case 1:
- (*o_mputc)(basis_64[((nkf_state->mimeout_state & 0xF) << 2)]);
- (*o_mputc)('=');
- base64_count += 2;
- break;
- }
- if (mimeout_mode > 0) {
- if (mimeout_f!=FIXED_MIME) {
- close_mime();
- } else if (mimeout_mode != 'Q')
- mimeout_mode = 'B';
- }
-}
-
-static void
-mimeout_addchar(nkf_char c)
-{
- switch(mimeout_mode) {
- case 'Q':
- if (c==CR||c==LF) {
- (*o_mputc)(c);
- base64_count = 0;
- } else if(!nkf_isalnum(c)) {
- (*o_mputc)('=');
- (*o_mputc)(bin2hex(((c>>4)&0xf)));
- (*o_mputc)(bin2hex((c&0xf)));
- base64_count += 3;
- } else {
- (*o_mputc)(c);
- base64_count++;
- }
- break;
- case 'B':
- nkf_state->mimeout_state=c;
- (*o_mputc)(basis_64[c>>2]);
- mimeout_mode=2;
- base64_count ++;
- break;
- case 2:
- (*o_mputc)(basis_64[((nkf_state->mimeout_state & 0x3)<< 4) | ((c & 0xF0) >> 4)]);
- nkf_state->mimeout_state=c;
- mimeout_mode=1;
- base64_count ++;
- break;
- case 1:
- (*o_mputc)(basis_64[((nkf_state->mimeout_state & 0xF) << 2) | ((c & 0xC0) >>6)]);
- (*o_mputc)(basis_64[c & 0x3F]);
- mimeout_mode='B';
- base64_count += 2;
- break;
- default:
- (*o_mputc)(c);
- base64_count++;
- break;
- }
-}
-
-static void
-mime_putc(nkf_char c)
-{
- int i, j;
- nkf_char lastchar;
-
- if (mimeout_f == FIXED_MIME){
- if (mimeout_mode == 'Q'){
- if (base64_count > 71){
- if (c!=CR && c!=LF) {
- (*o_mputc)('=');
- put_newline(o_mputc);
- }
- base64_count = 0;
- }
- }else{
- if (base64_count > 71){
- eof_mime();
- put_newline(o_mputc);
- base64_count = 0;
- }
- if (c == EOF) { /* c==EOF */
- eof_mime();
- }
- }
- if (c != EOF) { /* c==EOF */
- mimeout_addchar(c);
- }
- return;
- }
-
- /* mimeout_f != FIXED_MIME */
-
- if (c == EOF) { /* c==EOF */
- if (mimeout_mode == -1 && mimeout_state.count > 1) open_mime(output_mode);
- j = mimeout_state.count;
- mimeout_state.count = 0;
- i = 0;
- if (mimeout_mode > 0) {
- if (!nkf_isblank(mimeout_state.buf[j-1])) {
- for (;i<j;i++) {
- if (nkf_isspace(mimeout_state.buf[i]) && base64_count < 71){
- break;
- }
- mimeout_addchar(mimeout_state.buf[i]);
- }
- eof_mime();
- for (;i<j;i++) {
- mimeout_addchar(mimeout_state.buf[i]);
- }
- } else {
- for (;i<j;i++) {
- mimeout_addchar(mimeout_state.buf[i]);
- }
- eof_mime();
- }
- } else {
- for (;i<j;i++) {
- mimeout_addchar(mimeout_state.buf[i]);
- }
- }
- return;
- }
-
- if (mimeout_state.count > 0){
- lastchar = mimeout_state.buf[mimeout_state.count - 1];
- }else{
- lastchar = -1;
- }
-
- if (mimeout_mode=='Q') {
- if (c <= DEL && (output_mode==ASCII ||output_mode == ISO_8859_1)) {
- if (c == CR || c == LF) {
- close_mime();
- (*o_mputc)(c);
- base64_count = 0;
- return;
- } else if (c <= SP) {
- close_mime();
- if (base64_count > 70) {
- put_newline(o_mputc);
- base64_count = 0;
- }
- if (!nkf_isblank(c)) {
- (*o_mputc)(SP);
- base64_count++;
- }
- } else {
- if (base64_count > 70) {
- close_mime();
- put_newline(o_mputc);
- (*o_mputc)(SP);
- base64_count = 1;
- open_mime(output_mode);
- }
- if (!nkf_noescape_mime(c)) {
- mimeout_addchar(c);
- return;
- }
- }
- if (c != 0x1B) {
- (*o_mputc)(c);
- base64_count++;
- return;
- }
- }
- }
-
- if (mimeout_mode <= 0) {
- if (c <= DEL && (output_mode==ASCII || output_mode == ISO_8859_1 ||
- output_mode == UTF_8)) {
- if (nkf_isspace(c)) {
- int flag = 0;
- if (mimeout_mode == -1) {
- flag = 1;
- }
- if (c==CR || c==LF) {
- if (flag) {
- open_mime(output_mode);
- output_mode = 0;
- } else {
- base64_count = 0;
- }
- }
- for (i=0;i<mimeout_state.count;i++) {
- (*o_mputc)(mimeout_state.buf[i]);
- if (mimeout_state.buf[i] == CR || mimeout_state.buf[i] == LF){
- base64_count = 0;
- }else{
- base64_count++;
- }
- }
- if (flag) {
- eof_mime();
- base64_count = 0;
- mimeout_mode = 0;
- }
- mimeout_state.buf[0] = (char)c;
- mimeout_state.count = 1;
- }else{
- if (base64_count > 1
- && base64_count + mimeout_state.count > 76
- && mimeout_state.buf[0] != CR && mimeout_state.buf[0] != LF){
- static const char *str = "boundary=\"";
- static int len = 10;
- i = 0;
-
- for (; i < mimeout_state.count - len; ++i) {
- if (!strncmp((char *)(mimeout_state.buf+i), str, len)) {
- i += len - 2;
- break;
- }
- }
-
- if (i == 0 || i == mimeout_state.count - len) {
- put_newline(o_mputc);
- base64_count = 0;
- if (!nkf_isspace(mimeout_state.buf[0])){
- (*o_mputc)(SP);
- base64_count++;
- }
- }
- else {
- int j;
- for (j = 0; j <= i; ++j) {
- (*o_mputc)(mimeout_state.buf[j]);
- }
- put_newline(o_mputc);
- base64_count = 1;
- for (; j <= mimeout_state.count; ++j) {
- mimeout_state.buf[j - i] = mimeout_state.buf[j];
- }
- mimeout_state.count -= i;
- }
- }
- mimeout_state.buf[mimeout_state.count++] = (char)c;
- if (mimeout_state.count>MIMEOUT_BUF_LENGTH) {
- open_mime(output_mode);
- }
- }
- return;
- }else{
- if (lastchar==CR || lastchar == LF){
- for (i=0;i<mimeout_state.count;i++) {
- (*o_mputc)(mimeout_state.buf[i]);
- }
- base64_count = 0;
- mimeout_state.count = 0;
- }
- if (lastchar==SP) {
- for (i=0;i<mimeout_state.count-1;i++) {
- (*o_mputc)(mimeout_state.buf[i]);
- base64_count++;
- }
- mimeout_state.buf[0] = SP;
- mimeout_state.count = 1;
- }
- open_mime(output_mode);
- }
- }else{
- /* mimeout_mode == 'B', 1, 2 */
- if (c <= DEL && (output_mode==ASCII || output_mode == ISO_8859_1 ||
- output_mode == UTF_8)) {
- if (lastchar == CR || lastchar == LF){
- if (nkf_isblank(c)) {
- for (i=0;i<mimeout_state.count;i++) {
- mimeout_addchar(mimeout_state.buf[i]);
- }
- mimeout_state.count = 0;
- } else {
- eof_mime();
- for (i=0;i<mimeout_state.count;i++) {
- (*o_mputc)(mimeout_state.buf[i]);
- }
- base64_count = 0;
- mimeout_state.count = 0;
- }
- mimeout_state.buf[mimeout_state.count++] = (char)c;
- return;
- }
- if (nkf_isspace(c)) {
- for (i=0;i<mimeout_state.count;i++) {
- if (SP<mimeout_state.buf[i] && mimeout_state.buf[i]<DEL) {
- eof_mime();
- for (i=0;i<mimeout_state.count;i++) {
- (*o_mputc)(mimeout_state.buf[i]);
- base64_count++;
- }
- mimeout_state.count = 0;
- }
- }
- mimeout_state.buf[mimeout_state.count++] = (char)c;
- if (mimeout_state.count>MIMEOUT_BUF_LENGTH) {
- eof_mime();
- for (j=0;j<mimeout_state.count;j++) {
- (*o_mputc)(mimeout_state.buf[j]);
- base64_count++;
- }
- mimeout_state.count = 0;
- }
- return;
- }
- if (mimeout_state.count>0 && SP<c && c!='=') {
- mimeout_state.buf[mimeout_state.count++] = (char)c;
- if (mimeout_state.count>MIMEOUT_BUF_LENGTH) {
- j = mimeout_state.count;
- mimeout_state.count = 0;
- for (i=0;i<j;i++) {
- mimeout_addchar(mimeout_state.buf[i]);
- }
- }
- return;
- }
- }
- }
- if (mimeout_state.count>0) {
- j = mimeout_state.count;
- mimeout_state.count = 0;
- for (i=0;i<j;i++) {
- if (mimeout_state.buf[i]==CR || mimeout_state.buf[i]==LF)
- break;
- mimeout_addchar(mimeout_state.buf[i]);
- }
- if (i<j) {
- eof_mime();
- base64_count=0;
- for (;i<j;i++) {
- (*o_mputc)(mimeout_state.buf[i]);
- }
- open_mime(output_mode);
- }
- }
- mimeout_addchar(c);
-}
-
-static void
-base64_conv(nkf_char c2, nkf_char c1)
-{
- mime_prechar(c2, c1);
- (*o_base64conv)(c2,c1);
-}
-
-#ifdef HAVE_ICONV_H
-typedef struct nkf_iconv_t {
- iconv_t cd;
- char *input_buffer;
- size_t input_buffer_size;
- char *output_buffer;
- size_t output_buffer_size;
-};
-
-static nkf_iconv_t
-nkf_iconv_new(char *tocode, char *fromcode)
-{
- nkf_iconv_t converter;
-
- converter->input_buffer_size = IOBUF_SIZE;
- converter->input_buffer = nkf_xmalloc(converter->input_buffer_size);
- converter->output_buffer_size = IOBUF_SIZE * 2;
- converter->output_buffer = nkf_xmalloc(converter->output_buffer_size);
- converter->cd = iconv_open(tocode, fromcode);
- if (converter->cd == (iconv_t)-1)
- {
- switch (errno) {
- case EINVAL:
- perror(fprintf("iconv doesn't support %s to %s conversion.", fromcode, tocode));
- return -1;
- default:
- perror("can't iconv_open");
- }
- }
-}
-
-static size_t
-nkf_iconv_convert(nkf_iconv_t *converter, FILE *input)
-{
- size_t invalid = (size_t)0;
- char *input_buffer = converter->input_buffer;
- size_t input_length = (size_t)0;
- char *output_buffer = converter->output_buffer;
- size_t output_length = converter->output_buffer_size;
- int c;
-
- do {
- if (c != EOF) {
- while ((c = (*i_getc)(f)) != EOF) {
- input_buffer[input_length++] = c;
- if (input_length < converter->input_buffer_size) break;
- }
- }
-
- size_t ret = iconv(converter->cd, &input_buffer, &input_length, &output_buffer, &output_length);
- while (output_length-- > 0) {
- (*o_putc)(output_buffer[converter->output_buffer_size-output_length]);
- }
- if (ret == (size_t) - 1) {
- switch (errno) {
- case EINVAL:
- if (input_buffer != converter->input_buffer)
- memmove(converter->input_buffer, input_buffer, input_length);
- break;
- case E2BIG:
- converter->output_buffer_size *= 2;
- output_buffer = realloc(converter->outbuf, converter->output_buffer_size);
- if (output_buffer == NULL) {
- perror("can't realloc");
- return -1;
- }
- converter->output_buffer = output_buffer;
- break;
- default:
- perror("can't iconv");
- return -1;
- }
- } else {
- invalid += ret;
- }
- } while (1);
-
- return invalid;
-}
-
-
-static void
-nkf_iconv_close(nkf_iconv_t *convert)
-{
- nkf_xfree(converter->inbuf);
- nkf_xfree(converter->outbuf);
- iconv_close(converter->cd);
-}
-#endif
-
-
-static void
-reinit(void)
-{
- {
- struct input_code *p = input_code_list;
- while (p->name){
- status_reinit(p++);
- }
- }
- unbuf_f = FALSE;
- estab_f = FALSE;
- nop_f = FALSE;
- binmode_f = TRUE;
- rot_f = FALSE;
- hira_f = FALSE;
- alpha_f = FALSE;
- mime_f = MIME_DECODE_DEFAULT;
- mime_decode_f = FALSE;
- mimebuf_f = FALSE;
- broken_f = FALSE;
- iso8859_f = FALSE;
- mimeout_f = FALSE;
- x0201_f = NKF_UNSPECIFIED;
- iso2022jp_f = FALSE;
-#if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
- ms_ucs_map_f = UCS_MAP_ASCII;
-#endif
-#ifdef UTF8_INPUT_ENABLE
- no_cp932ext_f = FALSE;
- no_best_fit_chars_f = FALSE;
- encode_fallback = NULL;
- unicode_subchar = '?';
- input_endian = ENDIAN_BIG;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- output_bom_f = FALSE;
- output_endian = ENDIAN_BIG;
-#endif
-#ifdef UNICODE_NORMALIZATION
- nfc_f = FALSE;
-#endif
-#ifdef INPUT_OPTION
- cap_f = FALSE;
- url_f = FALSE;
- numchar_f = FALSE;
-#endif
-#ifdef CHECK_OPTION
- noout_f = FALSE;
- debug_f = FALSE;
-#endif
- guess_f = 0;
-#ifdef EXEC_IO
- exec_f = 0;
-#endif
-#ifdef SHIFTJIS_CP932
- cp51932_f = TRUE;
- cp932inv_f = TRUE;
-#endif
-#ifdef X0212_ENABLE
- x0212_f = FALSE;
- x0213_f = FALSE;
-#endif
- {
- int i;
- for (i = 0; i < 256; i++){
- prefix_table[i] = 0;
- }
- }
- hold_count = 0;
- mimeout_state.count = 0;
- mimeout_mode = 0;
- base64_count = 0;
- f_line = 0;
- f_prev = 0;
- fold_preserve_f = FALSE;
- fold_f = FALSE;
- fold_len = 0;
- kanji_intro = DEFAULT_J;
- ascii_intro = DEFAULT_R;
- fold_margin = FOLD_MARGIN;
- o_zconv = no_connection;
- o_fconv = no_connection;
- o_eol_conv = no_connection;
- o_rot_conv = no_connection;
- o_hira_conv = no_connection;
- o_base64conv = no_connection;
- o_iso2022jp_check_conv = no_connection;
- o_putc = std_putc;
- i_getc = std_getc;
- i_ungetc = std_ungetc;
- i_bgetc = std_getc;
- i_bungetc = std_ungetc;
- o_mputc = std_putc;
- i_mgetc = std_getc;
- i_mungetc = std_ungetc;
- i_mgetc_buf = std_getc;
- i_mungetc_buf = std_ungetc;
- output_mode = ASCII;
- input_mode = ASCII;
- mime_decode_mode = FALSE;
- file_out_f = FALSE;
- eolmode_f = 0;
- input_eol = 0;
- prev_cr = 0;
- option_mode = 0;
- z_prev2=0,z_prev1=0;
-#ifdef CHECK_OPTION
- iconv_for_check = 0;
-#endif
- input_codename = NULL;
- input_encoding = NULL;
- output_encoding = NULL;
- nkf_state_init();
-#ifdef WIN32DLL
- reinitdll();
-#endif /*WIN32DLL*/
-}
-
-static int
-module_connection(void)
-{
- if (input_encoding) set_input_encoding(input_encoding);
- if (!output_encoding) {
- output_encoding = nkf_default_encoding();
- }
- if (!output_encoding) {
- if (noout_f || guess_f) output_encoding = nkf_enc_from_index(ISO_2022_JP);
- else return -1;
- }
- set_output_encoding(output_encoding);
- oconv = nkf_enc_to_oconv(output_encoding);
- o_putc = std_putc;
- if (nkf_enc_unicode_p(output_encoding))
- output_mode = UTF_8;
-
- if (x0201_f == NKF_UNSPECIFIED) {
- x0201_f = X0201_DEFAULT;
- }
-
- /* replace continuation module, from output side */
-
- /* output redirection */
-#ifdef CHECK_OPTION
- if (noout_f || guess_f){
- o_putc = no_putc;
- }
-#endif
- if (mimeout_f) {
- o_mputc = o_putc;
- o_putc = mime_putc;
- if (mimeout_f == TRUE) {
- o_base64conv = oconv; oconv = base64_conv;
- }
- /* base64_count = 0; */
- }
-
- if (eolmode_f || guess_f) {
- o_eol_conv = oconv; oconv = eol_conv;
- }
- if (rot_f) {
- o_rot_conv = oconv; oconv = rot_conv;
- }
- if (iso2022jp_f) {
- o_iso2022jp_check_conv = oconv; oconv = iso2022jp_check_conv;
- }
- if (hira_f) {
- o_hira_conv = oconv; oconv = hira_conv;
- }
- if (fold_f) {
- o_fconv = oconv; oconv = fold_conv;
- f_line = 0;
- }
- if (alpha_f || x0201_f) {
- o_zconv = oconv; oconv = z_conv;
- }
-
- i_getc = std_getc;
- i_ungetc = std_ungetc;
- /* input redirection */
-#ifdef INPUT_OPTION
- if (cap_f){
- i_cgetc = i_getc; i_getc = cap_getc;
- i_cungetc = i_ungetc; i_ungetc= cap_ungetc;
- }
- if (url_f){
- i_ugetc = i_getc; i_getc = url_getc;
- i_uungetc = i_ungetc; i_ungetc= url_ungetc;
- }
-#endif
-#ifdef NUMCHAR_OPTION
- if (numchar_f){
- i_ngetc = i_getc; i_getc = numchar_getc;
- i_nungetc = i_ungetc; i_ungetc= numchar_ungetc;
- }
-#endif
-#ifdef UNICODE_NORMALIZATION
- if (nfc_f){
- i_nfc_getc = i_getc; i_getc = nfc_getc;
- i_nfc_ungetc = i_ungetc; i_ungetc= nfc_ungetc;
- }
-#endif
- if (mime_f && mimebuf_f==FIXED_MIME) {
- i_mgetc = i_getc; i_getc = mime_getc;
- i_mungetc = i_ungetc; i_ungetc = mime_ungetc;
- }
- if (broken_f & 1) {
- i_bgetc = i_getc; i_getc = broken_getc;
- i_bungetc = i_ungetc; i_ungetc = broken_ungetc;
- }
- if (input_encoding) {
- set_iconv(-TRUE, nkf_enc_to_iconv(input_encoding));
- } else {
- set_iconv(FALSE, e_iconv);
- }
-
- {
- struct input_code *p = input_code_list;
- while (p->name){
- status_reinit(p++);
- }
- }
- return 0;
-}
-
-/*
- Conversion main loop. Code detection only.
- */
-
-#if !defined(PERL_XS) && !defined(WIN32DLL)
-static nkf_char
-noconvert(FILE *f)
-{
- nkf_char c;
-
- if (nop_f == 2)
- module_connection();
- while ((c = (*i_getc)(f)) != EOF)
- (*o_putc)(c);
- (*o_putc)(EOF);
- return 1;
-}
-#endif
-
-#define NEXT continue /* no output, get next */
-#define SKIP c2=0;continue /* no output, get next */
-#define MORE c2=c1;continue /* need one more byte */
-#define SEND (void)0 /* output c1 and c2, get next */
-#define LAST break /* end of loop, go closing */
-#define set_input_mode(mode) do { \
- input_mode = mode; \
- shift_mode = 0; \
- set_input_codename("ISO-2022-JP"); \
- debug("ISO-2022-JP"); \
-} while (0)
-
-static int
-kanji_convert(FILE *f)
-{
- nkf_char c1=0, c2=0, c3=0, c4=0;
- int shift_mode = 0; /* 0, 1, 2, 3 */
- int g2 = 0;
- int is_8bit = FALSE;
-
- if (input_encoding && !nkf_enc_asciicompat(input_encoding)) {
- is_8bit = TRUE;
- }
-
- input_mode = ASCII;
- output_mode = ASCII;
-
- if (module_connection() < 0) {
-#if !defined(PERL_XS) && !defined(WIN32DLL)
- fprintf(stderr, "no output encoding given\n");
-#endif
- return -1;
- }
- check_bom(f);
-
-#ifdef UTF8_INPUT_ENABLE
- if(iconv == w_iconv32){
- while ((c1 = (*i_getc)(f)) != EOF &&
- (c2 = (*i_getc)(f)) != EOF &&
- (c3 = (*i_getc)(f)) != EOF &&
- (c4 = (*i_getc)(f)) != EOF) {
- nkf_char c5, c6, c7, c8;
- if (nkf_iconv_utf_32(c1, c2, c3, c4) == (size_t)NKF_ICONV_WAIT_COMBINING_CHAR) {
- if ((c5 = (*i_getc)(f)) != EOF &&
- (c6 = (*i_getc)(f)) != EOF &&
- (c7 = (*i_getc)(f)) != EOF &&
- (c8 = (*i_getc)(f)) != EOF) {
- if (nkf_iconv_utf_32_combine(c1, c2, c3, c4, c5, c6, c7, c8)) {
- (*i_ungetc)(c8, f);
- (*i_ungetc)(c7, f);
- (*i_ungetc)(c6, f);
- (*i_ungetc)(c5, f);
- nkf_iconv_utf_32_nocombine(c1, c2, c3, c4);
- }
- } else {
- nkf_iconv_utf_32_nocombine(c1, c2, c3, c4);
- }
- }
- }
- goto finished;
- }
- else if (iconv == w_iconv16) {
- while ((c1 = (*i_getc)(f)) != EOF &&
- (c2 = (*i_getc)(f)) != EOF) {
- size_t ret = nkf_iconv_utf_16(c1, c2, 0, 0);
- if (ret == NKF_ICONV_NEED_TWO_MORE_BYTES &&
- (c3 = (*i_getc)(f)) != EOF &&
- (c4 = (*i_getc)(f)) != EOF) {
- nkf_iconv_utf_16(c1, c2, c3, c4);
- } else if (ret == (size_t)NKF_ICONV_WAIT_COMBINING_CHAR) {
- if ((c3 = (*i_getc)(f)) != EOF &&
- (c4 = (*i_getc)(f)) != EOF) {
- if (nkf_iconv_utf_16_combine(c1, c2, c3, c4)) {
- (*i_ungetc)(c4, f);
- (*i_ungetc)(c3, f);
- nkf_iconv_utf_16_nocombine(c1, c2);
- }
- } else {
- nkf_iconv_utf_16_nocombine(c1, c2);
- }
- }
- }
- goto finished;
- }
-#endif
-
- while ((c1 = (*i_getc)(f)) != EOF) {
-#ifdef INPUT_CODE_FIX
- if (!input_encoding)
-#endif
- code_status(c1);
- if (c2) {
- /* second byte */
- if (c2 > ((input_encoding && nkf_enc_cp5022x_p(input_encoding)) ? 0x92 : DEL)) {
- /* in case of 8th bit is on */
- if (!estab_f&&!mime_decode_mode) {
- /* in case of not established yet */
- /* It is still ambiguous */
- if (h_conv(f, c2, c1)==EOF) {
- LAST;
- }
- else {
- SKIP;
- }
- }
- else {
- /* in case of already established */
- if (c1 < 0x40) {
- /* ignore bogus code */
- SKIP;
- } else {
- SEND;
- }
- }
- }
- else {
- /* 2nd byte of 7 bit code or SJIS */
- SEND;
- }
- }
- else if (nkf_char_unicode_p(c1)) {
- (*oconv)(0, c1);
- NEXT;
- }
- else {
- /* first byte */
- if (input_mode == JIS_X_0208 && DEL <= c1 && c1 < 0x92) {
- /* CP5022x */
- MORE;
- }else if (input_codename && input_codename[0] == 'I' &&
- 0xA1 <= c1 && c1 <= 0xDF) {
- /* JIS X 0201 Katakana in 8bit JIS */
- c2 = JIS_X_0201_1976_K;
- c1 &= 0x7f;
- SEND;
- } else if (c1 > DEL) {
- /* 8 bit code */
- if (!estab_f && !iso8859_f) {
- /* not established yet */
- MORE;
- } else { /* estab_f==TRUE */
- if (iso8859_f) {
- c2 = ISO_8859_1;
- c1 &= 0x7f;
- SEND;
- }
- else if ((iconv == s_iconv && 0xA0 <= c1 && c1 <= 0xDF) ||
- (ms_ucs_map_f == UCS_MAP_CP10001 && (c1 == 0xFD || c1 == 0xFE))) {
- /* JIS X 0201 */
- c2 = JIS_X_0201_1976_K;
- c1 &= 0x7f;
- SEND;
- }
- else {
- /* already established */
- MORE;
- }
- }
- } else if (SP < c1 && c1 < DEL) {
- /* in case of Roman characters */
- if (shift_mode) {
- /* output 1 shifted byte */
- if (iso8859_f) {
- c2 = ISO_8859_1;
- SEND;
- } else if (nkf_byte_jisx0201_katakana_p(c1)){
- /* output 1 shifted byte */
- c2 = JIS_X_0201_1976_K;
- SEND;
- } else {
- /* look like bogus code */
- SKIP;
- }
- } else if (input_mode == JIS_X_0208 || input_mode == JIS_X_0212 ||
- input_mode == JIS_X_0213_1 || input_mode == JIS_X_0213_2) {
- /* in case of Kanji shifted */
- MORE;
- } else if (c1 == '=' && mime_f && !mime_decode_mode) {
- /* Check MIME code */
- if ((c1 = (*i_getc)(f)) == EOF) {
- (*oconv)(0, '=');
- LAST;
- } else if (c1 == '?') {
- /* =? is mime conversion start sequence */
- if(mime_f == STRICT_MIME) {
- /* check in real detail */
- if (mime_begin_strict(f) == EOF)
- LAST;
- SKIP;
- } else if (mime_begin(f) == EOF)
- LAST;
- SKIP;
- } else {
- (*oconv)(0, '=');
- (*i_ungetc)(c1,f);
- SKIP;
- }
- } else {
- /* normal ASCII code */
- SEND;
- }
- } else if (c1 == SI && (!is_8bit || mime_decode_mode)) {
- shift_mode = 0;
- SKIP;
- } else if (c1 == SO && (!is_8bit || mime_decode_mode)) {
- shift_mode = 1;
- SKIP;
- } else if (c1 == ESC && (!is_8bit || mime_decode_mode)) {
- if ((c1 = (*i_getc)(f)) == EOF) {
- (*oconv)(0, ESC);
- LAST;
- }
- else if (c1 == '&') {
- /* IRR */
- if ((c1 = (*i_getc)(f)) == EOF) {
- LAST;
- } else {
- SKIP;
- }
- }
- else if (c1 == '$') {
- /* GZDMx */
- if ((c1 = (*i_getc)(f)) == EOF) {
- /* don't send bogus code
- (*oconv)(0, ESC);
- (*oconv)(0, '$'); */
- LAST;
- } else if (c1 == '@' || c1 == 'B') {
- /* JIS X 0208 */
- set_input_mode(JIS_X_0208);
- SKIP;
- } else if (c1 == '(') {
- /* GZDM4 */
- if ((c1 = (*i_getc)(f)) == EOF) {
- /* don't send bogus code
- (*oconv)(0, ESC);
- (*oconv)(0, '$');
- (*oconv)(0, '(');
- */
- LAST;
- } else if (c1 == '@'|| c1 == 'B') {
- /* JIS X 0208 */
- set_input_mode(JIS_X_0208);
- SKIP;
-#ifdef X0212_ENABLE
- } else if (c1 == 'D'){
- set_input_mode(JIS_X_0212);
- SKIP;
-#endif /* X0212_ENABLE */
- } else if (c1 == 'O' || c1 == 'Q'){
- set_input_mode(JIS_X_0213_1);
- SKIP;
- } else if (c1 == 'P'){
- set_input_mode(JIS_X_0213_2);
- SKIP;
- } else {
- /* could be some special code */
- (*oconv)(0, ESC);
- (*oconv)(0, '$');
- (*oconv)(0, '(');
- (*oconv)(0, c1);
- SKIP;
- }
- } else if (broken_f&0x2) {
- /* accept any ESC-(-x as broken code ... */
- input_mode = JIS_X_0208;
- shift_mode = 0;
- SKIP;
- } else {
- (*oconv)(0, ESC);
- (*oconv)(0, '$');
- (*oconv)(0, c1);
- SKIP;
- }
- } else if (c1 == '(') {
- /* GZD4 */
- if ((c1 = (*i_getc)(f)) == EOF) {
- /* don't send bogus code
- (*oconv)(0, ESC);
- (*oconv)(0, '('); */
- LAST;
- }
- else if (c1 == 'I') {
- /* JIS X 0201 Katakana */
- set_input_mode(JIS_X_0201_1976_K);
- shift_mode = 1;
- SKIP;
- }
- else if (c1 == 'B' || c1 == 'J' || c1 == 'H') {
- /* ISO-646IRV:1983 or JIS X 0201 Roman or JUNET */
- set_input_mode(ASCII);
- SKIP;
- }
- else if (broken_f&0x2) {
- set_input_mode(ASCII);
- SKIP;
- }
- else {
- (*oconv)(0, ESC);
- (*oconv)(0, '(');
- SEND;
- }
- }
- else if (c1 == '.') {
- /* G2D6 */
- if ((c1 = (*i_getc)(f)) == EOF) {
- LAST;
- }
- else if (c1 == 'A') {
- /* ISO-8859-1 */
- g2 = ISO_8859_1;
- SKIP;
- }
- else {
- (*oconv)(0, ESC);
- (*oconv)(0, '.');
- SEND;
- }
- }
- else if (c1 == 'N') {
- /* SS2 */
- c1 = (*i_getc)(f);
- if (g2 == ISO_8859_1) {
- c2 = ISO_8859_1;
- SEND;
- }else{
- (*i_ungetc)(c1, f);
- /* lonely ESC */
- (*oconv)(0, ESC);
- SEND;
- }
- }
- else {
- i_ungetc(c1,f);
- /* lonely ESC */
- (*oconv)(0, ESC);
- SKIP;
- }
- } else if (c1 == ESC && iconv == s_iconv) {
- /* ESC in Shift_JIS */
- if ((c1 = (*i_getc)(f)) == EOF) {
- (*oconv)(0, ESC);
- LAST;
- } else if (c1 == '$') {
- /* J-PHONE emoji */
- if ((c1 = (*i_getc)(f)) == EOF) {
- LAST;
- } else if (('E' <= c1 && c1 <= 'G') ||
- ('O' <= c1 && c1 <= 'Q')) {
- /*
- NUM : 0 1 2 3 4 5
- BYTE: G E F O P Q
- C%7 : 1 6 0 2 3 4
- C%7 : 0 1 2 3 4 5 6
- NUM : 2 0 3 4 5 X 1
- */
- static const nkf_char jphone_emoji_first_table[7] =
- {0xE1E0, 0xDFE0, 0xE2E0, 0xE3E0, 0xE4E0, 0xDFE0, 0xE0E0};
- c3 = nkf_char_unicode_new(jphone_emoji_first_table[c1 % 7]);
- if ((c1 = (*i_getc)(f)) == EOF) LAST;
- while (SP <= c1 && c1 <= 'z') {
- (*oconv)(0, c1 + c3);
- if ((c1 = (*i_getc)(f)) == EOF) LAST;
- }
- SKIP;
- }
- else {
- (*oconv)(0, ESC);
- (*oconv)(0, '$');
- SEND;
- }
- }
- else {
- i_ungetc(c1,f);
- /* lonely ESC */
- (*oconv)(0, ESC);
- SKIP;
- }
- } else if (c1 == LF || c1 == CR) {
- if (broken_f&4) {
- input_mode = ASCII; set_iconv(FALSE, 0);
- SEND;
- } else if (mime_decode_f && !mime_decode_mode){
- if (c1 == LF) {
- if ((c1=(*i_getc)(f))!=EOF && c1 == SP) {
- i_ungetc(SP,f);
- continue;
- } else {
- i_ungetc(c1,f);
- }
- c1 = LF;
- SEND;
- } else { /* if (c1 == CR)*/
- if ((c1=(*i_getc)(f))!=EOF) {
- if (c1==SP) {
- i_ungetc(SP,f);
- continue;
- } else if (c1 == LF && (c1=(*i_getc)(f))!=EOF && c1 == SP) {
- i_ungetc(SP,f);
- continue;
- } else {
- i_ungetc(c1,f);
- }
- i_ungetc(LF,f);
- } else {
- i_ungetc(c1,f);
- }
- c1 = CR;
- SEND;
- }
- }
- } else
- SEND;
- }
- /* send: */
- switch(input_mode){
- case ASCII:
- switch ((*iconv)(c2, c1, 0)) { /* can be EUC / SJIS / UTF-8 */
- case -2:
- /* 4 bytes UTF-8 */
- if ((c3 = (*i_getc)(f)) != EOF) {
- code_status(c3);
- c3 <<= 8;
- if ((c4 = (*i_getc)(f)) != EOF) {
- code_status(c4);
- (*iconv)(c2, c1, c3|c4);
- }
- }
- break;
- case -3:
- /* 4 bytes UTF-8 (check combining character) */
- if ((c3 = (*i_getc)(f)) != EOF) {
- if ((c4 = (*i_getc)(f)) != EOF) {
- if (w_iconv_combine(c2, c1, 0, c3, c4, 0)) {
- (*i_ungetc)(c4, f);
- (*i_ungetc)(c3, f);
- w_iconv_nocombine(c2, c1, 0);
- }
- } else {
- (*i_ungetc)(c3, f);
- w_iconv_nocombine(c2, c1, 0);
- }
- } else {
- w_iconv_nocombine(c2, c1, 0);
- }
- break;
- case -1:
- /* 3 bytes EUC or UTF-8 */
- if ((c3 = (*i_getc)(f)) != EOF) {
- code_status(c3);
- if ((*iconv)(c2, c1, c3) == -3) {
- /* 6 bytes UTF-8 (check combining character) */
- nkf_char c5, c6;
- if ((c4 = (*i_getc)(f)) != EOF) {
- if ((c5 = (*i_getc)(f)) != EOF) {
- if ((c6 = (*i_getc)(f)) != EOF) {
- if (w_iconv_combine(c2, c1, c3, c4, c5, c6)) {
- (*i_ungetc)(c6, f);
- (*i_ungetc)(c5, f);
- (*i_ungetc)(c4, f);
- w_iconv_nocombine(c2, c1, c3);
- }
- } else {
- (*i_ungetc)(c5, f);
- (*i_ungetc)(c4, f);
- w_iconv_nocombine(c2, c1, c3);
- }
- } else {
- (*i_ungetc)(c4, f);
- w_iconv_nocombine(c2, c1, c3);
- }
- } else {
- w_iconv_nocombine(c2, c1, c3);
- }
- }
- }
- break;
- }
- break;
- case JIS_X_0208:
- case JIS_X_0213_1:
- if (ms_ucs_map_f &&
- 0x7F <= c2 && c2 <= 0x92 &&
- 0x21 <= c1 && c1 <= 0x7E) {
- /* CP932 UDC */
- c1 = nkf_char_unicode_new((c2 - 0x7F) * 94 + c1 - 0x21 + 0xE000);
- c2 = 0;
- }
- (*oconv)(c2, c1); /* this is JIS, not SJIS/EUC case */
- break;
-#ifdef X0212_ENABLE
- case JIS_X_0212:
- (*oconv)(PREFIX_EUCG3 | c2, c1);
- break;
-#endif /* X0212_ENABLE */
- case JIS_X_0213_2:
- (*oconv)(PREFIX_EUCG3 | c2, c1);
- break;
- default:
- (*oconv)(input_mode, c1); /* other special case */
- }
-
- c2 = 0;
- c3 = 0;
- continue;
- /* goto next_word */
- }
-
-finished:
- /* epilogue */
- (*iconv)(EOF, 0, 0);
- if (!input_codename)
- {
- if (is_8bit) {
- struct input_code *p = input_code_list;
- struct input_code *result = p;
- while (p->name){
- if (p->score < result->score) result = p;
- ++p;
- }
- set_input_codename(result->name);
-#ifdef CHECK_OPTION
- debug(result->name);
-#endif
- }
- }
- return 0;
-}
-
-/*
- * int options(unsigned char *cp)
- *
- * return values:
- * 0: success
- * -1: ArgumentError
- */
-static int
-options(unsigned char *cp)
-{
- nkf_char i, j;
- unsigned char *p;
- unsigned char *cp_back = NULL;
- nkf_encoding *enc;
-
- if (option_mode==1)
- return 0;
- while(*cp && *cp++!='-');
- while (*cp || cp_back) {
- if(!*cp){
- cp = cp_back;
- cp_back = NULL;
- continue;
- }
- p = 0;
- switch (*cp++) {
- case '-': /* literal options */
- if (!*cp || *cp == SP) { /* ignore the rest of arguments */
- option_mode = 1;
- return 0;
- }
- for (i=0;i<(int)(sizeof(long_option)/sizeof(long_option[0]));i++) {
- p = (unsigned char *)long_option[i].name;
- for (j=0;*p && *p != '=' && *p == cp[j];p++, j++);
- if (*p == cp[j] || cp[j] == SP){
- p = &cp[j] + 1;
- break;
- }
- p = 0;
- }
- if (p == 0) {
-#if !defined(PERL_XS) && !defined(WIN32DLL)
- fprintf(stderr, "unknown long option: --%s\n", cp);
-#endif
- return -1;
- }
- while(*cp && *cp != SP && cp++);
- if (long_option[i].alias[0]){
- cp_back = cp;
- cp = (unsigned char *)long_option[i].alias;
- }else{
-#ifndef PERL_XS
- if (strcmp(long_option[i].name, "help") == 0){
- usage();
- exit(EXIT_SUCCESS);
- }
-#endif
- if (strcmp(long_option[i].name, "ic=") == 0){
- enc = nkf_enc_find((char *)p);
- if (!enc) continue;
- input_encoding = enc;
- continue;
- }
- if (strcmp(long_option[i].name, "oc=") == 0){
- enc = nkf_enc_find((char *)p);
- /* if (enc <= 0) continue; */
- if (!enc) continue;
- output_encoding = enc;
- continue;
- }
- if (strcmp(long_option[i].name, "guess=") == 0){
- if (p[0] == '0' || p[0] == '1') {
- guess_f = 1;
- } else {
- guess_f = 2;
- }
- continue;
- }
-#ifdef OVERWRITE
- if (strcmp(long_option[i].name, "overwrite") == 0){
- file_out_f = TRUE;
- overwrite_f = TRUE;
- preserve_time_f = TRUE;
- continue;
- }
- if (strcmp(long_option[i].name, "overwrite=") == 0){
- file_out_f = TRUE;
- overwrite_f = TRUE;
- preserve_time_f = TRUE;
- backup_f = TRUE;
- backup_suffix = (char *)p;
- continue;
- }
- if (strcmp(long_option[i].name, "in-place") == 0){
- file_out_f = TRUE;
- overwrite_f = TRUE;
- preserve_time_f = FALSE;
- continue;
- }
- if (strcmp(long_option[i].name, "in-place=") == 0){
- file_out_f = TRUE;
- overwrite_f = TRUE;
- preserve_time_f = FALSE;
- backup_f = TRUE;
- backup_suffix = (char *)p;
- continue;
- }
-#endif
-#ifdef INPUT_OPTION
- if (strcmp(long_option[i].name, "cap-input") == 0){
- cap_f = TRUE;
- continue;
- }
- if (strcmp(long_option[i].name, "url-input") == 0){
- url_f = TRUE;
- continue;
- }
-#endif
-#ifdef NUMCHAR_OPTION
- if (strcmp(long_option[i].name, "numchar-input") == 0){
- numchar_f = TRUE;
- continue;
- }
-#endif
-#ifdef CHECK_OPTION
- if (strcmp(long_option[i].name, "no-output") == 0){
- noout_f = TRUE;
- continue;
- }
- if (strcmp(long_option[i].name, "debug") == 0){
- debug_f = TRUE;
- continue;
- }
-#endif
- if (strcmp(long_option[i].name, "cp932") == 0){
-#ifdef SHIFTJIS_CP932
- cp51932_f = TRUE;
- cp932inv_f = -TRUE;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_CP932;
-#endif
- continue;
- }
- if (strcmp(long_option[i].name, "no-cp932") == 0){
-#ifdef SHIFTJIS_CP932
- cp51932_f = FALSE;
- cp932inv_f = FALSE;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- ms_ucs_map_f = UCS_MAP_ASCII;
-#endif
- continue;
- }
-#ifdef SHIFTJIS_CP932
- if (strcmp(long_option[i].name, "cp932inv") == 0){
- cp932inv_f = -TRUE;
- continue;
- }
-#endif
-
-#ifdef X0212_ENABLE
- if (strcmp(long_option[i].name, "x0212") == 0){
- x0212_f = TRUE;
- continue;
- }
-#endif
-
-#ifdef EXEC_IO
- if (strcmp(long_option[i].name, "exec-in") == 0){
- exec_f = 1;
- return 0;
- }
- if (strcmp(long_option[i].name, "exec-out") == 0){
- exec_f = -1;
- return 0;
- }
-#endif
-#if defined(UTF8_OUTPUT_ENABLE) && defined(UTF8_INPUT_ENABLE)
- if (strcmp(long_option[i].name, "no-cp932ext") == 0){
- no_cp932ext_f = TRUE;
- continue;
- }
- if (strcmp(long_option[i].name, "no-best-fit-chars") == 0){
- no_best_fit_chars_f = TRUE;
- continue;
- }
- if (strcmp(long_option[i].name, "fb-skip") == 0){
- encode_fallback = NULL;
- continue;
- }
- if (strcmp(long_option[i].name, "fb-html") == 0){
- encode_fallback = encode_fallback_html;
- continue;
- }
- if (strcmp(long_option[i].name, "fb-xml") == 0){
- encode_fallback = encode_fallback_xml;
- continue;
- }
- if (strcmp(long_option[i].name, "fb-java") == 0){
- encode_fallback = encode_fallback_java;
- continue;
- }
- if (strcmp(long_option[i].name, "fb-perl") == 0){
- encode_fallback = encode_fallback_perl;
- continue;
- }
- if (strcmp(long_option[i].name, "fb-subchar") == 0){
- encode_fallback = encode_fallback_subchar;
- continue;
- }
- if (strcmp(long_option[i].name, "fb-subchar=") == 0){
- encode_fallback = encode_fallback_subchar;
- unicode_subchar = 0;
- if (p[0] != '0'){
- /* decimal number */
- for (i = 0; i < 7 && nkf_isdigit(p[i]); i++){
- unicode_subchar *= 10;
- unicode_subchar += hex2bin(p[i]);
- }
- }else if(p[1] == 'x' || p[1] == 'X'){
- /* hexadecimal number */
- for (i = 2; i < 8 && nkf_isxdigit(p[i]); i++){
- unicode_subchar <<= 4;
- unicode_subchar |= hex2bin(p[i]);
- }
- }else{
- /* octal number */
- for (i = 1; i < 8 && nkf_isoctal(p[i]); i++){
- unicode_subchar *= 8;
- unicode_subchar += hex2bin(p[i]);
- }
- }
- w16e_conv(unicode_subchar, &i, &j);
- unicode_subchar = i<<8 | j;
- continue;
- }
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- if (strcmp(long_option[i].name, "ms-ucs-map") == 0){
- ms_ucs_map_f = UCS_MAP_MS;
- continue;
- }
-#endif
-#ifdef UNICODE_NORMALIZATION
- if (strcmp(long_option[i].name, "utf8mac-input") == 0){
- nfc_f = TRUE;
- continue;
- }
-#endif
- if (strcmp(long_option[i].name, "prefix=") == 0){
- if (nkf_isgraph(p[0])){
- for (i = 1; nkf_isgraph(p[i]); i++){
- prefix_table[p[i]] = p[0];
- }
- }
- continue;
- }
-#if !defined(PERL_XS) && !defined(WIN32DLL)
- fprintf(stderr, "unsupported long option: --%s\n", long_option[i].name);
-#endif
- return -1;
- }
- continue;
- case 'b': /* buffered mode */
- unbuf_f = FALSE;
- continue;
- case 'u': /* non bufferd mode */
- unbuf_f = TRUE;
- continue;
- case 't': /* transparent mode */
- if (*cp=='1') {
- /* alias of -t */
- cp++;
- nop_f = TRUE;
- } else if (*cp=='2') {
- /*
- * -t with put/get
- *
- * nkf -t2MB hoge.bin | nkf -t2mB | diff -s - hoge.bin
- *
- */
- cp++;
- nop_f = 2;
- } else
- nop_f = TRUE;
- continue;
- case 'j': /* JIS output */
- case 'n':
- output_encoding = nkf_enc_from_index(ISO_2022_JP);
- continue;
- case 'e': /* AT&T EUC output */
- output_encoding = nkf_enc_from_index(EUCJP_NKF);
- continue;
- case 's': /* SJIS output */
- output_encoding = nkf_enc_from_index(SHIFT_JIS);
- continue;
- case 'l': /* ISO8859 Latin-1 support, no conversion */
- iso8859_f = TRUE; /* Only compatible with ISO-2022-JP */
- input_encoding = nkf_enc_from_index(ISO_8859_1);
- continue;
- case 'i': /* Kanji IN ESC-$-@/B */
- if (*cp=='@'||*cp=='B')
- kanji_intro = *cp++;
- continue;
- case 'o': /* ASCII IN ESC-(-J/B/H */
- /* ESC ( H was used in initial JUNET messages */
- if (*cp=='J'||*cp=='B'||*cp=='H')
- ascii_intro = *cp++;
- continue;
- case 'h':
- /*
- bit:1 katakana->hiragana
- bit:2 hiragana->katakana
- */
- if ('9'>= *cp && *cp>='0')
- hira_f |= (*cp++ -'0');
- else
- hira_f |= 1;
- continue;
- case 'r':
- rot_f = TRUE;
- continue;
-#if defined(MSDOS) || defined(__OS2__)
- case 'T':
- binmode_f = FALSE;
- continue;
-#endif
-#ifndef PERL_XS
- case 'V':
- show_configuration();
- exit(EXIT_SUCCESS);
- break;
- case 'v':
- version();
- exit(EXIT_SUCCESS);
- break;
-#endif
-#ifdef UTF8_OUTPUT_ENABLE
- case 'w': /* UTF-{8,16,32} output */
- if (cp[0] == '8') {
- cp++;
- if (cp[0] == '0'){
- cp++;
- output_encoding = nkf_enc_from_index(UTF_8N);
- } else {
- output_bom_f = TRUE;
- output_encoding = nkf_enc_from_index(UTF_8_BOM);
- }
- } else {
- int enc_idx;
- if ('1'== cp[0] && '6'==cp[1]) {
- cp += 2;
- enc_idx = UTF_16;
- } else if ('3'== cp[0] && '2'==cp[1]) {
- cp += 2;
- enc_idx = UTF_32;
- } else {
- output_encoding = nkf_enc_from_index(UTF_8);
- continue;
- }
- if (cp[0]=='L') {
- cp++;
- output_endian = ENDIAN_LITTLE;
- output_bom_f = TRUE;
- } else if (cp[0] == 'B') {
- cp++;
- output_bom_f = TRUE;
- }
- if (cp[0] == '0'){
- output_bom_f = FALSE;
- cp++;
- enc_idx = enc_idx == UTF_16
- ? (output_endian == ENDIAN_LITTLE ? UTF_16LE : UTF_16BE)
- : (output_endian == ENDIAN_LITTLE ? UTF_32LE : UTF_32BE);
- } else {
- enc_idx = enc_idx == UTF_16
- ? (output_endian == ENDIAN_LITTLE ? UTF_16LE_BOM : UTF_16BE_BOM)
- : (output_endian == ENDIAN_LITTLE ? UTF_32LE_BOM : UTF_32BE_BOM);
- }
- output_encoding = nkf_enc_from_index(enc_idx);
- }
- continue;
-#endif
-#ifdef UTF8_INPUT_ENABLE
- case 'W': /* UTF input */
- if (cp[0] == '8') {
- cp++;
- input_encoding = nkf_enc_from_index(UTF_8);
- }else{
- int enc_idx;
- if ('1'== cp[0] && '6'==cp[1]) {
- cp += 2;
- input_endian = ENDIAN_BIG;
- enc_idx = UTF_16;
- } else if ('3'== cp[0] && '2'==cp[1]) {
- cp += 2;
- input_endian = ENDIAN_BIG;
- enc_idx = UTF_32;
- } else {
- input_encoding = nkf_enc_from_index(UTF_8);
- continue;
- }
- if (cp[0]=='L') {
- cp++;
- input_endian = ENDIAN_LITTLE;
- } else if (cp[0] == 'B') {
- cp++;
- input_endian = ENDIAN_BIG;
- }
- enc_idx = (enc_idx == UTF_16
- ? (input_endian == ENDIAN_LITTLE ? UTF_16LE : UTF_16BE)
- : (input_endian == ENDIAN_LITTLE ? UTF_32LE : UTF_32BE));
- input_encoding = nkf_enc_from_index(enc_idx);
- }
- continue;
-#endif
- /* Input code assumption */
- case 'J': /* ISO-2022-JP input */
- input_encoding = nkf_enc_from_index(ISO_2022_JP);
- continue;
- case 'E': /* EUC-JP input */
- input_encoding = nkf_enc_from_index(EUCJP_NKF);
- continue;
- case 'S': /* Shift_JIS input */
- input_encoding = nkf_enc_from_index(SHIFT_JIS);
- continue;
- case 'Z': /* Convert X0208 alphabet to ascii */
- /* alpha_f
- bit:0 Convert JIS X 0208 Alphabet to ASCII
- bit:1 Convert Kankaku to one space
- bit:2 Convert Kankaku to two spaces
- bit:3 Convert HTML Entity
- bit:4 Convert JIS X 0208 Katakana to JIS X 0201 Katakana
- */
- while ('0'<= *cp && *cp <='4') {
- alpha_f |= 1 << (*cp++ - '0');
- }
- alpha_f |= 1;
- continue;
- case 'x': /* Convert X0201 kana to X0208 or X0201 Conversion */
- x0201_f = FALSE; /* No X0201->X0208 conversion */
- /* accept X0201
- ESC-(-I in JIS, EUC, MS Kanji
- SI/SO in JIS, EUC, MS Kanji
- SS2 in EUC, JIS, not in MS Kanji
- MS Kanji (0xa0-0xdf)
- output X0201
- ESC-(-I in JIS (0x20-0x5f)
- SS2 in EUC (0xa0-0xdf)
- 0xa0-0xd in MS Kanji (0xa0-0xdf)
- */
- continue;
- case 'X': /* Convert X0201 kana to X0208 */
- x0201_f = TRUE;
- continue;
- case 'F': /* prserve new lines */
- fold_preserve_f = TRUE;
- case 'f': /* folding -f60 or -f */
- fold_f = TRUE;
- fold_len = 0;
- while('0'<= *cp && *cp <='9') { /* we don't use atoi here */
- fold_len *= 10;
- fold_len += *cp++ - '0';
- }
- if (!(0<fold_len && fold_len<BUFSIZ))
- fold_len = DEFAULT_FOLD;
- if (*cp=='-') {
- fold_margin = 0;
- cp++;
- while('0'<= *cp && *cp <='9') { /* we don't use atoi here */
- fold_margin *= 10;
- fold_margin += *cp++ - '0';
- }
- }
- continue;
- case 'm': /* MIME support */
- /* mime_decode_f = TRUE; */ /* this has too large side effects... */
- if (*cp=='B'||*cp=='Q') {
- mime_decode_mode = *cp++;
- mimebuf_f = FIXED_MIME;
- } else if (*cp=='N') {
- mime_f = TRUE; cp++;
- } else if (*cp=='S') {
- mime_f = STRICT_MIME; cp++;
- } else if (*cp=='0') {
- mime_decode_f = FALSE;
- mime_f = FALSE; cp++;
- } else {
- mime_f = STRICT_MIME;
- }
- continue;
- case 'M': /* MIME output */
- if (*cp=='B') {
- mimeout_mode = 'B';
- mimeout_f = FIXED_MIME; cp++;
- } else if (*cp=='Q') {
- mimeout_mode = 'Q';
- mimeout_f = FIXED_MIME; cp++;
- } else {
- mimeout_f = TRUE;
- }
- continue;
- case 'B': /* Broken JIS support */
- /* bit:0 no ESC JIS
- bit:1 allow any x on ESC-(-x or ESC-$-x
- bit:2 reset to ascii on NL
- */
- if ('9'>= *cp && *cp>='0')
- broken_f |= 1<<(*cp++ -'0');
- else
- broken_f |= TRUE;
- continue;
-#ifndef PERL_XS
- case 'O':/* for Output file */
- file_out_f = TRUE;
- continue;
-#endif
- case 'c':/* add cr code */
- eolmode_f = CRLF;
- continue;
- case 'd':/* delete cr code */
- eolmode_f = LF;
- continue;
- case 'I': /* ISO-2022-JP output */
- iso2022jp_f = TRUE;
- continue;
- case 'L': /* line mode */
- if (*cp=='u') { /* unix */
- eolmode_f = LF; cp++;
- } else if (*cp=='m') { /* mac */
- eolmode_f = CR; cp++;
- } else if (*cp=='w') { /* windows */
- eolmode_f = CRLF; cp++;
- } else if (*cp=='0') { /* no conversion */
- eolmode_f = 0; cp++;
- }
- continue;
-#ifndef PERL_XS
- case 'g':
- if ('2' <= *cp && *cp <= '9') {
- guess_f = 2;
- cp++;
- } else if (*cp == '0' || *cp == '1') {
- guess_f = 1;
- cp++;
- } else {
- guess_f = 1;
- }
- continue;
-#endif
- case SP:
- /* module multiple options in a string are allowed for Perl module */
- while(*cp && *cp++!='-');
- continue;
- default:
-#if !defined(PERL_XS) && !defined(WIN32DLL)
- fprintf(stderr, "unknown option: -%c\n", *(cp-1));
-#endif
- /* bogus option but ignored */
- return -1;
- }
- }
- return 0;
-}
-
-#ifdef WIN32DLL
-#include "nkf32dll.c"
-#elif defined(PERL_XS)
-#else /* WIN32DLL */
-int
-main(int argc, char **argv)
-{
- FILE *fin;
- unsigned char *cp;
-
- char *outfname = NULL;
- char *origfname;
-
-#ifdef EASYWIN /*Easy Win */
- _BufferSize.y = 400;/*Set Scroll Buffer Size*/
-#endif
-#ifdef DEFAULT_CODE_LOCALE
- setlocale(LC_CTYPE, "");
-#endif
- nkf_state_init();
-
- for (argc--,argv++; (argc > 0) && **argv == '-'; argc--, argv++) {
- cp = (unsigned char *)*argv;
- options(cp);
-#ifdef EXEC_IO
- if (exec_f){
- int fds[2], pid;
- if (pipe(fds) < 0 || (pid = fork()) < 0){
- abort();
- }
- if (pid == 0){
- if (exec_f > 0){
- close(fds[0]);
- dup2(fds[1], 1);
- }else{
- close(fds[1]);
- dup2(fds[0], 0);
- }
- execvp(argv[1], &argv[1]);
- }
- if (exec_f > 0){
- close(fds[1]);
- dup2(fds[0], 0);
- }else{
- close(fds[0]);
- dup2(fds[1], 1);
- }
- argc = 0;
- break;
- }
-#endif
- }
-
- if (guess_f) {
-#ifdef CHECK_OPTION
- int debug_f_back = debug_f;
-#endif
-#ifdef EXEC_IO
- int exec_f_back = exec_f;
-#endif
-#ifdef X0212_ENABLE
- int x0212_f_back = x0212_f;
-#endif
- int x0213_f_back = x0213_f;
- int guess_f_back = guess_f;
- reinit();
- guess_f = guess_f_back;
- mime_f = FALSE;
-#ifdef CHECK_OPTION
- debug_f = debug_f_back;
-#endif
-#ifdef EXEC_IO
- exec_f = exec_f_back;
-#endif
- x0212_f = x0212_f_back;
- x0213_f = x0213_f_back;
- }
-
- if (binmode_f == TRUE)
-#if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__))
- if (freopen("","wb",stdout) == NULL)
- return (-1);
-#else
- setbinmode(stdout);
-#endif
-
- if (unbuf_f)
- setbuf(stdout, (char *) NULL);
- else
- setvbuffer(stdout, (char *) stdobuf, IOBUF_SIZE);
-
- if (argc == 0) {
- if (binmode_f == TRUE)
-#if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__))
- if (freopen("","rb",stdin) == NULL) return (-1);
-#else
- setbinmode(stdin);
-#endif
- setvbuffer(stdin, (char *) stdibuf, IOBUF_SIZE);
- if (nop_f)
- noconvert(stdin);
- else {
- kanji_convert(stdin);
- if (guess_f) print_guessed_code(NULL);
- }
- } else {
- int nfiles = argc;
- int is_argument_error = FALSE;
- while (argc--) {
- input_codename = NULL;
- input_eol = 0;
-#ifdef CHECK_OPTION
- iconv_for_check = 0;
-#endif
- if ((fin = fopen((origfname = *argv++), "r")) == NULL) {
- perror(*(argv-1));
- is_argument_error = TRUE;
- continue;
- } else {
-#ifdef OVERWRITE
- int fd = 0;
- int fd_backup = 0;
-#endif
-
- /* reopen file for stdout */
- if (file_out_f == TRUE) {
-#ifdef OVERWRITE
- if (overwrite_f){
- outfname = nkf_xmalloc(strlen(origfname)
- + strlen(".nkftmpXXXXXX")
- + 1);
- strcpy(outfname, origfname);
-#ifdef MSDOS
- {
- int i;
- for (i = strlen(outfname); i; --i){
- if (outfname[i - 1] == '/'
- || outfname[i - 1] == '\\'){
- break;
- }
- }
- outfname[i] = '\0';
- }
- strcat(outfname, "ntXXXXXX");
- mktemp(outfname);
- fd = open(outfname, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL,
- S_IREAD | S_IWRITE);
-#else
- strcat(outfname, ".nkftmpXXXXXX");
- fd = mkstemp(outfname);
-#endif
- if (fd < 0
- || (fd_backup = dup(fileno(stdout))) < 0
- || dup2(fd, fileno(stdout)) < 0
- ){
- perror(origfname);
- return -1;
- }
- }else
-#endif
- if(argc == 1) {
- outfname = *argv++;
- argc--;
- } else {
- outfname = "nkf.out";
- }
-
- if(freopen(outfname, "w", stdout) == NULL) {
- perror (outfname);
- return (-1);
- }
- if (binmode_f == TRUE) {
-#if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__))
- if (freopen("","wb",stdout) == NULL)
- return (-1);
-#else
- setbinmode(stdout);
-#endif
- }
- }
- if (binmode_f == TRUE)
-#if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__))
- if (freopen("","rb",fin) == NULL)
- return (-1);
-#else
- setbinmode(fin);
-#endif
- setvbuffer(fin, (char *) stdibuf, IOBUF_SIZE);
- if (nop_f)
- noconvert(fin);
- else {
- char *filename = NULL;
- kanji_convert(fin);
- if (nfiles > 1) filename = origfname;
- if (guess_f) print_guessed_code(filename);
- }
- fclose(fin);
-#ifdef OVERWRITE
- if (overwrite_f) {
- struct stat sb;
-#if defined(MSDOS) && !defined(__MINGW32__) && !defined(__WIN32__) && !defined(__WATCOMC__) && !defined(__EMX__) && !defined(__OS2__) && !defined(__DJGPP__)
- time_t tb[2];
-#else
- struct utimbuf tb;
-#endif
-
- fflush(stdout);
- close(fd);
- if (dup2(fd_backup, fileno(stdout)) < 0){
- perror("dup2");
- }
- if (stat(origfname, &sb)) {
- fprintf(stderr, "Can't stat %s\n", origfname);
- }
- /* $B%Q!<%_%C%7%g%s$rI|85(B */
- if (chmod(outfname, sb.st_mode)) {
- fprintf(stderr, "Can't set permission %s\n", outfname);
- }
-
- /* $B%?%$%`%9%?%s%W$rI|85(B */
- if(preserve_time_f){
-#if defined(MSDOS) && !defined(__MINGW32__) && !defined(__WIN32__) && !defined(__WATCOMC__) && !defined(__EMX__) && !defined(__OS2__) && !defined(__DJGPP__)
- tb[0] = tb[1] = sb.st_mtime;
- if (utime(outfname, tb)) {
- fprintf(stderr, "Can't set timestamp %s\n", outfname);
- }
-#else
- tb.actime = sb.st_atime;
- tb.modtime = sb.st_mtime;
- if (utime(outfname, &tb)) {
- fprintf(stderr, "Can't set timestamp %s\n", outfname);
- }
-#endif
- }
- if(backup_f){
- char *backup_filename = get_backup_filename(backup_suffix, origfname);
-#ifdef MSDOS
- unlink(backup_filename);
-#endif
- if (rename(origfname, backup_filename)) {
- perror(backup_filename);
- fprintf(stderr, "Can't rename %s to %s\n",
- origfname, backup_filename);
- }
- nkf_xfree(backup_filename);
- }else{
-#ifdef MSDOS
- if (unlink(origfname)){
- perror(origfname);
- }
-#endif
- }
- if (rename(outfname, origfname)) {
- perror(origfname);
- fprintf(stderr, "Can't rename %s to %s\n",
- outfname, origfname);
- }
- nkf_xfree(outfname);
- }
-#endif
- }
- }
- if (is_argument_error)
- return(-1);
- }
-#ifdef EASYWIN /*Easy Win */
- if (file_out_f == FALSE)
- scanf("%d",&end_check);
- else
- fclose(stdout);
-#else /* for Other OS */
- if (file_out_f == TRUE)
- fclose(stdout);
-#endif /*Easy Win */
- return (0);
-}
-#endif /* WIN32DLL */
diff --git a/ext/nkf/nkf-utf8/nkf.h b/ext/nkf/nkf-utf8/nkf.h
deleted file mode 100644
index b3a520da54..0000000000
--- a/ext/nkf/nkf-utf8/nkf.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- *
- * nkf.h - Header file for nkf
- *
- */
-
-#ifndef NKF_H
-#define NKF_H
-
-/* Wrapper of configurations */
-
-#ifndef MIME_DECODE_DEFAULT
-#define MIME_DECODE_DEFAULT STRICT_MIME
-#endif
-#ifndef X0201_DEFAULT
-#define X0201_DEFAULT TRUE
-#endif
-
-#if defined(DEFAULT_NEWLINE) && DEFAULT_NEWLINE == 0x0D0A
-#elif defined(DEFAULT_NEWLINE) && DEFAULT_NEWLINE == 0x0D
-#else
-#define DEFAULT_NEWLINE 0x0A
-#endif
-#ifdef HELP_OUTPUT_STDERR
-#define HELP_OUTPUT stderr
-#else
-#define HELP_OUTPUT stdout
-#endif
-
-
-/* Compatibility definitions */
-
-#ifdef nkf_char
-#elif defined(INT_IS_SHORT)
-typedef long nkf_char;
-#define NKF_INT32_C(n) (n##L)
-#else
-typedef int nkf_char;
-#define NKF_INT32_C(n) (n)
-#endif
-
-#if (defined(__TURBOC__) || defined(_MSC_VER) || defined(LSI_C) || (defined(__WATCOMC__) && defined(__386__) && !defined(__LINUX__)) || defined(__MINGW32__) || defined(__EMX__) || defined(__MSDOS__) || defined(__WINDOWS__) || defined(__DOS__) || defined(__OS2__)) && !defined(MSDOS)
-#define MSDOS
-#if (defined(__Win32__) || defined(_WIN32)) && !defined(__WIN32__)
-#define __WIN32__
-#endif
-#endif
-
-#ifdef PERL_XS
-#undef OVERWRITE
-#endif
-
-#ifndef PERL_XS
-#include <stdio.h>
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-
-#if defined(MSDOS) || defined(__OS2__)
-#include <fcntl.h>
-#include <io.h>
-#if defined(_MSC_VER) || defined(__WATCOMC__)
-#define mktemp _mktemp
-#endif
-#endif
-
-#ifdef MSDOS
-#ifdef LSI_C
-#define setbinmode(fp) fsetbin(fp)
-#elif defined(__DJGPP__)
-#include <libc/dosio.h>
-void setbinmode(FILE *fp)
-{
- /* we do not use libc's setmode(), which changes COOKED/RAW mode in device. */
- int fd, m;
- fd = fileno(fp);
- m = (__file_handle_modes[fd] & (~O_TEXT)) | O_BINARY;
- __file_handle_set(fd, m);
-}
-#else /* Microsoft C, Turbo C */
-#define setbinmode(fp) setmode(fileno(fp), O_BINARY)
-#endif
-#else /* UNIX */
-#define setbinmode(fp) (void)(fp)
-#endif
-
-#ifdef _IOFBF /* SysV and MSDOS, Windows */
-#define setvbuffer(fp, buf, size) setvbuf(fp, buf, _IOFBF, size)
-#else /* BSD */
-#define setvbuffer(fp, buf, size) setbuffer(fp, buf, size)
-#endif
-
-/*Borland C++ 4.5 EasyWin*/
-#if defined(__TURBOC__) && defined(_Windows) && !defined(__WIN32__) /*Easy Win */
-#define EASYWIN
-#ifndef __WIN16__
-#define __WIN16__
-#endif
-#include <windows.h>
-#endif
-
-#ifdef OVERWRITE
-/* added by satoru@isoternet.org */
-#if defined(__EMX__)
-#include <sys/types.h>
-#endif
-#include <sys/stat.h>
-#if !defined(MSDOS) || defined(__DJGPP__) /* UNIX, djgpp */
-#include <unistd.h>
-#if defined(__WATCOMC__)
-#include <sys/utime.h>
-#else
-#include <utime.h>
-#endif
-#else /* defined(MSDOS) */
-#ifdef __WIN32__
-#ifdef __BORLANDC__ /* BCC32 */
-#include <utime.h>
-#else /* !defined(__BORLANDC__) */
-#include <sys/utime.h>
-#endif /* (__BORLANDC__) */
-#else /* !defined(__WIN32__) */
-#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__WATCOMC__) || defined(__OS2__) || defined(__EMX__) || defined(__IBMC__) || defined(__IBMCPP__) /* VC++, MinGW, Watcom, emx+gcc, IBM VAC++ */
-#include <sys/utime.h>
-#elif defined(__TURBOC__) /* BCC */
-#include <utime.h>
-#elif defined(LSI_C) /* LSI C */
-#endif /* (__WIN32__) */
-#endif
-#endif
-#endif
-
-#if !defined(DEFAULT_CODE_JIS) && !defined(DEFAULT_CODE_SJIS) && \
- !defined(DEFAULT_CODE_WINDOWS_31J) && !defined(DEFAULT_CODE_EUC) && \
- !defined(DEFAULT_CODE_UTF8) && !defined(DEFAULT_CODE_LOCALE)
-#define DEFAULT_CODE_LOCALE
-#endif
-
-#ifdef DEFAULT_CODE_LOCALE
-
-#if defined(__WIN32__) /* not win32 should be posix */
-# ifndef HAVE_LOCALE_H
-# define HAVE_LOCALE_H
-# endif
-#elif defined(__OS2__)
-# undef HAVE_LANGINFO_H /* We do not use kLIBC's langinfo. */
-# ifndef HAVE_LOCALE_H
-# define HAVE_LOCALE_H
-# endif
-#elif defined(MSDOS)
-# ifndef HAVE_LOCALE_H
-# define HAVE_LOCALE_H
-# endif
-#elif defined(__BIONIC__) /* bionic doesn't have locale */
-#else
-# ifndef HAVE_LANGINFO_H
-# define HAVE_LANGINFO_H
-# endif
-# ifndef HAVE_LOCALE_H
-# define HAVE_LOCALE_H
-# endif
-#endif
-
-#ifdef HAVE_LANGINFO_H
-#include <langinfo.h>
-#endif
-#ifdef HAVE_LOCALE_H
-#include <locale.h>
-#endif
-
-#endif /* DEFAULT_CODE_LOCALE */
-
-#define FALSE 0
-#define TRUE 1
-
-#ifndef ARG_UNUSED
-#if defined(__GNUC__)
-# define ARG_UNUSED __attribute__ ((unused))
-#else
-# define ARG_UNUSED
-#endif
-#endif
-
-#ifdef WIN32DLL
-#include "nkf32.h"
-#endif
-
-#endif /* NKF_H */
diff --git a/ext/nkf/nkf-utf8/utf8tbl.c b/ext/nkf/nkf-utf8/utf8tbl.c
deleted file mode 100644
index a31e4e7805..0000000000
--- a/ext/nkf/nkf-utf8/utf8tbl.c
+++ /dev/null
@@ -1,14638 +0,0 @@
-/*
- * utf8tbl.c - Conversion Table for nkf
- *
- */
-
-#include "config.h"
-#include "utf8tbl.h"
-
-#ifdef UTF8_OUTPUT_ENABLE
-static const unsigned short euc_to_utf8_A1[] = {
- 0x3000, 0x3001, 0x3002, 0xFF0C, 0xFF0E, 0x30FB, 0xFF1A,
- 0xFF1B, 0xFF1F, 0xFF01, 0x309B, 0x309C, 0x00B4, 0xFF40, 0x00A8,
- 0xFF3E, 0x203E, 0xFF3F, 0x30FD, 0x30FE, 0x309D, 0x309E, 0x3003,
- 0x4EDD, 0x3005, 0x3006, 0x3007, 0x30FC, 0x2014, 0x2010, 0xFF0F,
- 0xFF3C, 0x301C, 0x2016, 0xFF5C, 0x2026, 0x2025, 0x2018, 0x2019,
- 0x201C, 0x201D, 0xFF08, 0xFF09, 0x3014, 0x3015, 0xFF3B, 0xFF3D,
- 0xFF5B, 0xFF5D, 0x3008, 0x3009, 0x300A, 0x300B, 0x300C, 0x300D,
- 0x300E, 0x300F, 0x3010, 0x3011, 0xFF0B, 0x2212, 0x00B1, 0x00D7,
- 0x00F7, 0xFF1D, 0x2260, 0xFF1C, 0xFF1E, 0x2266, 0x2267, 0x221E,
- 0x2234, 0x2642, 0x2640, 0x00B0, 0x2032, 0x2033, 0x2103, 0x00A5,
- 0xFF04, 0x00A2, 0x00A3, 0xFF05, 0xFF03, 0xFF06, 0xFF0A, 0xFF20,
- 0x00A7, 0x2606, 0x2605, 0x25CB, 0x25CF, 0x25CE, 0x25C7,
-};
-
-/* Microsoft UCS Mapping Compatible */
-static const unsigned short euc_to_utf8_A1_ms[] = {
- 0x3000, 0x3001, 0x3002, 0xFF0C, 0xFF0E, 0x30FB, 0xFF1A,
- 0xFF1B, 0xFF1F, 0xFF01, 0x309B, 0x309C, 0x00B4, 0xFF40, 0x00A8,
- 0xFF3E, 0xFFE3, 0xFF3F, 0x30FD, 0x30FE, 0x309D, 0x309E, 0x3003,
- 0x4EDD, 0x3005, 0x3006, 0x3007, 0x30FC, 0x2015, 0x2010, 0xFF0F,
- 0xFF3C, 0xFF5E, 0x2225, 0xFF5C, 0x2026, 0x2025, 0x2018, 0x2019,
- 0x201C, 0x201D, 0xFF08, 0xFF09, 0x3014, 0x3015, 0xFF3B, 0xFF3D,
- 0xFF5B, 0xFF5D, 0x3008, 0x3009, 0x300A, 0x300B, 0x300C, 0x300D,
- 0x300E, 0x300F, 0x3010, 0x3011, 0xFF0B, 0xFF0D, 0x00B1, 0x00D7,
- 0x00F7, 0xFF1D, 0x2260, 0xFF1C, 0xFF1E, 0x2266, 0x2267, 0x221E,
- 0x2234, 0x2642, 0x2640, 0x00B0, 0x2032, 0x2033, 0x2103, 0xFFE5,
- 0xFF04, 0xFFE0, 0xFFE1, 0xFF05, 0xFF03, 0xFF06, 0xFF0A, 0xFF20,
- 0x00A7, 0x2606, 0x2605, 0x25CB, 0x25CF, 0x25CE, 0x25C7,
-};
-static const unsigned short euc_to_utf8_A2[] = {
- 0x25C6, 0x25A1, 0x25A0, 0x25B3, 0x25B2, 0x25BD, 0x25BC,
- 0x203B, 0x3012, 0x2192, 0x2190, 0x2191, 0x2193, 0x3013, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x2208, 0x220B, 0x2286, 0x2287, 0x2282, 0x2283,
- 0x222A, 0x2229, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x2227, 0x2228, 0x00AC, 0x21D2, 0x21D4, 0x2200,
- 0x2203, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x2220, 0x22A5, 0x2312, 0x2202,
- 0x2207, 0x2261, 0x2252, 0x226A, 0x226B, 0x221A, 0x223D, 0x221D,
- 0x2235, 0x222B, 0x222C, 0, 0, 0, 0, 0,
- 0, 0, 0x212B, 0x2030, 0x266F, 0x266D, 0x266A, 0x2020,
- 0x2021, 0x00B6, 0, 0, 0, 0, 0x25EF,
-};
-
-/* Microsoft UCS Mapping Compatible */
-static const unsigned short euc_to_utf8_A2_ms[] = {
- 0x25C6, 0x25A1, 0x25A0, 0x25B3, 0x25B2, 0x25BD, 0x25BC,
- 0x203B, 0x3012, 0x2192, 0x2190, 0x2191, 0x2193, 0x3013, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x2208, 0x220B, 0x2286, 0x2287, 0x2282, 0x2283,
- 0x222A, 0x2229, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x2227, 0x2228, 0xFFE2, 0x21D2, 0x21D4, 0x2200,
- 0x2203, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x2220, 0x22A5, 0x2312, 0x2202,
- 0x2207, 0x2261, 0x2252, 0x226A, 0x226B, 0x221A, 0x223D, 0x221D,
- 0x2235, 0x222B, 0x222C, 0, 0, 0, 0, 0,
- 0, 0, 0x212B, 0x2030, 0x266F, 0x266D, 0x266A, 0x2020,
- 0x2021, 0x00B6, 0, 0, 0, 0, 0x25EF,
-};
-static const unsigned short euc_to_utf8_A2_x0213[] = {
- 0x25C6, 0x25A1, 0x25A0, 0x25B3, 0x25B2, 0x25BD, 0x25BC,
- 0x203B, 0x3012, 0x2192, 0x2190, 0x2191, 0x2193, 0x3013, 0xFF07,
- 0xFF02, 0xFF0D, 0xFF5E, 0x3033, 0x3034, 0x3035, 0x303B, 0x303C,
- 0x30FF, 0x309F, 0x2208, 0x220B, 0x2286, 0x2287, 0x2282, 0x2283,
- 0x222A, 0x2229, 0x2284, 0x2285, 0x228A, 0x228B, 0x2209, 0x2205,
- 0x2305, 0x2306, 0x2227, 0x2228, 0x00AC, 0x21D2, 0x21D4, 0x2200,
- 0x2203, 0x2295, 0x2296, 0x2297, 0x2225, 0x2226, 0xFF5F, 0xFF60,
- 0x3018, 0x3019, 0x3016, 0x3017, 0x2220, 0x22A5, 0x2312, 0x2202,
- 0x2207, 0x2261, 0x2252, 0x226A, 0x226B, 0x221A, 0x223D, 0x221D,
- 0x2235, 0x222B, 0x222C, 0x2262, 0x2243, 0x2245, 0x2248, 0x2276,
- 0x2277, 0x2194, 0x212B, 0x2030, 0x266F, 0x266D, 0x266A, 0x2020,
- 0x2021, 0x00B6, 0x266E, 0x266B, 0x266C, 0x2669, 0x25EF,
-};
-static const unsigned short euc_to_utf8_A3[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17,
- 0xFF18, 0xFF19, 0, 0, 0, 0, 0, 0,
- 0, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27,
- 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F,
- 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37,
- 0xFF38, 0xFF39, 0xFF3A, 0, 0, 0, 0, 0,
- 0, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47,
- 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F,
- 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57,
- 0xFF58, 0xFF59, 0xFF5A, 0, 0, 0, 0,
-};
-static const unsigned short euc_to_utf8_A3_x0213[] = {
- 0x25B7, 0x25B6, 0x25C1, 0x25C0, 0x2197, 0x2198, 0x2196,
- 0x2199, 0x21C4, 0x21E8, 0x21E6, 0x21E7, 0x21E9, 0x2934, 0x2935,
- 0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17,
- 0xFF18, 0xFF19, 0x29BF, 0x25C9, 0x303D, 0xFE46, 0xFE45, 0x25E6,
- 0x2022, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27,
- 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F,
- 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37,
- 0xFF38, 0xFF39, 0xFF3A, 0x2213, 0x2135, 0x210F, 0x33CB, 0x2113,
- 0x2127, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47,
- 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F,
- 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57,
- 0xFF58, 0xFF59, 0xFF5A, 0x30A0, 0x2013, 0x29FA, 0x29FB,
-};
-static const unsigned short euc_to_utf8_A4[] = {
- 0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047,
- 0x3048, 0x3049, 0x304A, 0x304B, 0x304C, 0x304D, 0x304E, 0x304F,
- 0x3050, 0x3051, 0x3052, 0x3053, 0x3054, 0x3055, 0x3056, 0x3057,
- 0x3058, 0x3059, 0x305A, 0x305B, 0x305C, 0x305D, 0x305E, 0x305F,
- 0x3060, 0x3061, 0x3062, 0x3063, 0x3064, 0x3065, 0x3066, 0x3067,
- 0x3068, 0x3069, 0x306A, 0x306B, 0x306C, 0x306D, 0x306E, 0x306F,
- 0x3070, 0x3071, 0x3072, 0x3073, 0x3074, 0x3075, 0x3076, 0x3077,
- 0x3078, 0x3079, 0x307A, 0x307B, 0x307C, 0x307D, 0x307E, 0x307F,
- 0x3080, 0x3081, 0x3082, 0x3083, 0x3084, 0x3085, 0x3086, 0x3087,
- 0x3088, 0x3089, 0x308A, 0x308B, 0x308C, 0x308D, 0x308E, 0x308F,
- 0x3090, 0x3091, 0x3092, 0x3093, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short euc_to_utf8_A4_x0213[] = {
- 0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047,
- 0x3048, 0x3049, 0x304A, 0x304B, 0x304C, 0x304D, 0x304E, 0x304F,
- 0x3050, 0x3051, 0x3052, 0x3053, 0x3054, 0x3055, 0x3056, 0x3057,
- 0x3058, 0x3059, 0x305A, 0x305B, 0x305C, 0x305D, 0x305E, 0x305F,
- 0x3060, 0x3061, 0x3062, 0x3063, 0x3064, 0x3065, 0x3066, 0x3067,
- 0x3068, 0x3069, 0x306A, 0x306B, 0x306C, 0x306D, 0x306E, 0x306F,
- 0x3070, 0x3071, 0x3072, 0x3073, 0x3074, 0x3075, 0x3076, 0x3077,
- 0x3078, 0x3079, 0x307A, 0x307B, 0x307C, 0x307D, 0x307E, 0x307F,
- 0x3080, 0x3081, 0x3082, 0x3083, 0x3084, 0x3085, 0x3086, 0x3087,
- 0x3088, 0x3089, 0x308A, 0x308B, 0x308C, 0x308D, 0x308E, 0x308F,
- 0x3090, 0x3091, 0x3092, 0x3093, 0x3094, 0x3095, 0x3096, /*0x304B*/ 0x309A,
- /*0x304D*/ 0x309A, /*0x304F*/ 0x309A, /*0x3051*/ 0x309A, /*0x3053*/ 0x309A, 0, 0, 0,
-};
-static const unsigned short euc_to_utf8_A5[] = {
- 0x30A1, 0x30A2, 0x30A3, 0x30A4, 0x30A5, 0x30A6, 0x30A7,
- 0x30A8, 0x30A9, 0x30AA, 0x30AB, 0x30AC, 0x30AD, 0x30AE, 0x30AF,
- 0x30B0, 0x30B1, 0x30B2, 0x30B3, 0x30B4, 0x30B5, 0x30B6, 0x30B7,
- 0x30B8, 0x30B9, 0x30BA, 0x30BB, 0x30BC, 0x30BD, 0x30BE, 0x30BF,
- 0x30C0, 0x30C1, 0x30C2, 0x30C3, 0x30C4, 0x30C5, 0x30C6, 0x30C7,
- 0x30C8, 0x30C9, 0x30CA, 0x30CB, 0x30CC, 0x30CD, 0x30CE, 0x30CF,
- 0x30D0, 0x30D1, 0x30D2, 0x30D3, 0x30D4, 0x30D5, 0x30D6, 0x30D7,
- 0x30D8, 0x30D9, 0x30DA, 0x30DB, 0x30DC, 0x30DD, 0x30DE, 0x30DF,
- 0x30E0, 0x30E1, 0x30E2, 0x30E3, 0x30E4, 0x30E5, 0x30E6, 0x30E7,
- 0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EE, 0x30EF,
- 0x30F0, 0x30F1, 0x30F2, 0x30F3, 0x30F4, 0x30F5, 0x30F6, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short euc_to_utf8_A5_x0213[] = {
- 0x30A1, 0x30A2, 0x30A3, 0x30A4, 0x30A5, 0x30A6, 0x30A7,
- 0x30A8, 0x30A9, 0x30AA, 0x30AB, 0x30AC, 0x30AD, 0x30AE, 0x30AF,
- 0x30B0, 0x30B1, 0x30B2, 0x30B3, 0x30B4, 0x30B5, 0x30B6, 0x30B7,
- 0x30B8, 0x30B9, 0x30BA, 0x30BB, 0x30BC, 0x30BD, 0x30BE, 0x30BF,
- 0x30C0, 0x30C1, 0x30C2, 0x30C3, 0x30C4, 0x30C5, 0x30C6, 0x30C7,
- 0x30C8, 0x30C9, 0x30CA, 0x30CB, 0x30CC, 0x30CD, 0x30CE, 0x30CF,
- 0x30D0, 0x30D1, 0x30D2, 0x30D3, 0x30D4, 0x30D5, 0x30D6, 0x30D7,
- 0x30D8, 0x30D9, 0x30DA, 0x30DB, 0x30DC, 0x30DD, 0x30DE, 0x30DF,
- 0x30E0, 0x30E1, 0x30E2, 0x30E3, 0x30E4, 0x30E5, 0x30E6, 0x30E7,
- 0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EE, 0x30EF,
- 0x30F0, 0x30F1, 0x30F2, 0x30F3, 0x30F4, 0x30F5, 0x30F6, /*0x30AB*/ 0x309A,
- /*0x30AD*/ 0x309A, /*0x30AF*/ 0x309A, /*0x30B1*/ 0x309A, /*0x30B3*/ 0x309A, /*0x30BB*/ 0x309A, /*0x30C4*/ 0x309A, /*0x30C8*/ 0x309A,
-};
-static const unsigned short euc_to_utf8_A6[] = {
- 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
- 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
- 0x03A0, 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8,
- 0x03A9, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
- 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
- 0x03C0, 0x03C1, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8,
- 0x03C9, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short euc_to_utf8_A6_x0213[] = {
- 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
- 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
- 0x03A0, 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8,
- 0x03A9, 0x2664, 0x2660, 0x2662, 0x2666, 0x2661, 0x2665, 0x2667,
- 0x2663, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
- 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
- 0x03C0, 0x03C1, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8,
- 0x03C9, 0x03C2, 0x24F5, 0x24F6, 0x24F7, 0x24F8, 0x24F9, 0x24FA,
- 0x24FB, 0x24FC, 0x24FD, 0x24FE, 0x2616, 0x2617, 0x3020, 0x260E,
- 0x2600, 0x2601, 0x2602, 0x2603, 0x2668, 0x25B1, 0x31F0, 0x31F1,
- 0x31F2, 0x31F3, 0x31F4, 0x31F5, 0x31F6, 0x31F7, 0x31F8, 0x31F9,
- /*0x31F7*/ 0x309A, 0x31FA, 0x31FB, 0x31FC, 0x31FD, 0x31FE, 0x31FF,
-};
-static const unsigned short euc_to_utf8_A7[] = {
- 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0401,
- 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D,
- 0x041E, 0x041F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425,
- 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D,
- 0x042E, 0x042F, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0451,
- 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D,
- 0x043E, 0x043F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445,
- 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D,
- 0x044E, 0x044F, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short euc_to_utf8_A7_x0213[] = {
- 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0401,
- 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D,
- 0x041E, 0x041F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425,
- 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D,
- 0x042E, 0x042F, 0x23BE, 0x23BF, 0x23C0, 0x23C1, 0x23C2, 0x23C3,
- 0x23C4, 0x23C5, 0x23C6, 0x23C7, 0x23C8, 0x23C9, 0x23CA, 0x23CB,
- 0x23CC, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0451,
- 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D,
- 0x043E, 0x043F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445,
- 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D,
- 0x044E, 0x044F, 0x30F7, 0x30F8, 0x30F9, 0x30FA, 0x22DA, 0x22DB,
- 0x2153, 0x2154, 0x2155, 0x2713, 0x2318, 0x2423, 0x23CE,
-};
-static const unsigned short euc_to_utf8_A8[] = {
- 0x2500, 0x2502, 0x250C, 0x2510, 0x2518, 0x2514, 0x251C,
- 0x252C, 0x2524, 0x2534, 0x253C, 0x2501, 0x2503, 0x250F, 0x2513,
- 0x251B, 0x2517, 0x2523, 0x2533, 0x252B, 0x253B, 0x254B, 0x2520,
- 0x252F, 0x2528, 0x2537, 0x253F, 0x251D, 0x2530, 0x2525, 0x2538,
- 0x2542, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short euc_to_utf8_A8_x0213[] = {
- 0x2500, 0x2502, 0x250C, 0x2510, 0x2518, 0x2514, 0x251C,
- 0x252C, 0x2524, 0x2534, 0x253C, 0x2501, 0x2503, 0x250F, 0x2513,
- 0x251B, 0x2517, 0x2523, 0x2533, 0x252B, 0x253B, 0x254B, 0x2520,
- 0x252F, 0x2528, 0x2537, 0x253F, 0x251D, 0x2530, 0x2525, 0x2538,
- 0x2542, 0x3251, 0x3252, 0x3253, 0x3254, 0x3255, 0x3256, 0x3257,
- 0x3258, 0x3259, 0x325A, 0x325B, 0x325C, 0x325D, 0x325E, 0x325F,
- 0x32B1, 0x32B2, 0x32B3, 0x32B4, 0x32B5, 0x32B6, 0x32B7, 0x32B8,
- 0x32B9, 0x32BA, 0x32BB, 0x32BC, 0x32BD, 0x32BE, 0x32BF, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x25D0,
- 0x25D1, 0x25D2, 0x25D3, 0x203C, 0x2047, 0x2048, 0x2049, 0x01CD,
- 0x01CE, 0x01D0, 0x1E3E, 0x1E3F, 0x01F8, 0x01F9, 0x01D1, 0x01D2,
- 0x01D4, 0x01D6, 0x01D8, 0x01DA, 0x01DC, 0, 0,
-};
-static const unsigned short euc_to_utf8_A9[] = {
- 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466,
- 0x2467, 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E,
- 0x246F, 0x2470, 0x2471, 0x2472, 0x2473, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x2474,
- 0x2475, 0x2476, 0x2477, 0x2478, 0x2479, 0x247A, 0x247B, 0x247C,
- 0x247D, 0x247E, 0x247F, 0x2480, 0x2481, 0x2482, 0x2483, 0x2484,
- 0x2485, 0x2486, 0x2487, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x2776, 0x2777, 0x2778,
- 0x2779, 0x277A, 0x277B, 0x277C, 0x277D, 0x277E, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x2488, 0x2489, 0x248A, 0x248B, 0x248C, 0x248D,
- 0x248E, 0x248F, 0x2490, 0, 0, 0, 0,
-};
-static const unsigned short euc_to_utf8_A9_x0213[] = {
- 0x20AC, 0x00A0, 0x00A1, 0x00A4, 0x00A6, 0x00A9, 0x00AA,
- 0x00AB, 0x00AD, 0x00AE, 0x00AF, 0x00B2, 0x00B3, 0x00B7, 0x00B8,
- 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0,
- 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8,
- 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0,
- 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D8, 0x00D9,
- 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0, 0x00E1,
- 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9,
- 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F1,
- 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F8, 0x00F9, 0x00FA,
- 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF, 0x0100, 0x012A, 0x016A,
- 0x0112, 0x014C, 0x0101, 0x012B, 0x016B, 0x0113, 0x014D,
-};
-static const unsigned short euc_to_utf8_AA[] = {
- 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166,
- 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x2170, 0x2171, 0x2172,
- 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A,
- 0x217B, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x249C, 0x249D, 0x249E,
- 0x249F, 0x24A0, 0x24A1, 0x24A2, 0x24A3, 0x24A4, 0x24A5, 0x24A6,
- 0x24A7, 0x24A8, 0x24A9, 0x24AA, 0x24AB, 0x24AC, 0x24AD, 0x24AE,
- 0x24AF, 0x24B0, 0x24B1, 0x24B2, 0x24B3, 0x24B4, 0x24B5, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short euc_to_utf8_AA_x0213[] = {
- 0x0104, 0x02D8, 0x0141, 0x013D, 0x015A, 0x0160, 0x015E,
- 0x0164, 0x0179, 0x017D, 0x017B, 0x0105, 0x02DB, 0x0142, 0x013E,
- 0x015B, 0x02C7, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E,
- 0x017C, 0x0154, 0x0102, 0x0139, 0x0106, 0x010C, 0x0118, 0x011A,
- 0x010E, 0x0143, 0x0147, 0x0150, 0x0158, 0x016E, 0x0170, 0x0162,
- 0x0155, 0x0103, 0x013A, 0x0107, 0x010D, 0x0119, 0x011B, 0x010F,
- 0x0111, 0x0144, 0x0148, 0x0151, 0x0159, 0x016F, 0x0171, 0x0163,
- 0x02D9, 0x0108, 0x011C, 0x0124, 0x0134, 0x015C, 0x016C, 0x0109,
- 0x011D, 0x0125, 0x0135, 0x015D, 0x016D, 0x0271, 0x028B, 0x027E,
- 0x0283, 0x0292, 0x026C, 0x026E, 0x0279, 0x0288, 0x0256, 0x0273,
- 0x027D, 0x0282, 0x0290, 0x027B, 0x026D, 0x025F, 0x0272, 0x029D,
- 0x028E, 0x0261, 0x014B, 0x0270, 0x0281, 0x0127, 0x0295,
-};
-static const unsigned short euc_to_utf8_AB[] = {
- 0x339C, 0x339F, 0x339D, 0x33A0, 0x33A4, 0, 0x33A1,
- 0x33A5, 0x339E, 0x33A2, 0x338E, 0, 0x338F, 0x33C4, 0x3396,
- 0x3397, 0x2113, 0x3398, 0x33B3, 0x33B2, 0x33B1, 0x33B0, 0x2109,
- 0x33D4, 0x33CB, 0x3390, 0x3385, 0x3386, 0x3387, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x2116, 0x33CD, 0x2121, 0,
-};
-static const unsigned short euc_to_utf8_AB_x0213[] = {
- 0x0294, 0x0266, 0x0298, 0x01C2, 0x0253, 0x0257, 0x0284,
- 0x0260, 0x0193, 0x0153, 0x0152, 0x0268, 0x0289, 0x0258, 0x0275,
- 0x0259, 0x025C, 0x025E, 0x0250, 0x026F, 0x028A, 0x0264, 0x028C,
- 0x0254, 0x0251, 0x0252, 0x028D, 0x0265, 0x02A2, 0x02A1, 0x0255,
- 0x0291, 0x027A, 0x0267, 0x025A, /*0x00E6*/ 0x0300, 0x01FD, 0x1F70, 0x1F71,
- /*0x0254*/ 0x0300, /*0x0254*/ 0x0301, /*0x028C*/ 0x0300, /*0x028C*/ 0x0301, /*0x0259*/ 0x0300, /*0x0259*/ 0x0301, /*0x025A*/ 0x0300, /*0x025A*/ 0x0301,
- 0x1F72, 0x1F73, 0x0361, 0x02C8, 0x02CC, 0x02D0, 0x02D1, 0x0306,
- 0x203F, 0x030B, /*0*/ 0x0301, 0x0304, /*0*/ 0x0300, 0x030F, 0x030C, 0x0302,
- /*0*/ 0x02E5, 0x02E6, 0x02E7, 0x02E8, /*0*/ 0x02E9, /*0x02E9*/ 0x02E5, /*0x02E5*/ 0x02E9, 0x0325,
- 0x032C, 0x0339, 0x031C, 0x031F, 0x0320, 0x0308, 0x033D, 0x0329,
- 0x032F, 0x02DE, 0x0324, 0x0330, 0x033C, 0x0334, 0x031D, 0x031E,
- 0x0318, 0x0319, 0x032A, 0x033A, 0x033B, 0x0303, 0x031A,
-};
-static const unsigned short euc_to_utf8_AC[] = {
- 0x2664, 0x2667, 0x2661, 0x2662, 0x2660, 0x2663, 0x2665,
- 0x2666, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x3020, 0x260E, 0x3004,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x261E, 0x261C, 0x261D, 0x261F, 0x21C6, 0x21C4, 0x21C5,
- 0, 0x21E8, 0x21E6, 0x21E7, 0x21E9, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short euc_to_utf8_AC_mac[] = {
- 0x2664, 0x2667, 0x2661, 0x2662, 0x2660, 0x2663, 0x2665,
- 0x2666, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x3020, 0x260E, 0x3004,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x261E, 0x261C, 0x261D, 0x261F, 0x21C6, 0x21C4, 0x21C5,
- 0, 0x21E8, 0x21E6, 0x21E7, 0x21E9, 0x2192, 0x2190, 0x2191,
- 0x2193, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short euc_to_utf8_AC_x0213[] = {
- 0x2776, 0x2777, 0x2778, 0x2779, 0x277A, 0x277B, 0x277C,
- 0x277D, 0x277E, 0x277F, 0x24EB, 0x24EC, 0x24ED, 0x24EE, 0x24EF,
- 0x24F0, 0x24F1, 0x24F2, 0x24F3, 0x24F4, 0x2170, 0x2171, 0x2172,
- 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A,
- 0x217B, 0x24D0, 0x24D1, 0x24D2, 0x24D3, 0x24D4, 0x24D5, 0x24D6,
- 0x24D7, 0x24D8, 0x24D9, 0x24DA, 0x24DB, 0x24DC, 0x24DD, 0x24DE,
- 0x24DF, 0x24E0, 0x24E1, 0x24E2, 0x24E3, 0x24E4, 0x24E5, 0x24E6,
- 0x24E7, 0x24E8, 0x24E9, 0x32D0, 0x32D1, 0x32D2, 0x32D3, 0x32D4,
- 0x32D5, 0x32D6, 0x32D7, 0x32D8, 0x32D9, 0x32DA, 0x32DB, 0x32DC,
- 0x32DD, 0x32DE, 0x32DF, 0x32E0, 0x32E1, 0x32E2, 0x32E3, 0x32FA,
- 0x32E9, 0x32E5, 0x32ED, 0x32EC, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x2051, 0x2042,
-};
-static const unsigned short euc_to_utf8_AD[] = {
- 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466,
- 0x2467, 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E,
- 0x246F, 0x2470, 0x2471, 0x2472, 0x2473, 0x2160, 0x2161, 0x2162,
- 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0,
- 0x3349, 0x3314, 0x3322, 0x334D, 0x3318, 0x3327, 0x3303, 0x3336,
- 0x3351, 0x3357, 0x330D, 0x3326, 0x3323, 0x332B, 0x334A, 0x333B,
- 0x339C, 0x339D, 0x339E, 0x338E, 0x338F, 0x33C4, 0x33A1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x337B,
- 0x301D, 0x301F, 0x2116, 0x33CD, 0x2121, 0x32A4, 0x32A5, 0x32A6,
- 0x32A7, 0x32A8, 0x3231, 0x3232, 0x3239, 0x337E, 0x337D, 0x337C,
- 0x2252, 0x2261, 0x222B, 0x222E, 0x2211, 0x221A, 0x22A5, 0x2220,
- 0x221F, 0x22BF, 0x2235, 0x2229, 0x222A, 0, 0x3299,
-};
-static const unsigned short euc_to_utf8_AD_mac[] = {
- 0x65E5, 0x6708, 0x706B, 0x6C34, 0x6728, 0x91D1, 0x571F,
- 0x796D, 0x795D, 0x81EA, 0x81F3, 0x3239, 0x547C, 0x3231, 0x8CC7,
- 0x540D, 0x3232, 0x5B66, 0x8CA1, 0x793E, 0x7279, 0x76E3, 0x4F01,
- 0x5354, 0x52B4, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0,
- 0x3349, 0x3314, 0x3322, 0x334D, 0x3318, 0x3327, 0x3303, 0x3336,
- 0x3351, 0x3357, 0x330D, 0x3326, 0x3323, 0x332B, 0x334A, 0x333B,
- 0x339C, 0x339D, 0x339E, 0x338E, 0x338F, 0x33C4, 0x33A1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x337B,
- 0x301D, 0x301F, 0x2116, 0x33CD, 0x2121, 0x32A4, 0x32A5, 0x32A6,
- 0x32A7, 0x32A8, 0x3231, 0x3232, 0x3239, 0x337E, 0x337D, 0x337C,
- 0x2252, 0x5927, 0x5C0F, 0x32A4, 0x32A5, 0x32A6, 0x32A7, 0x32A8,
- 0x533B, 0x8CA1, 0x512A, 0x52B4, 0x5370, 0x63A7, 0x79D8,
-};
-static const unsigned short euc_to_utf8_AD_x0213[] = {
- 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466,
- 0x2467, 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E,
- 0x246F, 0x2470, 0x2471, 0x2472, 0x2473, 0x2160, 0x2161, 0x2162,
- 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A,
- 0x3349, 0x3314, 0x3322, 0x334D, 0x3318, 0x3327, 0x3303, 0x3336,
- 0x3351, 0x3357, 0x330D, 0x3326, 0x3323, 0x332B, 0x334A, 0x333B,
- 0x339C, 0x339D, 0x339E, 0x338E, 0x338F, 0x33C4, 0x33A1, 0x216B,
- 0, 0, 0, 0, 0, 0, 0, 0x337B,
- 0x301D, 0x301F, 0x2116, 0x33CD, 0x2121, 0x32A4, 0x32A5, 0x32A6,
- 0x32A7, 0x32A8, 0x3231, 0x3232, 0x3239, 0x337E, 0x337D, 0x337C,
- 0x2252, 0x2261, 0x222B, 0x222E, 0x2211, 0x221A, 0x22A5, 0x2220,
- 0x221F, 0x22BF, 0x2235, 0x2229, 0x222A, 0x2756, 0x261E,
-};
-static const unsigned short euc_to_utf8_AE[] = {
- 0x3349, 0x3322, 0x334D, 0x3314, 0x3316, 0x3305, 0x3333,
- 0x334E, 0x3303, 0x3336, 0x3318, 0x3315, 0x3327, 0x3351, 0x334A,
- 0x3339, 0x3357, 0x330D, 0x3342, 0x3323, 0x3326, 0x333B, 0x332B,
- 0, 0, 0, 0, 0, 0, 0, 0x3300,
- 0x331E, 0x332A, 0x3331, 0x3347, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x337E,
- 0x337D, 0x337C, 0x337B, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x337F, 0, 0,
-};
-static const unsigned short euc_to_utf8_AE_x0213[] = {
- 0x4FF1, 0xD840 /*0xDC0B*/, 0x3402, 0x4E28, 0x4E2F, 0x4E30, 0x4E8D,
- 0x4EE1, 0x4EFD, 0x4EFF, 0x4F03, 0x4F0B, 0x4F60, 0x4F48, 0x4F49,
- 0x4F56, 0x4F5F, 0x4F6A, 0x4F6C, 0x4F7E, 0x4F8A, 0x4F94, 0x4F97,
- 0xFA30, 0x4FC9, 0x4FE0, 0x5001, 0x5002, 0x500E, 0x5018, 0x5027,
- 0x502E, 0x5040, 0x503B, 0x5041, 0x5094, 0x50CC, 0x50F2, 0x50D0,
- 0x50E6, 0xFA31, 0x5106, 0x5103, 0x510B, 0x511E, 0x5135, 0x514A,
- 0xFA32, 0x5155, 0x5157, 0x34B5, 0x519D, 0x51C3, 0x51CA, 0x51DE,
- 0x51E2, 0x51EE, 0x5201, 0x34DB, 0x5213, 0x5215, 0x5249, 0x5257,
- 0x5261, 0x5293, 0x52C8, 0xFA33, 0x52CC, 0x52D0, 0x52D6, 0x52DB,
- 0xFA34, 0x52F0, 0x52FB, 0x5300, 0x5307, 0x531C, 0xFA35, 0x5361,
- 0x5363, 0x537D, 0x5393, 0x539D, 0x53B2, 0x5412, 0x5427, 0x544D,
- 0x549C, 0x546B, 0x5474, 0x547F, 0x5488, 0x5496, 0x54A1,
-};
-static const unsigned short euc_to_utf8_AF[] = {
- 0x222E, 0x221F, 0x22BF, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x301D, 0x301F, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x3094, 0, 0x30F7, 0x30F8, 0x30F9, 0x30FA, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short euc_to_utf8_AF_x0213[] = {
- 0x54A9, 0x54C6, 0x54FF, 0x550E, 0x552B, 0x5535, 0x5550,
- 0x555E, 0x5581, 0x5586, 0x558E, 0xFA36, 0x55AD, 0x55CE, 0xFA37,
- 0x5608, 0x560E, 0x563B, 0x5649, 0x5676, 0x5666, 0xFA38, 0x566F,
- 0x5671, 0x5672, 0x5699, 0x569E, 0x56A9, 0x56AC, 0x56B3, 0x56C9,
- 0x56CA, 0x570A, 0xD844 /*0xDE3D*/, 0x5721, 0x572F, 0x5733, 0x5734, 0x5770,
- 0x5777, 0x577C, 0x579C, 0xFA0F, 0xD844 /*0xDF1B*/, 0x57B8, 0x57C7, 0x57C8,
- 0x57CF, 0x57E4, 0x57ED, 0x57F5, 0x57F6, 0x57FF, 0x5809, 0xFA10,
- 0x5861, 0x5864, 0xFA39, 0x587C, 0x5889, 0x589E, 0xFA3A, 0x58A9,
- 0xD845 /*0xDC6E*/, 0x58D2, 0x58CE, 0x58D4, 0x58DA, 0x58E0, 0x58E9, 0x590C,
- 0x8641, 0x595D, 0x596D, 0x598B, 0x5992, 0x59A4, 0x59C3, 0x59D2,
- 0x59DD, 0x5A13, 0x5A23, 0x5A67, 0x5A6D, 0x5A77, 0x5A7E, 0x5A84,
- 0x5A9E, 0x5AA7, 0x5AC4, 0xD846 /*0xDCBD*/, 0x5B19, 0x5B25, 0x525D,
-};
-static const unsigned short euc_to_utf8_B0[] = {
- 0x4E9C, 0x5516, 0x5A03, 0x963F, 0x54C0, 0x611B, 0x6328,
- 0x59F6, 0x9022, 0x8475, 0x831C, 0x7A50, 0x60AA, 0x63E1, 0x6E25,
- 0x65ED, 0x8466, 0x82A6, 0x9BF5, 0x6893, 0x5727, 0x65A1, 0x6271,
- 0x5B9B, 0x59D0, 0x867B, 0x98F4, 0x7D62, 0x7DBE, 0x9B8E, 0x6216,
- 0x7C9F, 0x88B7, 0x5B89, 0x5EB5, 0x6309, 0x6697, 0x6848, 0x95C7,
- 0x978D, 0x674F, 0x4EE5, 0x4F0A, 0x4F4D, 0x4F9D, 0x5049, 0x56F2,
- 0x5937, 0x59D4, 0x5A01, 0x5C09, 0x60DF, 0x610F, 0x6170, 0x6613,
- 0x6905, 0x70BA, 0x754F, 0x7570, 0x79FB, 0x7DAD, 0x7DEF, 0x80C3,
- 0x840E, 0x8863, 0x8B02, 0x9055, 0x907A, 0x533B, 0x4E95, 0x4EA5,
- 0x57DF, 0x80B2, 0x90C1, 0x78EF, 0x4E00, 0x58F1, 0x6EA2, 0x9038,
- 0x7A32, 0x8328, 0x828B, 0x9C2F, 0x5141, 0x5370, 0x54BD, 0x54E1,
- 0x56E0, 0x59FB, 0x5F15, 0x98F2, 0x6DEB, 0x80E4, 0x852D,
-};
-static const unsigned short euc_to_utf8_B1[] = {
- 0x9662, 0x9670, 0x96A0, 0x97FB, 0x540B, 0x53F3, 0x5B87,
- 0x70CF, 0x7FBD, 0x8FC2, 0x96E8, 0x536F, 0x9D5C, 0x7ABA, 0x4E11,
- 0x7893, 0x81FC, 0x6E26, 0x5618, 0x5504, 0x6B1D, 0x851A, 0x9C3B,
- 0x59E5, 0x53A9, 0x6D66, 0x74DC, 0x958F, 0x5642, 0x4E91, 0x904B,
- 0x96F2, 0x834F, 0x990C, 0x53E1, 0x55B6, 0x5B30, 0x5F71, 0x6620,
- 0x66F3, 0x6804, 0x6C38, 0x6CF3, 0x6D29, 0x745B, 0x76C8, 0x7A4E,
- 0x9834, 0x82F1, 0x885B, 0x8A60, 0x92ED, 0x6DB2, 0x75AB, 0x76CA,
- 0x99C5, 0x60A6, 0x8B01, 0x8D8A, 0x95B2, 0x698E, 0x53AD, 0x5186,
- 0x5712, 0x5830, 0x5944, 0x5BB4, 0x5EF6, 0x6028, 0x63A9, 0x63F4,
- 0x6CBF, 0x6F14, 0x708E, 0x7114, 0x7159, 0x71D5, 0x733F, 0x7E01,
- 0x8276, 0x82D1, 0x8597, 0x9060, 0x925B, 0x9D1B, 0x5869, 0x65BC,
- 0x6C5A, 0x7525, 0x51F9, 0x592E, 0x5965, 0x5F80, 0x5FDC,
-};
-static const unsigned short euc_to_utf8_B2[] = {
- 0x62BC, 0x65FA, 0x6A2A, 0x6B27, 0x6BB4, 0x738B, 0x7FC1,
- 0x8956, 0x9D2C, 0x9D0E, 0x9EC4, 0x5CA1, 0x6C96, 0x837B, 0x5104,
- 0x5C4B, 0x61B6, 0x81C6, 0x6876, 0x7261, 0x4E59, 0x4FFA, 0x5378,
- 0x6069, 0x6E29, 0x7A4F, 0x97F3, 0x4E0B, 0x5316, 0x4EEE, 0x4F55,
- 0x4F3D, 0x4FA1, 0x4F73, 0x52A0, 0x53EF, 0x5609, 0x590F, 0x5AC1,
- 0x5BB6, 0x5BE1, 0x79D1, 0x6687, 0x679C, 0x67B6, 0x6B4C, 0x6CB3,
- 0x706B, 0x73C2, 0x798D, 0x79BE, 0x7A3C, 0x7B87, 0x82B1, 0x82DB,
- 0x8304, 0x8377, 0x83EF, 0x83D3, 0x8766, 0x8AB2, 0x5629, 0x8CA8,
- 0x8FE6, 0x904E, 0x971E, 0x868A, 0x4FC4, 0x5CE8, 0x6211, 0x7259,
- 0x753B, 0x81E5, 0x82BD, 0x86FE, 0x8CC0, 0x96C5, 0x9913, 0x99D5,
- 0x4ECB, 0x4F1A, 0x89E3, 0x56DE, 0x584A, 0x58CA, 0x5EFB, 0x5FEB,
- 0x602A, 0x6094, 0x6062, 0x61D0, 0x6212, 0x62D0, 0x6539,
-};
-static const unsigned short euc_to_utf8_B3[] = {
- 0x9B41, 0x6666, 0x68B0, 0x6D77, 0x7070, 0x754C, 0x7686,
- 0x7D75, 0x82A5, 0x87F9, 0x958B, 0x968E, 0x8C9D, 0x51F1, 0x52BE,
- 0x5916, 0x54B3, 0x5BB3, 0x5D16, 0x6168, 0x6982, 0x6DAF, 0x788D,
- 0x84CB, 0x8857, 0x8A72, 0x93A7, 0x9AB8, 0x6D6C, 0x99A8, 0x86D9,
- 0x57A3, 0x67FF, 0x86CE, 0x920E, 0x5283, 0x5687, 0x5404, 0x5ED3,
- 0x62E1, 0x64B9, 0x683C, 0x6838, 0x6BBB, 0x7372, 0x78BA, 0x7A6B,
- 0x899A, 0x89D2, 0x8D6B, 0x8F03, 0x90ED, 0x95A3, 0x9694, 0x9769,
- 0x5B66, 0x5CB3, 0x697D, 0x984D, 0x984E, 0x639B, 0x7B20, 0x6A2B,
- 0x6A7F, 0x68B6, 0x9C0D, 0x6F5F, 0x5272, 0x559D, 0x6070, 0x62EC,
- 0x6D3B, 0x6E07, 0x6ED1, 0x845B, 0x8910, 0x8F44, 0x4E14, 0x9C39,
- 0x53F6, 0x691B, 0x6A3A, 0x9784, 0x682A, 0x515C, 0x7AC3, 0x84B2,
- 0x91DC, 0x938C, 0x565B, 0x9D28, 0x6822, 0x8305, 0x8431,
-};
-static const unsigned short euc_to_utf8_B4[] = {
- 0x7CA5, 0x5208, 0x82C5, 0x74E6, 0x4E7E, 0x4F83, 0x51A0,
- 0x5BD2, 0x520A, 0x52D8, 0x52E7, 0x5DFB, 0x559A, 0x582A, 0x59E6,
- 0x5B8C, 0x5B98, 0x5BDB, 0x5E72, 0x5E79, 0x60A3, 0x611F, 0x6163,
- 0x61BE, 0x63DB, 0x6562, 0x67D1, 0x6853, 0x68FA, 0x6B3E, 0x6B53,
- 0x6C57, 0x6F22, 0x6F97, 0x6F45, 0x74B0, 0x7518, 0x76E3, 0x770B,
- 0x7AFF, 0x7BA1, 0x7C21, 0x7DE9, 0x7F36, 0x7FF0, 0x809D, 0x8266,
- 0x839E, 0x89B3, 0x8ACC, 0x8CAB, 0x9084, 0x9451, 0x9593, 0x9591,
- 0x95A2, 0x9665, 0x97D3, 0x9928, 0x8218, 0x4E38, 0x542B, 0x5CB8,
- 0x5DCC, 0x73A9, 0x764C, 0x773C, 0x5CA9, 0x7FEB, 0x8D0B, 0x96C1,
- 0x9811, 0x9854, 0x9858, 0x4F01, 0x4F0E, 0x5371, 0x559C, 0x5668,
- 0x57FA, 0x5947, 0x5B09, 0x5BC4, 0x5C90, 0x5E0C, 0x5E7E, 0x5FCC,
- 0x63EE, 0x673A, 0x65D7, 0x65E2, 0x671F, 0x68CB, 0x68C4,
-};
-static const unsigned short euc_to_utf8_B5[] = {
- 0x6A5F, 0x5E30, 0x6BC5, 0x6C17, 0x6C7D, 0x757F, 0x7948,
- 0x5B63, 0x7A00, 0x7D00, 0x5FBD, 0x898F, 0x8A18, 0x8CB4, 0x8D77,
- 0x8ECC, 0x8F1D, 0x98E2, 0x9A0E, 0x9B3C, 0x4E80, 0x507D, 0x5100,
- 0x5993, 0x5B9C, 0x622F, 0x6280, 0x64EC, 0x6B3A, 0x72A0, 0x7591,
- 0x7947, 0x7FA9, 0x87FB, 0x8ABC, 0x8B70, 0x63AC, 0x83CA, 0x97A0,
- 0x5409, 0x5403, 0x55AB, 0x6854, 0x6A58, 0x8A70, 0x7827, 0x6775,
- 0x9ECD, 0x5374, 0x5BA2, 0x811A, 0x8650, 0x9006, 0x4E18, 0x4E45,
- 0x4EC7, 0x4F11, 0x53CA, 0x5438, 0x5BAE, 0x5F13, 0x6025, 0x6551,
- 0x673D, 0x6C42, 0x6C72, 0x6CE3, 0x7078, 0x7403, 0x7A76, 0x7AAE,
- 0x7B08, 0x7D1A, 0x7CFE, 0x7D66, 0x65E7, 0x725B, 0x53BB, 0x5C45,
- 0x5DE8, 0x62D2, 0x62E0, 0x6319, 0x6E20, 0x865A, 0x8A31, 0x8DDD,
- 0x92F8, 0x6F01, 0x79A6, 0x9B5A, 0x4EA8, 0x4EAB, 0x4EAC,
-};
-static const unsigned short euc_to_utf8_B6[] = {
- 0x4F9B, 0x4FA0, 0x50D1, 0x5147, 0x7AF6, 0x5171, 0x51F6,
- 0x5354, 0x5321, 0x537F, 0x53EB, 0x55AC, 0x5883, 0x5CE1, 0x5F37,
- 0x5F4A, 0x602F, 0x6050, 0x606D, 0x631F, 0x6559, 0x6A4B, 0x6CC1,
- 0x72C2, 0x72ED, 0x77EF, 0x80F8, 0x8105, 0x8208, 0x854E, 0x90F7,
- 0x93E1, 0x97FF, 0x9957, 0x9A5A, 0x4EF0, 0x51DD, 0x5C2D, 0x6681,
- 0x696D, 0x5C40, 0x66F2, 0x6975, 0x7389, 0x6850, 0x7C81, 0x50C5,
- 0x52E4, 0x5747, 0x5DFE, 0x9326, 0x65A4, 0x6B23, 0x6B3D, 0x7434,
- 0x7981, 0x79BD, 0x7B4B, 0x7DCA, 0x82B9, 0x83CC, 0x887F, 0x895F,
- 0x8B39, 0x8FD1, 0x91D1, 0x541F, 0x9280, 0x4E5D, 0x5036, 0x53E5,
- 0x533A, 0x72D7, 0x7396, 0x77E9, 0x82E6, 0x8EAF, 0x99C6, 0x99C8,
- 0x99D2, 0x5177, 0x611A, 0x865E, 0x55B0, 0x7A7A, 0x5076, 0x5BD3,
- 0x9047, 0x9685, 0x4E32, 0x6ADB, 0x91E7, 0x5C51, 0x5C48,
-};
-static const unsigned short euc_to_utf8_B7[] = {
- 0x6398, 0x7A9F, 0x6C93, 0x9774, 0x8F61, 0x7AAA, 0x718A,
- 0x9688, 0x7C82, 0x6817, 0x7E70, 0x6851, 0x936C, 0x52F2, 0x541B,
- 0x85AB, 0x8A13, 0x7FA4, 0x8ECD, 0x90E1, 0x5366, 0x8888, 0x7941,
- 0x4FC2, 0x50BE, 0x5211, 0x5144, 0x5553, 0x572D, 0x73EA, 0x578B,
- 0x5951, 0x5F62, 0x5F84, 0x6075, 0x6176, 0x6167, 0x61A9, 0x63B2,
- 0x643A, 0x656C, 0x666F, 0x6842, 0x6E13, 0x7566, 0x7A3D, 0x7CFB,
- 0x7D4C, 0x7D99, 0x7E4B, 0x7F6B, 0x830E, 0x834A, 0x86CD, 0x8A08,
- 0x8A63, 0x8B66, 0x8EFD, 0x981A, 0x9D8F, 0x82B8, 0x8FCE, 0x9BE8,
- 0x5287, 0x621F, 0x6483, 0x6FC0, 0x9699, 0x6841, 0x5091, 0x6B20,
- 0x6C7A, 0x6F54, 0x7A74, 0x7D50, 0x8840, 0x8A23, 0x6708, 0x4EF6,
- 0x5039, 0x5026, 0x5065, 0x517C, 0x5238, 0x5263, 0x55A7, 0x570F,
- 0x5805, 0x5ACC, 0x5EFA, 0x61B2, 0x61F8, 0x62F3, 0x6372,
-};
-static const unsigned short euc_to_utf8_B8[] = {
- 0x691C, 0x6A29, 0x727D, 0x72AC, 0x732E, 0x7814, 0x786F,
- 0x7D79, 0x770C, 0x80A9, 0x898B, 0x8B19, 0x8CE2, 0x8ED2, 0x9063,
- 0x9375, 0x967A, 0x9855, 0x9A13, 0x9E78, 0x5143, 0x539F, 0x53B3,
- 0x5E7B, 0x5F26, 0x6E1B, 0x6E90, 0x7384, 0x73FE, 0x7D43, 0x8237,
- 0x8A00, 0x8AFA, 0x9650, 0x4E4E, 0x500B, 0x53E4, 0x547C, 0x56FA,
- 0x59D1, 0x5B64, 0x5DF1, 0x5EAB, 0x5F27, 0x6238, 0x6545, 0x67AF,
- 0x6E56, 0x72D0, 0x7CCA, 0x88B4, 0x80A1, 0x80E1, 0x83F0, 0x864E,
- 0x8A87, 0x8DE8, 0x9237, 0x96C7, 0x9867, 0x9F13, 0x4E94, 0x4E92,
- 0x4F0D, 0x5348, 0x5449, 0x543E, 0x5A2F, 0x5F8C, 0x5FA1, 0x609F,
- 0x68A7, 0x6A8E, 0x745A, 0x7881, 0x8A9E, 0x8AA4, 0x8B77, 0x9190,
- 0x4E5E, 0x9BC9, 0x4EA4, 0x4F7C, 0x4FAF, 0x5019, 0x5016, 0x5149,
- 0x516C, 0x529F, 0x52B9, 0x52FE, 0x539A, 0x53E3, 0x5411,
-};
-static const unsigned short euc_to_utf8_B9[] = {
- 0x540E, 0x5589, 0x5751, 0x57A2, 0x597D, 0x5B54, 0x5B5D,
- 0x5B8F, 0x5DE5, 0x5DE7, 0x5DF7, 0x5E78, 0x5E83, 0x5E9A, 0x5EB7,
- 0x5F18, 0x6052, 0x614C, 0x6297, 0x62D8, 0x63A7, 0x653B, 0x6602,
- 0x6643, 0x66F4, 0x676D, 0x6821, 0x6897, 0x69CB, 0x6C5F, 0x6D2A,
- 0x6D69, 0x6E2F, 0x6E9D, 0x7532, 0x7687, 0x786C, 0x7A3F, 0x7CE0,
- 0x7D05, 0x7D18, 0x7D5E, 0x7DB1, 0x8015, 0x8003, 0x80AF, 0x80B1,
- 0x8154, 0x818F, 0x822A, 0x8352, 0x884C, 0x8861, 0x8B1B, 0x8CA2,
- 0x8CFC, 0x90CA, 0x9175, 0x9271, 0x783F, 0x92FC, 0x95A4, 0x964D,
- 0x9805, 0x9999, 0x9AD8, 0x9D3B, 0x525B, 0x52AB, 0x53F7, 0x5408,
- 0x58D5, 0x62F7, 0x6FE0, 0x8C6A, 0x8F5F, 0x9EB9, 0x514B, 0x523B,
- 0x544A, 0x56FD, 0x7A40, 0x9177, 0x9D60, 0x9ED2, 0x7344, 0x6F09,
- 0x8170, 0x7511, 0x5FFD, 0x60DA, 0x9AA8, 0x72DB, 0x8FBC,
-};
-static const unsigned short euc_to_utf8_BA[] = {
- 0x6B64, 0x9803, 0x4ECA, 0x56F0, 0x5764, 0x58BE, 0x5A5A,
- 0x6068, 0x61C7, 0x660F, 0x6606, 0x6839, 0x68B1, 0x6DF7, 0x75D5,
- 0x7D3A, 0x826E, 0x9B42, 0x4E9B, 0x4F50, 0x53C9, 0x5506, 0x5D6F,
- 0x5DE6, 0x5DEE, 0x67FB, 0x6C99, 0x7473, 0x7802, 0x8A50, 0x9396,
- 0x88DF, 0x5750, 0x5EA7, 0x632B, 0x50B5, 0x50AC, 0x518D, 0x6700,
- 0x54C9, 0x585E, 0x59BB, 0x5BB0, 0x5F69, 0x624D, 0x63A1, 0x683D,
- 0x6B73, 0x6E08, 0x707D, 0x91C7, 0x7280, 0x7815, 0x7826, 0x796D,
- 0x658E, 0x7D30, 0x83DC, 0x88C1, 0x8F09, 0x969B, 0x5264, 0x5728,
- 0x6750, 0x7F6A, 0x8CA1, 0x51B4, 0x5742, 0x962A, 0x583A, 0x698A,
- 0x80B4, 0x54B2, 0x5D0E, 0x57FC, 0x7895, 0x9DFA, 0x4F5C, 0x524A,
- 0x548B, 0x643E, 0x6628, 0x6714, 0x67F5, 0x7A84, 0x7B56, 0x7D22,
- 0x932F, 0x685C, 0x9BAD, 0x7B39, 0x5319, 0x518A, 0x5237,
-};
-static const unsigned short euc_to_utf8_BB[] = {
- 0x5BDF, 0x62F6, 0x64AE, 0x64E6, 0x672D, 0x6BBA, 0x85A9,
- 0x96D1, 0x7690, 0x9BD6, 0x634C, 0x9306, 0x9BAB, 0x76BF, 0x6652,
- 0x4E09, 0x5098, 0x53C2, 0x5C71, 0x60E8, 0x6492, 0x6563, 0x685F,
- 0x71E6, 0x73CA, 0x7523, 0x7B97, 0x7E82, 0x8695, 0x8B83, 0x8CDB,
- 0x9178, 0x9910, 0x65AC, 0x66AB, 0x6B8B, 0x4ED5, 0x4ED4, 0x4F3A,
- 0x4F7F, 0x523A, 0x53F8, 0x53F2, 0x55E3, 0x56DB, 0x58EB, 0x59CB,
- 0x59C9, 0x59FF, 0x5B50, 0x5C4D, 0x5E02, 0x5E2B, 0x5FD7, 0x601D,
- 0x6307, 0x652F, 0x5B5C, 0x65AF, 0x65BD, 0x65E8, 0x679D, 0x6B62,
- 0x6B7B, 0x6C0F, 0x7345, 0x7949, 0x79C1, 0x7CF8, 0x7D19, 0x7D2B,
- 0x80A2, 0x8102, 0x81F3, 0x8996, 0x8A5E, 0x8A69, 0x8A66, 0x8A8C,
- 0x8AEE, 0x8CC7, 0x8CDC, 0x96CC, 0x98FC, 0x6B6F, 0x4E8B, 0x4F3C,
- 0x4F8D, 0x5150, 0x5B57, 0x5BFA, 0x6148, 0x6301, 0x6642,
-};
-static const unsigned short euc_to_utf8_BC[] = {
- 0x6B21, 0x6ECB, 0x6CBB, 0x723E, 0x74BD, 0x75D4, 0x78C1,
- 0x793A, 0x800C, 0x8033, 0x81EA, 0x8494, 0x8F9E, 0x6C50, 0x9E7F,
- 0x5F0F, 0x8B58, 0x9D2B, 0x7AFA, 0x8EF8, 0x5B8D, 0x96EB, 0x4E03,
- 0x53F1, 0x57F7, 0x5931, 0x5AC9, 0x5BA4, 0x6089, 0x6E7F, 0x6F06,
- 0x75BE, 0x8CEA, 0x5B9F, 0x8500, 0x7BE0, 0x5072, 0x67F4, 0x829D,
- 0x5C61, 0x854A, 0x7E1E, 0x820E, 0x5199, 0x5C04, 0x6368, 0x8D66,
- 0x659C, 0x716E, 0x793E, 0x7D17, 0x8005, 0x8B1D, 0x8ECA, 0x906E,
- 0x86C7, 0x90AA, 0x501F, 0x52FA, 0x5C3A, 0x6753, 0x707C, 0x7235,
- 0x914C, 0x91C8, 0x932B, 0x82E5, 0x5BC2, 0x5F31, 0x60F9, 0x4E3B,
- 0x53D6, 0x5B88, 0x624B, 0x6731, 0x6B8A, 0x72E9, 0x73E0, 0x7A2E,
- 0x816B, 0x8DA3, 0x9152, 0x9996, 0x5112, 0x53D7, 0x546A, 0x5BFF,
- 0x6388, 0x6A39, 0x7DAC, 0x9700, 0x56DA, 0x53CE, 0x5468,
-};
-static const unsigned short euc_to_utf8_BD[] = {
- 0x5B97, 0x5C31, 0x5DDE, 0x4FEE, 0x6101, 0x62FE, 0x6D32,
- 0x79C0, 0x79CB, 0x7D42, 0x7E4D, 0x7FD2, 0x81ED, 0x821F, 0x8490,
- 0x8846, 0x8972, 0x8B90, 0x8E74, 0x8F2F, 0x9031, 0x914B, 0x916C,
- 0x96C6, 0x919C, 0x4EC0, 0x4F4F, 0x5145, 0x5341, 0x5F93, 0x620E,
- 0x67D4, 0x6C41, 0x6E0B, 0x7363, 0x7E26, 0x91CD, 0x9283, 0x53D4,
- 0x5919, 0x5BBF, 0x6DD1, 0x795D, 0x7E2E, 0x7C9B, 0x587E, 0x719F,
- 0x51FA, 0x8853, 0x8FF0, 0x4FCA, 0x5CFB, 0x6625, 0x77AC, 0x7AE3,
- 0x821C, 0x99FF, 0x51C6, 0x5FAA, 0x65EC, 0x696F, 0x6B89, 0x6DF3,
- 0x6E96, 0x6F64, 0x76FE, 0x7D14, 0x5DE1, 0x9075, 0x9187, 0x9806,
- 0x51E6, 0x521D, 0x6240, 0x6691, 0x66D9, 0x6E1A, 0x5EB6, 0x7DD2,
- 0x7F72, 0x66F8, 0x85AF, 0x85F7, 0x8AF8, 0x52A9, 0x53D9, 0x5973,
- 0x5E8F, 0x5F90, 0x6055, 0x92E4, 0x9664, 0x50B7, 0x511F,
-};
-static const unsigned short euc_to_utf8_BE[] = {
- 0x52DD, 0x5320, 0x5347, 0x53EC, 0x54E8, 0x5546, 0x5531,
- 0x5617, 0x5968, 0x59BE, 0x5A3C, 0x5BB5, 0x5C06, 0x5C0F, 0x5C11,
- 0x5C1A, 0x5E84, 0x5E8A, 0x5EE0, 0x5F70, 0x627F, 0x6284, 0x62DB,
- 0x638C, 0x6377, 0x6607, 0x660C, 0x662D, 0x6676, 0x677E, 0x68A2,
- 0x6A1F, 0x6A35, 0x6CBC, 0x6D88, 0x6E09, 0x6E58, 0x713C, 0x7126,
- 0x7167, 0x75C7, 0x7701, 0x785D, 0x7901, 0x7965, 0x79F0, 0x7AE0,
- 0x7B11, 0x7CA7, 0x7D39, 0x8096, 0x83D6, 0x848B, 0x8549, 0x885D,
- 0x88F3, 0x8A1F, 0x8A3C, 0x8A54, 0x8A73, 0x8C61, 0x8CDE, 0x91A4,
- 0x9266, 0x937E, 0x9418, 0x969C, 0x9798, 0x4E0A, 0x4E08, 0x4E1E,
- 0x4E57, 0x5197, 0x5270, 0x57CE, 0x5834, 0x58CC, 0x5B22, 0x5E38,
- 0x60C5, 0x64FE, 0x6761, 0x6756, 0x6D44, 0x72B6, 0x7573, 0x7A63,
- 0x84B8, 0x8B72, 0x91B8, 0x9320, 0x5631, 0x57F4, 0x98FE,
-};
-static const unsigned short euc_to_utf8_BF[] = {
- 0x62ED, 0x690D, 0x6B96, 0x71ED, 0x7E54, 0x8077, 0x8272,
- 0x89E6, 0x98DF, 0x8755, 0x8FB1, 0x5C3B, 0x4F38, 0x4FE1, 0x4FB5,
- 0x5507, 0x5A20, 0x5BDD, 0x5BE9, 0x5FC3, 0x614E, 0x632F, 0x65B0,
- 0x664B, 0x68EE, 0x699B, 0x6D78, 0x6DF1, 0x7533, 0x75B9, 0x771F,
- 0x795E, 0x79E6, 0x7D33, 0x81E3, 0x82AF, 0x85AA, 0x89AA, 0x8A3A,
- 0x8EAB, 0x8F9B, 0x9032, 0x91DD, 0x9707, 0x4EBA, 0x4EC1, 0x5203,
- 0x5875, 0x58EC, 0x5C0B, 0x751A, 0x5C3D, 0x814E, 0x8A0A, 0x8FC5,
- 0x9663, 0x976D, 0x7B25, 0x8ACF, 0x9808, 0x9162, 0x56F3, 0x53A8,
- 0x9017, 0x5439, 0x5782, 0x5E25, 0x63A8, 0x6C34, 0x708A, 0x7761,
- 0x7C8B, 0x7FE0, 0x8870, 0x9042, 0x9154, 0x9310, 0x9318, 0x968F,
- 0x745E, 0x9AC4, 0x5D07, 0x5D69, 0x6570, 0x67A2, 0x8DA8, 0x96DB,
- 0x636E, 0x6749, 0x6919, 0x83C5, 0x9817, 0x96C0, 0x88FE,
-};
-static const unsigned short euc_to_utf8_C0[] = {
- 0x6F84, 0x647A, 0x5BF8, 0x4E16, 0x702C, 0x755D, 0x662F,
- 0x51C4, 0x5236, 0x52E2, 0x59D3, 0x5F81, 0x6027, 0x6210, 0x653F,
- 0x6574, 0x661F, 0x6674, 0x68F2, 0x6816, 0x6B63, 0x6E05, 0x7272,
- 0x751F, 0x76DB, 0x7CBE, 0x8056, 0x58F0, 0x88FD, 0x897F, 0x8AA0,
- 0x8A93, 0x8ACB, 0x901D, 0x9192, 0x9752, 0x9759, 0x6589, 0x7A0E,
- 0x8106, 0x96BB, 0x5E2D, 0x60DC, 0x621A, 0x65A5, 0x6614, 0x6790,
- 0x77F3, 0x7A4D, 0x7C4D, 0x7E3E, 0x810A, 0x8CAC, 0x8D64, 0x8DE1,
- 0x8E5F, 0x78A9, 0x5207, 0x62D9, 0x63A5, 0x6442, 0x6298, 0x8A2D,
- 0x7A83, 0x7BC0, 0x8AAC, 0x96EA, 0x7D76, 0x820C, 0x8749, 0x4ED9,
- 0x5148, 0x5343, 0x5360, 0x5BA3, 0x5C02, 0x5C16, 0x5DDD, 0x6226,
- 0x6247, 0x64B0, 0x6813, 0x6834, 0x6CC9, 0x6D45, 0x6D17, 0x67D3,
- 0x6F5C, 0x714E, 0x717D, 0x65CB, 0x7A7F, 0x7BAD, 0x7DDA,
-};
-static const unsigned short euc_to_utf8_C1[] = {
- 0x7E4A, 0x7FA8, 0x817A, 0x821B, 0x8239, 0x85A6, 0x8A6E,
- 0x8CCE, 0x8DF5, 0x9078, 0x9077, 0x92AD, 0x9291, 0x9583, 0x9BAE,
- 0x524D, 0x5584, 0x6F38, 0x7136, 0x5168, 0x7985, 0x7E55, 0x81B3,
- 0x7CCE, 0x564C, 0x5851, 0x5CA8, 0x63AA, 0x66FE, 0x66FD, 0x695A,
- 0x72D9, 0x758F, 0x758E, 0x790E, 0x7956, 0x79DF, 0x7C97, 0x7D20,
- 0x7D44, 0x8607, 0x8A34, 0x963B, 0x9061, 0x9F20, 0x50E7, 0x5275,
- 0x53CC, 0x53E2, 0x5009, 0x55AA, 0x58EE, 0x594F, 0x723D, 0x5B8B,
- 0x5C64, 0x531D, 0x60E3, 0x60F3, 0x635C, 0x6383, 0x633F, 0x63BB,
- 0x64CD, 0x65E9, 0x66F9, 0x5DE3, 0x69CD, 0x69FD, 0x6F15, 0x71E5,
- 0x4E89, 0x75E9, 0x76F8, 0x7A93, 0x7CDF, 0x7DCF, 0x7D9C, 0x8061,
- 0x8349, 0x8358, 0x846C, 0x84BC, 0x85FB, 0x88C5, 0x8D70, 0x9001,
- 0x906D, 0x9397, 0x971C, 0x9A12, 0x50CF, 0x5897, 0x618E,
-};
-static const unsigned short euc_to_utf8_C2[] = {
- 0x81D3, 0x8535, 0x8D08, 0x9020, 0x4FC3, 0x5074, 0x5247,
- 0x5373, 0x606F, 0x6349, 0x675F, 0x6E2C, 0x8DB3, 0x901F, 0x4FD7,
- 0x5C5E, 0x8CCA, 0x65CF, 0x7D9A, 0x5352, 0x8896, 0x5176, 0x63C3,
- 0x5B58, 0x5B6B, 0x5C0A, 0x640D, 0x6751, 0x905C, 0x4ED6, 0x591A,
- 0x592A, 0x6C70, 0x8A51, 0x553E, 0x5815, 0x59A5, 0x60F0, 0x6253,
- 0x67C1, 0x8235, 0x6955, 0x9640, 0x99C4, 0x9A28, 0x4F53, 0x5806,
- 0x5BFE, 0x8010, 0x5CB1, 0x5E2F, 0x5F85, 0x6020, 0x614B, 0x6234,
- 0x66FF, 0x6CF0, 0x6EDE, 0x80CE, 0x817F, 0x82D4, 0x888B, 0x8CB8,
- 0x9000, 0x902E, 0x968A, 0x9EDB, 0x9BDB, 0x4EE3, 0x53F0, 0x5927,
- 0x7B2C, 0x918D, 0x984C, 0x9DF9, 0x6EDD, 0x7027, 0x5353, 0x5544,
- 0x5B85, 0x6258, 0x629E, 0x62D3, 0x6CA2, 0x6FEF, 0x7422, 0x8A17,
- 0x9438, 0x6FC1, 0x8AFE, 0x8338, 0x51E7, 0x86F8, 0x53EA,
-};
-static const unsigned short euc_to_utf8_C3[] = {
- 0x53E9, 0x4F46, 0x9054, 0x8FB0, 0x596A, 0x8131, 0x5DFD,
- 0x7AEA, 0x8FBF, 0x68DA, 0x8C37, 0x72F8, 0x9C48, 0x6A3D, 0x8AB0,
- 0x4E39, 0x5358, 0x5606, 0x5766, 0x62C5, 0x63A2, 0x65E6, 0x6B4E,
- 0x6DE1, 0x6E5B, 0x70AD, 0x77ED, 0x7AEF, 0x7BAA, 0x7DBB, 0x803D,
- 0x80C6, 0x86CB, 0x8A95, 0x935B, 0x56E3, 0x58C7, 0x5F3E, 0x65AD,
- 0x6696, 0x6A80, 0x6BB5, 0x7537, 0x8AC7, 0x5024, 0x77E5, 0x5730,
- 0x5F1B, 0x6065, 0x667A, 0x6C60, 0x75F4, 0x7A1A, 0x7F6E, 0x81F4,
- 0x8718, 0x9045, 0x99B3, 0x7BC9, 0x755C, 0x7AF9, 0x7B51, 0x84C4,
- 0x9010, 0x79E9, 0x7A92, 0x8336, 0x5AE1, 0x7740, 0x4E2D, 0x4EF2,
- 0x5B99, 0x5FE0, 0x62BD, 0x663C, 0x67F1, 0x6CE8, 0x866B, 0x8877,
- 0x8A3B, 0x914E, 0x92F3, 0x99D0, 0x6A17, 0x7026, 0x732A, 0x82E7,
- 0x8457, 0x8CAF, 0x4E01, 0x5146, 0x51CB, 0x558B, 0x5BF5,
-};
-static const unsigned short euc_to_utf8_C4[] = {
- 0x5E16, 0x5E33, 0x5E81, 0x5F14, 0x5F35, 0x5F6B, 0x5FB4,
- 0x61F2, 0x6311, 0x66A2, 0x671D, 0x6F6E, 0x7252, 0x753A, 0x773A,
- 0x8074, 0x8139, 0x8178, 0x8776, 0x8ABF, 0x8ADC, 0x8D85, 0x8DF3,
- 0x929A, 0x9577, 0x9802, 0x9CE5, 0x52C5, 0x6357, 0x76F4, 0x6715,
- 0x6C88, 0x73CD, 0x8CC3, 0x93AE, 0x9673, 0x6D25, 0x589C, 0x690E,
- 0x69CC, 0x8FFD, 0x939A, 0x75DB, 0x901A, 0x585A, 0x6802, 0x63B4,
- 0x69FB, 0x4F43, 0x6F2C, 0x67D8, 0x8FBB, 0x8526, 0x7DB4, 0x9354,
- 0x693F, 0x6F70, 0x576A, 0x58F7, 0x5B2C, 0x7D2C, 0x722A, 0x540A,
- 0x91E3, 0x9DB4, 0x4EAD, 0x4F4E, 0x505C, 0x5075, 0x5243, 0x8C9E,
- 0x5448, 0x5824, 0x5B9A, 0x5E1D, 0x5E95, 0x5EAD, 0x5EF7, 0x5F1F,
- 0x608C, 0x62B5, 0x633A, 0x63D0, 0x68AF, 0x6C40, 0x7887, 0x798E,
- 0x7A0B, 0x7DE0, 0x8247, 0x8A02, 0x8AE6, 0x8E44, 0x9013,
-};
-static const unsigned short euc_to_utf8_C5[] = {
- 0x90B8, 0x912D, 0x91D8, 0x9F0E, 0x6CE5, 0x6458, 0x64E2,
- 0x6575, 0x6EF4, 0x7684, 0x7B1B, 0x9069, 0x93D1, 0x6EBA, 0x54F2,
- 0x5FB9, 0x64A4, 0x8F4D, 0x8FED, 0x9244, 0x5178, 0x586B, 0x5929,
- 0x5C55, 0x5E97, 0x6DFB, 0x7E8F, 0x751C, 0x8CBC, 0x8EE2, 0x985B,
- 0x70B9, 0x4F1D, 0x6BBF, 0x6FB1, 0x7530, 0x96FB, 0x514E, 0x5410,
- 0x5835, 0x5857, 0x59AC, 0x5C60, 0x5F92, 0x6597, 0x675C, 0x6E21,
- 0x767B, 0x83DF, 0x8CED, 0x9014, 0x90FD, 0x934D, 0x7825, 0x783A,
- 0x52AA, 0x5EA6, 0x571F, 0x5974, 0x6012, 0x5012, 0x515A, 0x51AC,
- 0x51CD, 0x5200, 0x5510, 0x5854, 0x5858, 0x5957, 0x5B95, 0x5CF6,
- 0x5D8B, 0x60BC, 0x6295, 0x642D, 0x6771, 0x6843, 0x68BC, 0x68DF,
- 0x76D7, 0x6DD8, 0x6E6F, 0x6D9B, 0x706F, 0x71C8, 0x5F53, 0x75D8,
- 0x7977, 0x7B49, 0x7B54, 0x7B52, 0x7CD6, 0x7D71, 0x5230,
-};
-static const unsigned short euc_to_utf8_C6[] = {
- 0x8463, 0x8569, 0x85E4, 0x8A0E, 0x8B04, 0x8C46, 0x8E0F,
- 0x9003, 0x900F, 0x9419, 0x9676, 0x982D, 0x9A30, 0x95D8, 0x50CD,
- 0x52D5, 0x540C, 0x5802, 0x5C0E, 0x61A7, 0x649E, 0x6D1E, 0x77B3,
- 0x7AE5, 0x80F4, 0x8404, 0x9053, 0x9285, 0x5CE0, 0x9D07, 0x533F,
- 0x5F97, 0x5FB3, 0x6D9C, 0x7279, 0x7763, 0x79BF, 0x7BE4, 0x6BD2,
- 0x72EC, 0x8AAD, 0x6803, 0x6A61, 0x51F8, 0x7A81, 0x6934, 0x5C4A,
- 0x9CF6, 0x82EB, 0x5BC5, 0x9149, 0x701E, 0x5678, 0x5C6F, 0x60C7,
- 0x6566, 0x6C8C, 0x8C5A, 0x9041, 0x9813, 0x5451, 0x66C7, 0x920D,
- 0x5948, 0x90A3, 0x5185, 0x4E4D, 0x51EA, 0x8599, 0x8B0E, 0x7058,
- 0x637A, 0x934B, 0x6962, 0x99B4, 0x7E04, 0x7577, 0x5357, 0x6960,
- 0x8EDF, 0x96E3, 0x6C5D, 0x4E8C, 0x5C3C, 0x5F10, 0x8FE9, 0x5302,
- 0x8CD1, 0x8089, 0x8679, 0x5EFF, 0x65E5, 0x4E73, 0x5165,
-};
-static const unsigned short euc_to_utf8_C7[] = {
- 0x5982, 0x5C3F, 0x97EE, 0x4EFB, 0x598A, 0x5FCD, 0x8A8D,
- 0x6FE1, 0x79B0, 0x7962, 0x5BE7, 0x8471, 0x732B, 0x71B1, 0x5E74,
- 0x5FF5, 0x637B, 0x649A, 0x71C3, 0x7C98, 0x4E43, 0x5EFC, 0x4E4B,
- 0x57DC, 0x56A2, 0x60A9, 0x6FC3, 0x7D0D, 0x80FD, 0x8133, 0x81BF,
- 0x8FB2, 0x8997, 0x86A4, 0x5DF4, 0x628A, 0x64AD, 0x8987, 0x6777,
- 0x6CE2, 0x6D3E, 0x7436, 0x7834, 0x5A46, 0x7F75, 0x82AD, 0x99AC,
- 0x4FF3, 0x5EC3, 0x62DD, 0x6392, 0x6557, 0x676F, 0x76C3, 0x724C,
- 0x80CC, 0x80BA, 0x8F29, 0x914D, 0x500D, 0x57F9, 0x5A92, 0x6885,
- 0x6973, 0x7164, 0x72FD, 0x8CB7, 0x58F2, 0x8CE0, 0x966A, 0x9019,
- 0x877F, 0x79E4, 0x77E7, 0x8429, 0x4F2F, 0x5265, 0x535A, 0x62CD,
- 0x67CF, 0x6CCA, 0x767D, 0x7B94, 0x7C95, 0x8236, 0x8584, 0x8FEB,
- 0x66DD, 0x6F20, 0x7206, 0x7E1B, 0x83AB, 0x99C1, 0x9EA6,
-};
-static const unsigned short euc_to_utf8_C8[] = {
- 0x51FD, 0x7BB1, 0x7872, 0x7BB8, 0x8087, 0x7B48, 0x6AE8,
- 0x5E61, 0x808C, 0x7551, 0x7560, 0x516B, 0x9262, 0x6E8C, 0x767A,
- 0x9197, 0x9AEA, 0x4F10, 0x7F70, 0x629C, 0x7B4F, 0x95A5, 0x9CE9,
- 0x567A, 0x5859, 0x86E4, 0x96BC, 0x4F34, 0x5224, 0x534A, 0x53CD,
- 0x53DB, 0x5E06, 0x642C, 0x6591, 0x677F, 0x6C3E, 0x6C4E, 0x7248,
- 0x72AF, 0x73ED, 0x7554, 0x7E41, 0x822C, 0x85E9, 0x8CA9, 0x7BC4,
- 0x91C6, 0x7169, 0x9812, 0x98EF, 0x633D, 0x6669, 0x756A, 0x76E4,
- 0x78D0, 0x8543, 0x86EE, 0x532A, 0x5351, 0x5426, 0x5983, 0x5E87,
- 0x5F7C, 0x60B2, 0x6249, 0x6279, 0x62AB, 0x6590, 0x6BD4, 0x6CCC,
- 0x75B2, 0x76AE, 0x7891, 0x79D8, 0x7DCB, 0x7F77, 0x80A5, 0x88AB,
- 0x8AB9, 0x8CBB, 0x907F, 0x975E, 0x98DB, 0x6A0B, 0x7C38, 0x5099,
- 0x5C3E, 0x5FAE, 0x6787, 0x6BD8, 0x7435, 0x7709, 0x7F8E,
-};
-static const unsigned short euc_to_utf8_C9[] = {
- 0x9F3B, 0x67CA, 0x7A17, 0x5339, 0x758B, 0x9AED, 0x5F66,
- 0x819D, 0x83F1, 0x8098, 0x5F3C, 0x5FC5, 0x7562, 0x7B46, 0x903C,
- 0x6867, 0x59EB, 0x5A9B, 0x7D10, 0x767E, 0x8B2C, 0x4FF5, 0x5F6A,
- 0x6A19, 0x6C37, 0x6F02, 0x74E2, 0x7968, 0x8868, 0x8A55, 0x8C79,
- 0x5EDF, 0x63CF, 0x75C5, 0x79D2, 0x82D7, 0x9328, 0x92F2, 0x849C,
- 0x86ED, 0x9C2D, 0x54C1, 0x5F6C, 0x658C, 0x6D5C, 0x7015, 0x8CA7,
- 0x8CD3, 0x983B, 0x654F, 0x74F6, 0x4E0D, 0x4ED8, 0x57E0, 0x592B,
- 0x5A66, 0x5BCC, 0x51A8, 0x5E03, 0x5E9C, 0x6016, 0x6276, 0x6577,
- 0x65A7, 0x666E, 0x6D6E, 0x7236, 0x7B26, 0x8150, 0x819A, 0x8299,
- 0x8B5C, 0x8CA0, 0x8CE6, 0x8D74, 0x961C, 0x9644, 0x4FAE, 0x64AB,
- 0x6B66, 0x821E, 0x8461, 0x856A, 0x90E8, 0x5C01, 0x6953, 0x98A8,
- 0x847A, 0x8557, 0x4F0F, 0x526F, 0x5FA9, 0x5E45, 0x670D,
-};
-static const unsigned short euc_to_utf8_CA[] = {
- 0x798F, 0x8179, 0x8907, 0x8986, 0x6DF5, 0x5F17, 0x6255,
- 0x6CB8, 0x4ECF, 0x7269, 0x9B92, 0x5206, 0x543B, 0x5674, 0x58B3,
- 0x61A4, 0x626E, 0x711A, 0x596E, 0x7C89, 0x7CDE, 0x7D1B, 0x96F0,
- 0x6587, 0x805E, 0x4E19, 0x4F75, 0x5175, 0x5840, 0x5E63, 0x5E73,
- 0x5F0A, 0x67C4, 0x4E26, 0x853D, 0x9589, 0x965B, 0x7C73, 0x9801,
- 0x50FB, 0x58C1, 0x7656, 0x78A7, 0x5225, 0x77A5, 0x8511, 0x7B86,
- 0x504F, 0x5909, 0x7247, 0x7BC7, 0x7DE8, 0x8FBA, 0x8FD4, 0x904D,
- 0x4FBF, 0x52C9, 0x5A29, 0x5F01, 0x97AD, 0x4FDD, 0x8217, 0x92EA,
- 0x5703, 0x6355, 0x6B69, 0x752B, 0x88DC, 0x8F14, 0x7A42, 0x52DF,
- 0x5893, 0x6155, 0x620A, 0x66AE, 0x6BCD, 0x7C3F, 0x83E9, 0x5023,
- 0x4FF8, 0x5305, 0x5446, 0x5831, 0x5949, 0x5B9D, 0x5CF0, 0x5CEF,
- 0x5D29, 0x5E96, 0x62B1, 0x6367, 0x653E, 0x65B9, 0x670B,
-};
-static const unsigned short euc_to_utf8_CB[] = {
- 0x6CD5, 0x6CE1, 0x70F9, 0x7832, 0x7E2B, 0x80DE, 0x82B3,
- 0x840C, 0x84EC, 0x8702, 0x8912, 0x8A2A, 0x8C4A, 0x90A6, 0x92D2,
- 0x98FD, 0x9CF3, 0x9D6C, 0x4E4F, 0x4EA1, 0x508D, 0x5256, 0x574A,
- 0x59A8, 0x5E3D, 0x5FD8, 0x5FD9, 0x623F, 0x66B4, 0x671B, 0x67D0,
- 0x68D2, 0x5192, 0x7D21, 0x80AA, 0x81A8, 0x8B00, 0x8C8C, 0x8CBF,
- 0x927E, 0x9632, 0x5420, 0x982C, 0x5317, 0x50D5, 0x535C, 0x58A8,
- 0x64B2, 0x6734, 0x7267, 0x7766, 0x7A46, 0x91E6, 0x52C3, 0x6CA1,
- 0x6B86, 0x5800, 0x5E4C, 0x5954, 0x672C, 0x7FFB, 0x51E1, 0x76C6,
- 0x6469, 0x78E8, 0x9B54, 0x9EBB, 0x57CB, 0x59B9, 0x6627, 0x679A,
- 0x6BCE, 0x54E9, 0x69D9, 0x5E55, 0x819C, 0x6795, 0x9BAA, 0x67FE,
- 0x9C52, 0x685D, 0x4EA6, 0x4FE3, 0x53C8, 0x62B9, 0x672B, 0x6CAB,
- 0x8FC4, 0x4FAD, 0x7E6D, 0x9EBF, 0x4E07, 0x6162, 0x6E80,
-};
-static const unsigned short euc_to_utf8_CC[] = {
- 0x6F2B, 0x8513, 0x5473, 0x672A, 0x9B45, 0x5DF3, 0x7B95,
- 0x5CAC, 0x5BC6, 0x871C, 0x6E4A, 0x84D1, 0x7A14, 0x8108, 0x5999,
- 0x7C8D, 0x6C11, 0x7720, 0x52D9, 0x5922, 0x7121, 0x725F, 0x77DB,
- 0x9727, 0x9D61, 0x690B, 0x5A7F, 0x5A18, 0x51A5, 0x540D, 0x547D,
- 0x660E, 0x76DF, 0x8FF7, 0x9298, 0x9CF4, 0x59EA, 0x725D, 0x6EC5,
- 0x514D, 0x68C9, 0x7DBF, 0x7DEC, 0x9762, 0x9EBA, 0x6478, 0x6A21,
- 0x8302, 0x5984, 0x5B5F, 0x6BDB, 0x731B, 0x76F2, 0x7DB2, 0x8017,
- 0x8499, 0x5132, 0x6728, 0x9ED9, 0x76EE, 0x6762, 0x52FF, 0x9905,
- 0x5C24, 0x623B, 0x7C7E, 0x8CB0, 0x554F, 0x60B6, 0x7D0B, 0x9580,
- 0x5301, 0x4E5F, 0x51B6, 0x591C, 0x723A, 0x8036, 0x91CE, 0x5F25,
- 0x77E2, 0x5384, 0x5F79, 0x7D04, 0x85AC, 0x8A33, 0x8E8D, 0x9756,
- 0x67F3, 0x85AE, 0x9453, 0x6109, 0x6108, 0x6CB9, 0x7652,
-};
-static const unsigned short euc_to_utf8_CD[] = {
- 0x8AED, 0x8F38, 0x552F, 0x4F51, 0x512A, 0x52C7, 0x53CB,
- 0x5BA5, 0x5E7D, 0x60A0, 0x6182, 0x63D6, 0x6709, 0x67DA, 0x6E67,
- 0x6D8C, 0x7336, 0x7337, 0x7531, 0x7950, 0x88D5, 0x8A98, 0x904A,
- 0x9091, 0x90F5, 0x96C4, 0x878D, 0x5915, 0x4E88, 0x4F59, 0x4E0E,
- 0x8A89, 0x8F3F, 0x9810, 0x50AD, 0x5E7C, 0x5996, 0x5BB9, 0x5EB8,
- 0x63DA, 0x63FA, 0x64C1, 0x66DC, 0x694A, 0x69D8, 0x6D0B, 0x6EB6,
- 0x7194, 0x7528, 0x7AAF, 0x7F8A, 0x8000, 0x8449, 0x84C9, 0x8981,
- 0x8B21, 0x8E0A, 0x9065, 0x967D, 0x990A, 0x617E, 0x6291, 0x6B32,
- 0x6C83, 0x6D74, 0x7FCC, 0x7FFC, 0x6DC0, 0x7F85, 0x87BA, 0x88F8,
- 0x6765, 0x83B1, 0x983C, 0x96F7, 0x6D1B, 0x7D61, 0x843D, 0x916A,
- 0x4E71, 0x5375, 0x5D50, 0x6B04, 0x6FEB, 0x85CD, 0x862D, 0x89A7,
- 0x5229, 0x540F, 0x5C65, 0x674E, 0x68A8, 0x7406, 0x7483,
-};
-static const unsigned short euc_to_utf8_CE[] = {
- 0x75E2, 0x88CF, 0x88E1, 0x91CC, 0x96E2, 0x9678, 0x5F8B,
- 0x7387, 0x7ACB, 0x844E, 0x63A0, 0x7565, 0x5289, 0x6D41, 0x6E9C,
- 0x7409, 0x7559, 0x786B, 0x7C92, 0x9686, 0x7ADC, 0x9F8D, 0x4FB6,
- 0x616E, 0x65C5, 0x865C, 0x4E86, 0x4EAE, 0x50DA, 0x4E21, 0x51CC,
- 0x5BEE, 0x6599, 0x6881, 0x6DBC, 0x731F, 0x7642, 0x77AD, 0x7A1C,
- 0x7CE7, 0x826F, 0x8AD2, 0x907C, 0x91CF, 0x9675, 0x9818, 0x529B,
- 0x7DD1, 0x502B, 0x5398, 0x6797, 0x6DCB, 0x71D0, 0x7433, 0x81E8,
- 0x8F2A, 0x96A3, 0x9C57, 0x9E9F, 0x7460, 0x5841, 0x6D99, 0x7D2F,
- 0x985E, 0x4EE4, 0x4F36, 0x4F8B, 0x51B7, 0x52B1, 0x5DBA, 0x601C,
- 0x73B2, 0x793C, 0x82D3, 0x9234, 0x96B7, 0x96F6, 0x970A, 0x9E97,
- 0x9F62, 0x66A6, 0x6B74, 0x5217, 0x52A3, 0x70C8, 0x88C2, 0x5EC9,
- 0x604B, 0x6190, 0x6F23, 0x7149, 0x7C3E, 0x7DF4, 0x806F,
-};
-static const unsigned short euc_to_utf8_CF[] = {
- 0x84EE, 0x9023, 0x932C, 0x5442, 0x9B6F, 0x6AD3, 0x7089,
- 0x8CC2, 0x8DEF, 0x9732, 0x52B4, 0x5A41, 0x5ECA, 0x5F04, 0x6717,
- 0x697C, 0x6994, 0x6D6A, 0x6F0F, 0x7262, 0x72FC, 0x7BED, 0x8001,
- 0x807E, 0x874B, 0x90CE, 0x516D, 0x9E93, 0x7984, 0x808B, 0x9332,
- 0x8AD6, 0x502D, 0x548C, 0x8A71, 0x6B6A, 0x8CC4, 0x8107, 0x60D1,
- 0x67A0, 0x9DF2, 0x4E99, 0x4E98, 0x9C10, 0x8A6B, 0x85C1, 0x8568,
- 0x6900, 0x6E7E, 0x7897, 0x8155, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short euc_to_utf8_CF_x0213[] = {
- 0x84EE, 0x9023, 0x932C, 0x5442, 0x9B6F, 0x6AD3, 0x7089,
- 0x8CC2, 0x8DEF, 0x9732, 0x52B4, 0x5A41, 0x5ECA, 0x5F04, 0x6717,
- 0x697C, 0x6994, 0x6D6A, 0x6F0F, 0x7262, 0x72FC, 0x7BED, 0x8001,
- 0x807E, 0x874B, 0x90CE, 0x516D, 0x9E93, 0x7984, 0x808B, 0x9332,
- 0x8AD6, 0x502D, 0x548C, 0x8A71, 0x6B6A, 0x8CC4, 0x8107, 0x60D1,
- 0x67A0, 0x9DF2, 0x4E99, 0x4E98, 0x9C10, 0x8A6B, 0x85C1, 0x8568,
- 0x6900, 0x6E7E, 0x7897, 0x8155, 0xD842 /*0xDF9F*/, 0x5B41, 0x5B56, 0x5B7D,
- 0x5B93, 0x5BD8, 0x5BEC, 0x5C12, 0x5C1E, 0x5C23, 0x5C2B, 0x378D,
- 0x5C62, 0xFA3B, 0xFA3C, 0xD845 /*0xDEB4*/, 0x5C7A, 0x5C8F, 0x5C9F, 0x5CA3,
- 0x5CAA, 0x5CBA, 0x5CCB, 0x5CD0, 0x5CD2, 0x5CF4, 0xD847 /*0xDE34*/, 0x37E2,
- 0x5D0D, 0x5D27, 0xFA11, 0x5D46, 0x5D47, 0x5D53, 0x5D4A, 0x5D6D,
- 0x5D81, 0x5DA0, 0x5DA4, 0x5DA7, 0x5DB8, 0x5DCB, 0x541E,
-};
-static const unsigned short euc_to_utf8_D0[] = {
- 0x5F0C, 0x4E10, 0x4E15, 0x4E2A, 0x4E31, 0x4E36, 0x4E3C,
- 0x4E3F, 0x4E42, 0x4E56, 0x4E58, 0x4E82, 0x4E85, 0x8C6B, 0x4E8A,
- 0x8212, 0x5F0D, 0x4E8E, 0x4E9E, 0x4E9F, 0x4EA0, 0x4EA2, 0x4EB0,
- 0x4EB3, 0x4EB6, 0x4ECE, 0x4ECD, 0x4EC4, 0x4EC6, 0x4EC2, 0x4ED7,
- 0x4EDE, 0x4EED, 0x4EDF, 0x4EF7, 0x4F09, 0x4F5A, 0x4F30, 0x4F5B,
- 0x4F5D, 0x4F57, 0x4F47, 0x4F76, 0x4F88, 0x4F8F, 0x4F98, 0x4F7B,
- 0x4F69, 0x4F70, 0x4F91, 0x4F6F, 0x4F86, 0x4F96, 0x5118, 0x4FD4,
- 0x4FDF, 0x4FCE, 0x4FD8, 0x4FDB, 0x4FD1, 0x4FDA, 0x4FD0, 0x4FE4,
- 0x4FE5, 0x501A, 0x5028, 0x5014, 0x502A, 0x5025, 0x5005, 0x4F1C,
- 0x4FF6, 0x5021, 0x5029, 0x502C, 0x4FFE, 0x4FEF, 0x5011, 0x5006,
- 0x5043, 0x5047, 0x6703, 0x5055, 0x5050, 0x5048, 0x505A, 0x5056,
- 0x506C, 0x5078, 0x5080, 0x509A, 0x5085, 0x50B4, 0x50B2,
-};
-static const unsigned short euc_to_utf8_D1[] = {
- 0x50C9, 0x50CA, 0x50B3, 0x50C2, 0x50D6, 0x50DE, 0x50E5,
- 0x50ED, 0x50E3, 0x50EE, 0x50F9, 0x50F5, 0x5109, 0x5101, 0x5102,
- 0x5116, 0x5115, 0x5114, 0x511A, 0x5121, 0x513A, 0x5137, 0x513C,
- 0x513B, 0x513F, 0x5140, 0x5152, 0x514C, 0x5154, 0x5162, 0x7AF8,
- 0x5169, 0x516A, 0x516E, 0x5180, 0x5182, 0x56D8, 0x518C, 0x5189,
- 0x518F, 0x5191, 0x5193, 0x5195, 0x5196, 0x51A4, 0x51A6, 0x51A2,
- 0x51A9, 0x51AA, 0x51AB, 0x51B3, 0x51B1, 0x51B2, 0x51B0, 0x51B5,
- 0x51BD, 0x51C5, 0x51C9, 0x51DB, 0x51E0, 0x8655, 0x51E9, 0x51ED,
- 0x51F0, 0x51F5, 0x51FE, 0x5204, 0x520B, 0x5214, 0x520E, 0x5227,
- 0x522A, 0x522E, 0x5233, 0x5239, 0x524F, 0x5244, 0x524B, 0x524C,
- 0x525E, 0x5254, 0x526A, 0x5274, 0x5269, 0x5273, 0x527F, 0x527D,
- 0x528D, 0x5294, 0x5292, 0x5271, 0x5288, 0x5291, 0x8FA8,
-};
-static const unsigned short euc_to_utf8_D2[] = {
- 0x8FA7, 0x52AC, 0x52AD, 0x52BC, 0x52B5, 0x52C1, 0x52CD,
- 0x52D7, 0x52DE, 0x52E3, 0x52E6, 0x98ED, 0x52E0, 0x52F3, 0x52F5,
- 0x52F8, 0x52F9, 0x5306, 0x5308, 0x7538, 0x530D, 0x5310, 0x530F,
- 0x5315, 0x531A, 0x5323, 0x532F, 0x5331, 0x5333, 0x5338, 0x5340,
- 0x5346, 0x5345, 0x4E17, 0x5349, 0x534D, 0x51D6, 0x535E, 0x5369,
- 0x536E, 0x5918, 0x537B, 0x5377, 0x5382, 0x5396, 0x53A0, 0x53A6,
- 0x53A5, 0x53AE, 0x53B0, 0x53B6, 0x53C3, 0x7C12, 0x96D9, 0x53DF,
- 0x66FC, 0x71EE, 0x53EE, 0x53E8, 0x53ED, 0x53FA, 0x5401, 0x543D,
- 0x5440, 0x542C, 0x542D, 0x543C, 0x542E, 0x5436, 0x5429, 0x541D,
- 0x544E, 0x548F, 0x5475, 0x548E, 0x545F, 0x5471, 0x5477, 0x5470,
- 0x5492, 0x547B, 0x5480, 0x5476, 0x5484, 0x5490, 0x5486, 0x54C7,
- 0x54A2, 0x54B8, 0x54A5, 0x54AC, 0x54C4, 0x54C8, 0x54A8,
-};
-static const unsigned short euc_to_utf8_D3[] = {
- 0x54AB, 0x54C2, 0x54A4, 0x54BE, 0x54BC, 0x54D8, 0x54E5,
- 0x54E6, 0x550F, 0x5514, 0x54FD, 0x54EE, 0x54ED, 0x54FA, 0x54E2,
- 0x5539, 0x5540, 0x5563, 0x554C, 0x552E, 0x555C, 0x5545, 0x5556,
- 0x5557, 0x5538, 0x5533, 0x555D, 0x5599, 0x5580, 0x54AF, 0x558A,
- 0x559F, 0x557B, 0x557E, 0x5598, 0x559E, 0x55AE, 0x557C, 0x5583,
- 0x55A9, 0x5587, 0x55A8, 0x55DA, 0x55C5, 0x55DF, 0x55C4, 0x55DC,
- 0x55E4, 0x55D4, 0x5614, 0x55F7, 0x5616, 0x55FE, 0x55FD, 0x561B,
- 0x55F9, 0x564E, 0x5650, 0x71DF, 0x5634, 0x5636, 0x5632, 0x5638,
- 0x566B, 0x5664, 0x562F, 0x566C, 0x566A, 0x5686, 0x5680, 0x568A,
- 0x56A0, 0x5694, 0x568F, 0x56A5, 0x56AE, 0x56B6, 0x56B4, 0x56C2,
- 0x56BC, 0x56C1, 0x56C3, 0x56C0, 0x56C8, 0x56CE, 0x56D1, 0x56D3,
- 0x56D7, 0x56EE, 0x56F9, 0x5700, 0x56FF, 0x5704, 0x5709,
-};
-static const unsigned short euc_to_utf8_D4[] = {
- 0x5708, 0x570B, 0x570D, 0x5713, 0x5718, 0x5716, 0x55C7,
- 0x571C, 0x5726, 0x5737, 0x5738, 0x574E, 0x573B, 0x5740, 0x574F,
- 0x5769, 0x57C0, 0x5788, 0x5761, 0x577F, 0x5789, 0x5793, 0x57A0,
- 0x57B3, 0x57A4, 0x57AA, 0x57B0, 0x57C3, 0x57C6, 0x57D4, 0x57D2,
- 0x57D3, 0x580A, 0x57D6, 0x57E3, 0x580B, 0x5819, 0x581D, 0x5872,
- 0x5821, 0x5862, 0x584B, 0x5870, 0x6BC0, 0x5852, 0x583D, 0x5879,
- 0x5885, 0x58B9, 0x589F, 0x58AB, 0x58BA, 0x58DE, 0x58BB, 0x58B8,
- 0x58AE, 0x58C5, 0x58D3, 0x58D1, 0x58D7, 0x58D9, 0x58D8, 0x58E5,
- 0x58DC, 0x58E4, 0x58DF, 0x58EF, 0x58FA, 0x58F9, 0x58FB, 0x58FC,
- 0x58FD, 0x5902, 0x590A, 0x5910, 0x591B, 0x68A6, 0x5925, 0x592C,
- 0x592D, 0x5932, 0x5938, 0x593E, 0x7AD2, 0x5955, 0x5950, 0x594E,
- 0x595A, 0x5958, 0x5962, 0x5960, 0x5967, 0x596C, 0x5969,
-};
-static const unsigned short euc_to_utf8_D5[] = {
- 0x5978, 0x5981, 0x599D, 0x4F5E, 0x4FAB, 0x59A3, 0x59B2,
- 0x59C6, 0x59E8, 0x59DC, 0x598D, 0x59D9, 0x59DA, 0x5A25, 0x5A1F,
- 0x5A11, 0x5A1C, 0x5A09, 0x5A1A, 0x5A40, 0x5A6C, 0x5A49, 0x5A35,
- 0x5A36, 0x5A62, 0x5A6A, 0x5A9A, 0x5ABC, 0x5ABE, 0x5ACB, 0x5AC2,
- 0x5ABD, 0x5AE3, 0x5AD7, 0x5AE6, 0x5AE9, 0x5AD6, 0x5AFA, 0x5AFB,
- 0x5B0C, 0x5B0B, 0x5B16, 0x5B32, 0x5AD0, 0x5B2A, 0x5B36, 0x5B3E,
- 0x5B43, 0x5B45, 0x5B40, 0x5B51, 0x5B55, 0x5B5A, 0x5B5B, 0x5B65,
- 0x5B69, 0x5B70, 0x5B73, 0x5B75, 0x5B78, 0x6588, 0x5B7A, 0x5B80,
- 0x5B83, 0x5BA6, 0x5BB8, 0x5BC3, 0x5BC7, 0x5BC9, 0x5BD4, 0x5BD0,
- 0x5BE4, 0x5BE6, 0x5BE2, 0x5BDE, 0x5BE5, 0x5BEB, 0x5BF0, 0x5BF6,
- 0x5BF3, 0x5C05, 0x5C07, 0x5C08, 0x5C0D, 0x5C13, 0x5C20, 0x5C22,
- 0x5C28, 0x5C38, 0x5C39, 0x5C41, 0x5C46, 0x5C4E, 0x5C53,
-};
-static const unsigned short euc_to_utf8_D6[] = {
- 0x5C50, 0x5C4F, 0x5B71, 0x5C6C, 0x5C6E, 0x4E62, 0x5C76,
- 0x5C79, 0x5C8C, 0x5C91, 0x5C94, 0x599B, 0x5CAB, 0x5CBB, 0x5CB6,
- 0x5CBC, 0x5CB7, 0x5CC5, 0x5CBE, 0x5CC7, 0x5CD9, 0x5CE9, 0x5CFD,
- 0x5CFA, 0x5CED, 0x5D8C, 0x5CEA, 0x5D0B, 0x5D15, 0x5D17, 0x5D5C,
- 0x5D1F, 0x5D1B, 0x5D11, 0x5D14, 0x5D22, 0x5D1A, 0x5D19, 0x5D18,
- 0x5D4C, 0x5D52, 0x5D4E, 0x5D4B, 0x5D6C, 0x5D73, 0x5D76, 0x5D87,
- 0x5D84, 0x5D82, 0x5DA2, 0x5D9D, 0x5DAC, 0x5DAE, 0x5DBD, 0x5D90,
- 0x5DB7, 0x5DBC, 0x5DC9, 0x5DCD, 0x5DD3, 0x5DD2, 0x5DD6, 0x5DDB,
- 0x5DEB, 0x5DF2, 0x5DF5, 0x5E0B, 0x5E1A, 0x5E19, 0x5E11, 0x5E1B,
- 0x5E36, 0x5E37, 0x5E44, 0x5E43, 0x5E40, 0x5E4E, 0x5E57, 0x5E54,
- 0x5E5F, 0x5E62, 0x5E64, 0x5E47, 0x5E75, 0x5E76, 0x5E7A, 0x9EBC,
- 0x5E7F, 0x5EA0, 0x5EC1, 0x5EC2, 0x5EC8, 0x5ED0, 0x5ECF,
-};
-static const unsigned short euc_to_utf8_D7[] = {
- 0x5ED6, 0x5EE3, 0x5EDD, 0x5EDA, 0x5EDB, 0x5EE2, 0x5EE1,
- 0x5EE8, 0x5EE9, 0x5EEC, 0x5EF1, 0x5EF3, 0x5EF0, 0x5EF4, 0x5EF8,
- 0x5EFE, 0x5F03, 0x5F09, 0x5F5D, 0x5F5C, 0x5F0B, 0x5F11, 0x5F16,
- 0x5F29, 0x5F2D, 0x5F38, 0x5F41, 0x5F48, 0x5F4C, 0x5F4E, 0x5F2F,
- 0x5F51, 0x5F56, 0x5F57, 0x5F59, 0x5F61, 0x5F6D, 0x5F73, 0x5F77,
- 0x5F83, 0x5F82, 0x5F7F, 0x5F8A, 0x5F88, 0x5F91, 0x5F87, 0x5F9E,
- 0x5F99, 0x5F98, 0x5FA0, 0x5FA8, 0x5FAD, 0x5FBC, 0x5FD6, 0x5FFB,
- 0x5FE4, 0x5FF8, 0x5FF1, 0x5FDD, 0x60B3, 0x5FFF, 0x6021, 0x6060,
- 0x6019, 0x6010, 0x6029, 0x600E, 0x6031, 0x601B, 0x6015, 0x602B,
- 0x6026, 0x600F, 0x603A, 0x605A, 0x6041, 0x606A, 0x6077, 0x605F,
- 0x604A, 0x6046, 0x604D, 0x6063, 0x6043, 0x6064, 0x6042, 0x606C,
- 0x606B, 0x6059, 0x6081, 0x608D, 0x60E7, 0x6083, 0x609A,
-};
-static const unsigned short euc_to_utf8_D8[] = {
- 0x6084, 0x609B, 0x6096, 0x6097, 0x6092, 0x60A7, 0x608B,
- 0x60E1, 0x60B8, 0x60E0, 0x60D3, 0x60B4, 0x5FF0, 0x60BD, 0x60C6,
- 0x60B5, 0x60D8, 0x614D, 0x6115, 0x6106, 0x60F6, 0x60F7, 0x6100,
- 0x60F4, 0x60FA, 0x6103, 0x6121, 0x60FB, 0x60F1, 0x610D, 0x610E,
- 0x6147, 0x613E, 0x6128, 0x6127, 0x614A, 0x613F, 0x613C, 0x612C,
- 0x6134, 0x613D, 0x6142, 0x6144, 0x6173, 0x6177, 0x6158, 0x6159,
- 0x615A, 0x616B, 0x6174, 0x616F, 0x6165, 0x6171, 0x615F, 0x615D,
- 0x6153, 0x6175, 0x6199, 0x6196, 0x6187, 0x61AC, 0x6194, 0x619A,
- 0x618A, 0x6191, 0x61AB, 0x61AE, 0x61CC, 0x61CA, 0x61C9, 0x61F7,
- 0x61C8, 0x61C3, 0x61C6, 0x61BA, 0x61CB, 0x7F79, 0x61CD, 0x61E6,
- 0x61E3, 0x61F6, 0x61FA, 0x61F4, 0x61FF, 0x61FD, 0x61FC, 0x61FE,
- 0x6200, 0x6208, 0x6209, 0x620D, 0x620C, 0x6214, 0x621B,
-};
-static const unsigned short euc_to_utf8_D9[] = {
- 0x621E, 0x6221, 0x622A, 0x622E, 0x6230, 0x6232, 0x6233,
- 0x6241, 0x624E, 0x625E, 0x6263, 0x625B, 0x6260, 0x6268, 0x627C,
- 0x6282, 0x6289, 0x627E, 0x6292, 0x6293, 0x6296, 0x62D4, 0x6283,
- 0x6294, 0x62D7, 0x62D1, 0x62BB, 0x62CF, 0x62FF, 0x62C6, 0x64D4,
- 0x62C8, 0x62DC, 0x62CC, 0x62CA, 0x62C2, 0x62C7, 0x629B, 0x62C9,
- 0x630C, 0x62EE, 0x62F1, 0x6327, 0x6302, 0x6308, 0x62EF, 0x62F5,
- 0x6350, 0x633E, 0x634D, 0x641C, 0x634F, 0x6396, 0x638E, 0x6380,
- 0x63AB, 0x6376, 0x63A3, 0x638F, 0x6389, 0x639F, 0x63B5, 0x636B,
- 0x6369, 0x63BE, 0x63E9, 0x63C0, 0x63C6, 0x63E3, 0x63C9, 0x63D2,
- 0x63F6, 0x63C4, 0x6416, 0x6434, 0x6406, 0x6413, 0x6426, 0x6436,
- 0x651D, 0x6417, 0x6428, 0x640F, 0x6467, 0x646F, 0x6476, 0x644E,
- 0x652A, 0x6495, 0x6493, 0x64A5, 0x64A9, 0x6488, 0x64BC,
-};
-static const unsigned short euc_to_utf8_DA[] = {
- 0x64DA, 0x64D2, 0x64C5, 0x64C7, 0x64BB, 0x64D8, 0x64C2,
- 0x64F1, 0x64E7, 0x8209, 0x64E0, 0x64E1, 0x62AC, 0x64E3, 0x64EF,
- 0x652C, 0x64F6, 0x64F4, 0x64F2, 0x64FA, 0x6500, 0x64FD, 0x6518,
- 0x651C, 0x6505, 0x6524, 0x6523, 0x652B, 0x6534, 0x6535, 0x6537,
- 0x6536, 0x6538, 0x754B, 0x6548, 0x6556, 0x6555, 0x654D, 0x6558,
- 0x655E, 0x655D, 0x6572, 0x6578, 0x6582, 0x6583, 0x8B8A, 0x659B,
- 0x659F, 0x65AB, 0x65B7, 0x65C3, 0x65C6, 0x65C1, 0x65C4, 0x65CC,
- 0x65D2, 0x65DB, 0x65D9, 0x65E0, 0x65E1, 0x65F1, 0x6772, 0x660A,
- 0x6603, 0x65FB, 0x6773, 0x6635, 0x6636, 0x6634, 0x661C, 0x664F,
- 0x6644, 0x6649, 0x6641, 0x665E, 0x665D, 0x6664, 0x6667, 0x6668,
- 0x665F, 0x6662, 0x6670, 0x6683, 0x6688, 0x668E, 0x6689, 0x6684,
- 0x6698, 0x669D, 0x66C1, 0x66B9, 0x66C9, 0x66BE, 0x66BC,
-};
-static const unsigned short euc_to_utf8_DB[] = {
- 0x66C4, 0x66B8, 0x66D6, 0x66DA, 0x66E0, 0x663F, 0x66E6,
- 0x66E9, 0x66F0, 0x66F5, 0x66F7, 0x670F, 0x6716, 0x671E, 0x6726,
- 0x6727, 0x9738, 0x672E, 0x673F, 0x6736, 0x6741, 0x6738, 0x6737,
- 0x6746, 0x675E, 0x6760, 0x6759, 0x6763, 0x6764, 0x6789, 0x6770,
- 0x67A9, 0x677C, 0x676A, 0x678C, 0x678B, 0x67A6, 0x67A1, 0x6785,
- 0x67B7, 0x67EF, 0x67B4, 0x67EC, 0x67B3, 0x67E9, 0x67B8, 0x67E4,
- 0x67DE, 0x67DD, 0x67E2, 0x67EE, 0x67B9, 0x67CE, 0x67C6, 0x67E7,
- 0x6A9C, 0x681E, 0x6846, 0x6829, 0x6840, 0x684D, 0x6832, 0x684E,
- 0x68B3, 0x682B, 0x6859, 0x6863, 0x6877, 0x687F, 0x689F, 0x688F,
- 0x68AD, 0x6894, 0x689D, 0x689B, 0x6883, 0x6AAE, 0x68B9, 0x6874,
- 0x68B5, 0x68A0, 0x68BA, 0x690F, 0x688D, 0x687E, 0x6901, 0x68CA,
- 0x6908, 0x68D8, 0x6922, 0x6926, 0x68E1, 0x690C, 0x68CD,
-};
-static const unsigned short euc_to_utf8_DC[] = {
- 0x68D4, 0x68E7, 0x68D5, 0x6936, 0x6912, 0x6904, 0x68D7,
- 0x68E3, 0x6925, 0x68F9, 0x68E0, 0x68EF, 0x6928, 0x692A, 0x691A,
- 0x6923, 0x6921, 0x68C6, 0x6979, 0x6977, 0x695C, 0x6978, 0x696B,
- 0x6954, 0x697E, 0x696E, 0x6939, 0x6974, 0x693D, 0x6959, 0x6930,
- 0x6961, 0x695E, 0x695D, 0x6981, 0x696A, 0x69B2, 0x69AE, 0x69D0,
- 0x69BF, 0x69C1, 0x69D3, 0x69BE, 0x69CE, 0x5BE8, 0x69CA, 0x69DD,
- 0x69BB, 0x69C3, 0x69A7, 0x6A2E, 0x6991, 0x69A0, 0x699C, 0x6995,
- 0x69B4, 0x69DE, 0x69E8, 0x6A02, 0x6A1B, 0x69FF, 0x6B0A, 0x69F9,
- 0x69F2, 0x69E7, 0x6A05, 0x69B1, 0x6A1E, 0x69ED, 0x6A14, 0x69EB,
- 0x6A0A, 0x6A12, 0x6AC1, 0x6A23, 0x6A13, 0x6A44, 0x6A0C, 0x6A72,
- 0x6A36, 0x6A78, 0x6A47, 0x6A62, 0x6A59, 0x6A66, 0x6A48, 0x6A38,
- 0x6A22, 0x6A90, 0x6A8D, 0x6AA0, 0x6A84, 0x6AA2, 0x6AA3,
-};
-static const unsigned short euc_to_utf8_DD[] = {
- 0x6A97, 0x8617, 0x6ABB, 0x6AC3, 0x6AC2, 0x6AB8, 0x6AB3,
- 0x6AAC, 0x6ADE, 0x6AD1, 0x6ADF, 0x6AAA, 0x6ADA, 0x6AEA, 0x6AFB,
- 0x6B05, 0x8616, 0x6AFA, 0x6B12, 0x6B16, 0x9B31, 0x6B1F, 0x6B38,
- 0x6B37, 0x76DC, 0x6B39, 0x98EE, 0x6B47, 0x6B43, 0x6B49, 0x6B50,
- 0x6B59, 0x6B54, 0x6B5B, 0x6B5F, 0x6B61, 0x6B78, 0x6B79, 0x6B7F,
- 0x6B80, 0x6B84, 0x6B83, 0x6B8D, 0x6B98, 0x6B95, 0x6B9E, 0x6BA4,
- 0x6BAA, 0x6BAB, 0x6BAF, 0x6BB2, 0x6BB1, 0x6BB3, 0x6BB7, 0x6BBC,
- 0x6BC6, 0x6BCB, 0x6BD3, 0x6BDF, 0x6BEC, 0x6BEB, 0x6BF3, 0x6BEF,
- 0x9EBE, 0x6C08, 0x6C13, 0x6C14, 0x6C1B, 0x6C24, 0x6C23, 0x6C5E,
- 0x6C55, 0x6C62, 0x6C6A, 0x6C82, 0x6C8D, 0x6C9A, 0x6C81, 0x6C9B,
- 0x6C7E, 0x6C68, 0x6C73, 0x6C92, 0x6C90, 0x6CC4, 0x6CF1, 0x6CD3,
- 0x6CBD, 0x6CD7, 0x6CC5, 0x6CDD, 0x6CAE, 0x6CB1, 0x6CBE,
-};
-static const unsigned short euc_to_utf8_DE[] = {
- 0x6CBA, 0x6CDB, 0x6CEF, 0x6CD9, 0x6CEA, 0x6D1F, 0x884D,
- 0x6D36, 0x6D2B, 0x6D3D, 0x6D38, 0x6D19, 0x6D35, 0x6D33, 0x6D12,
- 0x6D0C, 0x6D63, 0x6D93, 0x6D64, 0x6D5A, 0x6D79, 0x6D59, 0x6D8E,
- 0x6D95, 0x6FE4, 0x6D85, 0x6DF9, 0x6E15, 0x6E0A, 0x6DB5, 0x6DC7,
- 0x6DE6, 0x6DB8, 0x6DC6, 0x6DEC, 0x6DDE, 0x6DCC, 0x6DE8, 0x6DD2,
- 0x6DC5, 0x6DFA, 0x6DD9, 0x6DE4, 0x6DD5, 0x6DEA, 0x6DEE, 0x6E2D,
- 0x6E6E, 0x6E2E, 0x6E19, 0x6E72, 0x6E5F, 0x6E3E, 0x6E23, 0x6E6B,
- 0x6E2B, 0x6E76, 0x6E4D, 0x6E1F, 0x6E43, 0x6E3A, 0x6E4E, 0x6E24,
- 0x6EFF, 0x6E1D, 0x6E38, 0x6E82, 0x6EAA, 0x6E98, 0x6EC9, 0x6EB7,
- 0x6ED3, 0x6EBD, 0x6EAF, 0x6EC4, 0x6EB2, 0x6ED4, 0x6ED5, 0x6E8F,
- 0x6EA5, 0x6EC2, 0x6E9F, 0x6F41, 0x6F11, 0x704C, 0x6EEC, 0x6EF8,
- 0x6EFE, 0x6F3F, 0x6EF2, 0x6F31, 0x6EEF, 0x6F32, 0x6ECC,
-};
-static const unsigned short euc_to_utf8_DF[] = {
- 0x6F3E, 0x6F13, 0x6EF7, 0x6F86, 0x6F7A, 0x6F78, 0x6F81,
- 0x6F80, 0x6F6F, 0x6F5B, 0x6FF3, 0x6F6D, 0x6F82, 0x6F7C, 0x6F58,
- 0x6F8E, 0x6F91, 0x6FC2, 0x6F66, 0x6FB3, 0x6FA3, 0x6FA1, 0x6FA4,
- 0x6FB9, 0x6FC6, 0x6FAA, 0x6FDF, 0x6FD5, 0x6FEC, 0x6FD4, 0x6FD8,
- 0x6FF1, 0x6FEE, 0x6FDB, 0x7009, 0x700B, 0x6FFA, 0x7011, 0x7001,
- 0x700F, 0x6FFE, 0x701B, 0x701A, 0x6F74, 0x701D, 0x7018, 0x701F,
- 0x7030, 0x703E, 0x7032, 0x7051, 0x7063, 0x7099, 0x7092, 0x70AF,
- 0x70F1, 0x70AC, 0x70B8, 0x70B3, 0x70AE, 0x70DF, 0x70CB, 0x70DD,
- 0x70D9, 0x7109, 0x70FD, 0x711C, 0x7119, 0x7165, 0x7155, 0x7188,
- 0x7166, 0x7162, 0x714C, 0x7156, 0x716C, 0x718F, 0x71FB, 0x7184,
- 0x7195, 0x71A8, 0x71AC, 0x71D7, 0x71B9, 0x71BE, 0x71D2, 0x71C9,
- 0x71D4, 0x71CE, 0x71E0, 0x71EC, 0x71E7, 0x71F5, 0x71FC,
-};
-static const unsigned short euc_to_utf8_E0[] = {
- 0x71F9, 0x71FF, 0x720D, 0x7210, 0x721B, 0x7228, 0x722D,
- 0x722C, 0x7230, 0x7232, 0x723B, 0x723C, 0x723F, 0x7240, 0x7246,
- 0x724B, 0x7258, 0x7274, 0x727E, 0x7282, 0x7281, 0x7287, 0x7292,
- 0x7296, 0x72A2, 0x72A7, 0x72B9, 0x72B2, 0x72C3, 0x72C6, 0x72C4,
- 0x72CE, 0x72D2, 0x72E2, 0x72E0, 0x72E1, 0x72F9, 0x72F7, 0x500F,
- 0x7317, 0x730A, 0x731C, 0x7316, 0x731D, 0x7334, 0x732F, 0x7329,
- 0x7325, 0x733E, 0x734E, 0x734F, 0x9ED8, 0x7357, 0x736A, 0x7368,
- 0x7370, 0x7378, 0x7375, 0x737B, 0x737A, 0x73C8, 0x73B3, 0x73CE,
- 0x73BB, 0x73C0, 0x73E5, 0x73EE, 0x73DE, 0x74A2, 0x7405, 0x746F,
- 0x7425, 0x73F8, 0x7432, 0x743A, 0x7455, 0x743F, 0x745F, 0x7459,
- 0x7441, 0x745C, 0x7469, 0x7470, 0x7463, 0x746A, 0x7476, 0x747E,
- 0x748B, 0x749E, 0x74A7, 0x74CA, 0x74CF, 0x74D4, 0x73F1,
-};
-static const unsigned short euc_to_utf8_E1[] = {
- 0x74E0, 0x74E3, 0x74E7, 0x74E9, 0x74EE, 0x74F2, 0x74F0,
- 0x74F1, 0x74F8, 0x74F7, 0x7504, 0x7503, 0x7505, 0x750C, 0x750E,
- 0x750D, 0x7515, 0x7513, 0x751E, 0x7526, 0x752C, 0x753C, 0x7544,
- 0x754D, 0x754A, 0x7549, 0x755B, 0x7546, 0x755A, 0x7569, 0x7564,
- 0x7567, 0x756B, 0x756D, 0x7578, 0x7576, 0x7586, 0x7587, 0x7574,
- 0x758A, 0x7589, 0x7582, 0x7594, 0x759A, 0x759D, 0x75A5, 0x75A3,
- 0x75C2, 0x75B3, 0x75C3, 0x75B5, 0x75BD, 0x75B8, 0x75BC, 0x75B1,
- 0x75CD, 0x75CA, 0x75D2, 0x75D9, 0x75E3, 0x75DE, 0x75FE, 0x75FF,
- 0x75FC, 0x7601, 0x75F0, 0x75FA, 0x75F2, 0x75F3, 0x760B, 0x760D,
- 0x7609, 0x761F, 0x7627, 0x7620, 0x7621, 0x7622, 0x7624, 0x7634,
- 0x7630, 0x763B, 0x7647, 0x7648, 0x7646, 0x765C, 0x7658, 0x7661,
- 0x7662, 0x7668, 0x7669, 0x766A, 0x7667, 0x766C, 0x7670,
-};
-static const unsigned short euc_to_utf8_E2[] = {
- 0x7672, 0x7676, 0x7678, 0x767C, 0x7680, 0x7683, 0x7688,
- 0x768B, 0x768E, 0x7696, 0x7693, 0x7699, 0x769A, 0x76B0, 0x76B4,
- 0x76B8, 0x76B9, 0x76BA, 0x76C2, 0x76CD, 0x76D6, 0x76D2, 0x76DE,
- 0x76E1, 0x76E5, 0x76E7, 0x76EA, 0x862F, 0x76FB, 0x7708, 0x7707,
- 0x7704, 0x7729, 0x7724, 0x771E, 0x7725, 0x7726, 0x771B, 0x7737,
- 0x7738, 0x7747, 0x775A, 0x7768, 0x776B, 0x775B, 0x7765, 0x777F,
- 0x777E, 0x7779, 0x778E, 0x778B, 0x7791, 0x77A0, 0x779E, 0x77B0,
- 0x77B6, 0x77B9, 0x77BF, 0x77BC, 0x77BD, 0x77BB, 0x77C7, 0x77CD,
- 0x77D7, 0x77DA, 0x77DC, 0x77E3, 0x77EE, 0x77FC, 0x780C, 0x7812,
- 0x7926, 0x7820, 0x792A, 0x7845, 0x788E, 0x7874, 0x7886, 0x787C,
- 0x789A, 0x788C, 0x78A3, 0x78B5, 0x78AA, 0x78AF, 0x78D1, 0x78C6,
- 0x78CB, 0x78D4, 0x78BE, 0x78BC, 0x78C5, 0x78CA, 0x78EC,
-};
-static const unsigned short euc_to_utf8_E3[] = {
- 0x78E7, 0x78DA, 0x78FD, 0x78F4, 0x7907, 0x7912, 0x7911,
- 0x7919, 0x792C, 0x792B, 0x7940, 0x7960, 0x7957, 0x795F, 0x795A,
- 0x7955, 0x7953, 0x797A, 0x797F, 0x798A, 0x799D, 0x79A7, 0x9F4B,
- 0x79AA, 0x79AE, 0x79B3, 0x79B9, 0x79BA, 0x79C9, 0x79D5, 0x79E7,
- 0x79EC, 0x79E1, 0x79E3, 0x7A08, 0x7A0D, 0x7A18, 0x7A19, 0x7A20,
- 0x7A1F, 0x7980, 0x7A31, 0x7A3B, 0x7A3E, 0x7A37, 0x7A43, 0x7A57,
- 0x7A49, 0x7A61, 0x7A62, 0x7A69, 0x9F9D, 0x7A70, 0x7A79, 0x7A7D,
- 0x7A88, 0x7A97, 0x7A95, 0x7A98, 0x7A96, 0x7AA9, 0x7AC8, 0x7AB0,
- 0x7AB6, 0x7AC5, 0x7AC4, 0x7ABF, 0x9083, 0x7AC7, 0x7ACA, 0x7ACD,
- 0x7ACF, 0x7AD5, 0x7AD3, 0x7AD9, 0x7ADA, 0x7ADD, 0x7AE1, 0x7AE2,
- 0x7AE6, 0x7AED, 0x7AF0, 0x7B02, 0x7B0F, 0x7B0A, 0x7B06, 0x7B33,
- 0x7B18, 0x7B19, 0x7B1E, 0x7B35, 0x7B28, 0x7B36, 0x7B50,
-};
-static const unsigned short euc_to_utf8_E4[] = {
- 0x7B7A, 0x7B04, 0x7B4D, 0x7B0B, 0x7B4C, 0x7B45, 0x7B75,
- 0x7B65, 0x7B74, 0x7B67, 0x7B70, 0x7B71, 0x7B6C, 0x7B6E, 0x7B9D,
- 0x7B98, 0x7B9F, 0x7B8D, 0x7B9C, 0x7B9A, 0x7B8B, 0x7B92, 0x7B8F,
- 0x7B5D, 0x7B99, 0x7BCB, 0x7BC1, 0x7BCC, 0x7BCF, 0x7BB4, 0x7BC6,
- 0x7BDD, 0x7BE9, 0x7C11, 0x7C14, 0x7BE6, 0x7BE5, 0x7C60, 0x7C00,
- 0x7C07, 0x7C13, 0x7BF3, 0x7BF7, 0x7C17, 0x7C0D, 0x7BF6, 0x7C23,
- 0x7C27, 0x7C2A, 0x7C1F, 0x7C37, 0x7C2B, 0x7C3D, 0x7C4C, 0x7C43,
- 0x7C54, 0x7C4F, 0x7C40, 0x7C50, 0x7C58, 0x7C5F, 0x7C64, 0x7C56,
- 0x7C65, 0x7C6C, 0x7C75, 0x7C83, 0x7C90, 0x7CA4, 0x7CAD, 0x7CA2,
- 0x7CAB, 0x7CA1, 0x7CA8, 0x7CB3, 0x7CB2, 0x7CB1, 0x7CAE, 0x7CB9,
- 0x7CBD, 0x7CC0, 0x7CC5, 0x7CC2, 0x7CD8, 0x7CD2, 0x7CDC, 0x7CE2,
- 0x9B3B, 0x7CEF, 0x7CF2, 0x7CF4, 0x7CF6, 0x7CFA, 0x7D06,
-};
-static const unsigned short euc_to_utf8_E5[] = {
- 0x7D02, 0x7D1C, 0x7D15, 0x7D0A, 0x7D45, 0x7D4B, 0x7D2E,
- 0x7D32, 0x7D3F, 0x7D35, 0x7D46, 0x7D73, 0x7D56, 0x7D4E, 0x7D72,
- 0x7D68, 0x7D6E, 0x7D4F, 0x7D63, 0x7D93, 0x7D89, 0x7D5B, 0x7D8F,
- 0x7D7D, 0x7D9B, 0x7DBA, 0x7DAE, 0x7DA3, 0x7DB5, 0x7DC7, 0x7DBD,
- 0x7DAB, 0x7E3D, 0x7DA2, 0x7DAF, 0x7DDC, 0x7DB8, 0x7D9F, 0x7DB0,
- 0x7DD8, 0x7DDD, 0x7DE4, 0x7DDE, 0x7DFB, 0x7DF2, 0x7DE1, 0x7E05,
- 0x7E0A, 0x7E23, 0x7E21, 0x7E12, 0x7E31, 0x7E1F, 0x7E09, 0x7E0B,
- 0x7E22, 0x7E46, 0x7E66, 0x7E3B, 0x7E35, 0x7E39, 0x7E43, 0x7E37,
- 0x7E32, 0x7E3A, 0x7E67, 0x7E5D, 0x7E56, 0x7E5E, 0x7E59, 0x7E5A,
- 0x7E79, 0x7E6A, 0x7E69, 0x7E7C, 0x7E7B, 0x7E83, 0x7DD5, 0x7E7D,
- 0x8FAE, 0x7E7F, 0x7E88, 0x7E89, 0x7E8C, 0x7E92, 0x7E90, 0x7E93,
- 0x7E94, 0x7E96, 0x7E8E, 0x7E9B, 0x7E9C, 0x7F38, 0x7F3A,
-};
-static const unsigned short euc_to_utf8_E6[] = {
- 0x7F45, 0x7F4C, 0x7F4D, 0x7F4E, 0x7F50, 0x7F51, 0x7F55,
- 0x7F54, 0x7F58, 0x7F5F, 0x7F60, 0x7F68, 0x7F69, 0x7F67, 0x7F78,
- 0x7F82, 0x7F86, 0x7F83, 0x7F88, 0x7F87, 0x7F8C, 0x7F94, 0x7F9E,
- 0x7F9D, 0x7F9A, 0x7FA3, 0x7FAF, 0x7FB2, 0x7FB9, 0x7FAE, 0x7FB6,
- 0x7FB8, 0x8B71, 0x7FC5, 0x7FC6, 0x7FCA, 0x7FD5, 0x7FD4, 0x7FE1,
- 0x7FE6, 0x7FE9, 0x7FF3, 0x7FF9, 0x98DC, 0x8006, 0x8004, 0x800B,
- 0x8012, 0x8018, 0x8019, 0x801C, 0x8021, 0x8028, 0x803F, 0x803B,
- 0x804A, 0x8046, 0x8052, 0x8058, 0x805A, 0x805F, 0x8062, 0x8068,
- 0x8073, 0x8072, 0x8070, 0x8076, 0x8079, 0x807D, 0x807F, 0x8084,
- 0x8086, 0x8085, 0x809B, 0x8093, 0x809A, 0x80AD, 0x5190, 0x80AC,
- 0x80DB, 0x80E5, 0x80D9, 0x80DD, 0x80C4, 0x80DA, 0x80D6, 0x8109,
- 0x80EF, 0x80F1, 0x811B, 0x8129, 0x8123, 0x812F, 0x814B,
-};
-static const unsigned short euc_to_utf8_E7[] = {
- 0x968B, 0x8146, 0x813E, 0x8153, 0x8151, 0x80FC, 0x8171,
- 0x816E, 0x8165, 0x8166, 0x8174, 0x8183, 0x8188, 0x818A, 0x8180,
- 0x8182, 0x81A0, 0x8195, 0x81A4, 0x81A3, 0x815F, 0x8193, 0x81A9,
- 0x81B0, 0x81B5, 0x81BE, 0x81B8, 0x81BD, 0x81C0, 0x81C2, 0x81BA,
- 0x81C9, 0x81CD, 0x81D1, 0x81D9, 0x81D8, 0x81C8, 0x81DA, 0x81DF,
- 0x81E0, 0x81E7, 0x81FA, 0x81FB, 0x81FE, 0x8201, 0x8202, 0x8205,
- 0x8207, 0x820A, 0x820D, 0x8210, 0x8216, 0x8229, 0x822B, 0x8238,
- 0x8233, 0x8240, 0x8259, 0x8258, 0x825D, 0x825A, 0x825F, 0x8264,
- 0x8262, 0x8268, 0x826A, 0x826B, 0x822E, 0x8271, 0x8277, 0x8278,
- 0x827E, 0x828D, 0x8292, 0x82AB, 0x829F, 0x82BB, 0x82AC, 0x82E1,
- 0x82E3, 0x82DF, 0x82D2, 0x82F4, 0x82F3, 0x82FA, 0x8393, 0x8303,
- 0x82FB, 0x82F9, 0x82DE, 0x8306, 0x82DC, 0x8309, 0x82D9,
-};
-static const unsigned short euc_to_utf8_E8[] = {
- 0x8335, 0x8334, 0x8316, 0x8332, 0x8331, 0x8340, 0x8339,
- 0x8350, 0x8345, 0x832F, 0x832B, 0x8317, 0x8318, 0x8385, 0x839A,
- 0x83AA, 0x839F, 0x83A2, 0x8396, 0x8323, 0x838E, 0x8387, 0x838A,
- 0x837C, 0x83B5, 0x8373, 0x8375, 0x83A0, 0x8389, 0x83A8, 0x83F4,
- 0x8413, 0x83EB, 0x83CE, 0x83FD, 0x8403, 0x83D8, 0x840B, 0x83C1,
- 0x83F7, 0x8407, 0x83E0, 0x83F2, 0x840D, 0x8422, 0x8420, 0x83BD,
- 0x8438, 0x8506, 0x83FB, 0x846D, 0x842A, 0x843C, 0x855A, 0x8484,
- 0x8477, 0x846B, 0x84AD, 0x846E, 0x8482, 0x8469, 0x8446, 0x842C,
- 0x846F, 0x8479, 0x8435, 0x84CA, 0x8462, 0x84B9, 0x84BF, 0x849F,
- 0x84D9, 0x84CD, 0x84BB, 0x84DA, 0x84D0, 0x84C1, 0x84C6, 0x84D6,
- 0x84A1, 0x8521, 0x84FF, 0x84F4, 0x8517, 0x8518, 0x852C, 0x851F,
- 0x8515, 0x8514, 0x84FC, 0x8540, 0x8563, 0x8558, 0x8548,
-};
-static const unsigned short euc_to_utf8_E9[] = {
- 0x8541, 0x8602, 0x854B, 0x8555, 0x8580, 0x85A4, 0x8588,
- 0x8591, 0x858A, 0x85A8, 0x856D, 0x8594, 0x859B, 0x85EA, 0x8587,
- 0x859C, 0x8577, 0x857E, 0x8590, 0x85C9, 0x85BA, 0x85CF, 0x85B9,
- 0x85D0, 0x85D5, 0x85DD, 0x85E5, 0x85DC, 0x85F9, 0x860A, 0x8613,
- 0x860B, 0x85FE, 0x85FA, 0x8606, 0x8622, 0x861A, 0x8630, 0x863F,
- 0x864D, 0x4E55, 0x8654, 0x865F, 0x8667, 0x8671, 0x8693, 0x86A3,
- 0x86A9, 0x86AA, 0x868B, 0x868C, 0x86B6, 0x86AF, 0x86C4, 0x86C6,
- 0x86B0, 0x86C9, 0x8823, 0x86AB, 0x86D4, 0x86DE, 0x86E9, 0x86EC,
- 0x86DF, 0x86DB, 0x86EF, 0x8712, 0x8706, 0x8708, 0x8700, 0x8703,
- 0x86FB, 0x8711, 0x8709, 0x870D, 0x86F9, 0x870A, 0x8734, 0x873F,
- 0x8737, 0x873B, 0x8725, 0x8729, 0x871A, 0x8760, 0x875F, 0x8778,
- 0x874C, 0x874E, 0x8774, 0x8757, 0x8768, 0x876E, 0x8759,
-};
-static const unsigned short euc_to_utf8_EA[] = {
- 0x8753, 0x8763, 0x876A, 0x8805, 0x87A2, 0x879F, 0x8782,
- 0x87AF, 0x87CB, 0x87BD, 0x87C0, 0x87D0, 0x96D6, 0x87AB, 0x87C4,
- 0x87B3, 0x87C7, 0x87C6, 0x87BB, 0x87EF, 0x87F2, 0x87E0, 0x880F,
- 0x880D, 0x87FE, 0x87F6, 0x87F7, 0x880E, 0x87D2, 0x8811, 0x8816,
- 0x8815, 0x8822, 0x8821, 0x8831, 0x8836, 0x8839, 0x8827, 0x883B,
- 0x8844, 0x8842, 0x8852, 0x8859, 0x885E, 0x8862, 0x886B, 0x8881,
- 0x887E, 0x889E, 0x8875, 0x887D, 0x88B5, 0x8872, 0x8882, 0x8897,
- 0x8892, 0x88AE, 0x8899, 0x88A2, 0x888D, 0x88A4, 0x88B0, 0x88BF,
- 0x88B1, 0x88C3, 0x88C4, 0x88D4, 0x88D8, 0x88D9, 0x88DD, 0x88F9,
- 0x8902, 0x88FC, 0x88F4, 0x88E8, 0x88F2, 0x8904, 0x890C, 0x890A,
- 0x8913, 0x8943, 0x891E, 0x8925, 0x892A, 0x892B, 0x8941, 0x8944,
- 0x893B, 0x8936, 0x8938, 0x894C, 0x891D, 0x8960, 0x895E,
-};
-static const unsigned short euc_to_utf8_EB[] = {
- 0x8966, 0x8964, 0x896D, 0x896A, 0x896F, 0x8974, 0x8977,
- 0x897E, 0x8983, 0x8988, 0x898A, 0x8993, 0x8998, 0x89A1, 0x89A9,
- 0x89A6, 0x89AC, 0x89AF, 0x89B2, 0x89BA, 0x89BD, 0x89BF, 0x89C0,
- 0x89DA, 0x89DC, 0x89DD, 0x89E7, 0x89F4, 0x89F8, 0x8A03, 0x8A16,
- 0x8A10, 0x8A0C, 0x8A1B, 0x8A1D, 0x8A25, 0x8A36, 0x8A41, 0x8A5B,
- 0x8A52, 0x8A46, 0x8A48, 0x8A7C, 0x8A6D, 0x8A6C, 0x8A62, 0x8A85,
- 0x8A82, 0x8A84, 0x8AA8, 0x8AA1, 0x8A91, 0x8AA5, 0x8AA6, 0x8A9A,
- 0x8AA3, 0x8AC4, 0x8ACD, 0x8AC2, 0x8ADA, 0x8AEB, 0x8AF3, 0x8AE7,
- 0x8AE4, 0x8AF1, 0x8B14, 0x8AE0, 0x8AE2, 0x8AF7, 0x8ADE, 0x8ADB,
- 0x8B0C, 0x8B07, 0x8B1A, 0x8AE1, 0x8B16, 0x8B10, 0x8B17, 0x8B20,
- 0x8B33, 0x97AB, 0x8B26, 0x8B2B, 0x8B3E, 0x8B28, 0x8B41, 0x8B4C,
- 0x8B4F, 0x8B4E, 0x8B49, 0x8B56, 0x8B5B, 0x8B5A, 0x8B6B,
-};
-static const unsigned short euc_to_utf8_EC[] = {
- 0x8B5F, 0x8B6C, 0x8B6F, 0x8B74, 0x8B7D, 0x8B80, 0x8B8C,
- 0x8B8E, 0x8B92, 0x8B93, 0x8B96, 0x8B99, 0x8B9A, 0x8C3A, 0x8C41,
- 0x8C3F, 0x8C48, 0x8C4C, 0x8C4E, 0x8C50, 0x8C55, 0x8C62, 0x8C6C,
- 0x8C78, 0x8C7A, 0x8C82, 0x8C89, 0x8C85, 0x8C8A, 0x8C8D, 0x8C8E,
- 0x8C94, 0x8C7C, 0x8C98, 0x621D, 0x8CAD, 0x8CAA, 0x8CBD, 0x8CB2,
- 0x8CB3, 0x8CAE, 0x8CB6, 0x8CC8, 0x8CC1, 0x8CE4, 0x8CE3, 0x8CDA,
- 0x8CFD, 0x8CFA, 0x8CFB, 0x8D04, 0x8D05, 0x8D0A, 0x8D07, 0x8D0F,
- 0x8D0D, 0x8D10, 0x9F4E, 0x8D13, 0x8CCD, 0x8D14, 0x8D16, 0x8D67,
- 0x8D6D, 0x8D71, 0x8D73, 0x8D81, 0x8D99, 0x8DC2, 0x8DBE, 0x8DBA,
- 0x8DCF, 0x8DDA, 0x8DD6, 0x8DCC, 0x8DDB, 0x8DCB, 0x8DEA, 0x8DEB,
- 0x8DDF, 0x8DE3, 0x8DFC, 0x8E08, 0x8E09, 0x8DFF, 0x8E1D, 0x8E1E,
- 0x8E10, 0x8E1F, 0x8E42, 0x8E35, 0x8E30, 0x8E34, 0x8E4A,
-};
-static const unsigned short euc_to_utf8_ED[] = {
- 0x8E47, 0x8E49, 0x8E4C, 0x8E50, 0x8E48, 0x8E59, 0x8E64,
- 0x8E60, 0x8E2A, 0x8E63, 0x8E55, 0x8E76, 0x8E72, 0x8E7C, 0x8E81,
- 0x8E87, 0x8E85, 0x8E84, 0x8E8B, 0x8E8A, 0x8E93, 0x8E91, 0x8E94,
- 0x8E99, 0x8EAA, 0x8EA1, 0x8EAC, 0x8EB0, 0x8EC6, 0x8EB1, 0x8EBE,
- 0x8EC5, 0x8EC8, 0x8ECB, 0x8EDB, 0x8EE3, 0x8EFC, 0x8EFB, 0x8EEB,
- 0x8EFE, 0x8F0A, 0x8F05, 0x8F15, 0x8F12, 0x8F19, 0x8F13, 0x8F1C,
- 0x8F1F, 0x8F1B, 0x8F0C, 0x8F26, 0x8F33, 0x8F3B, 0x8F39, 0x8F45,
- 0x8F42, 0x8F3E, 0x8F4C, 0x8F49, 0x8F46, 0x8F4E, 0x8F57, 0x8F5C,
- 0x8F62, 0x8F63, 0x8F64, 0x8F9C, 0x8F9F, 0x8FA3, 0x8FAD, 0x8FAF,
- 0x8FB7, 0x8FDA, 0x8FE5, 0x8FE2, 0x8FEA, 0x8FEF, 0x9087, 0x8FF4,
- 0x9005, 0x8FF9, 0x8FFA, 0x9011, 0x9015, 0x9021, 0x900D, 0x901E,
- 0x9016, 0x900B, 0x9027, 0x9036, 0x9035, 0x9039, 0x8FF8,
-};
-static const unsigned short euc_to_utf8_EE[] = {
- 0x904F, 0x9050, 0x9051, 0x9052, 0x900E, 0x9049, 0x903E,
- 0x9056, 0x9058, 0x905E, 0x9068, 0x906F, 0x9076, 0x96A8, 0x9072,
- 0x9082, 0x907D, 0x9081, 0x9080, 0x908A, 0x9089, 0x908F, 0x90A8,
- 0x90AF, 0x90B1, 0x90B5, 0x90E2, 0x90E4, 0x6248, 0x90DB, 0x9102,
- 0x9112, 0x9119, 0x9132, 0x9130, 0x914A, 0x9156, 0x9158, 0x9163,
- 0x9165, 0x9169, 0x9173, 0x9172, 0x918B, 0x9189, 0x9182, 0x91A2,
- 0x91AB, 0x91AF, 0x91AA, 0x91B5, 0x91B4, 0x91BA, 0x91C0, 0x91C1,
- 0x91C9, 0x91CB, 0x91D0, 0x91D6, 0x91DF, 0x91E1, 0x91DB, 0x91FC,
- 0x91F5, 0x91F6, 0x921E, 0x91FF, 0x9214, 0x922C, 0x9215, 0x9211,
- 0x925E, 0x9257, 0x9245, 0x9249, 0x9264, 0x9248, 0x9295, 0x923F,
- 0x924B, 0x9250, 0x929C, 0x9296, 0x9293, 0x929B, 0x925A, 0x92CF,
- 0x92B9, 0x92B7, 0x92E9, 0x930F, 0x92FA, 0x9344, 0x932E,
-};
-static const unsigned short euc_to_utf8_EF[] = {
- 0x9319, 0x9322, 0x931A, 0x9323, 0x933A, 0x9335, 0x933B,
- 0x935C, 0x9360, 0x937C, 0x936E, 0x9356, 0x93B0, 0x93AC, 0x93AD,
- 0x9394, 0x93B9, 0x93D6, 0x93D7, 0x93E8, 0x93E5, 0x93D8, 0x93C3,
- 0x93DD, 0x93D0, 0x93C8, 0x93E4, 0x941A, 0x9414, 0x9413, 0x9403,
- 0x9407, 0x9410, 0x9436, 0x942B, 0x9435, 0x9421, 0x943A, 0x9441,
- 0x9452, 0x9444, 0x945B, 0x9460, 0x9462, 0x945E, 0x946A, 0x9229,
- 0x9470, 0x9475, 0x9477, 0x947D, 0x945A, 0x947C, 0x947E, 0x9481,
- 0x947F, 0x9582, 0x9587, 0x958A, 0x9594, 0x9596, 0x9598, 0x9599,
- 0x95A0, 0x95A8, 0x95A7, 0x95AD, 0x95BC, 0x95BB, 0x95B9, 0x95BE,
- 0x95CA, 0x6FF6, 0x95C3, 0x95CD, 0x95CC, 0x95D5, 0x95D4, 0x95D6,
- 0x95DC, 0x95E1, 0x95E5, 0x95E2, 0x9621, 0x9628, 0x962E, 0x962F,
- 0x9642, 0x964C, 0x964F, 0x964B, 0x9677, 0x965C, 0x965E,
-};
-static const unsigned short euc_to_utf8_F0[] = {
- 0x965D, 0x965F, 0x9666, 0x9672, 0x966C, 0x968D, 0x9698,
- 0x9695, 0x9697, 0x96AA, 0x96A7, 0x96B1, 0x96B2, 0x96B0, 0x96B4,
- 0x96B6, 0x96B8, 0x96B9, 0x96CE, 0x96CB, 0x96C9, 0x96CD, 0x894D,
- 0x96DC, 0x970D, 0x96D5, 0x96F9, 0x9704, 0x9706, 0x9708, 0x9713,
- 0x970E, 0x9711, 0x970F, 0x9716, 0x9719, 0x9724, 0x972A, 0x9730,
- 0x9739, 0x973D, 0x973E, 0x9744, 0x9746, 0x9748, 0x9742, 0x9749,
- 0x975C, 0x9760, 0x9764, 0x9766, 0x9768, 0x52D2, 0x976B, 0x9771,
- 0x9779, 0x9785, 0x977C, 0x9781, 0x977A, 0x9786, 0x978B, 0x978F,
- 0x9790, 0x979C, 0x97A8, 0x97A6, 0x97A3, 0x97B3, 0x97B4, 0x97C3,
- 0x97C6, 0x97C8, 0x97CB, 0x97DC, 0x97ED, 0x9F4F, 0x97F2, 0x7ADF,
- 0x97F6, 0x97F5, 0x980F, 0x980C, 0x9838, 0x9824, 0x9821, 0x9837,
- 0x983D, 0x9846, 0x984F, 0x984B, 0x986B, 0x986F, 0x9870,
-};
-static const unsigned short euc_to_utf8_F1[] = {
- 0x9871, 0x9874, 0x9873, 0x98AA, 0x98AF, 0x98B1, 0x98B6,
- 0x98C4, 0x98C3, 0x98C6, 0x98E9, 0x98EB, 0x9903, 0x9909, 0x9912,
- 0x9914, 0x9918, 0x9921, 0x991D, 0x991E, 0x9924, 0x9920, 0x992C,
- 0x992E, 0x993D, 0x993E, 0x9942, 0x9949, 0x9945, 0x9950, 0x994B,
- 0x9951, 0x9952, 0x994C, 0x9955, 0x9997, 0x9998, 0x99A5, 0x99AD,
- 0x99AE, 0x99BC, 0x99DF, 0x99DB, 0x99DD, 0x99D8, 0x99D1, 0x99ED,
- 0x99EE, 0x99F1, 0x99F2, 0x99FB, 0x99F8, 0x9A01, 0x9A0F, 0x9A05,
- 0x99E2, 0x9A19, 0x9A2B, 0x9A37, 0x9A45, 0x9A42, 0x9A40, 0x9A43,
- 0x9A3E, 0x9A55, 0x9A4D, 0x9A5B, 0x9A57, 0x9A5F, 0x9A62, 0x9A65,
- 0x9A64, 0x9A69, 0x9A6B, 0x9A6A, 0x9AAD, 0x9AB0, 0x9ABC, 0x9AC0,
- 0x9ACF, 0x9AD1, 0x9AD3, 0x9AD4, 0x9ADE, 0x9ADF, 0x9AE2, 0x9AE3,
- 0x9AE6, 0x9AEF, 0x9AEB, 0x9AEE, 0x9AF4, 0x9AF1, 0x9AF7,
-};
-static const unsigned short euc_to_utf8_F2[] = {
- 0x9AFB, 0x9B06, 0x9B18, 0x9B1A, 0x9B1F, 0x9B22, 0x9B23,
- 0x9B25, 0x9B27, 0x9B28, 0x9B29, 0x9B2A, 0x9B2E, 0x9B2F, 0x9B32,
- 0x9B44, 0x9B43, 0x9B4F, 0x9B4D, 0x9B4E, 0x9B51, 0x9B58, 0x9B74,
- 0x9B93, 0x9B83, 0x9B91, 0x9B96, 0x9B97, 0x9B9F, 0x9BA0, 0x9BA8,
- 0x9BB4, 0x9BC0, 0x9BCA, 0x9BB9, 0x9BC6, 0x9BCF, 0x9BD1, 0x9BD2,
- 0x9BE3, 0x9BE2, 0x9BE4, 0x9BD4, 0x9BE1, 0x9C3A, 0x9BF2, 0x9BF1,
- 0x9BF0, 0x9C15, 0x9C14, 0x9C09, 0x9C13, 0x9C0C, 0x9C06, 0x9C08,
- 0x9C12, 0x9C0A, 0x9C04, 0x9C2E, 0x9C1B, 0x9C25, 0x9C24, 0x9C21,
- 0x9C30, 0x9C47, 0x9C32, 0x9C46, 0x9C3E, 0x9C5A, 0x9C60, 0x9C67,
- 0x9C76, 0x9C78, 0x9CE7, 0x9CEC, 0x9CF0, 0x9D09, 0x9D08, 0x9CEB,
- 0x9D03, 0x9D06, 0x9D2A, 0x9D26, 0x9DAF, 0x9D23, 0x9D1F, 0x9D44,
- 0x9D15, 0x9D12, 0x9D41, 0x9D3F, 0x9D3E, 0x9D46, 0x9D48,
-};
-static const unsigned short euc_to_utf8_F3[] = {
- 0x9D5D, 0x9D5E, 0x9D64, 0x9D51, 0x9D50, 0x9D59, 0x9D72,
- 0x9D89, 0x9D87, 0x9DAB, 0x9D6F, 0x9D7A, 0x9D9A, 0x9DA4, 0x9DA9,
- 0x9DB2, 0x9DC4, 0x9DC1, 0x9DBB, 0x9DB8, 0x9DBA, 0x9DC6, 0x9DCF,
- 0x9DC2, 0x9DD9, 0x9DD3, 0x9DF8, 0x9DE6, 0x9DED, 0x9DEF, 0x9DFD,
- 0x9E1A, 0x9E1B, 0x9E1E, 0x9E75, 0x9E79, 0x9E7D, 0x9E81, 0x9E88,
- 0x9E8B, 0x9E8C, 0x9E92, 0x9E95, 0x9E91, 0x9E9D, 0x9EA5, 0x9EA9,
- 0x9EB8, 0x9EAA, 0x9EAD, 0x9761, 0x9ECC, 0x9ECE, 0x9ECF, 0x9ED0,
- 0x9ED4, 0x9EDC, 0x9EDE, 0x9EDD, 0x9EE0, 0x9EE5, 0x9EE8, 0x9EEF,
- 0x9EF4, 0x9EF6, 0x9EF7, 0x9EF9, 0x9EFB, 0x9EFC, 0x9EFD, 0x9F07,
- 0x9F08, 0x76B7, 0x9F15, 0x9F21, 0x9F2C, 0x9F3E, 0x9F4A, 0x9F52,
- 0x9F54, 0x9F63, 0x9F5F, 0x9F60, 0x9F61, 0x9F66, 0x9F67, 0x9F6C,
- 0x9F6A, 0x9F77, 0x9F72, 0x9F76, 0x9F95, 0x9F9C, 0x9FA0,
-};
-static const unsigned short euc_to_utf8_F4[] = {
- 0x582F, 0x69C7, 0x9059, 0x7464, 0x51DC, 0x7199, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short euc_to_utf8_F4_x0213[] = {
- 0x582F, 0x69C7, 0x9059, 0x7464, 0x51DC, 0x7199, 0x5653,
- 0x5DE2, 0x5E14, 0x5E18, 0x5E58, 0x5E5E, 0x5EBE, 0xF928, 0x5ECB,
- 0x5EF9, 0x5F00, 0x5F02, 0x5F07, 0x5F1D, 0x5F23, 0x5F34, 0x5F36,
- 0x5F3D, 0x5F40, 0x5F45, 0x5F54, 0x5F58, 0x5F64, 0x5F67, 0x5F7D,
- 0x5F89, 0x5F9C, 0x5FA7, 0x5FAF, 0x5FB5, 0x5FB7, 0x5FC9, 0x5FDE,
- 0x5FE1, 0x5FE9, 0x600D, 0x6014, 0x6018, 0x6033, 0x6035, 0x6047,
- 0xFA3D, 0x609D, 0x609E, 0x60CB, 0x60D4, 0x60D5, 0x60DD, 0x60F8,
- 0x611C, 0x612B, 0x6130, 0x6137, 0xFA3E, 0x618D, 0xFA3F, 0x61BC,
- 0x61B9, 0xFA40, 0x6222, 0x623E, 0x6243, 0x6256, 0x625A, 0x626F,
- 0x6285, 0x62C4, 0x62D6, 0x62FC, 0x630A, 0x6318, 0x6339, 0x6343,
- 0x6365, 0x637C, 0x63E5, 0x63ED, 0x63F5, 0x6410, 0x6414, 0x6422,
- 0x6479, 0x6451, 0x6460, 0x646D, 0x64CE, 0x64BE, 0x64BF,
-};
-static const unsigned short euc_to_utf8_F5[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFE33, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFE31, 0, 0,
- 0, 0, 0, 0, 0, 0xFE30, 0, 0,
- 0, 0, 0xFE35, 0xFE36, 0xFE39, 0xFE3A, 0, 0,
- 0xFE37, 0xFE38, 0xFE3F, 0xFE40, 0xFE3D, 0xFE3E, 0xFE41, 0xFE42,
- 0xFE43, 0xFE44, 0xFE3B, 0xFE3C, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short euc_to_utf8_F5_x0213[] = {
- 0x64C4, 0x64CA, 0x64D0, 0x64F7, 0x64FB, 0x6522, 0x6529,
- 0xFA41, 0x6567, 0x659D, 0xFA42, 0x6600, 0x6609, 0x6615, 0x661E,
- 0x663A, 0x6622, 0x6624, 0x662B, 0x6630, 0x6631, 0x6633, 0x66FB,
- 0x6648, 0x664C, 0xD84C /*0xDDC4*/, 0x6659, 0x665A, 0x6661, 0x6665, 0x6673,
- 0x6677, 0x6678, 0x668D, 0xFA43, 0x66A0, 0x66B2, 0x66BB, 0x66C6,
- 0x66C8, 0x3B22, 0x66DB, 0x66E8, 0x66FA, 0x6713, 0xF929, 0x6733,
- 0x6766, 0x6747, 0x6748, 0x677B, 0x6781, 0x6793, 0x6798, 0x679B,
- 0x67BB, 0x67F9, 0x67C0, 0x67D7, 0x67FC, 0x6801, 0x6852, 0x681D,
- 0x682C, 0x6831, 0x685B, 0x6872, 0x6875, 0xFA44, 0x68A3, 0x68A5,
- 0x68B2, 0x68C8, 0x68D0, 0x68E8, 0x68ED, 0x68F0, 0x68F1, 0x68FC,
- 0x690A, 0x6949, 0xD84D /*0xDDC4*/, 0x6935, 0x6942, 0x6957, 0x6963, 0x6964,
- 0x6968, 0x6980, 0xFA14, 0x69A5, 0x69AD, 0x69CF, 0x3BB6,
-};
-static const unsigned short euc_to_utf8_F6_x0213[] = {
- 0x3BC3, 0x69E2, 0x69E9, 0x69EA, 0x69F5, 0x69F6, 0x6A0F,
- 0x6A15, 0xD84D /*0xDF3F*/, 0x6A3B, 0x6A3E, 0x6A45, 0x6A50, 0x6A56, 0x6A5B,
- 0x6A6B, 0x6A73, 0xD84D /*0xDF63*/, 0x6A89, 0x6A94, 0x6A9D, 0x6A9E, 0x6AA5,
- 0x6AE4, 0x6AE7, 0x3C0F, 0xF91D, 0x6B1B, 0x6B1E, 0x6B2C, 0x6B35,
- 0x6B46, 0x6B56, 0x6B60, 0x6B65, 0x6B67, 0x6B77, 0x6B82, 0x6BA9,
- 0x6BAD, 0xF970, 0x6BCF, 0x6BD6, 0x6BD7, 0x6BFF, 0x6C05, 0x6C10,
- 0x6C33, 0x6C59, 0x6C5C, 0x6CAA, 0x6C74, 0x6C76, 0x6C85, 0x6C86,
- 0x6C98, 0x6C9C, 0x6CFB, 0x6CC6, 0x6CD4, 0x6CE0, 0x6CEB, 0x6CEE,
- 0xD84F /*0xDCFE*/, 0x6D04, 0x6D0E, 0x6D2E, 0x6D31, 0x6D39, 0x6D3F, 0x6D58,
- 0x6D65, 0xFA45, 0x6D82, 0x6D87, 0x6D89, 0x6D94, 0x6DAA, 0x6DAC,
- 0x6DBF, 0x6DC4, 0x6DD6, 0x6DDA, 0x6DDB, 0x6DDD, 0x6DFC, 0xFA46,
- 0x6E34, 0x6E44, 0x6E5C, 0x6E5E, 0x6EAB, 0x6EB1, 0x6EC1,
-};
-static const unsigned short euc_to_utf8_F7_x0213[] = {
- 0x6EC7, 0x6ECE, 0x6F10, 0x6F1A, 0xFA47, 0x6F2A, 0x6F2F,
- 0x6F33, 0x6F51, 0x6F59, 0x6F5E, 0x6F61, 0x6F62, 0x6F7E, 0x6F88,
- 0x6F8C, 0x6F8D, 0x6F94, 0x6FA0, 0x6FA7, 0x6FB6, 0x6FBC, 0x6FC7,
- 0x6FCA, 0x6FF9, 0x6FF0, 0x6FF5, 0x7005, 0x7006, 0x7028, 0x704A,
- 0x705D, 0x705E, 0x704E, 0x7064, 0x7075, 0x7085, 0x70A4, 0x70AB,
- 0x70B7, 0x70D4, 0x70D8, 0x70E4, 0x710F, 0x712B, 0x711E, 0x7120,
- 0x712E, 0x7130, 0x7146, 0x7147, 0x7151, 0xFA48, 0x7152, 0x715C,
- 0x7160, 0x7168, 0xFA15, 0x7185, 0x7187, 0x7192, 0x71C1, 0x71BA,
- 0x71C4, 0x71FE, 0x7200, 0x7215, 0x7255, 0x7256, 0x3E3F, 0x728D,
- 0x729B, 0x72BE, 0x72C0, 0x72FB, 0xD851 /*0xDFF1*/, 0x7327, 0x7328, 0xFA16,
- 0x7350, 0x7366, 0x737C, 0x7395, 0x739F, 0x73A0, 0x73A2, 0x73A6,
- 0x73AB, 0x73C9, 0x73CF, 0x73D6, 0x73D9, 0x73E3, 0x73E9,
-};
-static const unsigned short euc_to_utf8_F8_x0213[] = {
- 0x7407, 0x740A, 0x741A, 0x741B, 0xFA4A, 0x7426, 0x7428,
- 0x742A, 0x742B, 0x742C, 0x742E, 0x742F, 0x7430, 0x7444, 0x7446,
- 0x7447, 0x744B, 0x7457, 0x7462, 0x746B, 0x746D, 0x7486, 0x7487,
- 0x7489, 0x7498, 0x749C, 0x749F, 0x74A3, 0x7490, 0x74A6, 0x74A8,
- 0x74A9, 0x74B5, 0x74BF, 0x74C8, 0x74C9, 0x74DA, 0x74FF, 0x7501,
- 0x7517, 0x752F, 0x756F, 0x7579, 0x7592, 0x3F72, 0x75CE, 0x75E4,
- 0x7600, 0x7602, 0x7608, 0x7615, 0x7616, 0x7619, 0x761E, 0x762D,
- 0x7635, 0x7643, 0x764B, 0x7664, 0x7665, 0x766D, 0x766F, 0x7671,
- 0x7681, 0x769B, 0x769D, 0x769E, 0x76A6, 0x76AA, 0x76B6, 0x76C5,
- 0x76CC, 0x76CE, 0x76D4, 0x76E6, 0x76F1, 0x76FC, 0x770A, 0x7719,
- 0x7734, 0x7736, 0x7746, 0x774D, 0x774E, 0x775C, 0x775F, 0x7762,
- 0x777A, 0x7780, 0x7794, 0x77AA, 0x77E0, 0x782D, 0xD855 /*0xDC8E*/,
-};
-static const unsigned short euc_to_utf8_F9[] = {
- 0x7E8A, 0x891C, 0x9348, 0x9288, 0x84DC, 0x4FC9, 0x70BB,
- 0x6631, 0x68C8, 0x92F9, 0x66FB, 0x5F45, 0x4E28, 0x4EE1, 0x4EFC,
- 0x4F00, 0x4F03, 0x4F39, 0x4F56, 0x4F92, 0x4F8A, 0x4F9A, 0x4F94,
- 0x4FCD, 0x5040, 0x5022, 0x4FFF, 0x501E, 0x5046, 0x5070, 0x5042,
- 0x5094, 0x50F4, 0x50D8, 0x514A, 0x5164, 0x519D, 0x51BE, 0x51EC,
- 0x5215, 0x529C, 0x52A6, 0x52C0, 0x52DB, 0x5300, 0x5307, 0x5324,
- 0x5372, 0x5393, 0x53B2, 0x53DD, 0xFA0E, 0x549C, 0x548A, 0x54A9,
- 0x54FF, 0x5586, 0x5759, 0x5765, 0x57AC, 0x57C8, 0x57C7, 0xFA0F,
- 0xFA10, 0x589E, 0x58B2, 0x590B, 0x5953, 0x595B, 0x595D, 0x5963,
- 0x59A4, 0x59BA, 0x5B56, 0x5BC0, 0x752F, 0x5BD8, 0x5BEC, 0x5C1E,
- 0x5CA6, 0x5CBA, 0x5CF5, 0x5D27, 0x5D53, 0xFA11, 0x5D42, 0x5D6D,
- 0x5DB8, 0x5DB9, 0x5DD0, 0x5F21, 0x5F34, 0x5F67, 0x5FB7,
-};
-static const unsigned short euc_to_utf8_F9_x0213[] = {
- 0x7843, 0x784E, 0x784F, 0x7851, 0x7868, 0x786E, 0xFA4B,
- 0x78B0, 0xD855 /*0xDD0E*/, 0x78AD, 0x78E4, 0x78F2, 0x7900, 0x78F7, 0x791C,
- 0x792E, 0x7931, 0x7934, 0xFA4C, 0xFA4D, 0x7945, 0x7946, 0xFA4E,
- 0xFA4F, 0xFA50, 0x795C, 0xFA51, 0xFA19, 0xFA1A, 0x7979, 0xFA52,
- 0xFA53, 0xFA1B, 0x7998, 0x79B1, 0x79B8, 0x79C8, 0x79CA, 0xD855 /*0xDF71*/,
- 0x79D4, 0x79DE, 0x79EB, 0x79ED, 0x7A03, 0xFA54, 0x7A39, 0x7A5D,
- 0x7A6D, 0xFA55, 0x7A85, 0x7AA0, 0xD856 /*0xDDC4*/, 0x7AB3, 0x7ABB, 0x7ACE,
- 0x7AEB, 0x7AFD, 0x7B12, 0x7B2D, 0x7B3B, 0x7B47, 0x7B4E, 0x7B60,
- 0x7B6D, 0x7B6F, 0x7B72, 0x7B9E, 0xFA56, 0x7BD7, 0x7BD9, 0x7C01,
- 0x7C31, 0x7C1E, 0x7C20, 0x7C33, 0x7C36, 0x4264, 0xD857 /*0xDDA1*/, 0x7C59,
- 0x7C6D, 0x7C79, 0x7C8F, 0x7C94, 0x7CA0, 0x7CBC, 0x7CD5, 0x7CD9,
- 0x7CDD, 0x7D07, 0x7D08, 0x7D13, 0x7D1D, 0x7D23, 0x7D31,
-};
-static const unsigned short euc_to_utf8_FA[] = {
- 0x5FDE, 0x605D, 0x6085, 0x608A, 0x60DE, 0x60D5, 0x6120,
- 0x60F2, 0x6111, 0x6137, 0x6130, 0x6198, 0x6213, 0x62A6, 0x63F5,
- 0x6460, 0x649D, 0x64CE, 0x654E, 0x6600, 0x6615, 0x663B, 0x6609,
- 0x662E, 0x661E, 0x6624, 0x6665, 0x6657, 0x6659, 0xFA12, 0x6673,
- 0x6699, 0x66A0, 0x66B2, 0x66BF, 0x66FA, 0x670E, 0xF929, 0x6766,
- 0x67BB, 0x6852, 0x67C0, 0x6801, 0x6844, 0x68CF, 0xFA13, 0x6968,
- 0xFA14, 0x6998, 0x69E2, 0x6A30, 0x6A6B, 0x6A46, 0x6A73, 0x6A7E,
- 0x6AE2, 0x6AE4, 0x6BD6, 0x6C3F, 0x6C5C, 0x6C86, 0x6C6F, 0x6CDA,
- 0x6D04, 0x6D87, 0x6D6F, 0x6D96, 0x6DAC, 0x6DCF, 0x6DF8, 0x6DF2,
- 0x6DFC, 0x6E39, 0x6E5C, 0x6E27, 0x6E3C, 0x6EBF, 0x6F88, 0x6FB5,
- 0x6FF5, 0x7005, 0x7007, 0x7028, 0x7085, 0x70AB, 0x710F, 0x7104,
- 0x715C, 0x7146, 0x7147, 0xFA15, 0x71C1, 0x71FE, 0x72B1,
-};
-static const unsigned short euc_to_utf8_FA_x0213[] = {
- 0x7D41, 0x7D48, 0x7D53, 0x7D5C, 0x7D7A, 0x7D83, 0x7D8B,
- 0x7DA0, 0x7DA6, 0x7DC2, 0x7DCC, 0x7DD6, 0x7DE3, 0xFA57, 0x7E28,
- 0x7E08, 0x7E11, 0x7E15, 0xFA59, 0x7E47, 0x7E52, 0x7E61, 0x7E8A,
- 0x7E8D, 0x7F47, 0xFA5A, 0x7F91, 0x7F97, 0x7FBF, 0x7FCE, 0x7FDB,
- 0x7FDF, 0x7FEC, 0x7FEE, 0x7FFA, 0xFA5B, 0x8014, 0x8026, 0x8035,
- 0x8037, 0x803C, 0x80CA, 0x80D7, 0x80E0, 0x80F3, 0x8118, 0x814A,
- 0x8160, 0x8167, 0x8168, 0x816D, 0x81BB, 0x81CA, 0x81CF, 0x81D7,
- 0xFA5C, 0x4453, 0x445B, 0x8260, 0x8274, 0xD85A /*0xDEFF*/, 0x828E, 0x82A1,
- 0x82A3, 0x82A4, 0x82A9, 0x82AE, 0x82B7, 0x82BE, 0x82BF, 0x82C6,
- 0x82D5, 0x82FD, 0x82FE, 0x8300, 0x8301, 0x8362, 0x8322, 0x832D,
- 0x833A, 0x8343, 0x8347, 0x8351, 0x8355, 0x837D, 0x8386, 0x8392,
- 0x8398, 0x83A7, 0x83A9, 0x83BF, 0x83C0, 0x83C7, 0x83CF,
-};
-static const unsigned short euc_to_utf8_FB[] = {
- 0x72BE, 0x7324, 0xFA16, 0x7377, 0x73BD, 0x73C9, 0x73D6,
- 0x73E3, 0x73D2, 0x7407, 0x73F5, 0x7426, 0x742A, 0x7429, 0x742E,
- 0x7462, 0x7489, 0x749F, 0x7501, 0x756F, 0x7682, 0x769C, 0x769E,
- 0x769B, 0x76A6, 0xFA17, 0x7746, 0x52AF, 0x7821, 0x784E, 0x7864,
- 0x787A, 0x7930, 0xFA18, 0xFA19, 0xFA1A, 0x7994, 0xFA1B, 0x799B,
- 0x7AD1, 0x7AE7, 0xFA1C, 0x7AEB, 0x7B9E, 0xFA1D, 0x7D48, 0x7D5C,
- 0x7DB7, 0x7DA0, 0x7DD6, 0x7E52, 0x7F47, 0x7FA1, 0xFA1E, 0x8301,
- 0x8362, 0x837F, 0x83C7, 0x83F6, 0x8448, 0x84B4, 0x8553, 0x8559,
- 0x856B, 0xFA1F, 0x85B0, 0xFA20, 0xFA21, 0x8807, 0x88F5, 0x8A12,
- 0x8A37, 0x8A79, 0x8AA7, 0x8ABE, 0x8ADF, 0xFA22, 0x8AF6, 0x8B53,
- 0x8B7F, 0x8CF0, 0x8CF4, 0x8D12, 0x8D76, 0xFA23, 0x8ECF, 0xFA24,
- 0xFA25, 0x9067, 0x90DE, 0xFA26, 0x9115, 0x9127, 0x91DA,
-};
-static const unsigned short euc_to_utf8_FB_x0213[] = {
- 0x83D1, 0x83E1, 0x83EA, 0x8401, 0x8406, 0x840A, 0xFA5F,
- 0x8448, 0x845F, 0x8470, 0x8473, 0x8485, 0x849E, 0x84AF, 0x84B4,
- 0x84BA, 0x84C0, 0x84C2, 0xD85B /*0xDE40*/, 0x8532, 0x851E, 0x8523, 0x852F,
- 0x8559, 0x8564, 0xFA1F, 0x85AD, 0x857A, 0x858C, 0x858F, 0x85A2,
- 0x85B0, 0x85CB, 0x85CE, 0x85ED, 0x8612, 0x85FF, 0x8604, 0x8605,
- 0x8610, 0xD85C /*0xDCF4*/, 0x8618, 0x8629, 0x8638, 0x8657, 0x865B, 0xF936,
- 0x8662, 0x459D, 0x866C, 0x8675, 0x8698, 0x86B8, 0x86FA, 0x86FC,
- 0x86FD, 0x870B, 0x8771, 0x8787, 0x8788, 0x87AC, 0x87AD, 0x87B5,
- 0x45EA, 0x87D6, 0x87EC, 0x8806, 0x880A, 0x8810, 0x8814, 0x881F,
- 0x8898, 0x88AA, 0x88CA, 0x88CE, 0xD85D /*0xDE84*/, 0x88F5, 0x891C, 0xFA60,
- 0x8918, 0x8919, 0x891A, 0x8927, 0x8930, 0x8932, 0x8939, 0x8940,
- 0x8994, 0xFA61, 0x89D4, 0x89E5, 0x89F6, 0x8A12, 0x8A15,
-};
-static const unsigned short euc_to_utf8_FC[] = {
- 0x91D7, 0x91DE, 0x91ED, 0x91EE, 0x91E4, 0x91E5, 0x9206,
- 0x9210, 0x920A, 0x923A, 0x9240, 0x923C, 0x924E, 0x9259, 0x9251,
- 0x9239, 0x9267, 0x92A7, 0x9277, 0x9278, 0x92E7, 0x92D7, 0x92D9,
- 0x92D0, 0xFA27, 0x92D5, 0x92E0, 0x92D3, 0x9325, 0x9321, 0x92FB,
- 0xFA28, 0x931E, 0x92FF, 0x931D, 0x9302, 0x9370, 0x9357, 0x93A4,
- 0x93C6, 0x93DE, 0x93F8, 0x9431, 0x9445, 0x9448, 0x9592, 0xF9DC,
- 0xFA29, 0x969D, 0x96AF, 0x9733, 0x973B, 0x9743, 0x974D, 0x974F,
- 0x9751, 0x9755, 0x9857, 0x9865, 0xFA2A, 0xFA2B, 0x9927, 0xFA2C,
- 0x999E, 0x9A4E, 0x9AD9, 0x9ADC, 0x9B75, 0x9B72, 0x9B8F, 0x9BB1,
- 0x9BBB, 0x9C00, 0x9D70, 0x9D6B, 0xFA2D, 0x9E19, 0x9ED1, 0,
- 0, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176,
- 0x2177, 0x2178, 0x2179, 0xFFE2, 0x00A6, 0xFF07, 0xFF02,
-};
-
-/* Microsoft UCS Mapping Compatible */
-static const unsigned short euc_to_utf8_FC_ms[] = {
- 0x91D7, 0x91DE, 0x91ED, 0x91EE, 0x91E4, 0x91E5, 0x9206,
- 0x9210, 0x920A, 0x923A, 0x9240, 0x923C, 0x924E, 0x9259, 0x9251,
- 0x9239, 0x9267, 0x92A7, 0x9277, 0x9278, 0x92E7, 0x92D7, 0x92D9,
- 0x92D0, 0xFA27, 0x92D5, 0x92E0, 0x92D3, 0x9325, 0x9321, 0x92FB,
- 0xFA28, 0x931E, 0x92FF, 0x931D, 0x9302, 0x9370, 0x9357, 0x93A4,
- 0x93C6, 0x93DE, 0x93F8, 0x9431, 0x9445, 0x9448, 0x9592, 0xF9DC,
- 0xFA29, 0x969D, 0x96AF, 0x9733, 0x973B, 0x9743, 0x974D, 0x974F,
- 0x9751, 0x9755, 0x9857, 0x9865, 0xFA2A, 0xFA2B, 0x9927, 0xFA2C,
- 0x999E, 0x9A4E, 0x9AD9, 0x9ADC, 0x9B75, 0x9B72, 0x9B8F, 0x9BB1,
- 0x9BBB, 0x9C00, 0x9D70, 0x9D6B, 0xFA2D, 0x9E19, 0x9ED1, 0,
- 0, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176,
- 0x2177, 0x2178, 0x2179, 0xFFE2, 0xFFE4, 0xFF07, 0xFF02,
-};
-static const unsigned short euc_to_utf8_FC_x0213[] = {
- 0x8A22, 0x8A37, 0x8A47, 0x8A4E, 0x8A5D, 0x8A61, 0x8A75,
- 0x8A79, 0x8AA7, 0x8AD0, 0x8ADF, 0x8AF4, 0x8AF6, 0xFA22, 0xFA62,
- 0xFA63, 0x8B46, 0x8B54, 0x8B59, 0x8B69, 0x8B9D, 0x8C49, 0x8C68,
- 0xFA64, 0x8CE1, 0x8CF4, 0x8CF8, 0x8CFE, 0xFA65, 0x8D12, 0x8D1B,
- 0x8DAF, 0x8DCE, 0x8DD1, 0x8DD7, 0x8E20, 0x8E23, 0x8E3D, 0x8E70,
- 0x8E7B, 0xD860 /*0xDE77*/, 0x8EC0, 0x4844, 0x8EFA, 0x8F1E, 0x8F2D, 0x8F36,
- 0x8F54, 0xD860 /*0xDFCD*/, 0x8FA6, 0x8FB5, 0x8FE4, 0x8FE8, 0x8FEE, 0x9008,
- 0x902D, 0xFA67, 0x9088, 0x9095, 0x9097, 0x9099, 0x909B, 0x90A2,
- 0x90B3, 0x90BE, 0x90C4, 0x90C5, 0x90C7, 0x90D7, 0x90DD, 0x90DE,
- 0x90EF, 0x90F4, 0xFA26, 0x9114, 0x9115, 0x9116, 0x9122, 0x9123,
- 0x9127, 0x912F, 0x9131, 0x9134, 0x913D, 0x9148, 0x915B, 0x9183,
- 0x919E, 0x91AC, 0x91B1, 0x91BC, 0x91D7, 0x91FB, 0x91E4,
-};
-static const unsigned short euc_to_utf8_FD_x0213[] = {
- 0x91E5, 0x91ED, 0x91F1, 0x9207, 0x9210, 0x9238, 0x9239,
- 0x923A, 0x923C, 0x9240, 0x9243, 0x924F, 0x9278, 0x9288, 0x92C2,
- 0x92CB, 0x92CC, 0x92D3, 0x92E0, 0x92FF, 0x9304, 0x931F, 0x9321,
- 0x9325, 0x9348, 0x9349, 0x934A, 0x9364, 0x9365, 0x936A, 0x9370,
- 0x939B, 0x93A3, 0x93BA, 0x93C6, 0x93DE, 0x93DF, 0x9404, 0x93FD,
- 0x9433, 0x944A, 0x9463, 0x946B, 0x9471, 0x9472, 0x958E, 0x959F,
- 0x95A6, 0x95A9, 0x95AC, 0x95B6, 0x95BD, 0x95CB, 0x95D0, 0x95D3,
- 0x49B0, 0x95DA, 0x95DE, 0x9658, 0x9684, 0xF9DC, 0x969D, 0x96A4,
- 0x96A5, 0x96D2, 0x96DE, 0xFA68, 0x96E9, 0x96EF, 0x9733, 0x973B,
- 0x974D, 0x974E, 0x974F, 0x975A, 0x976E, 0x9773, 0x9795, 0x97AE,
- 0x97BA, 0x97C1, 0x97C9, 0x97DE, 0x97DB, 0x97F4, 0xFA69, 0x980A,
- 0x981E, 0x982B, 0x9830, 0xFA6A, 0x9852, 0x9853, 0x9856,
-};
-static const unsigned short euc_to_utf8_FE_x0213[] = {
- 0x9857, 0x9859, 0x985A, 0xF9D0, 0x9865, 0x986C, 0x98BA,
- 0x98C8, 0x98E7, 0x9958, 0x999E, 0x9A02, 0x9A03, 0x9A24, 0x9A2D,
- 0x9A2E, 0x9A38, 0x9A4A, 0x9A4E, 0x9A52, 0x9AB6, 0x9AC1, 0x9AC3,
- 0x9ACE, 0x9AD6, 0x9AF9, 0x9B02, 0x9B08, 0x9B20, 0x4C17, 0x9B2D,
- 0x9B5E, 0x9B79, 0x9B66, 0x9B72, 0x9B75, 0x9B84, 0x9B8A, 0x9B8F,
- 0x9B9E, 0x9BA7, 0x9BC1, 0x9BCE, 0x9BE5, 0x9BF8, 0x9BFD, 0x9C00,
- 0x9C23, 0x9C41, 0x9C4F, 0x9C50, 0x9C53, 0x9C63, 0x9C65, 0x9C77,
- 0x9D1D, 0x9D1E, 0x9D43, 0x9D47, 0x9D52, 0x9D63, 0x9D70, 0x9D7C,
- 0x9D8A, 0x9D96, 0x9DC0, 0x9DAC, 0x9DBC, 0x9DD7, 0xD868 /*0xDD90*/, 0x9DE7,
- 0x9E07, 0x9E15, 0x9E7C, 0x9E9E, 0x9EA4, 0x9EAC, 0x9EAF, 0x9EB4,
- 0x9EB5, 0x9EC3, 0x9ED1, 0x9F10, 0x9F39, 0x9F57, 0x9F90, 0x9F94,
- 0x9F97, 0x9FA2, 0x59F8, 0x5C5B, 0x5E77, 0x7626, 0x7E6B,
-};
-
-static const unsigned short euc_to_utf8_8FA1_x0213[] = {
- 0xD840 /*0xDC89*/, 0x4E02, 0x4E0F, 0x4E12, 0x4E29, 0x4E2B, 0x4E2E,
- 0x4E40, 0x4E47, 0x4E48, 0xD840 /*0xDCA2*/, 0x4E51, 0x3406, 0xD840 /*0xDCA4*/, 0x4E5A,
- 0x4E69, 0x4E9D, 0x342C, 0x342E, 0x4EB9, 0x4EBB, 0xD840 /*0xDDA2*/, 0x4EBC,
- 0x4EC3, 0x4EC8, 0x4ED0, 0x4EEB, 0x4EDA, 0x4EF1, 0x4EF5, 0x4F00,
- 0x4F16, 0x4F64, 0x4F37, 0x4F3E, 0x4F54, 0x4F58, 0xD840 /*0xDE13*/, 0x4F77,
- 0x4F78, 0x4F7A, 0x4F7D, 0x4F82, 0x4F85, 0x4F92, 0x4F9A, 0x4FE6,
- 0x4FB2, 0x4FBE, 0x4FC5, 0x4FCB, 0x4FCF, 0x4FD2, 0x346A, 0x4FF2,
- 0x5000, 0x5010, 0x5013, 0x501C, 0x501E, 0x5022, 0x3468, 0x5042,
- 0x5046, 0x504E, 0x5053, 0x5057, 0x5063, 0x5066, 0x506A, 0x5070,
- 0x50A3, 0x5088, 0x5092, 0x5093, 0x5095, 0x5096, 0x509C, 0x50AA,
- 0xD840 /*0xDF2B*/, 0x50B1, 0x50BA, 0x50BB, 0x50C4, 0x50C7, 0x50F3, 0xD840 /*0xDF81*/,
- 0x50CE, 0xD840 /*0xDF71*/, 0x50D4, 0x50D9, 0x50E1, 0x50E9, 0x3492,
-};
-static const unsigned short euc_to_utf8_8FA3_x0213[] = {
- 0x5108, 0xD840 /*0xDFF9*/, 0x5117, 0x511B, 0xD841 /*0xDC4A*/, 0x5160, 0xD841 /*0xDD09*/,
- 0x5173, 0x5183, 0x518B, 0x34BC, 0x5198, 0x51A3, 0x51AD, 0x34C7,
- 0x51BC, 0xD841 /*0xDDD6*/, 0xD841 /*0xDE28*/, 0x51F3, 0x51F4, 0x5202, 0x5212, 0x5216,
- 0xD841 /*0xDF4F*/, 0x5255, 0x525C, 0x526C, 0x5277, 0x5284, 0x5282, 0xD842 /*0xDC07*/,
- 0x5298, 0xD842 /*0xDC3A*/, 0x52A4, 0x52A6, 0x52AF, 0x52BA, 0x52BB, 0x52CA,
- 0x351F, 0x52D1, 0xD842 /*0xDCB9*/, 0x52F7, 0x530A, 0x530B, 0x5324, 0x5335,
- 0x533E, 0x5342, 0xD842 /*0xDD7C*/, 0xD842 /*0xDD9D*/, 0x5367, 0x536C, 0x537A, 0x53A4,
- 0x53B4, 0xD842 /*0xDED3*/, 0x53B7, 0x53C0, 0xD842 /*0xDF1D*/, 0x355D, 0x355E, 0x53D5,
- 0x53DA, 0x3563, 0x53F4, 0x53F5, 0x5455, 0x5424, 0x5428, 0x356E,
- 0x5443, 0x5462, 0x5466, 0x546C, 0x548A, 0x548D, 0x5495, 0x54A0,
- 0x54A6, 0x54AD, 0x54AE, 0x54B7, 0x54BA, 0x54BF, 0x54C3, 0xD843 /*0xDD45*/,
- 0x54EC, 0x54EF, 0x54F1, 0x54F3, 0x5500, 0x5501, 0x5509,
-};
-static const unsigned short euc_to_utf8_8FA4_x0213[] = {
- 0x553C, 0x5541, 0x35A6, 0x5547, 0x554A, 0x35A8, 0x5560,
- 0x5561, 0x5564, 0xD843 /*0xDDE1*/, 0x557D, 0x5582, 0x5588, 0x5591, 0x35C5,
- 0x55D2, 0xD843 /*0xDE95*/, 0xD843 /*0xDE6D*/, 0x55BF, 0x55C9, 0x55CC, 0x55D1, 0x55DD,
- 0x35DA, 0x55E2, 0xD843 /*0xDE64*/, 0x55E9, 0x5628, 0xD843 /*0xDF5F*/, 0x5607, 0x5610,
- 0x5630, 0x5637, 0x35F4, 0x563D, 0x563F, 0x5640, 0x5647, 0x565E,
- 0x5660, 0x566D, 0x3605, 0x5688, 0x568C, 0x5695, 0x569A, 0x569D,
- 0x56A8, 0x56AD, 0x56B2, 0x56C5, 0x56CD, 0x56DF, 0x56E8, 0x56F6,
- 0x56F7, 0xD844 /*0xDE01*/, 0x5715, 0x5723, 0xD844 /*0xDE55*/, 0x5729, 0xD844 /*0xDE7B*/, 0x5745,
- 0x5746, 0x574C, 0x574D, 0xD844 /*0xDE74*/, 0x5768, 0x576F, 0x5773, 0x5774,
- 0x5775, 0x577B, 0xD844 /*0xDEE4*/, 0xD844 /*0xDED7*/, 0x57AC, 0x579A, 0x579D, 0x579E,
- 0x57A8, 0x57D7, 0xD844 /*0xDEFD*/, 0x57CC, 0xD844 /*0xDF36*/, 0xD844 /*0xDF44*/, 0x57DE, 0x57E6,
- 0x57F0, 0x364A, 0x57F8, 0x57FB, 0x57FD, 0x5804, 0x581E,
-};
-static const unsigned short euc_to_utf8_8FA5_x0213[] = {
- 0x5820, 0x5827, 0x5832, 0x5839, 0xD844 /*0xDFC4*/, 0x5849, 0x584C,
- 0x5867, 0x588A, 0x588B, 0x588D, 0x588F, 0x5890, 0x5894, 0x589D,
- 0x58AA, 0x58B1, 0xD845 /*0xDC6D*/, 0x58C3, 0x58CD, 0x58E2, 0x58F3, 0x58F4,
- 0x5905, 0x5906, 0x590B, 0x590D, 0x5914, 0x5924, 0xD845 /*0xDDD7*/, 0x3691,
- 0x593D, 0x3699, 0x5946, 0x3696, 0xD85B /*0xDC29*/, 0x595B, 0x595F, 0xD845 /*0xDE47*/,
- 0x5975, 0x5976, 0x597C, 0x599F, 0x59AE, 0x59BC, 0x59C8, 0x59CD,
- 0x59DE, 0x59E3, 0x59E4, 0x59E7, 0x59EE, 0xD845 /*0xDF06*/, 0xD845 /*0xDF42*/, 0x36CF,
- 0x5A0C, 0x5A0D, 0x5A17, 0x5A27, 0x5A2D, 0x5A55, 0x5A65, 0x5A7A,
- 0x5A8B, 0x5A9C, 0x5A9F, 0x5AA0, 0x5AA2, 0x5AB1, 0x5AB3, 0x5AB5,
- 0x5ABA, 0x5ABF, 0x5ADA, 0x5ADC, 0x5AE0, 0x5AE5, 0x5AF0, 0x5AEE,
- 0x5AF5, 0x5B00, 0x5B08, 0x5B17, 0x5B34, 0x5B2D, 0x5B4C, 0x5B52,
- 0x5B68, 0x5B6F, 0x5B7C, 0x5B7F, 0x5B81, 0x5B84, 0xD846 /*0xDDC3*/,
-};
-static const unsigned short euc_to_utf8_8FA8_x0213[] = {
- 0x5B96, 0x5BAC, 0x3761, 0x5BC0, 0x3762, 0x5BCE, 0x5BD6,
- 0x376C, 0x376B, 0x5BF1, 0x5BFD, 0x3775, 0x5C03, 0x5C29, 0x5C30,
- 0xD847 /*0xDC56*/, 0x5C5F, 0x5C63, 0x5C67, 0x5C68, 0x5C69, 0x5C70, 0xD847 /*0xDD2D*/,
- 0xD847 /*0xDD45*/, 0x5C7C, 0xD847 /*0xDD78*/, 0xD847 /*0xDD62*/, 0x5C88, 0x5C8A, 0x37C1, 0xD847 /*0xDDA1*/,
- 0xD847 /*0xDD9C*/, 0x5CA0, 0x5CA2, 0x5CA6, 0x5CA7, 0xD847 /*0xDD92*/, 0x5CAD, 0x5CB5,
- 0xD847 /*0xDDB7*/, 0x5CC9, 0xD847 /*0xDDE0*/, 0xD847 /*0xDE33*/, 0x5D06, 0x5D10, 0x5D2B, 0x5D1D,
- 0x5D20, 0x5D24, 0x5D26, 0x5D31, 0x5D39, 0x5D42, 0x37E8, 0x5D61,
- 0x5D6A, 0x37F4, 0x5D70, 0xD847 /*0xDF1E*/, 0x37FD, 0x5D88, 0x3800, 0x5D92,
- 0x5D94, 0x5D97, 0x5D99, 0x5DB0, 0x5DB2, 0x5DB4, 0xD847 /*0xDF76*/, 0x5DB9,
- 0x5DD1, 0x5DD7, 0x5DD8, 0x5DE0, 0xD847 /*0xDFFA*/, 0x5DE4, 0x5DE9, 0x382F,
- 0x5E00, 0x3836, 0x5E12, 0x5E15, 0x3840, 0x5E1F, 0x5E2E, 0x5E3E,
- 0x5E49, 0x385C, 0x5E56, 0x3861, 0x5E6B, 0x5E6C, 0x5E6D,
-};
-static const unsigned short euc_to_utf8_8FAC_x0213[] = {
- 0x5E6E, 0xD848 /*0xDD7B*/, 0x5EA5, 0x5EAA, 0x5EAC, 0x5EB9, 0x5EBF,
- 0x5EC6, 0x5ED2, 0x5ED9, 0xD848 /*0xDF1E*/, 0x5EFD, 0x5F08, 0x5F0E, 0x5F1C,
- 0xD848 /*0xDFAD*/, 0x5F1E, 0x5F47, 0x5F63, 0x5F72, 0x5F7E, 0x5F8F, 0x5FA2,
- 0x5FA4, 0x5FB8, 0x5FC4, 0x38FA, 0x5FC7, 0x5FCB, 0x5FD2, 0x5FD3,
- 0x5FD4, 0x5FE2, 0x5FEE, 0x5FEF, 0x5FF3, 0x5FFC, 0x3917, 0x6017,
- 0x6022, 0x6024, 0x391A, 0x604C, 0x607F, 0x608A, 0x6095, 0x60A8,
- 0xD849 /*0xDEF3*/, 0x60B0, 0x60B1, 0x60BE, 0x60C8, 0x60D9, 0x60DB, 0x60EE,
- 0x60F2, 0x60F5, 0x6110, 0x6112, 0x6113, 0x6119, 0x611E, 0x613A,
- 0x396F, 0x6141, 0x6146, 0x6160, 0x617C, 0xD84A /*0xDC5B*/, 0x6192, 0x6193,
- 0x6197, 0x6198, 0x61A5, 0x61A8, 0x61AD, 0xD84A /*0xDCAB*/, 0x61D5, 0x61DD,
- 0x61DF, 0x61F5, 0xD84A /*0xDD8F*/, 0x6215, 0x6223, 0x6229, 0x6246, 0x624C,
- 0x6251, 0x6252, 0x6261, 0x6264, 0x627B, 0x626D, 0x6273,
-};
-static const unsigned short euc_to_utf8_8FAD_x0213[] = {
- 0x6299, 0x62A6, 0x62D5, 0xD84A /*0xDEB8*/, 0x62FD, 0x6303, 0x630D,
- 0x6310, 0xD84A /*0xDF4F*/, 0xD84A /*0xDF50*/, 0x6332, 0x6335, 0x633B, 0x633C, 0x6341,
- 0x6344, 0x634E, 0xD84A /*0xDF46*/, 0x6359, 0xD84B /*0xDC1D*/, 0xD84A /*0xDFA6*/, 0x636C, 0x6384,
- 0x6399, 0xD84B /*0xDC24*/, 0x6394, 0x63BD, 0x63F7, 0x63D4, 0x63D5, 0x63DC,
- 0x63E0, 0x63EB, 0x63EC, 0x63F2, 0x6409, 0x641E, 0x6425, 0x6429,
- 0x642F, 0x645A, 0x645B, 0x645D, 0x6473, 0x647D, 0x6487, 0x6491,
- 0x649D, 0x649F, 0x64CB, 0x64CC, 0x64D5, 0x64D7, 0xD84B /*0xDDE1*/, 0x64E4,
- 0x64E5, 0x64FF, 0x6504, 0x3A6E, 0x650F, 0x6514, 0x6516, 0x3A73,
- 0x651E, 0x6532, 0x6544, 0x6554, 0x656B, 0x657A, 0x6581, 0x6584,
- 0x6585, 0x658A, 0x65B2, 0x65B5, 0x65B8, 0x65BF, 0x65C2, 0x65C9,
- 0x65D4, 0x3AD6, 0x65F2, 0x65F9, 0x65FC, 0x6604, 0x6608, 0x6621,
- 0x662A, 0x6645, 0x6651, 0x664E, 0x3AEA, 0xD84C /*0xDDC3*/, 0x6657,
-};
-static const unsigned short euc_to_utf8_8FAE_x0213[] = {
- 0x665B, 0x6663, 0xD84C /*0xDDF5*/, 0xD84C /*0xDDB6*/, 0x666A, 0x666B, 0x666C,
- 0x666D, 0x667B, 0x6680, 0x6690, 0x6692, 0x6699, 0x3B0E, 0x66AD,
- 0x66B1, 0x66B5, 0x3B1A, 0x66BF, 0x3B1C, 0x66EC, 0x3AD7, 0x6701,
- 0x6705, 0x6712, 0xD84C /*0xDF72*/, 0x6719, 0xD84C /*0xDFD3*/, 0xD84C /*0xDFD2*/, 0x674C, 0x674D,
- 0x6754, 0x675D, 0xD84C /*0xDFD0*/, 0xD84C /*0xDFE4*/, 0xD84C /*0xDFD5*/, 0x6774, 0x6776, 0xD84C /*0xDFDA*/,
- 0x6792, 0xD84C /*0xDFDF*/, 0x8363, 0x6810, 0x67B0, 0x67B2, 0x67C3, 0x67C8,
- 0x67D2, 0x67D9, 0x67DB, 0x67F0, 0x67F7, 0xD84D /*0xDC4A*/, 0xD84D /*0xDC51*/, 0xD84D /*0xDC4B*/,
- 0x6818, 0x681F, 0x682D, 0xD84D /*0xDC65*/, 0x6833, 0x683B, 0x683E, 0x6844,
- 0x6845, 0x6849, 0x684C, 0x6855, 0x6857, 0x3B77, 0x686B, 0x686E,
- 0x687A, 0x687C, 0x6882, 0x6890, 0x6896, 0x3B6D, 0x6898, 0x6899,
- 0x689A, 0x689C, 0x68AA, 0x68AB, 0x68B4, 0x68BB, 0x68FB, 0xD84D /*0xDCE4*/,
- 0xD84D /*0xDD5A*/, 0xFA13, 0x68C3, 0x68C5, 0x68CC, 0x68CF, 0x68D6,
-};
-static const unsigned short euc_to_utf8_8FAF_x0213[] = {
- 0x68D9, 0x68E4, 0x68E5, 0x68EC, 0x68F7, 0x6903, 0x6907,
- 0x3B87, 0x3B88, 0xD84D /*0xDD94*/, 0x693B, 0x3B8D, 0x6946, 0x6969, 0x696C,
- 0x6972, 0x697A, 0x697F, 0x6992, 0x3BA4, 0x6996, 0x6998, 0x69A6,
- 0x69B0, 0x69B7, 0x69BA, 0x69BC, 0x69C0, 0x69D1, 0x69D6, 0xD84D /*0xDE39*/,
- 0xD84D /*0xDE47*/, 0x6A30, 0xD84D /*0xDE38*/, 0xD84D /*0xDE3A*/, 0x69E3, 0x69EE, 0x69EF, 0x69F3,
- 0x3BCD, 0x69F4, 0x69FE, 0x6A11, 0x6A1A, 0x6A1D, 0xD84D /*0xDF1C*/, 0x6A32,
- 0x6A33, 0x6A34, 0x6A3F, 0x6A46, 0x6A49, 0x6A7A, 0x6A4E, 0x6A52,
- 0x6A64, 0xD84D /*0xDF0C*/, 0x6A7E, 0x6A83, 0x6A8B, 0x3BF0, 0x6A91, 0x6A9F,
- 0x6AA1, 0xD84D /*0xDF64*/, 0x6AAB, 0x6ABD, 0x6AC6, 0x6AD4, 0x6AD0, 0x6ADC,
- 0x6ADD, 0xD84D /*0xDFFF*/, 0xD84D /*0xDFE7*/, 0x6AEC, 0x6AF1, 0x6AF2, 0x6AF3, 0x6AFD,
- 0xD84E /*0xDC24*/, 0x6B0B, 0x6B0F, 0x6B10, 0x6B11, 0xD84E /*0xDC3D*/, 0x6B17, 0x3C26,
- 0x6B2F, 0x6B4A, 0x6B58, 0x6B6C, 0x6B75, 0x6B7A, 0x6B81,
-};
-static const unsigned short euc_to_utf8_8FEE_x0213[] = {
- 0x6B9B, 0x6BAE, 0xD84E /*0xDE98*/, 0x6BBD, 0x6BBE, 0x6BC7, 0x6BC8,
- 0x6BC9, 0x6BDA, 0x6BE6, 0x6BE7, 0x6BEE, 0x6BF1, 0x6C02, 0x6C0A,
- 0x6C0E, 0x6C35, 0x6C36, 0x6C3A, 0xD84F /*0xDC7F*/, 0x6C3F, 0x6C4D, 0x6C5B,
- 0x6C6D, 0x6C84, 0x6C89, 0x3CC3, 0x6C94, 0x6C95, 0x6C97, 0x6CAD,
- 0x6CC2, 0x6CD0, 0x3CD2, 0x6CD6, 0x6CDA, 0x6CDC, 0x6CE9, 0x6CEC,
- 0x6CED, 0xD84F /*0xDD00*/, 0x6D00, 0x6D0A, 0x6D24, 0x6D26, 0x6D27, 0x6C67,
- 0x6D2F, 0x6D3C, 0x6D5B, 0x6D5E, 0x6D60, 0x6D70, 0x6D80, 0x6D81,
- 0x6D8A, 0x6D8D, 0x6D91, 0x6D98, 0xD84F /*0xDD40*/, 0x6E17, 0xD84F /*0xDDFA*/, 0xD84F /*0xDDF9*/,
- 0xD84F /*0xDDD3*/, 0x6DAB, 0x6DAE, 0x6DB4, 0x6DC2, 0x6D34, 0x6DC8, 0x6DCE,
- 0x6DCF, 0x6DD0, 0x6DDF, 0x6DE9, 0x6DF6, 0x6E36, 0x6E1E, 0x6E22,
- 0x6E27, 0x3D11, 0x6E32, 0x6E3C, 0x6E48, 0x6E49, 0x6E4B, 0x6E4C,
- 0x6E4F, 0x6E51, 0x6E53, 0x6E54, 0x6E57, 0x6E63, 0x3D1E,
-};
-static const unsigned short euc_to_utf8_8FEF_x0213[] = {
- 0x6E93, 0x6EA7, 0x6EB4, 0x6EBF, 0x6EC3, 0x6ECA, 0x6ED9,
- 0x6F35, 0x6EEB, 0x6EF9, 0x6EFB, 0x6F0A, 0x6F0C, 0x6F18, 0x6F25,
- 0x6F36, 0x6F3C, 0xD84F /*0xDF7E*/, 0x6F52, 0x6F57, 0x6F5A, 0x6F60, 0x6F68,
- 0x6F98, 0x6F7D, 0x6F90, 0x6F96, 0x6FBE, 0x6F9F, 0x6FA5, 0x6FAF,
- 0x3D64, 0x6FB5, 0x6FC8, 0x6FC9, 0x6FDA, 0x6FDE, 0x6FE9, 0xD850 /*0xDC96*/,
- 0x6FFC, 0x7000, 0x7007, 0x700A, 0x7023, 0xD850 /*0xDD03*/, 0x7039, 0x703A,
- 0x703C, 0x7043, 0x7047, 0x704B, 0x3D9A, 0x7054, 0x7065, 0x7069,
- 0x706C, 0x706E, 0x7076, 0x707E, 0x7081, 0x7086, 0x7095, 0x7097,
- 0x70BB, 0xD850 /*0xDDC6*/, 0x709F, 0x70B1, 0xD850 /*0xDDFE*/, 0x70EC, 0x70CA, 0x70D1,
- 0x70D3, 0x70DC, 0x7103, 0x7104, 0x7106, 0x7107, 0x7108, 0x710C,
- 0x3DC0, 0x712F, 0x7131, 0x7150, 0x714A, 0x7153, 0x715E, 0x3DD4,
- 0x7196, 0x7180, 0x719B, 0x71A0, 0x71A2, 0x71AE, 0x71AF,
-};
-static const unsigned short euc_to_utf8_8FF0_x0213[] = {
- 0x71B3, 0xD850 /*0xDFBC*/, 0x71CB, 0x71D3, 0x71D9, 0x71DC, 0x7207,
- 0x3E05, 0xFA49, 0x722B, 0x7234, 0x7238, 0x7239, 0x4E2C, 0x7242,
- 0x7253, 0x7257, 0x7263, 0xD851 /*0xDE29*/, 0x726E, 0x726F, 0x7278, 0x727F,
- 0x728E, 0xD851 /*0xDEA5*/, 0x72AD, 0x72AE, 0x72B0, 0x72B1, 0x72C1, 0x3E60,
- 0x72CC, 0x3E66, 0x3E68, 0x72F3, 0x72FA, 0x7307, 0x7312, 0x7318,
- 0x7319, 0x3E83, 0x7339, 0x732C, 0x7331, 0x7333, 0x733D, 0x7352,
- 0x3E94, 0x736B, 0x736C, 0xD852 /*0xDC96*/, 0x736E, 0x736F, 0x7371, 0x7377,
- 0x7381, 0x7385, 0x738A, 0x7394, 0x7398, 0x739C, 0x739E, 0x73A5,
- 0x73A8, 0x73B5, 0x73B7, 0x73B9, 0x73BC, 0x73BF, 0x73C5, 0x73CB,
- 0x73E1, 0x73E7, 0x73F9, 0x7413, 0x73FA, 0x7401, 0x7424, 0x7431,
- 0x7439, 0x7453, 0x7440, 0x7443, 0x744D, 0x7452, 0x745D, 0x7471,
- 0x7481, 0x7485, 0x7488, 0xD852 /*0xDE4D*/, 0x7492, 0x7497, 0x7499,
-};
-static const unsigned short euc_to_utf8_8FF1_x0213[] = {
- 0x74A0, 0x74A1, 0x74A5, 0x74AA, 0x74AB, 0x74B9, 0x74BB,
- 0x74BA, 0x74D6, 0x74D8, 0x74DE, 0x74EF, 0x74EB, 0xD852 /*0xDF56*/, 0x74FA,
- 0xD852 /*0xDF6F*/, 0x7520, 0x7524, 0x752A, 0x3F57, 0xD853 /*0xDC16*/, 0x753D, 0x753E,
- 0x7540, 0x7548, 0x754E, 0x7550, 0x7552, 0x756C, 0x7572, 0x7571,
- 0x757A, 0x757D, 0x757E, 0x7581, 0xD853 /*0xDD14*/, 0x758C, 0x3F75, 0x75A2,
- 0x3F77, 0x75B0, 0x75B7, 0x75BF, 0x75C0, 0x75C6, 0x75CF, 0x75D3,
- 0x75DD, 0x75DF, 0x75E0, 0x75E7, 0x75EC, 0x75EE, 0x75F1, 0x75F9,
- 0x7603, 0x7618, 0x7607, 0x760F, 0x3FAE, 0xD853 /*0xDE0E*/, 0x7613, 0x761B,
- 0x761C, 0xD853 /*0xDE37*/, 0x7625, 0x7628, 0x763C, 0x7633, 0xD853 /*0xDE6A*/, 0x3FC9,
- 0x7641, 0xD853 /*0xDE8B*/, 0x7649, 0x7655, 0x3FD7, 0x766E, 0x7695, 0x769C,
- 0x76A1, 0x76A0, 0x76A7, 0x76A8, 0x76AF, 0xD854 /*0xDC4A*/, 0x76C9, 0xD854 /*0xDC55*/,
- 0x76E8, 0x76EC, 0xD854 /*0xDD22*/, 0x7717, 0x771A, 0x772D, 0x7735,
-};
-static const unsigned short euc_to_utf8_8FF2_x0213[] = {
- 0xD854 /*0xDDA9*/, 0x4039, 0xD854 /*0xDDE5*/, 0xD854 /*0xDDCD*/, 0x7758, 0x7760, 0x776A,
- 0xD854 /*0xDE1E*/, 0x7772, 0x777C, 0x777D, 0xD854 /*0xDE4C*/, 0x4058, 0x779A, 0x779F,
- 0x77A2, 0x77A4, 0x77A9, 0x77DE, 0x77DF, 0x77E4, 0x77E6, 0x77EA,
- 0x77EC, 0x4093, 0x77F0, 0x77F4, 0x77FB, 0xD855 /*0xDC2E*/, 0x7805, 0x7806,
- 0x7809, 0x780D, 0x7819, 0x7821, 0x782C, 0x7847, 0x7864, 0x786A,
- 0xD855 /*0xDCD9*/, 0x788A, 0x7894, 0x78A4, 0x789D, 0x789E, 0x789F, 0x78BB,
- 0x78C8, 0x78CC, 0x78CE, 0x78D5, 0x78E0, 0x78E1, 0x78E6, 0x78F9,
- 0x78FA, 0x78FB, 0x78FE, 0xD855 /*0xDDA7*/, 0x7910, 0x791B, 0x7930, 0x7925,
- 0x793B, 0x794A, 0x7958, 0x795B, 0x4105, 0x7967, 0x7972, 0x7994,
- 0x7995, 0x7996, 0x799B, 0x79A1, 0x79A9, 0x79B4, 0x79BB, 0x79C2,
- 0x79C7, 0x79CC, 0x79CD, 0x79D6, 0x4148, 0xD855 /*0xDFA9*/, 0xD855 /*0xDFB4*/, 0x414F,
- 0x7A0A, 0x7A11, 0x7A15, 0x7A1B, 0x7A1E, 0x4163, 0x7A2D,
-};
-static const unsigned short euc_to_utf8_8FF3_x0213[] = {
- 0x7A38, 0x7A47, 0x7A4C, 0x7A56, 0x7A59, 0x7A5C, 0x7A5F,
- 0x7A60, 0x7A67, 0x7A6A, 0x7A75, 0x7A78, 0x7A82, 0x7A8A, 0x7A90,
- 0x7AA3, 0x7AAC, 0xD856 /*0xDDD4*/, 0x41B4, 0x7AB9, 0x7ABC, 0x7ABE, 0x41BF,
- 0x7ACC, 0x7AD1, 0x7AE7, 0x7AE8, 0x7AF4, 0xD856 /*0xDEE4*/, 0xD856 /*0xDEE3*/, 0x7B07,
- 0xD856 /*0xDEF1*/, 0x7B3D, 0x7B27, 0x7B2A, 0x7B2E, 0x7B2F, 0x7B31, 0x41E6,
- 0x41F3, 0x7B7F, 0x7B41, 0x41EE, 0x7B55, 0x7B79, 0x7B64, 0x7B66,
- 0x7B69, 0x7B73, 0xD856 /*0xDFB2*/, 0x4207, 0x7B90, 0x7B91, 0x7B9B, 0x420E,
- 0x7BAF, 0x7BB5, 0x7BBC, 0x7BC5, 0x7BCA, 0xD857 /*0xDC4B*/, 0xD857 /*0xDC64*/, 0x7BD4,
- 0x7BD6, 0x7BDA, 0x7BEA, 0x7BF0, 0x7C03, 0x7C0B, 0x7C0E, 0x7C0F,
- 0x7C26, 0x7C45, 0x7C4A, 0x7C51, 0x7C57, 0x7C5E, 0x7C61, 0x7C69,
- 0x7C6E, 0x7C6F, 0x7C70, 0xD857 /*0xDE2E*/, 0xD857 /*0xDE56*/, 0xD857 /*0xDE65*/, 0x7CA6, 0xD857 /*0xDE62*/,
- 0x7CB6, 0x7CB7, 0x7CBF, 0xD857 /*0xDED8*/, 0x7CC4, 0xD857 /*0xDEC2*/, 0x7CC8,
-};
-static const unsigned short euc_to_utf8_8FF4_x0213[] = {
- 0x7CCD, 0xD857 /*0xDEE8*/, 0x7CD7, 0xD857 /*0xDF23*/, 0x7CE6, 0x7CEB, 0xD857 /*0xDF5C*/,
- 0x7CF5, 0x7D03, 0x7D09, 0x42C6, 0x7D12, 0x7D1E, 0xD857 /*0xDFE0*/, 0xD857 /*0xDFD4*/,
- 0x7D3D, 0x7D3E, 0x7D40, 0x7D47, 0xD858 /*0xDC0C*/, 0xD857 /*0xDFFB*/, 0x42D6, 0x7D59,
- 0x7D5A, 0x7D6A, 0x7D70, 0x42DD, 0x7D7F, 0xD858 /*0xDC17*/, 0x7D86, 0x7D88,
- 0x7D8C, 0x7D97, 0xD858 /*0xDC60*/, 0x7D9D, 0x7DA7, 0x7DAA, 0x7DB6, 0x7DB7,
- 0x7DC0, 0x7DD7, 0x7DD9, 0x7DE6, 0x7DF1, 0x7DF9, 0x4302, 0xD858 /*0xDCED*/,
- 0xFA58, 0x7E10, 0x7E17, 0x7E1D, 0x7E20, 0x7E27, 0x7E2C, 0x7E45,
- 0x7E73, 0x7E75, 0x7E7E, 0x7E86, 0x7E87, 0x432B, 0x7E91, 0x7E98,
- 0x7E9A, 0x4343, 0x7F3C, 0x7F3B, 0x7F3E, 0x7F43, 0x7F44, 0x7F4F,
- 0x34C1, 0xD858 /*0xDE70*/, 0x7F52, 0xD858 /*0xDE86*/, 0x7F61, 0x7F63, 0x7F64, 0x7F6D,
- 0x7F7D, 0x7F7E, 0xD858 /*0xDF4C*/, 0x7F90, 0x517B, 0xD84F /*0xDD0E*/, 0x7F96, 0x7F9C,
- 0x7FAD, 0xD859 /*0xDC02*/, 0x7FC3, 0x7FCF, 0x7FE3, 0x7FE5, 0x7FEF,
-};
-static const unsigned short euc_to_utf8_8FF5_x0213[] = {
- 0x7FF2, 0x8002, 0x800A, 0x8008, 0x800E, 0x8011, 0x8016,
- 0x8024, 0x802C, 0x8030, 0x8043, 0x8066, 0x8071, 0x8075, 0x807B,
- 0x8099, 0x809C, 0x80A4, 0x80A7, 0x80B8, 0xD859 /*0xDE7E*/, 0x80C5, 0x80D5,
- 0x80D8, 0x80E6, 0xD859 /*0xDEB0*/, 0x810D, 0x80F5, 0x80FB, 0x43EE, 0x8135,
- 0x8116, 0x811E, 0x43F0, 0x8124, 0x8127, 0x812C, 0xD859 /*0xDF1D*/, 0x813D,
- 0x4408, 0x8169, 0x4417, 0x8181, 0x441C, 0x8184, 0x8185, 0x4422,
- 0x8198, 0x81B2, 0x81C1, 0x81C3, 0x81D6, 0x81DB, 0xD85A /*0xDCDD*/, 0x81E4,
- 0xD85A /*0xDCEA*/, 0x81EC, 0xD85A /*0xDD51*/, 0x81FD, 0x81FF, 0xD85A /*0xDD6F*/, 0x8204, 0xD85A /*0xDDDD*/,
- 0x8219, 0x8221, 0x8222, 0xD85A /*0xDE1E*/, 0x8232, 0x8234, 0x823C, 0x8246,
- 0x8249, 0x8245, 0xD85A /*0xDE58*/, 0x824B, 0x4476, 0x824F, 0x447A, 0x8257,
- 0xD85A /*0xDE8C*/, 0x825C, 0x8263, 0xD85A /*0xDEB7*/, 0xFA5D, 0xFA5E, 0x8279, 0x4491,
- 0x827D, 0x827F, 0x8283, 0x828A, 0x8293, 0x82A7, 0x82A8,
-};
-static const unsigned short euc_to_utf8_8FF6_x0213[] = {
- 0x82B2, 0x82B4, 0x82BA, 0x82BC, 0x82E2, 0x82E8, 0x82F7,
- 0x8307, 0x8308, 0x830C, 0x8354, 0x831B, 0x831D, 0x8330, 0x833C,
- 0x8344, 0x8357, 0x44BE, 0x837F, 0x44D4, 0x44B3, 0x838D, 0x8394,
- 0x8395, 0x839B, 0x839D, 0x83C9, 0x83D0, 0x83D4, 0x83DD, 0x83E5,
- 0x83F9, 0x840F, 0x8411, 0x8415, 0xD85B /*0xDC73*/, 0x8417, 0x8439, 0x844A,
- 0x844F, 0x8451, 0x8452, 0x8459, 0x845A, 0x845C, 0xD85B /*0xDCDD*/, 0x8465,
- 0x8476, 0x8478, 0x847C, 0x8481, 0x450D, 0x84DC, 0x8497, 0x84A6,
- 0x84BE, 0x4508, 0x84CE, 0x84CF, 0x84D3, 0xD85B /*0xDE65*/, 0x84E7, 0x84EA,
- 0x84EF, 0x84F0, 0x84F1, 0x84FA, 0x84FD, 0x850C, 0x851B, 0x8524,
- 0x8525, 0x852B, 0x8534, 0x854F, 0x856F, 0x4525, 0x4543, 0x853E,
- 0x8551, 0x8553, 0x855E, 0x8561, 0x8562, 0xD85B /*0xDF94*/, 0x857B, 0x857D,
- 0x857F, 0x8581, 0x8586, 0x8593, 0x859D, 0x859F, 0xD85B /*0xDFF8*/,
-};
-static const unsigned short euc_to_utf8_8FF7_x0213[] = {
- 0xD85B /*0xDFF6*/, 0xD85B /*0xDFF7*/, 0x85B7, 0x85BC, 0x85C7, 0x85CA, 0x85D8,
- 0x85D9, 0x85DF, 0x85E1, 0x85E6, 0x85F6, 0x8600, 0x8611, 0x861E,
- 0x8621, 0x8624, 0x8627, 0xD85C /*0xDD0D*/, 0x8639, 0x863C, 0xD85C /*0xDD39*/, 0x8640,
- 0xFA20, 0x8653, 0x8656, 0x866F, 0x8677, 0x867A, 0x8687, 0x8689,
- 0x868D, 0x8691, 0x869C, 0x869D, 0x86A8, 0xFA21, 0x86B1, 0x86B3,
- 0x86C1, 0x86C3, 0x86D1, 0x86D5, 0x86D7, 0x86E3, 0x86E6, 0x45B8,
- 0x8705, 0x8707, 0x870E, 0x8710, 0x8713, 0x8719, 0x871F, 0x8721,
- 0x8723, 0x8731, 0x873A, 0x873E, 0x8740, 0x8743, 0x8751, 0x8758,
- 0x8764, 0x8765, 0x8772, 0x877C, 0xD85C /*0xDFDB*/, 0xD85C /*0xDFDA*/, 0x87A7, 0x8789,
- 0x878B, 0x8793, 0x87A0, 0xD85C /*0xDFFE*/, 0x45E5, 0x87BE, 0xD85D /*0xDC10*/, 0x87C1,
- 0x87CE, 0x87F5, 0x87DF, 0xD85D /*0xDC49*/, 0x87E3, 0x87E5, 0x87E6, 0x87EA,
- 0x87EB, 0x87ED, 0x8801, 0x8803, 0x880B, 0x8813, 0x8828,
-};
-static const unsigned short euc_to_utf8_8FF8_x0213[] = {
- 0x882E, 0x8832, 0x883C, 0x460F, 0x884A, 0x8858, 0x885F,
- 0x8864, 0xD85D /*0xDE15*/, 0xD85D /*0xDE14*/, 0x8869, 0xD85D /*0xDE31*/, 0x886F, 0x88A0, 0x88BC,
- 0x88BD, 0x88BE, 0x88C0, 0x88D2, 0xD85D /*0xDE93*/, 0x88D1, 0x88D3, 0x88DB,
- 0x88F0, 0x88F1, 0x4641, 0x8901, 0xD85D /*0xDF0E*/, 0x8937, 0xD85D /*0xDF23*/, 0x8942,
- 0x8945, 0x8949, 0xD85D /*0xDF52*/, 0x4665, 0x8962, 0x8980, 0x8989, 0x8990,
- 0x899F, 0x89B0, 0x89B7, 0x89D6, 0x89D8, 0x89EB, 0x46A1, 0x89F1,
- 0x89F3, 0x89FD, 0x89FF, 0x46AF, 0x8A11, 0x8A14, 0xD85E /*0xDD85*/, 0x8A21,
- 0x8A35, 0x8A3E, 0x8A45, 0x8A4D, 0x8A58, 0x8AAE, 0x8A90, 0x8AB7,
- 0x8ABE, 0x8AD7, 0x8AFC, 0xD85E /*0xDE84*/, 0x8B0A, 0x8B05, 0x8B0D, 0x8B1C,
- 0x8B1F, 0x8B2D, 0x8B43, 0x470C, 0x8B51, 0x8B5E, 0x8B76, 0x8B7F,
- 0x8B81, 0x8B8B, 0x8B94, 0x8B95, 0x8B9C, 0x8B9E, 0x8C39, 0xD85E /*0xDFB3*/,
- 0x8C3D, 0xD85E /*0xDFBE*/, 0xD85E /*0xDFC7*/, 0x8C45, 0x8C47, 0x8C4F, 0x8C54,
-};
-static const unsigned short euc_to_utf8_8FF9_x0213[] = {
- 0x8C57, 0x8C69, 0x8C6D, 0x8C73, 0xD85F /*0xDCB8*/, 0x8C93, 0x8C92,
- 0x8C99, 0x4764, 0x8C9B, 0x8CA4, 0x8CD6, 0x8CD5, 0x8CD9, 0xD85F /*0xDDA0*/,
- 0x8CF0, 0x8CF1, 0xD85F /*0xDE10*/, 0x8D09, 0x8D0E, 0x8D6C, 0x8D84, 0x8D95,
- 0x8DA6, 0xD85F /*0xDFB7*/, 0x8DC6, 0x8DC8, 0x8DD9, 0x8DEC, 0x8E0C, 0x47FD,
- 0x8DFD, 0x8E06, 0xD860 /*0xDC8A*/, 0x8E14, 0x8E16, 0x8E21, 0x8E22, 0x8E27,
- 0xD860 /*0xDCBB*/, 0x4816, 0x8E36, 0x8E39, 0x8E4B, 0x8E54, 0x8E62, 0x8E6C,
- 0x8E6D, 0x8E6F, 0x8E98, 0x8E9E, 0x8EAE, 0x8EB3, 0x8EB5, 0x8EB6,
- 0x8EBB, 0xD860 /*0xDE82*/, 0x8ED1, 0x8ED4, 0x484E, 0x8EF9, 0xD860 /*0xDEF3*/, 0x8F00,
- 0x8F08, 0x8F17, 0x8F2B, 0x8F40, 0x8F4A, 0x8F58, 0xD861 /*0xDC0C*/, 0x8FA4,
- 0x8FB4, 0xFA66, 0x8FB6, 0xD861 /*0xDC55*/, 0x8FC1, 0x8FC6, 0xFA24, 0x8FCA,
- 0x8FCD, 0x8FD3, 0x8FD5, 0x8FE0, 0x8FF1, 0x8FF5, 0x8FFB, 0x9002,
- 0x900C, 0x9037, 0xD861 /*0xDD6B*/, 0x9043, 0x9044, 0x905D, 0xD861 /*0xDDC8*/,
-};
-static const unsigned short euc_to_utf8_8FFA_x0213[] = {
- 0xD861 /*0xDDC9*/, 0x9085, 0x908C, 0x9090, 0x961D, 0x90A1, 0x48B5,
- 0x90B0, 0x90B6, 0x90C3, 0x90C8, 0xD861 /*0xDED7*/, 0x90DC, 0x90DF, 0xD861 /*0xDEFA*/,
- 0x90F6, 0x90F2, 0x9100, 0x90EB, 0x90FE, 0x90FF, 0x9104, 0x9106,
- 0x9118, 0x911C, 0x911E, 0x9137, 0x9139, 0x913A, 0x9146, 0x9147,
- 0x9157, 0x9159, 0x9161, 0x9164, 0x9174, 0x9179, 0x9185, 0x918E,
- 0x91A8, 0x91AE, 0x91B3, 0x91B6, 0x91C3, 0x91C4, 0x91DA, 0xD862 /*0xDD49*/,
- 0xD862 /*0xDD46*/, 0x91EC, 0x91EE, 0x9201, 0x920A, 0x9216, 0x9217, 0xD862 /*0xDD6B*/,
- 0x9233, 0x9242, 0x9247, 0x924A, 0x924E, 0x9251, 0x9256, 0x9259,
- 0x9260, 0x9261, 0x9265, 0x9267, 0x9268, 0xD862 /*0xDD87*/, 0xD862 /*0xDD88*/, 0x927C,
- 0x927D, 0x927F, 0x9289, 0x928D, 0x9297, 0x9299, 0x929F, 0x92A7,
- 0x92AB, 0xD862 /*0xDDBA*/, 0xD862 /*0xDDBB*/, 0x92B2, 0x92BF, 0x92C0, 0x92C6, 0x92CE,
- 0x92D0, 0x92D7, 0x92D9, 0x92E5, 0x92E7, 0x9311, 0xD862 /*0xDE1E*/,
-};
-static const unsigned short euc_to_utf8_8FFB_x0213[] = {
- 0xD862 /*0xDE29*/, 0x92F7, 0x92F9, 0x92FB, 0x9302, 0x930D, 0x9315,
- 0x931D, 0x931E, 0x9327, 0x9329, 0xD862 /*0xDE71*/, 0xD862 /*0xDE43*/, 0x9347, 0x9351,
- 0x9357, 0x935A, 0x936B, 0x9371, 0x9373, 0x93A1, 0xD862 /*0xDE99*/, 0xD862 /*0xDECD*/,
- 0x9388, 0x938B, 0x938F, 0x939E, 0x93F5, 0xD862 /*0xDEE4*/, 0xD862 /*0xDEDD*/, 0x93F1,
- 0x93C1, 0x93C7, 0x93DC, 0x93E2, 0x93E7, 0x9409, 0x940F, 0x9416,
- 0x9417, 0x93FB, 0x9432, 0x9434, 0x943B, 0x9445, 0xD862 /*0xDFC1*/, 0xD862 /*0xDFEF*/,
- 0x946D, 0x946F, 0x9578, 0x9579, 0x9586, 0x958C, 0x958D, 0xD863 /*0xDD10*/,
- 0x95AB, 0x95B4, 0xD863 /*0xDD71*/, 0x95C8, 0xD863 /*0xDDFB*/, 0xD863 /*0xDE1F*/, 0x962C, 0x9633,
- 0x9634, 0xD863 /*0xDE36*/, 0x963C, 0x9641, 0x9661, 0xD863 /*0xDE89*/, 0x9682, 0xD863 /*0xDEEB*/,
- 0x969A, 0xD863 /*0xDF32*/, 0x49E7, 0x96A9, 0x96AF, 0x96B3, 0x96BA, 0x96BD,
- 0x49FA, 0xD863 /*0xDFF8*/, 0x96D8, 0x96DA, 0x96DD, 0x4A04, 0x9714, 0x9723,
- 0x4A29, 0x9736, 0x9741, 0x9747, 0x9755, 0x9757, 0x975B,
-};
-static const unsigned short euc_to_utf8_8FFC_x0213[] = {
- 0x976A, 0xD864 /*0xDEA0*/, 0xD864 /*0xDEB1*/, 0x9796, 0x979A, 0x979E, 0x97A2,
- 0x97B1, 0x97B2, 0x97BE, 0x97CC, 0x97D1, 0x97D4, 0x97D8, 0x97D9,
- 0x97E1, 0x97F1, 0x9804, 0x980D, 0x980E, 0x9814, 0x9816, 0x4ABC,
- 0xD865 /*0xDC90*/, 0x9823, 0x9832, 0x9833, 0x9825, 0x9847, 0x9866, 0x98AB,
- 0x98AD, 0x98B0, 0xD865 /*0xDDCF*/, 0x98B7, 0x98B8, 0x98BB, 0x98BC, 0x98BF,
- 0x98C2, 0x98C7, 0x98CB, 0x98E0, 0xD865 /*0xDE7F*/, 0x98E1, 0x98E3, 0x98E5,
- 0x98EA, 0x98F0, 0x98F1, 0x98F3, 0x9908, 0x4B3B, 0xD865 /*0xDEF0*/, 0x9916,
- 0x9917, 0xD865 /*0xDF19*/, 0x991A, 0x991B, 0x991C, 0xD865 /*0xDF50*/, 0x9931, 0x9932,
- 0x9933, 0x993A, 0x993B, 0x993C, 0x9940, 0x9941, 0x9946, 0x994D,
- 0x994E, 0x995C, 0x995F, 0x9960, 0x99A3, 0x99A6, 0x99B9, 0x99BD,
- 0x99BF, 0x99C3, 0x99C9, 0x99D4, 0x99D9, 0x99DE, 0xD866 /*0xDCC6*/, 0x99F0,
- 0x99F9, 0x99FC, 0x9A0A, 0x9A11, 0x9A16, 0x9A1A, 0x9A20,
-};
-static const unsigned short euc_to_utf8_8FFD_x0213[] = {
- 0x9A31, 0x9A36, 0x9A44, 0x9A4C, 0x9A58, 0x4BC2, 0x9AAF,
- 0x4BCA, 0x9AB7, 0x4BD2, 0x9AB9, 0xD866 /*0xDE72*/, 0x9AC6, 0x9AD0, 0x9AD2,
- 0x9AD5, 0x4BE8, 0x9ADC, 0x9AE0, 0x9AE5, 0x9AE9, 0x9B03, 0x9B0C,
- 0x9B10, 0x9B12, 0x9B16, 0x9B1C, 0x9B2B, 0x9B33, 0x9B3D, 0x4C20,
- 0x9B4B, 0x9B63, 0x9B65, 0x9B6B, 0x9B6C, 0x9B73, 0x9B76, 0x9B77,
- 0x9BA6, 0x9BAC, 0x9BB1, 0xD867 /*0xDDDB*/, 0xD867 /*0xDE3D*/, 0x9BB2, 0x9BB8, 0x9BBE,
- 0x9BC7, 0x9BF3, 0x9BD8, 0x9BDD, 0x9BE7, 0x9BEA, 0x9BEB, 0x9BEF,
- 0x9BEE, 0xD867 /*0xDE15*/, 0x9BFA, 0xD867 /*0xDE8A*/, 0x9BF7, 0xD867 /*0xDE49*/, 0x9C16, 0x9C18,
- 0x9C19, 0x9C1A, 0x9C1D, 0x9C22, 0x9C27, 0x9C29, 0x9C2A, 0xD867 /*0xDEC4*/,
- 0x9C31, 0x9C36, 0x9C37, 0x9C45, 0x9C5C, 0xD867 /*0xDEE9*/, 0x9C49, 0x9C4A,
- 0xD867 /*0xDEDB*/, 0x9C54, 0x9C58, 0x9C5B, 0x9C5D, 0x9C5F, 0x9C69, 0x9C6A,
- 0x9C6B, 0x9C6D, 0x9C6E, 0x9C70, 0x9C72, 0x9C75, 0x9C7A,
-};
-static const unsigned short euc_to_utf8_8FFE_x0213[] = {
- 0x9CE6, 0x9CF2, 0x9D0B, 0x9D02, 0xD867 /*0xDFCE*/, 0x9D11, 0x9D17,
- 0x9D18, 0xD868 /*0xDC2F*/, 0x4CC4, 0xD868 /*0xDC1A*/, 0x9D32, 0x4CD1, 0x9D42, 0x9D4A,
- 0x9D5F, 0x9D62, 0xD868 /*0xDCF9*/, 0x9D69, 0x9D6B, 0xD868 /*0xDC82*/, 0x9D73, 0x9D76,
- 0x9D77, 0x9D7E, 0x9D84, 0x9D8D, 0x9D99, 0x9DA1, 0x9DBF, 0x9DB5,
- 0x9DB9, 0x9DBD, 0x9DC3, 0x9DC7, 0x9DC9, 0x9DD6, 0x9DDA, 0x9DDF,
- 0x9DE0, 0x9DE3, 0x9DF4, 0x4D07, 0x9E0A, 0x9E02, 0x9E0D, 0x9E19,
- 0x9E1C, 0x9E1D, 0x9E7B, 0xD848 /*0xDE18*/, 0x9E80, 0x9E85, 0x9E9B, 0x9EA8,
- 0xD868 /*0xDF8C*/, 0x9EBD, 0xD869 /*0xDC37*/, 0x9EDF, 0x9EE7, 0x9EEE, 0x9EFF, 0x9F02,
- 0x4D77, 0x9F03, 0x9F17, 0x9F19, 0x9F2F, 0x9F37, 0x9F3A, 0x9F3D,
- 0x9F41, 0x9F45, 0x9F46, 0x9F53, 0x9F55, 0x9F58, 0xD869 /*0xDDF1*/, 0x9F5D,
- 0xD869 /*0xDE02*/, 0x9F69, 0xD869 /*0xDE1A*/, 0x9F6D, 0x9F70, 0x9F75, 0xD869 /*0xDEB2*/, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-
-#ifdef X0212_ENABLE
-static const unsigned short euc_to_utf8_8FA2[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x02D8,
- 0x02C7, 0x00B8, 0x02D9, 0x02DD, 0x00AF, 0x02DB, 0x02DA, 0xFF5E,
- 0x0384, 0x0385, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x00A1, 0xFFE4, 0x00BF, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x00BA, 0x00AA, 0x00A9, 0x00AE, 0x2122,
- 0x00A4, 0x2116, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short euc_to_utf8_8FA6[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x0386, 0x0388, 0x0389, 0x038A, 0x03AA, 0, 0x038C,
- 0, 0x038E, 0x03AB, 0, 0x038F, 0, 0, 0,
- 0, 0x03AC, 0x03AD, 0x03AE, 0x03AF, 0x03CA, 0x0390, 0x03CC,
- 0x03C2, 0x03CD, 0x03CB, 0x03B0, 0x03CE, 0, 0,
-};
-static const unsigned short euc_to_utf8_8FA7[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
- 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x040E, 0x040F, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
- 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x045E, 0x045F,
-};
-static const unsigned short euc_to_utf8_8FA9[] = {
- 0x00C6, 0x0110, 0, 0x0126, 0, 0x0132, 0,
- 0x0141, 0x013F, 0, 0x014A, 0x00D8, 0x0152, 0, 0x0166,
- 0x00DE, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x00E6, 0x0111, 0x00F0, 0x0127, 0x0131, 0x0133, 0x0138,
- 0x0142, 0x0140, 0x0149, 0x014B, 0x00F8, 0x0153, 0x00DF, 0x0167,
- 0x00FE, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short euc_to_utf8_8FAA[] = {
- 0x00C1, 0x00C0, 0x00C4, 0x00C2, 0x0102, 0x01CD, 0x0100,
- 0x0104, 0x00C5, 0x00C3, 0x0106, 0x0108, 0x010C, 0x00C7, 0x010A,
- 0x010E, 0x00C9, 0x00C8, 0x00CB, 0x00CA, 0x011A, 0x0116, 0x0112,
- 0x0118, 0, 0x011C, 0x011E, 0x0122, 0x0120, 0x0124, 0x00CD,
- 0x00CC, 0x00CF, 0x00CE, 0x01CF, 0x0130, 0x012A, 0x012E, 0x0128,
- 0x0134, 0x0136, 0x0139, 0x013D, 0x013B, 0x0143, 0x0147, 0x0145,
- 0x00D1, 0x00D3, 0x00D2, 0x00D6, 0x00D4, 0x01D1, 0x0150, 0x014C,
- 0x00D5, 0x0154, 0x0158, 0x0156, 0x015A, 0x015C, 0x0160, 0x015E,
- 0x0164, 0x0162, 0x00DA, 0x00D9, 0x00DC, 0x00DB, 0x016C, 0x01D3,
- 0x0170, 0x016A, 0x0172, 0x016E, 0x0168, 0x01D7, 0x01DB, 0x01D9,
- 0x01D5, 0x0174, 0x00DD, 0x0178, 0x0176, 0x0179, 0x017D, 0x017B,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short euc_to_utf8_8FAB[] = {
- 0x00E1, 0x00E0, 0x00E4, 0x00E2, 0x0103, 0x01CE, 0x0101,
- 0x0105, 0x00E5, 0x00E3, 0x0107, 0x0109, 0x010D, 0x00E7, 0x010B,
- 0x010F, 0x00E9, 0x00E8, 0x00EB, 0x00EA, 0x011B, 0x0117, 0x0113,
- 0x0119, 0x01F5, 0x011D, 0x011F, 0, 0x0121, 0x0125, 0x00ED,
- 0x00EC, 0x00EF, 0x00EE, 0x01D0, 0, 0x012B, 0x012F, 0x0129,
- 0x0135, 0x0137, 0x013A, 0x013E, 0x013C, 0x0144, 0x0148, 0x0146,
- 0x00F1, 0x00F3, 0x00F2, 0x00F6, 0x00F4, 0x01D2, 0x0151, 0x014D,
- 0x00F5, 0x0155, 0x0159, 0x0157, 0x015B, 0x015D, 0x0161, 0x015F,
- 0x0165, 0x0163, 0x00FA, 0x00F9, 0x00FC, 0x00FB, 0x016D, 0x01D4,
- 0x0171, 0x016B, 0x0173, 0x016F, 0x0169, 0x01D8, 0x01DC, 0x01DA,
- 0x01D6, 0x0175, 0x00FD, 0x00FF, 0x0177, 0x017A, 0x017E, 0x017C,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short euc_to_utf8_8FB0[] = {
- 0x4E02, 0x4E04, 0x4E05, 0x4E0C, 0x4E12, 0x4E1F, 0x4E23,
- 0x4E24, 0x4E28, 0x4E2B, 0x4E2E, 0x4E2F, 0x4E30, 0x4E35, 0x4E40,
- 0x4E41, 0x4E44, 0x4E47, 0x4E51, 0x4E5A, 0x4E5C, 0x4E63, 0x4E68,
- 0x4E69, 0x4E74, 0x4E75, 0x4E79, 0x4E7F, 0x4E8D, 0x4E96, 0x4E97,
- 0x4E9D, 0x4EAF, 0x4EB9, 0x4EC3, 0x4ED0, 0x4EDA, 0x4EDB, 0x4EE0,
- 0x4EE1, 0x4EE2, 0x4EE8, 0x4EEF, 0x4EF1, 0x4EF3, 0x4EF5, 0x4EFD,
- 0x4EFE, 0x4EFF, 0x4F00, 0x4F02, 0x4F03, 0x4F08, 0x4F0B, 0x4F0C,
- 0x4F12, 0x4F15, 0x4F16, 0x4F17, 0x4F19, 0x4F2E, 0x4F31, 0x4F60,
- 0x4F33, 0x4F35, 0x4F37, 0x4F39, 0x4F3B, 0x4F3E, 0x4F40, 0x4F42,
- 0x4F48, 0x4F49, 0x4F4B, 0x4F4C, 0x4F52, 0x4F54, 0x4F56, 0x4F58,
- 0x4F5F, 0x4F63, 0x4F6A, 0x4F6C, 0x4F6E, 0x4F71, 0x4F77, 0x4F78,
- 0x4F79, 0x4F7A, 0x4F7D, 0x4F7E, 0x4F81, 0x4F82, 0x4F84,
-};
-static const unsigned short euc_to_utf8_8FB1[] = {
- 0x4F85, 0x4F89, 0x4F8A, 0x4F8C, 0x4F8E, 0x4F90, 0x4F92,
- 0x4F93, 0x4F94, 0x4F97, 0x4F99, 0x4F9A, 0x4F9E, 0x4F9F, 0x4FB2,
- 0x4FB7, 0x4FB9, 0x4FBB, 0x4FBC, 0x4FBD, 0x4FBE, 0x4FC0, 0x4FC1,
- 0x4FC5, 0x4FC6, 0x4FC8, 0x4FC9, 0x4FCB, 0x4FCC, 0x4FCD, 0x4FCF,
- 0x4FD2, 0x4FDC, 0x4FE0, 0x4FE2, 0x4FF0, 0x4FF2, 0x4FFC, 0x4FFD,
- 0x4FFF, 0x5000, 0x5001, 0x5004, 0x5007, 0x500A, 0x500C, 0x500E,
- 0x5010, 0x5013, 0x5017, 0x5018, 0x501B, 0x501C, 0x501D, 0x501E,
- 0x5022, 0x5027, 0x502E, 0x5030, 0x5032, 0x5033, 0x5035, 0x5040,
- 0x5041, 0x5042, 0x5045, 0x5046, 0x504A, 0x504C, 0x504E, 0x5051,
- 0x5052, 0x5053, 0x5057, 0x5059, 0x505F, 0x5060, 0x5062, 0x5063,
- 0x5066, 0x5067, 0x506A, 0x506D, 0x5070, 0x5071, 0x503B, 0x5081,
- 0x5083, 0x5084, 0x5086, 0x508A, 0x508E, 0x508F, 0x5090,
-};
-static const unsigned short euc_to_utf8_8FB2[] = {
- 0x5092, 0x5093, 0x5094, 0x5096, 0x509B, 0x509C, 0x509E,
- 0x509F, 0x50A0, 0x50A1, 0x50A2, 0x50AA, 0x50AF, 0x50B0, 0x50B9,
- 0x50BA, 0x50BD, 0x50C0, 0x50C3, 0x50C4, 0x50C7, 0x50CC, 0x50CE,
- 0x50D0, 0x50D3, 0x50D4, 0x50D8, 0x50DC, 0x50DD, 0x50DF, 0x50E2,
- 0x50E4, 0x50E6, 0x50E8, 0x50E9, 0x50EF, 0x50F1, 0x50F6, 0x50FA,
- 0x50FE, 0x5103, 0x5106, 0x5107, 0x5108, 0x510B, 0x510C, 0x510D,
- 0x510E, 0x50F2, 0x5110, 0x5117, 0x5119, 0x511B, 0x511C, 0x511D,
- 0x511E, 0x5123, 0x5127, 0x5128, 0x512C, 0x512D, 0x512F, 0x5131,
- 0x5133, 0x5134, 0x5135, 0x5138, 0x5139, 0x5142, 0x514A, 0x514F,
- 0x5153, 0x5155, 0x5157, 0x5158, 0x515F, 0x5164, 0x5166, 0x517E,
- 0x5183, 0x5184, 0x518B, 0x518E, 0x5198, 0x519D, 0x51A1, 0x51A3,
- 0x51AD, 0x51B8, 0x51BA, 0x51BC, 0x51BE, 0x51BF, 0x51C2,
-};
-static const unsigned short euc_to_utf8_8FB3[] = {
- 0x51C8, 0x51CF, 0x51D1, 0x51D2, 0x51D3, 0x51D5, 0x51D8,
- 0x51DE, 0x51E2, 0x51E5, 0x51EE, 0x51F2, 0x51F3, 0x51F4, 0x51F7,
- 0x5201, 0x5202, 0x5205, 0x5212, 0x5213, 0x5215, 0x5216, 0x5218,
- 0x5222, 0x5228, 0x5231, 0x5232, 0x5235, 0x523C, 0x5245, 0x5249,
- 0x5255, 0x5257, 0x5258, 0x525A, 0x525C, 0x525F, 0x5260, 0x5261,
- 0x5266, 0x526E, 0x5277, 0x5278, 0x5279, 0x5280, 0x5282, 0x5285,
- 0x528A, 0x528C, 0x5293, 0x5295, 0x5296, 0x5297, 0x5298, 0x529A,
- 0x529C, 0x52A4, 0x52A5, 0x52A6, 0x52A7, 0x52AF, 0x52B0, 0x52B6,
- 0x52B7, 0x52B8, 0x52BA, 0x52BB, 0x52BD, 0x52C0, 0x52C4, 0x52C6,
- 0x52C8, 0x52CC, 0x52CF, 0x52D1, 0x52D4, 0x52D6, 0x52DB, 0x52DC,
- 0x52E1, 0x52E5, 0x52E8, 0x52E9, 0x52EA, 0x52EC, 0x52F0, 0x52F1,
- 0x52F4, 0x52F6, 0x52F7, 0x5300, 0x5303, 0x530A, 0x530B,
-};
-static const unsigned short euc_to_utf8_8FB4[] = {
- 0x530C, 0x5311, 0x5313, 0x5318, 0x531B, 0x531C, 0x531E,
- 0x531F, 0x5325, 0x5327, 0x5328, 0x5329, 0x532B, 0x532C, 0x532D,
- 0x5330, 0x5332, 0x5335, 0x533C, 0x533D, 0x533E, 0x5342, 0x534C,
- 0x534B, 0x5359, 0x535B, 0x5361, 0x5363, 0x5365, 0x536C, 0x536D,
- 0x5372, 0x5379, 0x537E, 0x5383, 0x5387, 0x5388, 0x538E, 0x5393,
- 0x5394, 0x5399, 0x539D, 0x53A1, 0x53A4, 0x53AA, 0x53AB, 0x53AF,
- 0x53B2, 0x53B4, 0x53B5, 0x53B7, 0x53B8, 0x53BA, 0x53BD, 0x53C0,
- 0x53C5, 0x53CF, 0x53D2, 0x53D3, 0x53D5, 0x53DA, 0x53DD, 0x53DE,
- 0x53E0, 0x53E6, 0x53E7, 0x53F5, 0x5402, 0x5413, 0x541A, 0x5421,
- 0x5427, 0x5428, 0x542A, 0x542F, 0x5431, 0x5434, 0x5435, 0x5443,
- 0x5444, 0x5447, 0x544D, 0x544F, 0x545E, 0x5462, 0x5464, 0x5466,
- 0x5467, 0x5469, 0x546B, 0x546D, 0x546E, 0x5474, 0x547F,
-};
-static const unsigned short euc_to_utf8_8FB5[] = {
- 0x5481, 0x5483, 0x5485, 0x5488, 0x5489, 0x548D, 0x5491,
- 0x5495, 0x5496, 0x549C, 0x549F, 0x54A1, 0x54A6, 0x54A7, 0x54A9,
- 0x54AA, 0x54AD, 0x54AE, 0x54B1, 0x54B7, 0x54B9, 0x54BA, 0x54BB,
- 0x54BF, 0x54C6, 0x54CA, 0x54CD, 0x54CE, 0x54E0, 0x54EA, 0x54EC,
- 0x54EF, 0x54F6, 0x54FC, 0x54FE, 0x54FF, 0x5500, 0x5501, 0x5505,
- 0x5508, 0x5509, 0x550C, 0x550D, 0x550E, 0x5515, 0x552A, 0x552B,
- 0x5532, 0x5535, 0x5536, 0x553B, 0x553C, 0x553D, 0x5541, 0x5547,
- 0x5549, 0x554A, 0x554D, 0x5550, 0x5551, 0x5558, 0x555A, 0x555B,
- 0x555E, 0x5560, 0x5561, 0x5564, 0x5566, 0x557F, 0x5581, 0x5582,
- 0x5586, 0x5588, 0x558E, 0x558F, 0x5591, 0x5592, 0x5593, 0x5594,
- 0x5597, 0x55A3, 0x55A4, 0x55AD, 0x55B2, 0x55BF, 0x55C1, 0x55C3,
- 0x55C6, 0x55C9, 0x55CB, 0x55CC, 0x55CE, 0x55D1, 0x55D2,
-};
-static const unsigned short euc_to_utf8_8FB6[] = {
- 0x55D3, 0x55D7, 0x55D8, 0x55DB, 0x55DE, 0x55E2, 0x55E9,
- 0x55F6, 0x55FF, 0x5605, 0x5608, 0x560A, 0x560D, 0x560E, 0x560F,
- 0x5610, 0x5611, 0x5612, 0x5619, 0x562C, 0x5630, 0x5633, 0x5635,
- 0x5637, 0x5639, 0x563B, 0x563C, 0x563D, 0x563F, 0x5640, 0x5641,
- 0x5643, 0x5644, 0x5646, 0x5649, 0x564B, 0x564D, 0x564F, 0x5654,
- 0x565E, 0x5660, 0x5661, 0x5662, 0x5663, 0x5666, 0x5669, 0x566D,
- 0x566F, 0x5671, 0x5672, 0x5675, 0x5684, 0x5685, 0x5688, 0x568B,
- 0x568C, 0x5695, 0x5699, 0x569A, 0x569D, 0x569E, 0x569F, 0x56A6,
- 0x56A7, 0x56A8, 0x56A9, 0x56AB, 0x56AC, 0x56AD, 0x56B1, 0x56B3,
- 0x56B7, 0x56BE, 0x56C5, 0x56C9, 0x56CA, 0x56CB, 0x56CF, 0x56D0,
- 0x56CC, 0x56CD, 0x56D9, 0x56DC, 0x56DD, 0x56DF, 0x56E1, 0x56E4,
- 0x56E5, 0x56E6, 0x56E7, 0x56E8, 0x56F1, 0x56EB, 0x56ED,
-};
-static const unsigned short euc_to_utf8_8FB7[] = {
- 0x56F6, 0x56F7, 0x5701, 0x5702, 0x5707, 0x570A, 0x570C,
- 0x5711, 0x5715, 0x571A, 0x571B, 0x571D, 0x5720, 0x5722, 0x5723,
- 0x5724, 0x5725, 0x5729, 0x572A, 0x572C, 0x572E, 0x572F, 0x5733,
- 0x5734, 0x573D, 0x573E, 0x573F, 0x5745, 0x5746, 0x574C, 0x574D,
- 0x5752, 0x5762, 0x5765, 0x5767, 0x5768, 0x576B, 0x576D, 0x576E,
- 0x576F, 0x5770, 0x5771, 0x5773, 0x5774, 0x5775, 0x5777, 0x5779,
- 0x577A, 0x577B, 0x577C, 0x577E, 0x5781, 0x5783, 0x578C, 0x5794,
- 0x5797, 0x5799, 0x579A, 0x579C, 0x579D, 0x579E, 0x579F, 0x57A1,
- 0x5795, 0x57A7, 0x57A8, 0x57A9, 0x57AC, 0x57B8, 0x57BD, 0x57C7,
- 0x57C8, 0x57CC, 0x57CF, 0x57D5, 0x57DD, 0x57DE, 0x57E4, 0x57E6,
- 0x57E7, 0x57E9, 0x57ED, 0x57F0, 0x57F5, 0x57F6, 0x57F8, 0x57FD,
- 0x57FE, 0x57FF, 0x5803, 0x5804, 0x5808, 0x5809, 0x57E1,
-};
-static const unsigned short euc_to_utf8_8FB8[] = {
- 0x580C, 0x580D, 0x581B, 0x581E, 0x581F, 0x5820, 0x5826,
- 0x5827, 0x582D, 0x5832, 0x5839, 0x583F, 0x5849, 0x584C, 0x584D,
- 0x584F, 0x5850, 0x5855, 0x585F, 0x5861, 0x5864, 0x5867, 0x5868,
- 0x5878, 0x587C, 0x587F, 0x5880, 0x5881, 0x5887, 0x5888, 0x5889,
- 0x588A, 0x588C, 0x588D, 0x588F, 0x5890, 0x5894, 0x5896, 0x589D,
- 0x58A0, 0x58A1, 0x58A2, 0x58A6, 0x58A9, 0x58B1, 0x58B2, 0x58C4,
- 0x58BC, 0x58C2, 0x58C8, 0x58CD, 0x58CE, 0x58D0, 0x58D2, 0x58D4,
- 0x58D6, 0x58DA, 0x58DD, 0x58E1, 0x58E2, 0x58E9, 0x58F3, 0x5905,
- 0x5906, 0x590B, 0x590C, 0x5912, 0x5913, 0x5914, 0x8641, 0x591D,
- 0x5921, 0x5923, 0x5924, 0x5928, 0x592F, 0x5930, 0x5933, 0x5935,
- 0x5936, 0x593F, 0x5943, 0x5946, 0x5952, 0x5953, 0x5959, 0x595B,
- 0x595D, 0x595E, 0x595F, 0x5961, 0x5963, 0x596B, 0x596D,
-};
-static const unsigned short euc_to_utf8_8FB9[] = {
- 0x596F, 0x5972, 0x5975, 0x5976, 0x5979, 0x597B, 0x597C,
- 0x598B, 0x598C, 0x598E, 0x5992, 0x5995, 0x5997, 0x599F, 0x59A4,
- 0x59A7, 0x59AD, 0x59AE, 0x59AF, 0x59B0, 0x59B3, 0x59B7, 0x59BA,
- 0x59BC, 0x59C1, 0x59C3, 0x59C4, 0x59C8, 0x59CA, 0x59CD, 0x59D2,
- 0x59DD, 0x59DE, 0x59DF, 0x59E3, 0x59E4, 0x59E7, 0x59EE, 0x59EF,
- 0x59F1, 0x59F2, 0x59F4, 0x59F7, 0x5A00, 0x5A04, 0x5A0C, 0x5A0D,
- 0x5A0E, 0x5A12, 0x5A13, 0x5A1E, 0x5A23, 0x5A24, 0x5A27, 0x5A28,
- 0x5A2A, 0x5A2D, 0x5A30, 0x5A44, 0x5A45, 0x5A47, 0x5A48, 0x5A4C,
- 0x5A50, 0x5A55, 0x5A5E, 0x5A63, 0x5A65, 0x5A67, 0x5A6D, 0x5A77,
- 0x5A7A, 0x5A7B, 0x5A7E, 0x5A8B, 0x5A90, 0x5A93, 0x5A96, 0x5A99,
- 0x5A9C, 0x5A9E, 0x5A9F, 0x5AA0, 0x5AA2, 0x5AA7, 0x5AAC, 0x5AB1,
- 0x5AB2, 0x5AB3, 0x5AB5, 0x5AB8, 0x5ABA, 0x5ABB, 0x5ABF,
-};
-static const unsigned short euc_to_utf8_8FBA[] = {
- 0x5AC4, 0x5AC6, 0x5AC8, 0x5ACF, 0x5ADA, 0x5ADC, 0x5AE0,
- 0x5AE5, 0x5AEA, 0x5AEE, 0x5AF5, 0x5AF6, 0x5AFD, 0x5B00, 0x5B01,
- 0x5B08, 0x5B17, 0x5B34, 0x5B19, 0x5B1B, 0x5B1D, 0x5B21, 0x5B25,
- 0x5B2D, 0x5B38, 0x5B41, 0x5B4B, 0x5B4C, 0x5B52, 0x5B56, 0x5B5E,
- 0x5B68, 0x5B6E, 0x5B6F, 0x5B7C, 0x5B7D, 0x5B7E, 0x5B7F, 0x5B81,
- 0x5B84, 0x5B86, 0x5B8A, 0x5B8E, 0x5B90, 0x5B91, 0x5B93, 0x5B94,
- 0x5B96, 0x5BA8, 0x5BA9, 0x5BAC, 0x5BAD, 0x5BAF, 0x5BB1, 0x5BB2,
- 0x5BB7, 0x5BBA, 0x5BBC, 0x5BC0, 0x5BC1, 0x5BCD, 0x5BCF, 0x5BD6,
- 0x5BD7, 0x5BD8, 0x5BD9, 0x5BDA, 0x5BE0, 0x5BEF, 0x5BF1, 0x5BF4,
- 0x5BFD, 0x5C0C, 0x5C17, 0x5C1E, 0x5C1F, 0x5C23, 0x5C26, 0x5C29,
- 0x5C2B, 0x5C2C, 0x5C2E, 0x5C30, 0x5C32, 0x5C35, 0x5C36, 0x5C59,
- 0x5C5A, 0x5C5C, 0x5C62, 0x5C63, 0x5C67, 0x5C68, 0x5C69,
-};
-static const unsigned short euc_to_utf8_8FBB[] = {
- 0x5C6D, 0x5C70, 0x5C74, 0x5C75, 0x5C7A, 0x5C7B, 0x5C7C,
- 0x5C7D, 0x5C87, 0x5C88, 0x5C8A, 0x5C8F, 0x5C92, 0x5C9D, 0x5C9F,
- 0x5CA0, 0x5CA2, 0x5CA3, 0x5CA6, 0x5CAA, 0x5CB2, 0x5CB4, 0x5CB5,
- 0x5CBA, 0x5CC9, 0x5CCB, 0x5CD2, 0x5CDD, 0x5CD7, 0x5CEE, 0x5CF1,
- 0x5CF2, 0x5CF4, 0x5D01, 0x5D06, 0x5D0D, 0x5D12, 0x5D2B, 0x5D23,
- 0x5D24, 0x5D26, 0x5D27, 0x5D31, 0x5D34, 0x5D39, 0x5D3D, 0x5D3F,
- 0x5D42, 0x5D43, 0x5D46, 0x5D48, 0x5D55, 0x5D51, 0x5D59, 0x5D4A,
- 0x5D5F, 0x5D60, 0x5D61, 0x5D62, 0x5D64, 0x5D6A, 0x5D6D, 0x5D70,
- 0x5D79, 0x5D7A, 0x5D7E, 0x5D7F, 0x5D81, 0x5D83, 0x5D88, 0x5D8A,
- 0x5D92, 0x5D93, 0x5D94, 0x5D95, 0x5D99, 0x5D9B, 0x5D9F, 0x5DA0,
- 0x5DA7, 0x5DAB, 0x5DB0, 0x5DB4, 0x5DB8, 0x5DB9, 0x5DC3, 0x5DC7,
- 0x5DCB, 0x5DD0, 0x5DCE, 0x5DD8, 0x5DD9, 0x5DE0, 0x5DE4,
-};
-static const unsigned short euc_to_utf8_8FBC[] = {
- 0x5DE9, 0x5DF8, 0x5DF9, 0x5E00, 0x5E07, 0x5E0D, 0x5E12,
- 0x5E14, 0x5E15, 0x5E18, 0x5E1F, 0x5E20, 0x5E2E, 0x5E28, 0x5E32,
- 0x5E35, 0x5E3E, 0x5E4B, 0x5E50, 0x5E49, 0x5E51, 0x5E56, 0x5E58,
- 0x5E5B, 0x5E5C, 0x5E5E, 0x5E68, 0x5E6A, 0x5E6B, 0x5E6C, 0x5E6D,
- 0x5E6E, 0x5E70, 0x5E80, 0x5E8B, 0x5E8E, 0x5EA2, 0x5EA4, 0x5EA5,
- 0x5EA8, 0x5EAA, 0x5EAC, 0x5EB1, 0x5EB3, 0x5EBD, 0x5EBE, 0x5EBF,
- 0x5EC6, 0x5ECC, 0x5ECB, 0x5ECE, 0x5ED1, 0x5ED2, 0x5ED4, 0x5ED5,
- 0x5EDC, 0x5EDE, 0x5EE5, 0x5EEB, 0x5F02, 0x5F06, 0x5F07, 0x5F08,
- 0x5F0E, 0x5F19, 0x5F1C, 0x5F1D, 0x5F21, 0x5F22, 0x5F23, 0x5F24,
- 0x5F28, 0x5F2B, 0x5F2C, 0x5F2E, 0x5F30, 0x5F34, 0x5F36, 0x5F3B,
- 0x5F3D, 0x5F3F, 0x5F40, 0x5F44, 0x5F45, 0x5F47, 0x5F4D, 0x5F50,
- 0x5F54, 0x5F58, 0x5F5B, 0x5F60, 0x5F63, 0x5F64, 0x5F67,
-};
-static const unsigned short euc_to_utf8_8FBD[] = {
- 0x5F6F, 0x5F72, 0x5F74, 0x5F75, 0x5F78, 0x5F7A, 0x5F7D,
- 0x5F7E, 0x5F89, 0x5F8D, 0x5F8F, 0x5F96, 0x5F9C, 0x5F9D, 0x5FA2,
- 0x5FA7, 0x5FAB, 0x5FA4, 0x5FAC, 0x5FAF, 0x5FB0, 0x5FB1, 0x5FB8,
- 0x5FC4, 0x5FC7, 0x5FC8, 0x5FC9, 0x5FCB, 0x5FD0, 0x5FD1, 0x5FD2,
- 0x5FD3, 0x5FD4, 0x5FDE, 0x5FE1, 0x5FE2, 0x5FE8, 0x5FE9, 0x5FEA,
- 0x5FEC, 0x5FED, 0x5FEE, 0x5FEF, 0x5FF2, 0x5FF3, 0x5FF6, 0x5FFA,
- 0x5FFC, 0x6007, 0x600A, 0x600D, 0x6013, 0x6014, 0x6017, 0x6018,
- 0x601A, 0x601F, 0x6024, 0x602D, 0x6033, 0x6035, 0x6040, 0x6047,
- 0x6048, 0x6049, 0x604C, 0x6051, 0x6054, 0x6056, 0x6057, 0x605D,
- 0x6061, 0x6067, 0x6071, 0x607E, 0x607F, 0x6082, 0x6086, 0x6088,
- 0x608A, 0x608E, 0x6091, 0x6093, 0x6095, 0x6098, 0x609D, 0x609E,
- 0x60A2, 0x60A4, 0x60A5, 0x60A8, 0x60B0, 0x60B1, 0x60B7,
-};
-static const unsigned short euc_to_utf8_8FBE[] = {
- 0x60BB, 0x60BE, 0x60C2, 0x60C4, 0x60C8, 0x60C9, 0x60CA,
- 0x60CB, 0x60CE, 0x60CF, 0x60D4, 0x60D5, 0x60D9, 0x60DB, 0x60DD,
- 0x60DE, 0x60E2, 0x60E5, 0x60F2, 0x60F5, 0x60F8, 0x60FC, 0x60FD,
- 0x6102, 0x6107, 0x610A, 0x610C, 0x6110, 0x6111, 0x6112, 0x6113,
- 0x6114, 0x6116, 0x6117, 0x6119, 0x611C, 0x611E, 0x6122, 0x612A,
- 0x612B, 0x6130, 0x6131, 0x6135, 0x6136, 0x6137, 0x6139, 0x6141,
- 0x6145, 0x6146, 0x6149, 0x615E, 0x6160, 0x616C, 0x6172, 0x6178,
- 0x617B, 0x617C, 0x617F, 0x6180, 0x6181, 0x6183, 0x6184, 0x618B,
- 0x618D, 0x6192, 0x6193, 0x6197, 0x6198, 0x619C, 0x619D, 0x619F,
- 0x61A0, 0x61A5, 0x61A8, 0x61AA, 0x61AD, 0x61B8, 0x61B9, 0x61BC,
- 0x61C0, 0x61C1, 0x61C2, 0x61CE, 0x61CF, 0x61D5, 0x61DC, 0x61DD,
- 0x61DE, 0x61DF, 0x61E1, 0x61E2, 0x61E7, 0x61E9, 0x61E5,
-};
-static const unsigned short euc_to_utf8_8FBF[] = {
- 0x61EC, 0x61ED, 0x61EF, 0x6201, 0x6203, 0x6204, 0x6207,
- 0x6213, 0x6215, 0x621C, 0x6220, 0x6222, 0x6223, 0x6227, 0x6229,
- 0x622B, 0x6239, 0x623D, 0x6242, 0x6243, 0x6244, 0x6246, 0x624C,
- 0x6250, 0x6251, 0x6252, 0x6254, 0x6256, 0x625A, 0x625C, 0x6264,
- 0x626D, 0x626F, 0x6273, 0x627A, 0x627D, 0x628D, 0x628E, 0x628F,
- 0x6290, 0x62A6, 0x62A8, 0x62B3, 0x62B6, 0x62B7, 0x62BA, 0x62BE,
- 0x62BF, 0x62C4, 0x62CE, 0x62D5, 0x62D6, 0x62DA, 0x62EA, 0x62F2,
- 0x62F4, 0x62FC, 0x62FD, 0x6303, 0x6304, 0x630A, 0x630B, 0x630D,
- 0x6310, 0x6313, 0x6316, 0x6318, 0x6329, 0x632A, 0x632D, 0x6335,
- 0x6336, 0x6339, 0x633C, 0x6341, 0x6342, 0x6343, 0x6344, 0x6346,
- 0x634A, 0x634B, 0x634E, 0x6352, 0x6353, 0x6354, 0x6358, 0x635B,
- 0x6365, 0x6366, 0x636C, 0x636D, 0x6371, 0x6374, 0x6375,
-};
-static const unsigned short euc_to_utf8_8FC0[] = {
- 0x6378, 0x637C, 0x637D, 0x637F, 0x6382, 0x6384, 0x6387,
- 0x638A, 0x6390, 0x6394, 0x6395, 0x6399, 0x639A, 0x639E, 0x63A4,
- 0x63A6, 0x63AD, 0x63AE, 0x63AF, 0x63BD, 0x63C1, 0x63C5, 0x63C8,
- 0x63CE, 0x63D1, 0x63D3, 0x63D4, 0x63D5, 0x63DC, 0x63E0, 0x63E5,
- 0x63EA, 0x63EC, 0x63F2, 0x63F3, 0x63F5, 0x63F8, 0x63F9, 0x6409,
- 0x640A, 0x6410, 0x6412, 0x6414, 0x6418, 0x641E, 0x6420, 0x6422,
- 0x6424, 0x6425, 0x6429, 0x642A, 0x642F, 0x6430, 0x6435, 0x643D,
- 0x643F, 0x644B, 0x644F, 0x6451, 0x6452, 0x6453, 0x6454, 0x645A,
- 0x645B, 0x645C, 0x645D, 0x645F, 0x6460, 0x6461, 0x6463, 0x646D,
- 0x6473, 0x6474, 0x647B, 0x647D, 0x6485, 0x6487, 0x648F, 0x6490,
- 0x6491, 0x6498, 0x6499, 0x649B, 0x649D, 0x649F, 0x64A1, 0x64A3,
- 0x64A6, 0x64A8, 0x64AC, 0x64B3, 0x64BD, 0x64BE, 0x64BF,
-};
-static const unsigned short euc_to_utf8_8FC1[] = {
- 0x64C4, 0x64C9, 0x64CA, 0x64CB, 0x64CC, 0x64CE, 0x64D0,
- 0x64D1, 0x64D5, 0x64D7, 0x64E4, 0x64E5, 0x64E9, 0x64EA, 0x64ED,
- 0x64F0, 0x64F5, 0x64F7, 0x64FB, 0x64FF, 0x6501, 0x6504, 0x6508,
- 0x6509, 0x650A, 0x650F, 0x6513, 0x6514, 0x6516, 0x6519, 0x651B,
- 0x651E, 0x651F, 0x6522, 0x6526, 0x6529, 0x652E, 0x6531, 0x653A,
- 0x653C, 0x653D, 0x6543, 0x6547, 0x6549, 0x6550, 0x6552, 0x6554,
- 0x655F, 0x6560, 0x6567, 0x656B, 0x657A, 0x657D, 0x6581, 0x6585,
- 0x658A, 0x6592, 0x6595, 0x6598, 0x659D, 0x65A0, 0x65A3, 0x65A6,
- 0x65AE, 0x65B2, 0x65B3, 0x65B4, 0x65BF, 0x65C2, 0x65C8, 0x65C9,
- 0x65CE, 0x65D0, 0x65D4, 0x65D6, 0x65D8, 0x65DF, 0x65F0, 0x65F2,
- 0x65F4, 0x65F5, 0x65F9, 0x65FE, 0x65FF, 0x6600, 0x6604, 0x6608,
- 0x6609, 0x660D, 0x6611, 0x6612, 0x6615, 0x6616, 0x661D,
-};
-static const unsigned short euc_to_utf8_8FC2[] = {
- 0x661E, 0x6621, 0x6622, 0x6623, 0x6624, 0x6626, 0x6629,
- 0x662A, 0x662B, 0x662C, 0x662E, 0x6630, 0x6631, 0x6633, 0x6639,
- 0x6637, 0x6640, 0x6645, 0x6646, 0x664A, 0x664C, 0x6651, 0x664E,
- 0x6657, 0x6658, 0x6659, 0x665B, 0x665C, 0x6660, 0x6661, 0x66FB,
- 0x666A, 0x666B, 0x666C, 0x667E, 0x6673, 0x6675, 0x667F, 0x6677,
- 0x6678, 0x6679, 0x667B, 0x6680, 0x667C, 0x668B, 0x668C, 0x668D,
- 0x6690, 0x6692, 0x6699, 0x669A, 0x669B, 0x669C, 0x669F, 0x66A0,
- 0x66A4, 0x66AD, 0x66B1, 0x66B2, 0x66B5, 0x66BB, 0x66BF, 0x66C0,
- 0x66C2, 0x66C3, 0x66C8, 0x66CC, 0x66CE, 0x66CF, 0x66D4, 0x66DB,
- 0x66DF, 0x66E8, 0x66EB, 0x66EC, 0x66EE, 0x66FA, 0x6705, 0x6707,
- 0x670E, 0x6713, 0x6719, 0x671C, 0x6720, 0x6722, 0x6733, 0x673E,
- 0x6745, 0x6747, 0x6748, 0x674C, 0x6754, 0x6755, 0x675D,
-};
-static const unsigned short euc_to_utf8_8FC3[] = {
- 0x6766, 0x676C, 0x676E, 0x6774, 0x6776, 0x677B, 0x6781,
- 0x6784, 0x678E, 0x678F, 0x6791, 0x6793, 0x6796, 0x6798, 0x6799,
- 0x679B, 0x67B0, 0x67B1, 0x67B2, 0x67B5, 0x67BB, 0x67BC, 0x67BD,
- 0x67F9, 0x67C0, 0x67C2, 0x67C3, 0x67C5, 0x67C8, 0x67C9, 0x67D2,
- 0x67D7, 0x67D9, 0x67DC, 0x67E1, 0x67E6, 0x67F0, 0x67F2, 0x67F6,
- 0x67F7, 0x6852, 0x6814, 0x6819, 0x681D, 0x681F, 0x6828, 0x6827,
- 0x682C, 0x682D, 0x682F, 0x6830, 0x6831, 0x6833, 0x683B, 0x683F,
- 0x6844, 0x6845, 0x684A, 0x684C, 0x6855, 0x6857, 0x6858, 0x685B,
- 0x686B, 0x686E, 0x686F, 0x6870, 0x6871, 0x6872, 0x6875, 0x6879,
- 0x687A, 0x687B, 0x687C, 0x6882, 0x6884, 0x6886, 0x6888, 0x6896,
- 0x6898, 0x689A, 0x689C, 0x68A1, 0x68A3, 0x68A5, 0x68A9, 0x68AA,
- 0x68AE, 0x68B2, 0x68BB, 0x68C5, 0x68C8, 0x68CC, 0x68CF,
-};
-static const unsigned short euc_to_utf8_8FC4[] = {
- 0x68D0, 0x68D1, 0x68D3, 0x68D6, 0x68D9, 0x68DC, 0x68DD,
- 0x68E5, 0x68E8, 0x68EA, 0x68EB, 0x68EC, 0x68ED, 0x68F0, 0x68F1,
- 0x68F5, 0x68F6, 0x68FB, 0x68FC, 0x68FD, 0x6906, 0x6909, 0x690A,
- 0x6910, 0x6911, 0x6913, 0x6916, 0x6917, 0x6931, 0x6933, 0x6935,
- 0x6938, 0x693B, 0x6942, 0x6945, 0x6949, 0x694E, 0x6957, 0x695B,
- 0x6963, 0x6964, 0x6965, 0x6966, 0x6968, 0x6969, 0x696C, 0x6970,
- 0x6971, 0x6972, 0x697A, 0x697B, 0x697F, 0x6980, 0x698D, 0x6992,
- 0x6996, 0x6998, 0x69A1, 0x69A5, 0x69A6, 0x69A8, 0x69AB, 0x69AD,
- 0x69AF, 0x69B7, 0x69B8, 0x69BA, 0x69BC, 0x69C5, 0x69C8, 0x69D1,
- 0x69D6, 0x69D7, 0x69E2, 0x69E5, 0x69EE, 0x69EF, 0x69F1, 0x69F3,
- 0x69F5, 0x69FE, 0x6A00, 0x6A01, 0x6A03, 0x6A0F, 0x6A11, 0x6A15,
- 0x6A1A, 0x6A1D, 0x6A20, 0x6A24, 0x6A28, 0x6A30, 0x6A32,
-};
-static const unsigned short euc_to_utf8_8FC5[] = {
- 0x6A34, 0x6A37, 0x6A3B, 0x6A3E, 0x6A3F, 0x6A45, 0x6A46,
- 0x6A49, 0x6A4A, 0x6A4E, 0x6A50, 0x6A51, 0x6A52, 0x6A55, 0x6A56,
- 0x6A5B, 0x6A64, 0x6A67, 0x6A6A, 0x6A71, 0x6A73, 0x6A7E, 0x6A81,
- 0x6A83, 0x6A86, 0x6A87, 0x6A89, 0x6A8B, 0x6A91, 0x6A9B, 0x6A9D,
- 0x6A9E, 0x6A9F, 0x6AA5, 0x6AAB, 0x6AAF, 0x6AB0, 0x6AB1, 0x6AB4,
- 0x6ABD, 0x6ABE, 0x6ABF, 0x6AC6, 0x6AC9, 0x6AC8, 0x6ACC, 0x6AD0,
- 0x6AD4, 0x6AD5, 0x6AD6, 0x6ADC, 0x6ADD, 0x6AE4, 0x6AE7, 0x6AEC,
- 0x6AF0, 0x6AF1, 0x6AF2, 0x6AFC, 0x6AFD, 0x6B02, 0x6B03, 0x6B06,
- 0x6B07, 0x6B09, 0x6B0F, 0x6B10, 0x6B11, 0x6B17, 0x6B1B, 0x6B1E,
- 0x6B24, 0x6B28, 0x6B2B, 0x6B2C, 0x6B2F, 0x6B35, 0x6B36, 0x6B3B,
- 0x6B3F, 0x6B46, 0x6B4A, 0x6B4D, 0x6B52, 0x6B56, 0x6B58, 0x6B5D,
- 0x6B60, 0x6B67, 0x6B6B, 0x6B6E, 0x6B70, 0x6B75, 0x6B7D,
-};
-static const unsigned short euc_to_utf8_8FC6[] = {
- 0x6B7E, 0x6B82, 0x6B85, 0x6B97, 0x6B9B, 0x6B9F, 0x6BA0,
- 0x6BA2, 0x6BA3, 0x6BA8, 0x6BA9, 0x6BAC, 0x6BAD, 0x6BAE, 0x6BB0,
- 0x6BB8, 0x6BB9, 0x6BBD, 0x6BBE, 0x6BC3, 0x6BC4, 0x6BC9, 0x6BCC,
- 0x6BD6, 0x6BDA, 0x6BE1, 0x6BE3, 0x6BE6, 0x6BE7, 0x6BEE, 0x6BF1,
- 0x6BF7, 0x6BF9, 0x6BFF, 0x6C02, 0x6C04, 0x6C05, 0x6C09, 0x6C0D,
- 0x6C0E, 0x6C10, 0x6C12, 0x6C19, 0x6C1F, 0x6C26, 0x6C27, 0x6C28,
- 0x6C2C, 0x6C2E, 0x6C33, 0x6C35, 0x6C36, 0x6C3A, 0x6C3B, 0x6C3F,
- 0x6C4A, 0x6C4B, 0x6C4D, 0x6C4F, 0x6C52, 0x6C54, 0x6C59, 0x6C5B,
- 0x6C5C, 0x6C6B, 0x6C6D, 0x6C6F, 0x6C74, 0x6C76, 0x6C78, 0x6C79,
- 0x6C7B, 0x6C85, 0x6C86, 0x6C87, 0x6C89, 0x6C94, 0x6C95, 0x6C97,
- 0x6C98, 0x6C9C, 0x6C9F, 0x6CB0, 0x6CB2, 0x6CB4, 0x6CC2, 0x6CC6,
- 0x6CCD, 0x6CCF, 0x6CD0, 0x6CD1, 0x6CD2, 0x6CD4, 0x6CD6,
-};
-static const unsigned short euc_to_utf8_8FC7[] = {
- 0x6CDA, 0x6CDC, 0x6CE0, 0x6CE7, 0x6CE9, 0x6CEB, 0x6CEC,
- 0x6CEE, 0x6CF2, 0x6CF4, 0x6D04, 0x6D07, 0x6D0A, 0x6D0E, 0x6D0F,
- 0x6D11, 0x6D13, 0x6D1A, 0x6D26, 0x6D27, 0x6D28, 0x6C67, 0x6D2E,
- 0x6D2F, 0x6D31, 0x6D39, 0x6D3C, 0x6D3F, 0x6D57, 0x6D5E, 0x6D5F,
- 0x6D61, 0x6D65, 0x6D67, 0x6D6F, 0x6D70, 0x6D7C, 0x6D82, 0x6D87,
- 0x6D91, 0x6D92, 0x6D94, 0x6D96, 0x6D97, 0x6D98, 0x6DAA, 0x6DAC,
- 0x6DB4, 0x6DB7, 0x6DB9, 0x6DBD, 0x6DBF, 0x6DC4, 0x6DC8, 0x6DCA,
- 0x6DCE, 0x6DCF, 0x6DD6, 0x6DDB, 0x6DDD, 0x6DDF, 0x6DE0, 0x6DE2,
- 0x6DE5, 0x6DE9, 0x6DEF, 0x6DF0, 0x6DF4, 0x6DF6, 0x6DFC, 0x6E00,
- 0x6E04, 0x6E1E, 0x6E22, 0x6E27, 0x6E32, 0x6E36, 0x6E39, 0x6E3B,
- 0x6E3C, 0x6E44, 0x6E45, 0x6E48, 0x6E49, 0x6E4B, 0x6E4F, 0x6E51,
- 0x6E52, 0x6E53, 0x6E54, 0x6E57, 0x6E5C, 0x6E5D, 0x6E5E,
-};
-static const unsigned short euc_to_utf8_8FC8[] = {
- 0x6E62, 0x6E63, 0x6E68, 0x6E73, 0x6E7B, 0x6E7D, 0x6E8D,
- 0x6E93, 0x6E99, 0x6EA0, 0x6EA7, 0x6EAD, 0x6EAE, 0x6EB1, 0x6EB3,
- 0x6EBB, 0x6EBF, 0x6EC0, 0x6EC1, 0x6EC3, 0x6EC7, 0x6EC8, 0x6ECA,
- 0x6ECD, 0x6ECE, 0x6ECF, 0x6EEB, 0x6EED, 0x6EEE, 0x6EF9, 0x6EFB,
- 0x6EFD, 0x6F04, 0x6F08, 0x6F0A, 0x6F0C, 0x6F0D, 0x6F16, 0x6F18,
- 0x6F1A, 0x6F1B, 0x6F26, 0x6F29, 0x6F2A, 0x6F2F, 0x6F30, 0x6F33,
- 0x6F36, 0x6F3B, 0x6F3C, 0x6F2D, 0x6F4F, 0x6F51, 0x6F52, 0x6F53,
- 0x6F57, 0x6F59, 0x6F5A, 0x6F5D, 0x6F5E, 0x6F61, 0x6F62, 0x6F68,
- 0x6F6C, 0x6F7D, 0x6F7E, 0x6F83, 0x6F87, 0x6F88, 0x6F8B, 0x6F8C,
- 0x6F8D, 0x6F90, 0x6F92, 0x6F93, 0x6F94, 0x6F96, 0x6F9A, 0x6F9F,
- 0x6FA0, 0x6FA5, 0x6FA6, 0x6FA7, 0x6FA8, 0x6FAE, 0x6FAF, 0x6FB0,
- 0x6FB5, 0x6FB6, 0x6FBC, 0x6FC5, 0x6FC7, 0x6FC8, 0x6FCA,
-};
-static const unsigned short euc_to_utf8_8FC9[] = {
- 0x6FDA, 0x6FDE, 0x6FE8, 0x6FE9, 0x6FF0, 0x6FF5, 0x6FF9,
- 0x6FFC, 0x6FFD, 0x7000, 0x7005, 0x7006, 0x7007, 0x700D, 0x7017,
- 0x7020, 0x7023, 0x702F, 0x7034, 0x7037, 0x7039, 0x703C, 0x7043,
- 0x7044, 0x7048, 0x7049, 0x704A, 0x704B, 0x7054, 0x7055, 0x705D,
- 0x705E, 0x704E, 0x7064, 0x7065, 0x706C, 0x706E, 0x7075, 0x7076,
- 0x707E, 0x7081, 0x7085, 0x7086, 0x7094, 0x7095, 0x7096, 0x7097,
- 0x7098, 0x709B, 0x70A4, 0x70AB, 0x70B0, 0x70B1, 0x70B4, 0x70B7,
- 0x70CA, 0x70D1, 0x70D3, 0x70D4, 0x70D5, 0x70D6, 0x70D8, 0x70DC,
- 0x70E4, 0x70FA, 0x7103, 0x7104, 0x7105, 0x7106, 0x7107, 0x710B,
- 0x710C, 0x710F, 0x711E, 0x7120, 0x712B, 0x712D, 0x712F, 0x7130,
- 0x7131, 0x7138, 0x7141, 0x7145, 0x7146, 0x7147, 0x714A, 0x714B,
- 0x7150, 0x7152, 0x7157, 0x715A, 0x715C, 0x715E, 0x7160,
-};
-static const unsigned short euc_to_utf8_8FCA[] = {
- 0x7168, 0x7179, 0x7180, 0x7185, 0x7187, 0x718C, 0x7192,
- 0x719A, 0x719B, 0x71A0, 0x71A2, 0x71AF, 0x71B0, 0x71B2, 0x71B3,
- 0x71BA, 0x71BF, 0x71C0, 0x71C1, 0x71C4, 0x71CB, 0x71CC, 0x71D3,
- 0x71D6, 0x71D9, 0x71DA, 0x71DC, 0x71F8, 0x71FE, 0x7200, 0x7207,
- 0x7208, 0x7209, 0x7213, 0x7217, 0x721A, 0x721D, 0x721F, 0x7224,
- 0x722B, 0x722F, 0x7234, 0x7238, 0x7239, 0x7241, 0x7242, 0x7243,
- 0x7245, 0x724E, 0x724F, 0x7250, 0x7253, 0x7255, 0x7256, 0x725A,
- 0x725C, 0x725E, 0x7260, 0x7263, 0x7268, 0x726B, 0x726E, 0x726F,
- 0x7271, 0x7277, 0x7278, 0x727B, 0x727C, 0x727F, 0x7284, 0x7289,
- 0x728D, 0x728E, 0x7293, 0x729B, 0x72A8, 0x72AD, 0x72AE, 0x72B1,
- 0x72B4, 0x72BE, 0x72C1, 0x72C7, 0x72C9, 0x72CC, 0x72D5, 0x72D6,
- 0x72D8, 0x72DF, 0x72E5, 0x72F3, 0x72F4, 0x72FA, 0x72FB,
-};
-static const unsigned short euc_to_utf8_8FCB[] = {
- 0x72FE, 0x7302, 0x7304, 0x7305, 0x7307, 0x730B, 0x730D,
- 0x7312, 0x7313, 0x7318, 0x7319, 0x731E, 0x7322, 0x7324, 0x7327,
- 0x7328, 0x732C, 0x7331, 0x7332, 0x7335, 0x733A, 0x733B, 0x733D,
- 0x7343, 0x734D, 0x7350, 0x7352, 0x7356, 0x7358, 0x735D, 0x735E,
- 0x735F, 0x7360, 0x7366, 0x7367, 0x7369, 0x736B, 0x736C, 0x736E,
- 0x736F, 0x7371, 0x7377, 0x7379, 0x737C, 0x7380, 0x7381, 0x7383,
- 0x7385, 0x7386, 0x738E, 0x7390, 0x7393, 0x7395, 0x7397, 0x7398,
- 0x739C, 0x739E, 0x739F, 0x73A0, 0x73A2, 0x73A5, 0x73A6, 0x73AA,
- 0x73AB, 0x73AD, 0x73B5, 0x73B7, 0x73B9, 0x73BC, 0x73BD, 0x73BF,
- 0x73C5, 0x73C6, 0x73C9, 0x73CB, 0x73CC, 0x73CF, 0x73D2, 0x73D3,
- 0x73D6, 0x73D9, 0x73DD, 0x73E1, 0x73E3, 0x73E6, 0x73E7, 0x73E9,
- 0x73F4, 0x73F5, 0x73F7, 0x73F9, 0x73FA, 0x73FB, 0x73FD,
-};
-static const unsigned short euc_to_utf8_8FCC[] = {
- 0x73FF, 0x7400, 0x7401, 0x7404, 0x7407, 0x740A, 0x7411,
- 0x741A, 0x741B, 0x7424, 0x7426, 0x7428, 0x7429, 0x742A, 0x742B,
- 0x742C, 0x742D, 0x742E, 0x742F, 0x7430, 0x7431, 0x7439, 0x7440,
- 0x7443, 0x7444, 0x7446, 0x7447, 0x744B, 0x744D, 0x7451, 0x7452,
- 0x7457, 0x745D, 0x7462, 0x7466, 0x7467, 0x7468, 0x746B, 0x746D,
- 0x746E, 0x7471, 0x7472, 0x7480, 0x7481, 0x7485, 0x7486, 0x7487,
- 0x7489, 0x748F, 0x7490, 0x7491, 0x7492, 0x7498, 0x7499, 0x749A,
- 0x749C, 0x749F, 0x74A0, 0x74A1, 0x74A3, 0x74A6, 0x74A8, 0x74A9,
- 0x74AA, 0x74AB, 0x74AE, 0x74AF, 0x74B1, 0x74B2, 0x74B5, 0x74B9,
- 0x74BB, 0x74BF, 0x74C8, 0x74C9, 0x74CC, 0x74D0, 0x74D3, 0x74D8,
- 0x74DA, 0x74DB, 0x74DE, 0x74DF, 0x74E4, 0x74E8, 0x74EA, 0x74EB,
- 0x74EF, 0x74F4, 0x74FA, 0x74FB, 0x74FC, 0x74FF, 0x7506,
-};
-static const unsigned short euc_to_utf8_8FCD[] = {
- 0x7512, 0x7516, 0x7517, 0x7520, 0x7521, 0x7524, 0x7527,
- 0x7529, 0x752A, 0x752F, 0x7536, 0x7539, 0x753D, 0x753E, 0x753F,
- 0x7540, 0x7543, 0x7547, 0x7548, 0x754E, 0x7550, 0x7552, 0x7557,
- 0x755E, 0x755F, 0x7561, 0x756F, 0x7571, 0x7579, 0x757A, 0x757B,
- 0x757C, 0x757D, 0x757E, 0x7581, 0x7585, 0x7590, 0x7592, 0x7593,
- 0x7595, 0x7599, 0x759C, 0x75A2, 0x75A4, 0x75B4, 0x75BA, 0x75BF,
- 0x75C0, 0x75C1, 0x75C4, 0x75C6, 0x75CC, 0x75CE, 0x75CF, 0x75D7,
- 0x75DC, 0x75DF, 0x75E0, 0x75E1, 0x75E4, 0x75E7, 0x75EC, 0x75EE,
- 0x75EF, 0x75F1, 0x75F9, 0x7600, 0x7602, 0x7603, 0x7604, 0x7607,
- 0x7608, 0x760A, 0x760C, 0x760F, 0x7612, 0x7613, 0x7615, 0x7616,
- 0x7619, 0x761B, 0x761C, 0x761D, 0x761E, 0x7623, 0x7625, 0x7626,
- 0x7629, 0x762D, 0x7632, 0x7633, 0x7635, 0x7638, 0x7639,
-};
-static const unsigned short euc_to_utf8_8FCE[] = {
- 0x763A, 0x763C, 0x764A, 0x7640, 0x7641, 0x7643, 0x7644,
- 0x7645, 0x7649, 0x764B, 0x7655, 0x7659, 0x765F, 0x7664, 0x7665,
- 0x766D, 0x766E, 0x766F, 0x7671, 0x7674, 0x7681, 0x7685, 0x768C,
- 0x768D, 0x7695, 0x769B, 0x769C, 0x769D, 0x769F, 0x76A0, 0x76A2,
- 0x76A3, 0x76A4, 0x76A5, 0x76A6, 0x76A7, 0x76A8, 0x76AA, 0x76AD,
- 0x76BD, 0x76C1, 0x76C5, 0x76C9, 0x76CB, 0x76CC, 0x76CE, 0x76D4,
- 0x76D9, 0x76E0, 0x76E6, 0x76E8, 0x76EC, 0x76F0, 0x76F1, 0x76F6,
- 0x76F9, 0x76FC, 0x7700, 0x7706, 0x770A, 0x770E, 0x7712, 0x7714,
- 0x7715, 0x7717, 0x7719, 0x771A, 0x771C, 0x7722, 0x7728, 0x772D,
- 0x772E, 0x772F, 0x7734, 0x7735, 0x7736, 0x7739, 0x773D, 0x773E,
- 0x7742, 0x7745, 0x7746, 0x774A, 0x774D, 0x774E, 0x774F, 0x7752,
- 0x7756, 0x7757, 0x775C, 0x775E, 0x775F, 0x7760, 0x7762,
-};
-static const unsigned short euc_to_utf8_8FCF[] = {
- 0x7764, 0x7767, 0x776A, 0x776C, 0x7770, 0x7772, 0x7773,
- 0x7774, 0x777A, 0x777D, 0x7780, 0x7784, 0x778C, 0x778D, 0x7794,
- 0x7795, 0x7796, 0x779A, 0x779F, 0x77A2, 0x77A7, 0x77AA, 0x77AE,
- 0x77AF, 0x77B1, 0x77B5, 0x77BE, 0x77C3, 0x77C9, 0x77D1, 0x77D2,
- 0x77D5, 0x77D9, 0x77DE, 0x77DF, 0x77E0, 0x77E4, 0x77E6, 0x77EA,
- 0x77EC, 0x77F0, 0x77F1, 0x77F4, 0x77F8, 0x77FB, 0x7805, 0x7806,
- 0x7809, 0x780D, 0x780E, 0x7811, 0x781D, 0x7821, 0x7822, 0x7823,
- 0x782D, 0x782E, 0x7830, 0x7835, 0x7837, 0x7843, 0x7844, 0x7847,
- 0x7848, 0x784C, 0x784E, 0x7852, 0x785C, 0x785E, 0x7860, 0x7861,
- 0x7863, 0x7864, 0x7868, 0x786A, 0x786E, 0x787A, 0x787E, 0x788A,
- 0x788F, 0x7894, 0x7898, 0x78A1, 0x789D, 0x789E, 0x789F, 0x78A4,
- 0x78A8, 0x78AC, 0x78AD, 0x78B0, 0x78B1, 0x78B2, 0x78B3,
-};
-static const unsigned short euc_to_utf8_8FD0[] = {
- 0x78BB, 0x78BD, 0x78BF, 0x78C7, 0x78C8, 0x78C9, 0x78CC,
- 0x78CE, 0x78D2, 0x78D3, 0x78D5, 0x78D6, 0x78E4, 0x78DB, 0x78DF,
- 0x78E0, 0x78E1, 0x78E6, 0x78EA, 0x78F2, 0x78F3, 0x7900, 0x78F6,
- 0x78F7, 0x78FA, 0x78FB, 0x78FF, 0x7906, 0x790C, 0x7910, 0x791A,
- 0x791C, 0x791E, 0x791F, 0x7920, 0x7925, 0x7927, 0x7929, 0x792D,
- 0x7931, 0x7934, 0x7935, 0x793B, 0x793D, 0x793F, 0x7944, 0x7945,
- 0x7946, 0x794A, 0x794B, 0x794F, 0x7951, 0x7954, 0x7958, 0x795B,
- 0x795C, 0x7967, 0x7969, 0x796B, 0x7972, 0x7979, 0x797B, 0x797C,
- 0x797E, 0x798B, 0x798C, 0x7991, 0x7993, 0x7994, 0x7995, 0x7996,
- 0x7998, 0x799B, 0x799C, 0x79A1, 0x79A8, 0x79A9, 0x79AB, 0x79AF,
- 0x79B1, 0x79B4, 0x79B8, 0x79BB, 0x79C2, 0x79C4, 0x79C7, 0x79C8,
- 0x79CA, 0x79CF, 0x79D4, 0x79D6, 0x79DA, 0x79DD, 0x79DE,
-};
-static const unsigned short euc_to_utf8_8FD1[] = {
- 0x79E0, 0x79E2, 0x79E5, 0x79EA, 0x79EB, 0x79ED, 0x79F1,
- 0x79F8, 0x79FC, 0x7A02, 0x7A03, 0x7A07, 0x7A09, 0x7A0A, 0x7A0C,
- 0x7A11, 0x7A15, 0x7A1B, 0x7A1E, 0x7A21, 0x7A27, 0x7A2B, 0x7A2D,
- 0x7A2F, 0x7A30, 0x7A34, 0x7A35, 0x7A38, 0x7A39, 0x7A3A, 0x7A44,
- 0x7A45, 0x7A47, 0x7A48, 0x7A4C, 0x7A55, 0x7A56, 0x7A59, 0x7A5C,
- 0x7A5D, 0x7A5F, 0x7A60, 0x7A65, 0x7A67, 0x7A6A, 0x7A6D, 0x7A75,
- 0x7A78, 0x7A7E, 0x7A80, 0x7A82, 0x7A85, 0x7A86, 0x7A8A, 0x7A8B,
- 0x7A90, 0x7A91, 0x7A94, 0x7A9E, 0x7AA0, 0x7AA3, 0x7AAC, 0x7AB3,
- 0x7AB5, 0x7AB9, 0x7ABB, 0x7ABC, 0x7AC6, 0x7AC9, 0x7ACC, 0x7ACE,
- 0x7AD1, 0x7ADB, 0x7AE8, 0x7AE9, 0x7AEB, 0x7AEC, 0x7AF1, 0x7AF4,
- 0x7AFB, 0x7AFD, 0x7AFE, 0x7B07, 0x7B14, 0x7B1F, 0x7B23, 0x7B27,
- 0x7B29, 0x7B2A, 0x7B2B, 0x7B2D, 0x7B2E, 0x7B2F, 0x7B30,
-};
-static const unsigned short euc_to_utf8_8FD2[] = {
- 0x7B31, 0x7B34, 0x7B3D, 0x7B3F, 0x7B40, 0x7B41, 0x7B47,
- 0x7B4E, 0x7B55, 0x7B60, 0x7B64, 0x7B66, 0x7B69, 0x7B6A, 0x7B6D,
- 0x7B6F, 0x7B72, 0x7B73, 0x7B77, 0x7B84, 0x7B89, 0x7B8E, 0x7B90,
- 0x7B91, 0x7B96, 0x7B9B, 0x7B9E, 0x7BA0, 0x7BA5, 0x7BAC, 0x7BAF,
- 0x7BB0, 0x7BB2, 0x7BB5, 0x7BB6, 0x7BBA, 0x7BBB, 0x7BBC, 0x7BBD,
- 0x7BC2, 0x7BC5, 0x7BC8, 0x7BCA, 0x7BD4, 0x7BD6, 0x7BD7, 0x7BD9,
- 0x7BDA, 0x7BDB, 0x7BE8, 0x7BEA, 0x7BF2, 0x7BF4, 0x7BF5, 0x7BF8,
- 0x7BF9, 0x7BFA, 0x7BFC, 0x7BFE, 0x7C01, 0x7C02, 0x7C03, 0x7C04,
- 0x7C06, 0x7C09, 0x7C0B, 0x7C0C, 0x7C0E, 0x7C0F, 0x7C19, 0x7C1B,
- 0x7C20, 0x7C25, 0x7C26, 0x7C28, 0x7C2C, 0x7C31, 0x7C33, 0x7C34,
- 0x7C36, 0x7C39, 0x7C3A, 0x7C46, 0x7C4A, 0x7C55, 0x7C51, 0x7C52,
- 0x7C53, 0x7C59, 0x7C5A, 0x7C5B, 0x7C5C, 0x7C5D, 0x7C5E,
-};
-static const unsigned short euc_to_utf8_8FD3[] = {
- 0x7C61, 0x7C63, 0x7C67, 0x7C69, 0x7C6D, 0x7C6E, 0x7C70,
- 0x7C72, 0x7C79, 0x7C7C, 0x7C7D, 0x7C86, 0x7C87, 0x7C8F, 0x7C94,
- 0x7C9E, 0x7CA0, 0x7CA6, 0x7CB0, 0x7CB6, 0x7CB7, 0x7CBA, 0x7CBB,
- 0x7CBC, 0x7CBF, 0x7CC4, 0x7CC7, 0x7CC8, 0x7CC9, 0x7CCD, 0x7CCF,
- 0x7CD3, 0x7CD4, 0x7CD5, 0x7CD7, 0x7CD9, 0x7CDA, 0x7CDD, 0x7CE6,
- 0x7CE9, 0x7CEB, 0x7CF5, 0x7D03, 0x7D07, 0x7D08, 0x7D09, 0x7D0F,
- 0x7D11, 0x7D12, 0x7D13, 0x7D16, 0x7D1D, 0x7D1E, 0x7D23, 0x7D26,
- 0x7D2A, 0x7D2D, 0x7D31, 0x7D3C, 0x7D3D, 0x7D3E, 0x7D40, 0x7D41,
- 0x7D47, 0x7D48, 0x7D4D, 0x7D51, 0x7D53, 0x7D57, 0x7D59, 0x7D5A,
- 0x7D5C, 0x7D5D, 0x7D65, 0x7D67, 0x7D6A, 0x7D70, 0x7D78, 0x7D7A,
- 0x7D7B, 0x7D7F, 0x7D81, 0x7D82, 0x7D83, 0x7D85, 0x7D86, 0x7D88,
- 0x7D8B, 0x7D8C, 0x7D8D, 0x7D91, 0x7D96, 0x7D97, 0x7D9D,
-};
-static const unsigned short euc_to_utf8_8FD4[] = {
- 0x7D9E, 0x7DA6, 0x7DA7, 0x7DAA, 0x7DB3, 0x7DB6, 0x7DB7,
- 0x7DB9, 0x7DC2, 0x7DC3, 0x7DC4, 0x7DC5, 0x7DC6, 0x7DCC, 0x7DCD,
- 0x7DCE, 0x7DD7, 0x7DD9, 0x7E00, 0x7DE2, 0x7DE5, 0x7DE6, 0x7DEA,
- 0x7DEB, 0x7DED, 0x7DF1, 0x7DF5, 0x7DF6, 0x7DF9, 0x7DFA, 0x7E08,
- 0x7E10, 0x7E11, 0x7E15, 0x7E17, 0x7E1C, 0x7E1D, 0x7E20, 0x7E27,
- 0x7E28, 0x7E2C, 0x7E2D, 0x7E2F, 0x7E33, 0x7E36, 0x7E3F, 0x7E44,
- 0x7E45, 0x7E47, 0x7E4E, 0x7E50, 0x7E52, 0x7E58, 0x7E5F, 0x7E61,
- 0x7E62, 0x7E65, 0x7E6B, 0x7E6E, 0x7E6F, 0x7E73, 0x7E78, 0x7E7E,
- 0x7E81, 0x7E86, 0x7E87, 0x7E8A, 0x7E8D, 0x7E91, 0x7E95, 0x7E98,
- 0x7E9A, 0x7E9D, 0x7E9E, 0x7F3C, 0x7F3B, 0x7F3D, 0x7F3E, 0x7F3F,
- 0x7F43, 0x7F44, 0x7F47, 0x7F4F, 0x7F52, 0x7F53, 0x7F5B, 0x7F5C,
- 0x7F5D, 0x7F61, 0x7F63, 0x7F64, 0x7F65, 0x7F66, 0x7F6D,
-};
-static const unsigned short euc_to_utf8_8FD5[] = {
- 0x7F71, 0x7F7D, 0x7F7E, 0x7F7F, 0x7F80, 0x7F8B, 0x7F8D,
- 0x7F8F, 0x7F90, 0x7F91, 0x7F96, 0x7F97, 0x7F9C, 0x7FA1, 0x7FA2,
- 0x7FA6, 0x7FAA, 0x7FAD, 0x7FB4, 0x7FBC, 0x7FBF, 0x7FC0, 0x7FC3,
- 0x7FC8, 0x7FCE, 0x7FCF, 0x7FDB, 0x7FDF, 0x7FE3, 0x7FE5, 0x7FE8,
- 0x7FEC, 0x7FEE, 0x7FEF, 0x7FF2, 0x7FFA, 0x7FFD, 0x7FFE, 0x7FFF,
- 0x8007, 0x8008, 0x800A, 0x800D, 0x800E, 0x800F, 0x8011, 0x8013,
- 0x8014, 0x8016, 0x801D, 0x801E, 0x801F, 0x8020, 0x8024, 0x8026,
- 0x802C, 0x802E, 0x8030, 0x8034, 0x8035, 0x8037, 0x8039, 0x803A,
- 0x803C, 0x803E, 0x8040, 0x8044, 0x8060, 0x8064, 0x8066, 0x806D,
- 0x8071, 0x8075, 0x8081, 0x8088, 0x808E, 0x809C, 0x809E, 0x80A6,
- 0x80A7, 0x80AB, 0x80B8, 0x80B9, 0x80C8, 0x80CD, 0x80CF, 0x80D2,
- 0x80D4, 0x80D5, 0x80D7, 0x80D8, 0x80E0, 0x80ED, 0x80EE,
-};
-static const unsigned short euc_to_utf8_8FD6[] = {
- 0x80F0, 0x80F2, 0x80F3, 0x80F6, 0x80F9, 0x80FA, 0x80FE,
- 0x8103, 0x810B, 0x8116, 0x8117, 0x8118, 0x811C, 0x811E, 0x8120,
- 0x8124, 0x8127, 0x812C, 0x8130, 0x8135, 0x813A, 0x813C, 0x8145,
- 0x8147, 0x814A, 0x814C, 0x8152, 0x8157, 0x8160, 0x8161, 0x8167,
- 0x8168, 0x8169, 0x816D, 0x816F, 0x8177, 0x8181, 0x8190, 0x8184,
- 0x8185, 0x8186, 0x818B, 0x818E, 0x8196, 0x8198, 0x819B, 0x819E,
- 0x81A2, 0x81AE, 0x81B2, 0x81B4, 0x81BB, 0x81CB, 0x81C3, 0x81C5,
- 0x81CA, 0x81CE, 0x81CF, 0x81D5, 0x81D7, 0x81DB, 0x81DD, 0x81DE,
- 0x81E1, 0x81E4, 0x81EB, 0x81EC, 0x81F0, 0x81F1, 0x81F2, 0x81F5,
- 0x81F6, 0x81F8, 0x81F9, 0x81FD, 0x81FF, 0x8200, 0x8203, 0x820F,
- 0x8213, 0x8214, 0x8219, 0x821A, 0x821D, 0x8221, 0x8222, 0x8228,
- 0x8232, 0x8234, 0x823A, 0x8243, 0x8244, 0x8245, 0x8246,
-};
-static const unsigned short euc_to_utf8_8FD7[] = {
- 0x824B, 0x824E, 0x824F, 0x8251, 0x8256, 0x825C, 0x8260,
- 0x8263, 0x8267, 0x826D, 0x8274, 0x827B, 0x827D, 0x827F, 0x8280,
- 0x8281, 0x8283, 0x8284, 0x8287, 0x8289, 0x828A, 0x828E, 0x8291,
- 0x8294, 0x8296, 0x8298, 0x829A, 0x829B, 0x82A0, 0x82A1, 0x82A3,
- 0x82A4, 0x82A7, 0x82A8, 0x82A9, 0x82AA, 0x82AE, 0x82B0, 0x82B2,
- 0x82B4, 0x82B7, 0x82BA, 0x82BC, 0x82BE, 0x82BF, 0x82C6, 0x82D0,
- 0x82D5, 0x82DA, 0x82E0, 0x82E2, 0x82E4, 0x82E8, 0x82EA, 0x82ED,
- 0x82EF, 0x82F6, 0x82F7, 0x82FD, 0x82FE, 0x8300, 0x8301, 0x8307,
- 0x8308, 0x830A, 0x830B, 0x8354, 0x831B, 0x831D, 0x831E, 0x831F,
- 0x8321, 0x8322, 0x832C, 0x832D, 0x832E, 0x8330, 0x8333, 0x8337,
- 0x833A, 0x833C, 0x833D, 0x8342, 0x8343, 0x8344, 0x8347, 0x834D,
- 0x834E, 0x8351, 0x8355, 0x8356, 0x8357, 0x8370, 0x8378,
-};
-static const unsigned short euc_to_utf8_8FD8[] = {
- 0x837D, 0x837F, 0x8380, 0x8382, 0x8384, 0x8386, 0x838D,
- 0x8392, 0x8394, 0x8395, 0x8398, 0x8399, 0x839B, 0x839C, 0x839D,
- 0x83A6, 0x83A7, 0x83A9, 0x83AC, 0x83BE, 0x83BF, 0x83C0, 0x83C7,
- 0x83C9, 0x83CF, 0x83D0, 0x83D1, 0x83D4, 0x83DD, 0x8353, 0x83E8,
- 0x83EA, 0x83F6, 0x83F8, 0x83F9, 0x83FC, 0x8401, 0x8406, 0x840A,
- 0x840F, 0x8411, 0x8415, 0x8419, 0x83AD, 0x842F, 0x8439, 0x8445,
- 0x8447, 0x8448, 0x844A, 0x844D, 0x844F, 0x8451, 0x8452, 0x8456,
- 0x8458, 0x8459, 0x845A, 0x845C, 0x8460, 0x8464, 0x8465, 0x8467,
- 0x846A, 0x8470, 0x8473, 0x8474, 0x8476, 0x8478, 0x847C, 0x847D,
- 0x8481, 0x8485, 0x8492, 0x8493, 0x8495, 0x849E, 0x84A6, 0x84A8,
- 0x84A9, 0x84AA, 0x84AF, 0x84B1, 0x84B4, 0x84BA, 0x84BD, 0x84BE,
- 0x84C0, 0x84C2, 0x84C7, 0x84C8, 0x84CC, 0x84CF, 0x84D3,
-};
-static const unsigned short euc_to_utf8_8FD9[] = {
- 0x84DC, 0x84E7, 0x84EA, 0x84EF, 0x84F0, 0x84F1, 0x84F2,
- 0x84F7, 0x8532, 0x84FA, 0x84FB, 0x84FD, 0x8502, 0x8503, 0x8507,
- 0x850C, 0x850E, 0x8510, 0x851C, 0x851E, 0x8522, 0x8523, 0x8524,
- 0x8525, 0x8527, 0x852A, 0x852B, 0x852F, 0x8533, 0x8534, 0x8536,
- 0x853F, 0x8546, 0x854F, 0x8550, 0x8551, 0x8552, 0x8553, 0x8556,
- 0x8559, 0x855C, 0x855D, 0x855E, 0x855F, 0x8560, 0x8561, 0x8562,
- 0x8564, 0x856B, 0x856F, 0x8579, 0x857A, 0x857B, 0x857D, 0x857F,
- 0x8581, 0x8585, 0x8586, 0x8589, 0x858B, 0x858C, 0x858F, 0x8593,
- 0x8598, 0x859D, 0x859F, 0x85A0, 0x85A2, 0x85A5, 0x85A7, 0x85B4,
- 0x85B6, 0x85B7, 0x85B8, 0x85BC, 0x85BD, 0x85BE, 0x85BF, 0x85C2,
- 0x85C7, 0x85CA, 0x85CB, 0x85CE, 0x85AD, 0x85D8, 0x85DA, 0x85DF,
- 0x85E0, 0x85E6, 0x85E8, 0x85ED, 0x85F3, 0x85F6, 0x85FC,
-};
-static const unsigned short euc_to_utf8_8FDA[] = {
- 0x85FF, 0x8600, 0x8604, 0x8605, 0x860D, 0x860E, 0x8610,
- 0x8611, 0x8612, 0x8618, 0x8619, 0x861B, 0x861E, 0x8621, 0x8627,
- 0x8629, 0x8636, 0x8638, 0x863A, 0x863C, 0x863D, 0x8640, 0x8642,
- 0x8646, 0x8652, 0x8653, 0x8656, 0x8657, 0x8658, 0x8659, 0x865D,
- 0x8660, 0x8661, 0x8662, 0x8663, 0x8664, 0x8669, 0x866C, 0x866F,
- 0x8675, 0x8676, 0x8677, 0x867A, 0x868D, 0x8691, 0x8696, 0x8698,
- 0x869A, 0x869C, 0x86A1, 0x86A6, 0x86A7, 0x86A8, 0x86AD, 0x86B1,
- 0x86B3, 0x86B4, 0x86B5, 0x86B7, 0x86B8, 0x86B9, 0x86BF, 0x86C0,
- 0x86C1, 0x86C3, 0x86C5, 0x86D1, 0x86D2, 0x86D5, 0x86D7, 0x86DA,
- 0x86DC, 0x86E0, 0x86E3, 0x86E5, 0x86E7, 0x8688, 0x86FA, 0x86FC,
- 0x86FD, 0x8704, 0x8705, 0x8707, 0x870B, 0x870E, 0x870F, 0x8710,
- 0x8713, 0x8714, 0x8719, 0x871E, 0x871F, 0x8721, 0x8723,
-};
-static const unsigned short euc_to_utf8_8FDB[] = {
- 0x8728, 0x872E, 0x872F, 0x8731, 0x8732, 0x8739, 0x873A,
- 0x873C, 0x873D, 0x873E, 0x8740, 0x8743, 0x8745, 0x874D, 0x8758,
- 0x875D, 0x8761, 0x8764, 0x8765, 0x876F, 0x8771, 0x8772, 0x877B,
- 0x8783, 0x8784, 0x8785, 0x8786, 0x8787, 0x8788, 0x8789, 0x878B,
- 0x878C, 0x8790, 0x8793, 0x8795, 0x8797, 0x8798, 0x8799, 0x879E,
- 0x87A0, 0x87A3, 0x87A7, 0x87AC, 0x87AD, 0x87AE, 0x87B1, 0x87B5,
- 0x87BE, 0x87BF, 0x87C1, 0x87C8, 0x87C9, 0x87CA, 0x87CE, 0x87D5,
- 0x87D6, 0x87D9, 0x87DA, 0x87DC, 0x87DF, 0x87E2, 0x87E3, 0x87E4,
- 0x87EA, 0x87EB, 0x87ED, 0x87F1, 0x87F3, 0x87F8, 0x87FA, 0x87FF,
- 0x8801, 0x8803, 0x8806, 0x8809, 0x880A, 0x880B, 0x8810, 0x8819,
- 0x8812, 0x8813, 0x8814, 0x8818, 0x881A, 0x881B, 0x881C, 0x881E,
- 0x881F, 0x8828, 0x882D, 0x882E, 0x8830, 0x8832, 0x8835,
-};
-static const unsigned short euc_to_utf8_8FDC[] = {
- 0x883A, 0x883C, 0x8841, 0x8843, 0x8845, 0x8848, 0x8849,
- 0x884A, 0x884B, 0x884E, 0x8851, 0x8855, 0x8856, 0x8858, 0x885A,
- 0x885C, 0x885F, 0x8860, 0x8864, 0x8869, 0x8871, 0x8879, 0x887B,
- 0x8880, 0x8898, 0x889A, 0x889B, 0x889C, 0x889F, 0x88A0, 0x88A8,
- 0x88AA, 0x88BA, 0x88BD, 0x88BE, 0x88C0, 0x88CA, 0x88CB, 0x88CC,
- 0x88CD, 0x88CE, 0x88D1, 0x88D2, 0x88D3, 0x88DB, 0x88DE, 0x88E7,
- 0x88EF, 0x88F0, 0x88F1, 0x88F5, 0x88F7, 0x8901, 0x8906, 0x890D,
- 0x890E, 0x890F, 0x8915, 0x8916, 0x8918, 0x8919, 0x891A, 0x891C,
- 0x8920, 0x8926, 0x8927, 0x8928, 0x8930, 0x8931, 0x8932, 0x8935,
- 0x8939, 0x893A, 0x893E, 0x8940, 0x8942, 0x8945, 0x8946, 0x8949,
- 0x894F, 0x8952, 0x8957, 0x895A, 0x895B, 0x895C, 0x8961, 0x8962,
- 0x8963, 0x896B, 0x896E, 0x8970, 0x8973, 0x8975, 0x897A,
-};
-static const unsigned short euc_to_utf8_8FDD[] = {
- 0x897B, 0x897C, 0x897D, 0x8989, 0x898D, 0x8990, 0x8994,
- 0x8995, 0x899B, 0x899C, 0x899F, 0x89A0, 0x89A5, 0x89B0, 0x89B4,
- 0x89B5, 0x89B6, 0x89B7, 0x89BC, 0x89D4, 0x89D5, 0x89D6, 0x89D7,
- 0x89D8, 0x89E5, 0x89E9, 0x89EB, 0x89ED, 0x89F1, 0x89F3, 0x89F6,
- 0x89F9, 0x89FD, 0x89FF, 0x8A04, 0x8A05, 0x8A07, 0x8A0F, 0x8A11,
- 0x8A12, 0x8A14, 0x8A15, 0x8A1E, 0x8A20, 0x8A22, 0x8A24, 0x8A26,
- 0x8A2B, 0x8A2C, 0x8A2F, 0x8A35, 0x8A37, 0x8A3D, 0x8A3E, 0x8A40,
- 0x8A43, 0x8A45, 0x8A47, 0x8A49, 0x8A4D, 0x8A4E, 0x8A53, 0x8A56,
- 0x8A57, 0x8A58, 0x8A5C, 0x8A5D, 0x8A61, 0x8A65, 0x8A67, 0x8A75,
- 0x8A76, 0x8A77, 0x8A79, 0x8A7A, 0x8A7B, 0x8A7E, 0x8A7F, 0x8A80,
- 0x8A83, 0x8A86, 0x8A8B, 0x8A8F, 0x8A90, 0x8A92, 0x8A96, 0x8A97,
- 0x8A99, 0x8A9F, 0x8AA7, 0x8AA9, 0x8AAE, 0x8AAF, 0x8AB3,
-};
-static const unsigned short euc_to_utf8_8FDE[] = {
- 0x8AB6, 0x8AB7, 0x8ABB, 0x8ABE, 0x8AC3, 0x8AC6, 0x8AC8,
- 0x8AC9, 0x8ACA, 0x8AD1, 0x8AD3, 0x8AD4, 0x8AD5, 0x8AD7, 0x8ADD,
- 0x8ADF, 0x8AEC, 0x8AF0, 0x8AF4, 0x8AF5, 0x8AF6, 0x8AFC, 0x8AFF,
- 0x8B05, 0x8B06, 0x8B0B, 0x8B11, 0x8B1C, 0x8B1E, 0x8B1F, 0x8B0A,
- 0x8B2D, 0x8B30, 0x8B37, 0x8B3C, 0x8B42, 0x8B43, 0x8B44, 0x8B45,
- 0x8B46, 0x8B48, 0x8B52, 0x8B53, 0x8B54, 0x8B59, 0x8B4D, 0x8B5E,
- 0x8B63, 0x8B6D, 0x8B76, 0x8B78, 0x8B79, 0x8B7C, 0x8B7E, 0x8B81,
- 0x8B84, 0x8B85, 0x8B8B, 0x8B8D, 0x8B8F, 0x8B94, 0x8B95, 0x8B9C,
- 0x8B9E, 0x8B9F, 0x8C38, 0x8C39, 0x8C3D, 0x8C3E, 0x8C45, 0x8C47,
- 0x8C49, 0x8C4B, 0x8C4F, 0x8C51, 0x8C53, 0x8C54, 0x8C57, 0x8C58,
- 0x8C5B, 0x8C5D, 0x8C59, 0x8C63, 0x8C64, 0x8C66, 0x8C68, 0x8C69,
- 0x8C6D, 0x8C73, 0x8C75, 0x8C76, 0x8C7B, 0x8C7E, 0x8C86,
-};
-static const unsigned short euc_to_utf8_8FDF[] = {
- 0x8C87, 0x8C8B, 0x8C90, 0x8C92, 0x8C93, 0x8C99, 0x8C9B,
- 0x8C9C, 0x8CA4, 0x8CB9, 0x8CBA, 0x8CC5, 0x8CC6, 0x8CC9, 0x8CCB,
- 0x8CCF, 0x8CD6, 0x8CD5, 0x8CD9, 0x8CDD, 0x8CE1, 0x8CE8, 0x8CEC,
- 0x8CEF, 0x8CF0, 0x8CF2, 0x8CF5, 0x8CF7, 0x8CF8, 0x8CFE, 0x8CFF,
- 0x8D01, 0x8D03, 0x8D09, 0x8D12, 0x8D17, 0x8D1B, 0x8D65, 0x8D69,
- 0x8D6C, 0x8D6E, 0x8D7F, 0x8D82, 0x8D84, 0x8D88, 0x8D8D, 0x8D90,
- 0x8D91, 0x8D95, 0x8D9E, 0x8D9F, 0x8DA0, 0x8DA6, 0x8DAB, 0x8DAC,
- 0x8DAF, 0x8DB2, 0x8DB5, 0x8DB7, 0x8DB9, 0x8DBB, 0x8DC0, 0x8DC5,
- 0x8DC6, 0x8DC7, 0x8DC8, 0x8DCA, 0x8DCE, 0x8DD1, 0x8DD4, 0x8DD5,
- 0x8DD7, 0x8DD9, 0x8DE4, 0x8DE5, 0x8DE7, 0x8DEC, 0x8DF0, 0x8DBC,
- 0x8DF1, 0x8DF2, 0x8DF4, 0x8DFD, 0x8E01, 0x8E04, 0x8E05, 0x8E06,
- 0x8E0B, 0x8E11, 0x8E14, 0x8E16, 0x8E20, 0x8E21, 0x8E22,
-};
-static const unsigned short euc_to_utf8_8FE0[] = {
- 0x8E23, 0x8E26, 0x8E27, 0x8E31, 0x8E33, 0x8E36, 0x8E37,
- 0x8E38, 0x8E39, 0x8E3D, 0x8E40, 0x8E41, 0x8E4B, 0x8E4D, 0x8E4E,
- 0x8E4F, 0x8E54, 0x8E5B, 0x8E5C, 0x8E5D, 0x8E5E, 0x8E61, 0x8E62,
- 0x8E69, 0x8E6C, 0x8E6D, 0x8E6F, 0x8E70, 0x8E71, 0x8E79, 0x8E7A,
- 0x8E7B, 0x8E82, 0x8E83, 0x8E89, 0x8E90, 0x8E92, 0x8E95, 0x8E9A,
- 0x8E9B, 0x8E9D, 0x8E9E, 0x8EA2, 0x8EA7, 0x8EA9, 0x8EAD, 0x8EAE,
- 0x8EB3, 0x8EB5, 0x8EBA, 0x8EBB, 0x8EC0, 0x8EC1, 0x8EC3, 0x8EC4,
- 0x8EC7, 0x8ECF, 0x8ED1, 0x8ED4, 0x8EDC, 0x8EE8, 0x8EEE, 0x8EF0,
- 0x8EF1, 0x8EF7, 0x8EF9, 0x8EFA, 0x8EED, 0x8F00, 0x8F02, 0x8F07,
- 0x8F08, 0x8F0F, 0x8F10, 0x8F16, 0x8F17, 0x8F18, 0x8F1E, 0x8F20,
- 0x8F21, 0x8F23, 0x8F25, 0x8F27, 0x8F28, 0x8F2C, 0x8F2D, 0x8F2E,
- 0x8F34, 0x8F35, 0x8F36, 0x8F37, 0x8F3A, 0x8F40, 0x8F41,
-};
-static const unsigned short euc_to_utf8_8FE1[] = {
- 0x8F43, 0x8F47, 0x8F4F, 0x8F51, 0x8F52, 0x8F53, 0x8F54,
- 0x8F55, 0x8F58, 0x8F5D, 0x8F5E, 0x8F65, 0x8F9D, 0x8FA0, 0x8FA1,
- 0x8FA4, 0x8FA5, 0x8FA6, 0x8FB5, 0x8FB6, 0x8FB8, 0x8FBE, 0x8FC0,
- 0x8FC1, 0x8FC6, 0x8FCA, 0x8FCB, 0x8FCD, 0x8FD0, 0x8FD2, 0x8FD3,
- 0x8FD5, 0x8FE0, 0x8FE3, 0x8FE4, 0x8FE8, 0x8FEE, 0x8FF1, 0x8FF5,
- 0x8FF6, 0x8FFB, 0x8FFE, 0x9002, 0x9004, 0x9008, 0x900C, 0x9018,
- 0x901B, 0x9028, 0x9029, 0x902F, 0x902A, 0x902C, 0x902D, 0x9033,
- 0x9034, 0x9037, 0x903F, 0x9043, 0x9044, 0x904C, 0x905B, 0x905D,
- 0x9062, 0x9066, 0x9067, 0x906C, 0x9070, 0x9074, 0x9079, 0x9085,
- 0x9088, 0x908B, 0x908C, 0x908E, 0x9090, 0x9095, 0x9097, 0x9098,
- 0x9099, 0x909B, 0x90A0, 0x90A1, 0x90A2, 0x90A5, 0x90B0, 0x90B2,
- 0x90B3, 0x90B4, 0x90B6, 0x90BD, 0x90CC, 0x90BE, 0x90C3,
-};
-static const unsigned short euc_to_utf8_8FE2[] = {
- 0x90C4, 0x90C5, 0x90C7, 0x90C8, 0x90D5, 0x90D7, 0x90D8,
- 0x90D9, 0x90DC, 0x90DD, 0x90DF, 0x90E5, 0x90D2, 0x90F6, 0x90EB,
- 0x90EF, 0x90F0, 0x90F4, 0x90FE, 0x90FF, 0x9100, 0x9104, 0x9105,
- 0x9106, 0x9108, 0x910D, 0x9110, 0x9114, 0x9116, 0x9117, 0x9118,
- 0x911A, 0x911C, 0x911E, 0x9120, 0x9125, 0x9122, 0x9123, 0x9127,
- 0x9129, 0x912E, 0x912F, 0x9131, 0x9134, 0x9136, 0x9137, 0x9139,
- 0x913A, 0x913C, 0x913D, 0x9143, 0x9147, 0x9148, 0x914F, 0x9153,
- 0x9157, 0x9159, 0x915A, 0x915B, 0x9161, 0x9164, 0x9167, 0x916D,
- 0x9174, 0x9179, 0x917A, 0x917B, 0x9181, 0x9183, 0x9185, 0x9186,
- 0x918A, 0x918E, 0x9191, 0x9193, 0x9194, 0x9195, 0x9198, 0x919E,
- 0x91A1, 0x91A6, 0x91A8, 0x91AC, 0x91AD, 0x91AE, 0x91B0, 0x91B1,
- 0x91B2, 0x91B3, 0x91B6, 0x91BB, 0x91BC, 0x91BD, 0x91BF,
-};
-static const unsigned short euc_to_utf8_8FE3[] = {
- 0x91C2, 0x91C3, 0x91C5, 0x91D3, 0x91D4, 0x91D7, 0x91D9,
- 0x91DA, 0x91DE, 0x91E4, 0x91E5, 0x91E9, 0x91EA, 0x91EC, 0x91ED,
- 0x91EE, 0x91EF, 0x91F0, 0x91F1, 0x91F7, 0x91F9, 0x91FB, 0x91FD,
- 0x9200, 0x9201, 0x9204, 0x9205, 0x9206, 0x9207, 0x9209, 0x920A,
- 0x920C, 0x9210, 0x9212, 0x9213, 0x9216, 0x9218, 0x921C, 0x921D,
- 0x9223, 0x9224, 0x9225, 0x9226, 0x9228, 0x922E, 0x922F, 0x9230,
- 0x9233, 0x9235, 0x9236, 0x9238, 0x9239, 0x923A, 0x923C, 0x923E,
- 0x9240, 0x9242, 0x9243, 0x9246, 0x9247, 0x924A, 0x924D, 0x924E,
- 0x924F, 0x9251, 0x9258, 0x9259, 0x925C, 0x925D, 0x9260, 0x9261,
- 0x9265, 0x9267, 0x9268, 0x9269, 0x926E, 0x926F, 0x9270, 0x9275,
- 0x9276, 0x9277, 0x9278, 0x9279, 0x927B, 0x927C, 0x927D, 0x927F,
- 0x9288, 0x9289, 0x928A, 0x928D, 0x928E, 0x9292, 0x9297,
-};
-static const unsigned short euc_to_utf8_8FE4[] = {
- 0x9299, 0x929F, 0x92A0, 0x92A4, 0x92A5, 0x92A7, 0x92A8,
- 0x92AB, 0x92AF, 0x92B2, 0x92B6, 0x92B8, 0x92BA, 0x92BB, 0x92BC,
- 0x92BD, 0x92BF, 0x92C0, 0x92C1, 0x92C2, 0x92C3, 0x92C5, 0x92C6,
- 0x92C7, 0x92C8, 0x92CB, 0x92CC, 0x92CD, 0x92CE, 0x92D0, 0x92D3,
- 0x92D5, 0x92D7, 0x92D8, 0x92D9, 0x92DC, 0x92DD, 0x92DF, 0x92E0,
- 0x92E1, 0x92E3, 0x92E5, 0x92E7, 0x92E8, 0x92EC, 0x92EE, 0x92F0,
- 0x92F9, 0x92FB, 0x92FF, 0x9300, 0x9302, 0x9308, 0x930D, 0x9311,
- 0x9314, 0x9315, 0x931C, 0x931D, 0x931E, 0x931F, 0x9321, 0x9324,
- 0x9325, 0x9327, 0x9329, 0x932A, 0x9333, 0x9334, 0x9336, 0x9337,
- 0x9347, 0x9348, 0x9349, 0x9350, 0x9351, 0x9352, 0x9355, 0x9357,
- 0x9358, 0x935A, 0x935E, 0x9364, 0x9365, 0x9367, 0x9369, 0x936A,
- 0x936D, 0x936F, 0x9370, 0x9371, 0x9373, 0x9374, 0x9376,
-};
-static const unsigned short euc_to_utf8_8FE5[] = {
- 0x937A, 0x937D, 0x937F, 0x9380, 0x9381, 0x9382, 0x9388,
- 0x938A, 0x938B, 0x938D, 0x938F, 0x9392, 0x9395, 0x9398, 0x939B,
- 0x939E, 0x93A1, 0x93A3, 0x93A4, 0x93A6, 0x93A8, 0x93AB, 0x93B4,
- 0x93B5, 0x93B6, 0x93BA, 0x93A9, 0x93C1, 0x93C4, 0x93C5, 0x93C6,
- 0x93C7, 0x93C9, 0x93CA, 0x93CB, 0x93CC, 0x93CD, 0x93D3, 0x93D9,
- 0x93DC, 0x93DE, 0x93DF, 0x93E2, 0x93E6, 0x93E7, 0x93F9, 0x93F7,
- 0x93F8, 0x93FA, 0x93FB, 0x93FD, 0x9401, 0x9402, 0x9404, 0x9408,
- 0x9409, 0x940D, 0x940E, 0x940F, 0x9415, 0x9416, 0x9417, 0x941F,
- 0x942E, 0x942F, 0x9431, 0x9432, 0x9433, 0x9434, 0x943B, 0x943F,
- 0x943D, 0x9443, 0x9445, 0x9448, 0x944A, 0x944C, 0x9455, 0x9459,
- 0x945C, 0x945F, 0x9461, 0x9463, 0x9468, 0x946B, 0x946D, 0x946E,
- 0x946F, 0x9471, 0x9472, 0x9484, 0x9483, 0x9578, 0x9579,
-};
-static const unsigned short euc_to_utf8_8FE6[] = {
- 0x957E, 0x9584, 0x9588, 0x958C, 0x958D, 0x958E, 0x959D,
- 0x959E, 0x959F, 0x95A1, 0x95A6, 0x95A9, 0x95AB, 0x95AC, 0x95B4,
- 0x95B6, 0x95BA, 0x95BD, 0x95BF, 0x95C6, 0x95C8, 0x95C9, 0x95CB,
- 0x95D0, 0x95D1, 0x95D2, 0x95D3, 0x95D9, 0x95DA, 0x95DD, 0x95DE,
- 0x95DF, 0x95E0, 0x95E4, 0x95E6, 0x961D, 0x961E, 0x9622, 0x9624,
- 0x9625, 0x9626, 0x962C, 0x9631, 0x9633, 0x9637, 0x9638, 0x9639,
- 0x963A, 0x963C, 0x963D, 0x9641, 0x9652, 0x9654, 0x9656, 0x9657,
- 0x9658, 0x9661, 0x966E, 0x9674, 0x967B, 0x967C, 0x967E, 0x967F,
- 0x9681, 0x9682, 0x9683, 0x9684, 0x9689, 0x9691, 0x9696, 0x969A,
- 0x969D, 0x969F, 0x96A4, 0x96A5, 0x96A6, 0x96A9, 0x96AE, 0x96AF,
- 0x96B3, 0x96BA, 0x96CA, 0x96D2, 0x5DB2, 0x96D8, 0x96DA, 0x96DD,
- 0x96DE, 0x96DF, 0x96E9, 0x96EF, 0x96F1, 0x96FA, 0x9702,
-};
-static const unsigned short euc_to_utf8_8FE7[] = {
- 0x9703, 0x9705, 0x9709, 0x971A, 0x971B, 0x971D, 0x9721,
- 0x9722, 0x9723, 0x9728, 0x9731, 0x9733, 0x9741, 0x9743, 0x974A,
- 0x974E, 0x974F, 0x9755, 0x9757, 0x9758, 0x975A, 0x975B, 0x9763,
- 0x9767, 0x976A, 0x976E, 0x9773, 0x9776, 0x9777, 0x9778, 0x977B,
- 0x977D, 0x977F, 0x9780, 0x9789, 0x9795, 0x9796, 0x9797, 0x9799,
- 0x979A, 0x979E, 0x979F, 0x97A2, 0x97AC, 0x97AE, 0x97B1, 0x97B2,
- 0x97B5, 0x97B6, 0x97B8, 0x97B9, 0x97BA, 0x97BC, 0x97BE, 0x97BF,
- 0x97C1, 0x97C4, 0x97C5, 0x97C7, 0x97C9, 0x97CA, 0x97CC, 0x97CD,
- 0x97CE, 0x97D0, 0x97D1, 0x97D4, 0x97D7, 0x97D8, 0x97D9, 0x97DD,
- 0x97DE, 0x97E0, 0x97DB, 0x97E1, 0x97E4, 0x97EF, 0x97F1, 0x97F4,
- 0x97F7, 0x97F8, 0x97FA, 0x9807, 0x980A, 0x9819, 0x980D, 0x980E,
- 0x9814, 0x9816, 0x981C, 0x981E, 0x9820, 0x9823, 0x9826,
-};
-static const unsigned short euc_to_utf8_8FE8[] = {
- 0x982B, 0x982E, 0x982F, 0x9830, 0x9832, 0x9833, 0x9835,
- 0x9825, 0x983E, 0x9844, 0x9847, 0x984A, 0x9851, 0x9852, 0x9853,
- 0x9856, 0x9857, 0x9859, 0x985A, 0x9862, 0x9863, 0x9865, 0x9866,
- 0x986A, 0x986C, 0x98AB, 0x98AD, 0x98AE, 0x98B0, 0x98B4, 0x98B7,
- 0x98B8, 0x98BA, 0x98BB, 0x98BF, 0x98C2, 0x98C5, 0x98C8, 0x98CC,
- 0x98E1, 0x98E3, 0x98E5, 0x98E6, 0x98E7, 0x98EA, 0x98F3, 0x98F6,
- 0x9902, 0x9907, 0x9908, 0x9911, 0x9915, 0x9916, 0x9917, 0x991A,
- 0x991B, 0x991C, 0x991F, 0x9922, 0x9926, 0x9927, 0x992B, 0x9931,
- 0x9932, 0x9933, 0x9934, 0x9935, 0x9939, 0x993A, 0x993B, 0x993C,
- 0x9940, 0x9941, 0x9946, 0x9947, 0x9948, 0x994D, 0x994E, 0x9954,
- 0x9958, 0x9959, 0x995B, 0x995C, 0x995E, 0x995F, 0x9960, 0x999B,
- 0x999D, 0x999F, 0x99A6, 0x99B0, 0x99B1, 0x99B2, 0x99B5,
-};
-static const unsigned short euc_to_utf8_8FE9[] = {
- 0x99B9, 0x99BA, 0x99BD, 0x99BF, 0x99C3, 0x99C9, 0x99D3,
- 0x99D4, 0x99D9, 0x99DA, 0x99DC, 0x99DE, 0x99E7, 0x99EA, 0x99EB,
- 0x99EC, 0x99F0, 0x99F4, 0x99F5, 0x99F9, 0x99FD, 0x99FE, 0x9A02,
- 0x9A03, 0x9A04, 0x9A0B, 0x9A0C, 0x9A10, 0x9A11, 0x9A16, 0x9A1E,
- 0x9A20, 0x9A22, 0x9A23, 0x9A24, 0x9A27, 0x9A2D, 0x9A2E, 0x9A33,
- 0x9A35, 0x9A36, 0x9A38, 0x9A47, 0x9A41, 0x9A44, 0x9A4A, 0x9A4B,
- 0x9A4C, 0x9A4E, 0x9A51, 0x9A54, 0x9A56, 0x9A5D, 0x9AAA, 0x9AAC,
- 0x9AAE, 0x9AAF, 0x9AB2, 0x9AB4, 0x9AB5, 0x9AB6, 0x9AB9, 0x9ABB,
- 0x9ABE, 0x9ABF, 0x9AC1, 0x9AC3, 0x9AC6, 0x9AC8, 0x9ACE, 0x9AD0,
- 0x9AD2, 0x9AD5, 0x9AD6, 0x9AD7, 0x9ADB, 0x9ADC, 0x9AE0, 0x9AE4,
- 0x9AE5, 0x9AE7, 0x9AE9, 0x9AEC, 0x9AF2, 0x9AF3, 0x9AF5, 0x9AF9,
- 0x9AFA, 0x9AFD, 0x9AFF, 0x9B00, 0x9B01, 0x9B02, 0x9B03,
-};
-static const unsigned short euc_to_utf8_8FEA[] = {
- 0x9B04, 0x9B05, 0x9B08, 0x9B09, 0x9B0B, 0x9B0C, 0x9B0D,
- 0x9B0E, 0x9B10, 0x9B12, 0x9B16, 0x9B19, 0x9B1B, 0x9B1C, 0x9B20,
- 0x9B26, 0x9B2B, 0x9B2D, 0x9B33, 0x9B34, 0x9B35, 0x9B37, 0x9B39,
- 0x9B3A, 0x9B3D, 0x9B48, 0x9B4B, 0x9B4C, 0x9B55, 0x9B56, 0x9B57,
- 0x9B5B, 0x9B5E, 0x9B61, 0x9B63, 0x9B65, 0x9B66, 0x9B68, 0x9B6A,
- 0x9B6B, 0x9B6C, 0x9B6D, 0x9B6E, 0x9B73, 0x9B75, 0x9B77, 0x9B78,
- 0x9B79, 0x9B7F, 0x9B80, 0x9B84, 0x9B85, 0x9B86, 0x9B87, 0x9B89,
- 0x9B8A, 0x9B8B, 0x9B8D, 0x9B8F, 0x9B90, 0x9B94, 0x9B9A, 0x9B9D,
- 0x9B9E, 0x9BA6, 0x9BA7, 0x9BA9, 0x9BAC, 0x9BB0, 0x9BB1, 0x9BB2,
- 0x9BB7, 0x9BB8, 0x9BBB, 0x9BBC, 0x9BBE, 0x9BBF, 0x9BC1, 0x9BC7,
- 0x9BC8, 0x9BCE, 0x9BD0, 0x9BD7, 0x9BD8, 0x9BDD, 0x9BDF, 0x9BE5,
- 0x9BE7, 0x9BEA, 0x9BEB, 0x9BEF, 0x9BF3, 0x9BF7, 0x9BF8,
-};
-static const unsigned short euc_to_utf8_8FEB[] = {
- 0x9BF9, 0x9BFA, 0x9BFD, 0x9BFF, 0x9C00, 0x9C02, 0x9C0B,
- 0x9C0F, 0x9C11, 0x9C16, 0x9C18, 0x9C19, 0x9C1A, 0x9C1C, 0x9C1E,
- 0x9C22, 0x9C23, 0x9C26, 0x9C27, 0x9C28, 0x9C29, 0x9C2A, 0x9C31,
- 0x9C35, 0x9C36, 0x9C37, 0x9C3D, 0x9C41, 0x9C43, 0x9C44, 0x9C45,
- 0x9C49, 0x9C4A, 0x9C4E, 0x9C4F, 0x9C50, 0x9C53, 0x9C54, 0x9C56,
- 0x9C58, 0x9C5B, 0x9C5D, 0x9C5E, 0x9C5F, 0x9C63, 0x9C69, 0x9C6A,
- 0x9C5C, 0x9C6B, 0x9C68, 0x9C6E, 0x9C70, 0x9C72, 0x9C75, 0x9C77,
- 0x9C7B, 0x9CE6, 0x9CF2, 0x9CF7, 0x9CF9, 0x9D0B, 0x9D02, 0x9D11,
- 0x9D17, 0x9D18, 0x9D1C, 0x9D1D, 0x9D1E, 0x9D2F, 0x9D30, 0x9D32,
- 0x9D33, 0x9D34, 0x9D3A, 0x9D3C, 0x9D45, 0x9D3D, 0x9D42, 0x9D43,
- 0x9D47, 0x9D4A, 0x9D53, 0x9D54, 0x9D5F, 0x9D63, 0x9D62, 0x9D65,
- 0x9D69, 0x9D6A, 0x9D6B, 0x9D70, 0x9D76, 0x9D77, 0x9D7B,
-};
-static const unsigned short euc_to_utf8_8FEC[] = {
- 0x9D7C, 0x9D7E, 0x9D83, 0x9D84, 0x9D86, 0x9D8A, 0x9D8D,
- 0x9D8E, 0x9D92, 0x9D93, 0x9D95, 0x9D96, 0x9D97, 0x9D98, 0x9DA1,
- 0x9DAA, 0x9DAC, 0x9DAE, 0x9DB1, 0x9DB5, 0x9DB9, 0x9DBC, 0x9DBF,
- 0x9DC3, 0x9DC7, 0x9DC9, 0x9DCA, 0x9DD4, 0x9DD5, 0x9DD6, 0x9DD7,
- 0x9DDA, 0x9DDE, 0x9DDF, 0x9DE0, 0x9DE5, 0x9DE7, 0x9DE9, 0x9DEB,
- 0x9DEE, 0x9DF0, 0x9DF3, 0x9DF4, 0x9DFE, 0x9E0A, 0x9E02, 0x9E07,
- 0x9E0E, 0x9E10, 0x9E11, 0x9E12, 0x9E15, 0x9E16, 0x9E19, 0x9E1C,
- 0x9E1D, 0x9E7A, 0x9E7B, 0x9E7C, 0x9E80, 0x9E82, 0x9E83, 0x9E84,
- 0x9E85, 0x9E87, 0x9E8E, 0x9E8F, 0x9E96, 0x9E98, 0x9E9B, 0x9E9E,
- 0x9EA4, 0x9EA8, 0x9EAC, 0x9EAE, 0x9EAF, 0x9EB0, 0x9EB3, 0x9EB4,
- 0x9EB5, 0x9EC6, 0x9EC8, 0x9ECB, 0x9ED5, 0x9EDF, 0x9EE4, 0x9EE7,
- 0x9EEC, 0x9EED, 0x9EEE, 0x9EF0, 0x9EF1, 0x9EF2, 0x9EF5,
-};
-static const unsigned short euc_to_utf8_8FED[] = {
- 0x9EF8, 0x9EFF, 0x9F02, 0x9F03, 0x9F09, 0x9F0F, 0x9F10,
- 0x9F11, 0x9F12, 0x9F14, 0x9F16, 0x9F17, 0x9F19, 0x9F1A, 0x9F1B,
- 0x9F1F, 0x9F22, 0x9F26, 0x9F2A, 0x9F2B, 0x9F2F, 0x9F31, 0x9F32,
- 0x9F34, 0x9F37, 0x9F39, 0x9F3A, 0x9F3C, 0x9F3D, 0x9F3F, 0x9F41,
- 0x9F43, 0x9F44, 0x9F45, 0x9F46, 0x9F47, 0x9F53, 0x9F55, 0x9F56,
- 0x9F57, 0x9F58, 0x9F5A, 0x9F5D, 0x9F5E, 0x9F68, 0x9F69, 0x9F6D,
- 0x9F6E, 0x9F6F, 0x9F70, 0x9F71, 0x9F73, 0x9F75, 0x9F7A, 0x9F7D,
- 0x9F8F, 0x9F90, 0x9F91, 0x9F92, 0x9F94, 0x9F96, 0x9F97, 0x9F9E,
- 0x9FA1, 0x9FA2, 0x9FA3, 0x9FA5, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short euc_to_utf8_8FF3[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174,
- 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x2160, 0x2161,
-};
-static const unsigned short euc_to_utf8_8FF4[] = {
- 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168,
- 0x2169, 0xff07, 0xff02, 0x3231, 0x2116, 0x2121, 0x70bb, 0x4efc,
- 0x50f4, 0x51ec, 0x5307, 0x5324, 0xfa0e, 0x548a, 0x5759, 0xfa0f,
- 0xfa10, 0x589e, 0x5bec, 0x5cf5, 0x5d53, 0xfa11, 0x5fb7, 0x6085,
- 0x6120, 0x654e, 0x663b, 0x6665, 0xfa12, 0xf929, 0x6801, 0xfa13,
- 0xfa14, 0x6a6b, 0x6ae2, 0x6df8, 0x6df2, 0x7028, 0xfa15, 0xfa16,
- 0x7501, 0x7682, 0x769e, 0xfa17, 0x7930, 0xfa18, 0xfa19, 0xfa1a,
- 0xfa1b, 0x7ae7, 0xfa1c, 0xfa1d, 0x7da0, 0x7dd6, 0xfa1e, 0x8362,
- 0xfa1f, 0x85b0, 0xfa20, 0xfa21, 0x8807, 0xfa22, 0x8b7f, 0x8cf4,
- 0x8d76, 0xfa23, 0xfa24, 0xfa25, 0x90de, 0xfa26, 0x9115, 0xfa27,
- 0xfa28, 0x9592, 0xf9dc, 0xfa29, 0x973b, 0x974d, 0x9751, 0xfa2a,
- 0xfa2b, 0xfa2c, 0x999e, 0x9ad9, 0x9b72, 0xfa2d, 0x9ed1,
-};
-#endif /* X0212_ENABLE */
-
-const unsigned short euc_to_utf8_1byte[] = {
- 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67,
- 0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F,
- 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77,
- 0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F,
- 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87,
- 0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F,
- 0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97,
- 0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x00A9, 0x2122,
-};
-const unsigned short *const euc_to_utf8_2bytes[] = {
- euc_to_utf8_A1, euc_to_utf8_A2, euc_to_utf8_A3,
- euc_to_utf8_A4, euc_to_utf8_A5, euc_to_utf8_A6, euc_to_utf8_A7,
- euc_to_utf8_A8, euc_to_utf8_A9, euc_to_utf8_AA, euc_to_utf8_AB,
- euc_to_utf8_AC, euc_to_utf8_AD, euc_to_utf8_AE, euc_to_utf8_AF,
- euc_to_utf8_B0, euc_to_utf8_B1, euc_to_utf8_B2, euc_to_utf8_B3,
- euc_to_utf8_B4, euc_to_utf8_B5, euc_to_utf8_B6, euc_to_utf8_B7,
- euc_to_utf8_B8, euc_to_utf8_B9, euc_to_utf8_BA, euc_to_utf8_BB,
- euc_to_utf8_BC, euc_to_utf8_BD, euc_to_utf8_BE, euc_to_utf8_BF,
- euc_to_utf8_C0, euc_to_utf8_C1, euc_to_utf8_C2, euc_to_utf8_C3,
- euc_to_utf8_C4, euc_to_utf8_C5, euc_to_utf8_C6, euc_to_utf8_C7,
- euc_to_utf8_C8, euc_to_utf8_C9, euc_to_utf8_CA, euc_to_utf8_CB,
- euc_to_utf8_CC, euc_to_utf8_CD, euc_to_utf8_CE, euc_to_utf8_CF,
- euc_to_utf8_D0, euc_to_utf8_D1, euc_to_utf8_D2, euc_to_utf8_D3,
- euc_to_utf8_D4, euc_to_utf8_D5, euc_to_utf8_D6, euc_to_utf8_D7,
- euc_to_utf8_D8, euc_to_utf8_D9, euc_to_utf8_DA, euc_to_utf8_DB,
- euc_to_utf8_DC, euc_to_utf8_DD, euc_to_utf8_DE, euc_to_utf8_DF,
- euc_to_utf8_E0, euc_to_utf8_E1, euc_to_utf8_E2, euc_to_utf8_E3,
- euc_to_utf8_E4, euc_to_utf8_E5, euc_to_utf8_E6, euc_to_utf8_E7,
- euc_to_utf8_E8, euc_to_utf8_E9, euc_to_utf8_EA, euc_to_utf8_EB,
- euc_to_utf8_EC, euc_to_utf8_ED, euc_to_utf8_EE, euc_to_utf8_EF,
- euc_to_utf8_F0, euc_to_utf8_F1, euc_to_utf8_F2, euc_to_utf8_F3,
- euc_to_utf8_F4, euc_to_utf8_F5, 0, 0,
- 0, euc_to_utf8_F9, euc_to_utf8_FA, euc_to_utf8_FB,
- euc_to_utf8_FC, 0, 0,
-};
-/* Microsoft UCS Mapping Compatible */
-const unsigned short *const euc_to_utf8_2bytes_ms[] = {
- euc_to_utf8_A1_ms, euc_to_utf8_A2_ms, euc_to_utf8_A3,
- euc_to_utf8_A4, euc_to_utf8_A5, euc_to_utf8_A6, euc_to_utf8_A7,
- euc_to_utf8_A8, euc_to_utf8_A9, euc_to_utf8_AA, euc_to_utf8_AB,
- euc_to_utf8_AC, euc_to_utf8_AD, euc_to_utf8_AE, euc_to_utf8_AF,
- euc_to_utf8_B0, euc_to_utf8_B1, euc_to_utf8_B2, euc_to_utf8_B3,
- euc_to_utf8_B4, euc_to_utf8_B5, euc_to_utf8_B6, euc_to_utf8_B7,
- euc_to_utf8_B8, euc_to_utf8_B9, euc_to_utf8_BA, euc_to_utf8_BB,
- euc_to_utf8_BC, euc_to_utf8_BD, euc_to_utf8_BE, euc_to_utf8_BF,
- euc_to_utf8_C0, euc_to_utf8_C1, euc_to_utf8_C2, euc_to_utf8_C3,
- euc_to_utf8_C4, euc_to_utf8_C5, euc_to_utf8_C6, euc_to_utf8_C7,
- euc_to_utf8_C8, euc_to_utf8_C9, euc_to_utf8_CA, euc_to_utf8_CB,
- euc_to_utf8_CC, euc_to_utf8_CD, euc_to_utf8_CE, euc_to_utf8_CF,
- euc_to_utf8_D0, euc_to_utf8_D1, euc_to_utf8_D2, euc_to_utf8_D3,
- euc_to_utf8_D4, euc_to_utf8_D5, euc_to_utf8_D6, euc_to_utf8_D7,
- euc_to_utf8_D8, euc_to_utf8_D9, euc_to_utf8_DA, euc_to_utf8_DB,
- euc_to_utf8_DC, euc_to_utf8_DD, euc_to_utf8_DE, euc_to_utf8_DF,
- euc_to_utf8_E0, euc_to_utf8_E1, euc_to_utf8_E2, euc_to_utf8_E3,
- euc_to_utf8_E4, euc_to_utf8_E5, euc_to_utf8_E6, euc_to_utf8_E7,
- euc_to_utf8_E8, euc_to_utf8_E9, euc_to_utf8_EA, euc_to_utf8_EB,
- euc_to_utf8_EC, euc_to_utf8_ED, euc_to_utf8_EE, euc_to_utf8_EF,
- euc_to_utf8_F0, euc_to_utf8_F1, euc_to_utf8_F2, euc_to_utf8_F3,
- euc_to_utf8_F4, euc_to_utf8_F5, 0, 0,
- 0, euc_to_utf8_F9, euc_to_utf8_FA, euc_to_utf8_FB,
- euc_to_utf8_FC_ms, 0, 0,
-};
-/* CP10001 */
-const unsigned short *const euc_to_utf8_2bytes_mac[] = {
- euc_to_utf8_A1_ms, euc_to_utf8_A2_ms, euc_to_utf8_A3,
- euc_to_utf8_A4, euc_to_utf8_A5, euc_to_utf8_A6, euc_to_utf8_A7,
- euc_to_utf8_A8, euc_to_utf8_A9, euc_to_utf8_AA, euc_to_utf8_AB,
- euc_to_utf8_AC_mac, euc_to_utf8_AD_mac, euc_to_utf8_AE, euc_to_utf8_AF,
- euc_to_utf8_B0, euc_to_utf8_B1, euc_to_utf8_B2, euc_to_utf8_B3,
- euc_to_utf8_B4, euc_to_utf8_B5, euc_to_utf8_B6, euc_to_utf8_B7,
- euc_to_utf8_B8, euc_to_utf8_B9, euc_to_utf8_BA, euc_to_utf8_BB,
- euc_to_utf8_BC, euc_to_utf8_BD, euc_to_utf8_BE, euc_to_utf8_BF,
- euc_to_utf8_C0, euc_to_utf8_C1, euc_to_utf8_C2, euc_to_utf8_C3,
- euc_to_utf8_C4, euc_to_utf8_C5, euc_to_utf8_C6, euc_to_utf8_C7,
- euc_to_utf8_C8, euc_to_utf8_C9, euc_to_utf8_CA, euc_to_utf8_CB,
- euc_to_utf8_CC, euc_to_utf8_CD, euc_to_utf8_CE, euc_to_utf8_CF,
- euc_to_utf8_D0, euc_to_utf8_D1, euc_to_utf8_D2, euc_to_utf8_D3,
- euc_to_utf8_D4, euc_to_utf8_D5, euc_to_utf8_D6, euc_to_utf8_D7,
- euc_to_utf8_D8, euc_to_utf8_D9, euc_to_utf8_DA, euc_to_utf8_DB,
- euc_to_utf8_DC, euc_to_utf8_DD, euc_to_utf8_DE, euc_to_utf8_DF,
- euc_to_utf8_E0, euc_to_utf8_E1, euc_to_utf8_E2, euc_to_utf8_E3,
- euc_to_utf8_E4, euc_to_utf8_E5, euc_to_utf8_E6, euc_to_utf8_E7,
- euc_to_utf8_E8, euc_to_utf8_E9, euc_to_utf8_EA, euc_to_utf8_EB,
- euc_to_utf8_EC, euc_to_utf8_ED, euc_to_utf8_EE, euc_to_utf8_EF,
- euc_to_utf8_F0, euc_to_utf8_F1, euc_to_utf8_F2, euc_to_utf8_F3,
- euc_to_utf8_F4, euc_to_utf8_F5, 0, 0,
- 0, euc_to_utf8_F9, euc_to_utf8_FA, euc_to_utf8_FB,
- euc_to_utf8_FC_ms, 0, 0,
-};
-const unsigned short *const euc_to_utf8_2bytes_x0213[] = {
- euc_to_utf8_A1, euc_to_utf8_A2_x0213, euc_to_utf8_A3_x0213,
- euc_to_utf8_A4_x0213, euc_to_utf8_A5_x0213, euc_to_utf8_A6_x0213, euc_to_utf8_A7_x0213,
- euc_to_utf8_A8_x0213, euc_to_utf8_A9_x0213, euc_to_utf8_AA_x0213, euc_to_utf8_AB_x0213,
- euc_to_utf8_AC_x0213, euc_to_utf8_AD_x0213, euc_to_utf8_AE_x0213, euc_to_utf8_AF_x0213,
- euc_to_utf8_B0, euc_to_utf8_B1, euc_to_utf8_B2, euc_to_utf8_B3,
- euc_to_utf8_B4, euc_to_utf8_B5, euc_to_utf8_B6, euc_to_utf8_B7,
- euc_to_utf8_B8, euc_to_utf8_B9, euc_to_utf8_BA, euc_to_utf8_BB,
- euc_to_utf8_BC, euc_to_utf8_BD, euc_to_utf8_BE, euc_to_utf8_BF,
- euc_to_utf8_C0, euc_to_utf8_C1, euc_to_utf8_C2, euc_to_utf8_C3,
- euc_to_utf8_C4, euc_to_utf8_C5, euc_to_utf8_C6, euc_to_utf8_C7,
- euc_to_utf8_C8, euc_to_utf8_C9, euc_to_utf8_CA, euc_to_utf8_CB,
- euc_to_utf8_CC, euc_to_utf8_CD, euc_to_utf8_CE, euc_to_utf8_CF_x0213,
- euc_to_utf8_D0, euc_to_utf8_D1, euc_to_utf8_D2, euc_to_utf8_D3,
- euc_to_utf8_D4, euc_to_utf8_D5, euc_to_utf8_D6, euc_to_utf8_D7,
- euc_to_utf8_D8, euc_to_utf8_D9, euc_to_utf8_DA, euc_to_utf8_DB,
- euc_to_utf8_DC, euc_to_utf8_DD, euc_to_utf8_DE, euc_to_utf8_DF,
- euc_to_utf8_E0, euc_to_utf8_E1, euc_to_utf8_E2, euc_to_utf8_E3,
- euc_to_utf8_E4, euc_to_utf8_E5, euc_to_utf8_E6, euc_to_utf8_E7,
- euc_to_utf8_E8, euc_to_utf8_E9, euc_to_utf8_EA, euc_to_utf8_EB,
- euc_to_utf8_EC, euc_to_utf8_ED, euc_to_utf8_EE, euc_to_utf8_EF,
- euc_to_utf8_F0, euc_to_utf8_F1, euc_to_utf8_F2, euc_to_utf8_F3,
- euc_to_utf8_F4_x0213, euc_to_utf8_F5_x0213, euc_to_utf8_F6_x0213, euc_to_utf8_F7_x0213,
- euc_to_utf8_F8_x0213, euc_to_utf8_F9_x0213, euc_to_utf8_FA_x0213, euc_to_utf8_FB_x0213,
- euc_to_utf8_FC_x0213, euc_to_utf8_FD_x0213, euc_to_utf8_FE_x0213,
-};
-
-#ifdef X0212_ENABLE
-const unsigned short *const x0212_to_utf8_2bytes[] = {
- 0, euc_to_utf8_8FA2, 0,
- 0, 0, euc_to_utf8_8FA6, euc_to_utf8_8FA7,
- 0, euc_to_utf8_8FA9, euc_to_utf8_8FAA, euc_to_utf8_8FAB,
- 0, 0, 0, 0,
- euc_to_utf8_8FB0, euc_to_utf8_8FB1, euc_to_utf8_8FB2, euc_to_utf8_8FB3,
- euc_to_utf8_8FB4, euc_to_utf8_8FB5, euc_to_utf8_8FB6, euc_to_utf8_8FB7,
- euc_to_utf8_8FB8, euc_to_utf8_8FB9, euc_to_utf8_8FBA, euc_to_utf8_8FBB,
- euc_to_utf8_8FBC, euc_to_utf8_8FBD, euc_to_utf8_8FBE, euc_to_utf8_8FBF,
- euc_to_utf8_8FC0, euc_to_utf8_8FC1, euc_to_utf8_8FC2, euc_to_utf8_8FC3,
- euc_to_utf8_8FC4, euc_to_utf8_8FC5, euc_to_utf8_8FC6, euc_to_utf8_8FC7,
- euc_to_utf8_8FC8, euc_to_utf8_8FC9, euc_to_utf8_8FCA, euc_to_utf8_8FCB,
- euc_to_utf8_8FCC, euc_to_utf8_8FCD, euc_to_utf8_8FCE, euc_to_utf8_8FCF,
- euc_to_utf8_8FD0, euc_to_utf8_8FD1, euc_to_utf8_8FD2, euc_to_utf8_8FD3,
- euc_to_utf8_8FD4, euc_to_utf8_8FD5, euc_to_utf8_8FD6, euc_to_utf8_8FD7,
- euc_to_utf8_8FD8, euc_to_utf8_8FD9, euc_to_utf8_8FDA, euc_to_utf8_8FDB,
- euc_to_utf8_8FDC, euc_to_utf8_8FDD, euc_to_utf8_8FDE, euc_to_utf8_8FDF,
- euc_to_utf8_8FE0, euc_to_utf8_8FE1, euc_to_utf8_8FE2, euc_to_utf8_8FE3,
- euc_to_utf8_8FE4, euc_to_utf8_8FE5, euc_to_utf8_8FE6, euc_to_utf8_8FE7,
- euc_to_utf8_8FE8, euc_to_utf8_8FE9, euc_to_utf8_8FEA, euc_to_utf8_8FEB,
- euc_to_utf8_8FEC, euc_to_utf8_8FED, 0, 0,
- 0, 0, 0, euc_to_utf8_8FF3,
- euc_to_utf8_8FF4, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0,};
-
-const unsigned short *const x0212_to_utf8_2bytes_x0213[] = {
- euc_to_utf8_8FA1_x0213, euc_to_utf8_8FA2, euc_to_utf8_8FA3_x0213,
- euc_to_utf8_8FA4_x0213, euc_to_utf8_8FA5_x0213, euc_to_utf8_8FA6, euc_to_utf8_8FA7,
- euc_to_utf8_8FA8_x0213, euc_to_utf8_8FA9, euc_to_utf8_8FAA, euc_to_utf8_8FAB,
- euc_to_utf8_8FAC_x0213, euc_to_utf8_8FAD_x0213, euc_to_utf8_8FAE_x0213, euc_to_utf8_8FAF_x0213,
- euc_to_utf8_8FB0, euc_to_utf8_8FB1, euc_to_utf8_8FB2, euc_to_utf8_8FB3,
- euc_to_utf8_8FB4, euc_to_utf8_8FB5, euc_to_utf8_8FB6, euc_to_utf8_8FB7,
- euc_to_utf8_8FB8, euc_to_utf8_8FB9, euc_to_utf8_8FBA, euc_to_utf8_8FBB,
- euc_to_utf8_8FBC, euc_to_utf8_8FBD, euc_to_utf8_8FBE, euc_to_utf8_8FBF,
- euc_to_utf8_8FC0, euc_to_utf8_8FC1, euc_to_utf8_8FC2, euc_to_utf8_8FC3,
- euc_to_utf8_8FC4, euc_to_utf8_8FC5, euc_to_utf8_8FC6, euc_to_utf8_8FC7,
- euc_to_utf8_8FC8, euc_to_utf8_8FC9, euc_to_utf8_8FCA, euc_to_utf8_8FCB,
- euc_to_utf8_8FCC, euc_to_utf8_8FCD, euc_to_utf8_8FCE, euc_to_utf8_8FCF,
- euc_to_utf8_8FD0, euc_to_utf8_8FD1, euc_to_utf8_8FD2, euc_to_utf8_8FD3,
- euc_to_utf8_8FD4, euc_to_utf8_8FD5, euc_to_utf8_8FD6, euc_to_utf8_8FD7,
- euc_to_utf8_8FD8, euc_to_utf8_8FD9, euc_to_utf8_8FDA, euc_to_utf8_8FDB,
- euc_to_utf8_8FDC, euc_to_utf8_8FDD, euc_to_utf8_8FDE, euc_to_utf8_8FDF,
- euc_to_utf8_8FE0, euc_to_utf8_8FE1, euc_to_utf8_8FE2, euc_to_utf8_8FE3,
- euc_to_utf8_8FE4, euc_to_utf8_8FE5, euc_to_utf8_8FE6, euc_to_utf8_8FE7,
- euc_to_utf8_8FE8, euc_to_utf8_8FE9, euc_to_utf8_8FEA, euc_to_utf8_8FEB,
- euc_to_utf8_8FEC, euc_to_utf8_8FED, euc_to_utf8_8FEE_x0213, euc_to_utf8_8FEF_x0213,
- euc_to_utf8_8FF0_x0213, euc_to_utf8_8FF1_x0213, euc_to_utf8_8FF2_x0213, euc_to_utf8_8FF3_x0213,
- euc_to_utf8_8FF4_x0213, euc_to_utf8_8FF5_x0213, euc_to_utf8_8FF6_x0213, euc_to_utf8_8FF7_x0213,
- euc_to_utf8_8FF8_x0213, euc_to_utf8_8FF9_x0213, euc_to_utf8_8FFA_x0213, euc_to_utf8_8FFB_x0213,
- euc_to_utf8_8FFC_x0213, euc_to_utf8_8FFD_x0213, euc_to_utf8_8FFE_x0213,};
-#endif /* X0212_ENABLE */
-
-const unsigned short x0213_combining_chars[sizeof_x0213_combining_chars] = {
- 0x309A, 0x0300, 0x0301, 0x02E5, 0x02E9,
-};
-const unsigned short x0213_combining_table[sizeof_x0213_combining_table][3] = {
- {0x2477, 0x304B, 0x309A},
- {0x2478, 0x304D, 0x309A},
- {0x2479, 0x304F, 0x309A},
- {0x247A, 0x3051, 0x309A},
- {0x247B, 0x3053, 0x309A},
- {0x2577, 0x30AB, 0x309A},
- {0x2578, 0x30AD, 0x309A},
- {0x2579, 0x30AF, 0x309A},
- {0x257A, 0x30B1, 0x309A},
- {0x257B, 0x30B3, 0x309A},
- {0x257C, 0x30BB, 0x309A},
- {0x257D, 0x30C4, 0x309A},
- {0x257E, 0x30C8, 0x309A},
- {0x2678, 0x31F7, 0x309A},
- {0x2B44, 0x00E6, 0x0300},
- {0x2B48, 0x0254, 0x0300},
- {0x2B49, 0x0254, 0x0301},
- {0x2B4A, 0x028C, 0x0300},
- {0x2B4B, 0x028C, 0x0301},
- {0x2B4C, 0x0259, 0x0300},
- {0x2B4D, 0x0259, 0x0301},
- {0x2B4E, 0x025A, 0x0300},
- {0x2B4F, 0x025A, 0x0301},
- {0x2B65, 0x02E9, 0x02E5},
- {0x2B66, 0x02E5, 0x02E9},
-};
-const unsigned short x0213_1_surrogate_table[sizeof_x0213_1_surrogate_table][3] = {
- {0x2E22, 0xD840, 0xDC0B},
- {0x2F42, 0xD844, 0xDE3D},
- {0x2F4C, 0xD844, 0xDF1B},
- {0x2F60, 0xD845, 0xDC6E},
- {0x2F7B, 0xD846, 0xDCBD},
- {0x4F54, 0xD842, 0xDF9F},
- {0x4F63, 0xD845, 0xDEB4},
- {0x4F6E, 0xD847, 0xDE34},
- {0x753A, 0xD84C, 0xDDC4},
- {0x7572, 0xD84D, 0xDDC4},
- {0x7629, 0xD84D, 0xDF3F},
- {0x7632, 0xD84D, 0xDF63},
- {0x7660, 0xD84F, 0xDCFE},
- {0x776C, 0xD851, 0xDFF1},
- {0x787E, 0xD855, 0xDC8E},
- {0x7929, 0xD855, 0xDD0E},
- {0x7947, 0xD855, 0xDF71},
- {0x7954, 0xD856, 0xDDC4},
- {0x796E, 0xD857, 0xDDA1},
- {0x7A5D, 0xD85A, 0xDEFF},
- {0x7B33, 0xD85B, 0xDE40},
- {0x7B49, 0xD85C, 0xDCF4},
- {0x7B6C, 0xD85D, 0xDE84},
- {0x7C49, 0xD860, 0xDE77},
- {0x7C51, 0xD860, 0xDFCD},
- {0x7E66, 0xD868, 0xDD90},
-};
-const unsigned short x0213_2_surrogate_table[sizeof_x0213_2_surrogate_table][3] = {
- {0x2121, 0xD840, 0xDC89},
- {0x212B, 0xD840, 0xDCA2},
- {0x212E, 0xD840, 0xDCA4},
- {0x2136, 0xD840, 0xDDA2},
- {0x2146, 0xD840, 0xDE13},
- {0x2170, 0xD840, 0xDF2B},
- {0x2177, 0xD840, 0xDF81},
- {0x2179, 0xD840, 0xDF71},
- {0x2322, 0xD840, 0xDFF9},
- {0x2325, 0xD841, 0xDC4A},
- {0x2327, 0xD841, 0xDD09},
- {0x2331, 0xD841, 0xDDD6},
- {0x2332, 0xD841, 0xDE28},
- {0x2338, 0xD841, 0xDF4F},
- {0x233F, 0xD842, 0xDC07},
- {0x2341, 0xD842, 0xDC3A},
- {0x234A, 0xD842, 0xDCB9},
- {0x2352, 0xD842, 0xDD7C},
- {0x2353, 0xD842, 0xDD9D},
- {0x2359, 0xD842, 0xDED3},
- {0x235C, 0xD842, 0xDF1D},
- {0x2377, 0xD843, 0xDD45},
- {0x242A, 0xD843, 0xDDE1},
- {0x2431, 0xD843, 0xDE95},
- {0x2432, 0xD843, 0xDE6D},
- {0x243A, 0xD843, 0xDE64},
- {0x243D, 0xD843, 0xDF5F},
- {0x2459, 0xD844, 0xDE01},
- {0x245C, 0xD844, 0xDE55},
- {0x245E, 0xD844, 0xDE7B},
- {0x2463, 0xD844, 0xDE74},
- {0x246A, 0xD844, 0xDEE4},
- {0x246B, 0xD844, 0xDED7},
- {0x2472, 0xD844, 0xDEFD},
- {0x2474, 0xD844, 0xDF36},
- {0x2475, 0xD844, 0xDF44},
- {0x2525, 0xD844, 0xDFC4},
- {0x2532, 0xD845, 0xDC6D},
- {0x253E, 0xD845, 0xDDD7},
- {0x2544, 0xD85B, 0xDC29},
- {0x2547, 0xD845, 0xDE47},
- {0x2555, 0xD845, 0xDF06},
- {0x2556, 0xD845, 0xDF42},
- {0x257E, 0xD846, 0xDDC3},
- {0x2830, 0xD847, 0xDC56},
- {0x2837, 0xD847, 0xDD2D},
- {0x2838, 0xD847, 0xDD45},
- {0x283A, 0xD847, 0xDD78},
- {0x283B, 0xD847, 0xDD62},
- {0x283F, 0xD847, 0xDDA1},
- {0x2840, 0xD847, 0xDD9C},
- {0x2845, 0xD847, 0xDD92},
- {0x2848, 0xD847, 0xDDB7},
- {0x284A, 0xD847, 0xDDE0},
- {0x284B, 0xD847, 0xDE33},
- {0x285B, 0xD847, 0xDF1E},
- {0x2866, 0xD847, 0xDF76},
- {0x286C, 0xD847, 0xDFFA},
- {0x2C22, 0xD848, 0xDD7B},
- {0x2C2B, 0xD848, 0xDF1E},
- {0x2C30, 0xD848, 0xDFAD},
- {0x2C50, 0xD849, 0xDEF3},
- {0x2C65, 0xD84A, 0xDC5B},
- {0x2C6D, 0xD84A, 0xDCAB},
- {0x2C72, 0xD84A, 0xDD8F},
- {0x2D24, 0xD84A, 0xDEB8},
- {0x2D29, 0xD84A, 0xDF4F},
- {0x2D2A, 0xD84A, 0xDF50},
- {0x2D32, 0xD84A, 0xDF46},
- {0x2D34, 0xD84B, 0xDC1D},
- {0x2D35, 0xD84A, 0xDFA6},
- {0x2D39, 0xD84B, 0xDC24},
- {0x2D56, 0xD84B, 0xDDE1},
- {0x2D7D, 0xD84C, 0xDDC3},
- {0x2E23, 0xD84C, 0xDDF5},
- {0x2E24, 0xD84C, 0xDDB6},
- {0x2E3A, 0xD84C, 0xDF72},
- {0x2E3C, 0xD84C, 0xDFD3},
- {0x2E3D, 0xD84C, 0xDFD2},
- {0x2E42, 0xD84C, 0xDFD0},
- {0x2E43, 0xD84C, 0xDFE4},
- {0x2E44, 0xD84C, 0xDFD5},
- {0x2E47, 0xD84C, 0xDFDA},
- {0x2E49, 0xD84C, 0xDFDF},
- {0x2E55, 0xD84D, 0xDC4A},
- {0x2E56, 0xD84D, 0xDC51},
- {0x2E57, 0xD84D, 0xDC4B},
- {0x2E5B, 0xD84D, 0xDC65},
- {0x2E77, 0xD84D, 0xDCE4},
- {0x2E78, 0xD84D, 0xDD5A},
- {0x2F2A, 0xD84D, 0xDD94},
- {0x2F3F, 0xD84D, 0xDE39},
- {0x2F40, 0xD84D, 0xDE47},
- {0x2F42, 0xD84D, 0xDE38},
- {0x2F43, 0xD84D, 0xDE3A},
- {0x2F4E, 0xD84D, 0xDF1C},
- {0x2F59, 0xD84D, 0xDF0C},
- {0x2F61, 0xD84D, 0xDF64},
- {0x2F69, 0xD84D, 0xDFFF},
- {0x2F6A, 0xD84D, 0xDFE7},
- {0x2F70, 0xD84E, 0xDC24},
- {0x2F75, 0xD84E, 0xDC3D},
- {0x6E23, 0xD84E, 0xDE98},
- {0x6E34, 0xD84F, 0xDC7F},
- {0x6E49, 0xD84F, 0xDD00},
- {0x6E5C, 0xD84F, 0xDD40},
- {0x6E5E, 0xD84F, 0xDDFA},
- {0x6E5F, 0xD84F, 0xDDF9},
- {0x6E60, 0xD84F, 0xDDD3},
- {0x6F32, 0xD84F, 0xDF7E},
- {0x6F47, 0xD850, 0xDC96},
- {0x6F4D, 0xD850, 0xDD03},
- {0x6F61, 0xD850, 0xDDC6},
- {0x6F64, 0xD850, 0xDDFE},
- {0x7022, 0xD850, 0xDFBC},
- {0x7033, 0xD851, 0xDE29},
- {0x7039, 0xD851, 0xDEA5},
- {0x7053, 0xD852, 0xDC96},
- {0x707B, 0xD852, 0xDE4D},
- {0x712E, 0xD852, 0xDF56},
- {0x7130, 0xD852, 0xDF6F},
- {0x7135, 0xD853, 0xDC16},
- {0x7144, 0xD853, 0xDD14},
- {0x715D, 0xD853, 0xDE0E},
- {0x7161, 0xD853, 0xDE37},
- {0x7166, 0xD853, 0xDE6A},
- {0x7169, 0xD853, 0xDE8B},
- {0x7175, 0xD854, 0xDC4A},
- {0x7177, 0xD854, 0xDC55},
- {0x717A, 0xD854, 0xDD22},
- {0x7221, 0xD854, 0xDDA9},
- {0x7223, 0xD854, 0xDDE5},
- {0x7224, 0xD854, 0xDDCD},
- {0x7228, 0xD854, 0xDE1E},
- {0x722C, 0xD854, 0xDE4C},
- {0x723D, 0xD855, 0xDC2E},
- {0x7248, 0xD855, 0xDCD9},
- {0x725B, 0xD855, 0xDDA7},
- {0x7275, 0xD855, 0xDFA9},
- {0x7276, 0xD855, 0xDFB4},
- {0x7332, 0xD856, 0xDDD4},
- {0x733D, 0xD856, 0xDEE4},
- {0x733E, 0xD856, 0xDEE3},
- {0x7340, 0xD856, 0xDEF1},
- {0x7352, 0xD856, 0xDFB2},
- {0x735D, 0xD857, 0xDC4B},
- {0x735E, 0xD857, 0xDC64},
- {0x7373, 0xD857, 0xDE2E},
- {0x7374, 0xD857, 0xDE56},
- {0x7375, 0xD857, 0xDE65},
- {0x7377, 0xD857, 0xDE62},
- {0x737B, 0xD857, 0xDED8},
- {0x737D, 0xD857, 0xDEC2},
- {0x7422, 0xD857, 0xDEE8},
- {0x7424, 0xD857, 0xDF23},
- {0x7427, 0xD857, 0xDF5C},
- {0x742E, 0xD857, 0xDFE0},
- {0x742F, 0xD857, 0xDFD4},
- {0x7434, 0xD858, 0xDC0C},
- {0x7435, 0xD857, 0xDFFB},
- {0x743D, 0xD858, 0xDC17},
- {0x7442, 0xD858, 0xDC60},
- {0x744F, 0xD858, 0xDCED},
- {0x7469, 0xD858, 0xDE70},
- {0x746B, 0xD858, 0xDE86},
- {0x7472, 0xD858, 0xDF4C},
- {0x7475, 0xD84F, 0xDD0E},
- {0x7479, 0xD859, 0xDC02},
- {0x7535, 0xD859, 0xDE7E},
- {0x753A, 0xD859, 0xDEB0},
- {0x7546, 0xD859, 0xDF1D},
- {0x7556, 0xD85A, 0xDCDD},
- {0x7558, 0xD85A, 0xDCEA},
- {0x755A, 0xD85A, 0xDD51},
- {0x755D, 0xD85A, 0xDD6F},
- {0x755F, 0xD85A, 0xDDDD},
- {0x7563, 0xD85A, 0xDE1E},
- {0x756A, 0xD85A, 0xDE58},
- {0x7570, 0xD85A, 0xDE8C},
- {0x7573, 0xD85A, 0xDEB7},
- {0x7644, 0xD85B, 0xDC73},
- {0x764E, 0xD85B, 0xDCDD},
- {0x765D, 0xD85B, 0xDE65},
- {0x7675, 0xD85B, 0xDF94},
- {0x767E, 0xD85B, 0xDFF8},
- {0x7721, 0xD85B, 0xDFF6},
- {0x7722, 0xD85B, 0xDFF7},
- {0x7733, 0xD85C, 0xDD0D},
- {0x7736, 0xD85C, 0xDD39},
- {0x7764, 0xD85C, 0xDFDB},
- {0x7765, 0xD85C, 0xDFDA},
- {0x776B, 0xD85C, 0xDFFE},
- {0x776E, 0xD85D, 0xDC10},
- {0x7773, 0xD85D, 0xDC49},
- {0x7829, 0xD85D, 0xDE15},
- {0x782A, 0xD85D, 0xDE14},
- {0x782C, 0xD85D, 0xDE31},
- {0x7834, 0xD85D, 0xDE93},
- {0x783C, 0xD85D, 0xDF0E},
- {0x783E, 0xD85D, 0xDF23},
- {0x7842, 0xD85D, 0xDF52},
- {0x7856, 0xD85E, 0xDD85},
- {0x7863, 0xD85E, 0xDE84},
- {0x7877, 0xD85E, 0xDFB3},
- {0x7879, 0xD85E, 0xDFBE},
- {0x787A, 0xD85E, 0xDFC7},
- {0x7925, 0xD85F, 0xDCB8},
- {0x792F, 0xD85F, 0xDDA0},
- {0x7932, 0xD85F, 0xDE10},
- {0x7939, 0xD85F, 0xDFB7},
- {0x7942, 0xD860, 0xDC8A},
- {0x7948, 0xD860, 0xDCBB},
- {0x7959, 0xD860, 0xDE82},
- {0x795E, 0xD860, 0xDEF3},
- {0x7966, 0xD861, 0xDC0C},
- {0x796B, 0xD861, 0xDC55},
- {0x797A, 0xD861, 0xDD6B},
- {0x797E, 0xD861, 0xDDC8},
- {0x7A21, 0xD861, 0xDDC9},
- {0x7A2C, 0xD861, 0xDED7},
- {0x7A2F, 0xD861, 0xDEFA},
- {0x7A4F, 0xD862, 0xDD49},
- {0x7A50, 0xD862, 0xDD46},
- {0x7A57, 0xD862, 0xDD6B},
- {0x7A65, 0xD862, 0xDD87},
- {0x7A66, 0xD862, 0xDD88},
- {0x7A71, 0xD862, 0xDDBA},
- {0x7A72, 0xD862, 0xDDBB},
- {0x7A7E, 0xD862, 0xDE1E},
- {0x7B21, 0xD862, 0xDE29},
- {0x7B2C, 0xD862, 0xDE71},
- {0x7B2D, 0xD862, 0xDE43},
- {0x7B36, 0xD862, 0xDE99},
- {0x7B37, 0xD862, 0xDECD},
- {0x7B3D, 0xD862, 0xDEE4},
- {0x7B3E, 0xD862, 0xDEDD},
- {0x7B4E, 0xD862, 0xDFC1},
- {0x7B4F, 0xD862, 0xDFEF},
- {0x7B57, 0xD863, 0xDD10},
- {0x7B5A, 0xD863, 0xDD71},
- {0x7B5C, 0xD863, 0xDDFB},
- {0x7B5D, 0xD863, 0xDE1F},
- {0x7B61, 0xD863, 0xDE36},
- {0x7B65, 0xD863, 0xDE89},
- {0x7B67, 0xD863, 0xDEEB},
- {0x7B69, 0xD863, 0xDF32},
- {0x7B71, 0xD863, 0xDFF8},
- {0x7C22, 0xD864, 0xDEA0},
- {0x7C23, 0xD864, 0xDEB1},
- {0x7C38, 0xD865, 0xDC90},
- {0x7C42, 0xD865, 0xDDCF},
- {0x7C4C, 0xD865, 0xDE7F},
- {0x7C56, 0xD865, 0xDEF0},
- {0x7C59, 0xD865, 0xDF19},
- {0x7C5D, 0xD865, 0xDF50},
- {0x7C76, 0xD866, 0xDCC6},
- {0x7D2C, 0xD866, 0xDE72},
- {0x7D4B, 0xD867, 0xDDDB},
- {0x7D4C, 0xD867, 0xDE3D},
- {0x7D59, 0xD867, 0xDE15},
- {0x7D5B, 0xD867, 0xDE8A},
- {0x7D5D, 0xD867, 0xDE49},
- {0x7D67, 0xD867, 0xDEC4},
- {0x7D6D, 0xD867, 0xDEE9},
- {0x7D70, 0xD867, 0xDEDB},
- {0x7E25, 0xD867, 0xDFCE},
- {0x7E29, 0xD868, 0xDC2F},
- {0x7E2B, 0xD868, 0xDC1A},
- {0x7E32, 0xD868, 0xDCF9},
- {0x7E35, 0xD868, 0xDC82},
- {0x7E53, 0xD848, 0xDE18},
- {0x7E58, 0xD868, 0xDF8C},
- {0x7E5A, 0xD869, 0xDC37},
- {0x7E6E, 0xD869, 0xDDF1},
- {0x7E70, 0xD869, 0xDE02},
- {0x7E72, 0xD869, 0xDE1A},
- {0x7E76, 0xD869, 0xDEB2},
-};
-#endif /* UTF8_OUTPUT_ENABLE */
-
-#ifdef UTF8_INPUT_ENABLE
-static const unsigned short utf8_to_euc_C2[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xA242, 0x2171, 0x2172, 0xA270, 0x216F, 0xA243, 0x2178,
- 0x212F, 0xA26D, 0xA26C, 0, 0x224C, 0, 0xA26E, 0xA234,
- 0x216B, 0x215E, 0, 0, 0x212D, 0, 0x2279, 0,
- 0xA231, 0, 0xA26B, 0, 0, 0, 0, 0xA244,
-};
-static const unsigned short utf8_to_euc_C2_ms[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xA242, 0x2171, 0x2172, 0xA270, 0x5C, 0xA243, 0x2178,
- 0x212F, 0xA26D, 0xA26C, 0, 0x224C, 0, 0xA26E, 0xA234,
- 0x216B, 0x215E, 0, 0, 0x212D, 0, 0x2279, 0,
- 0xA231, 0, 0xA26B, 0, 0, 0, 0, 0xA244,
-};
-static const unsigned short utf8_to_euc_C2_mac[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x00A0, 0xA242, 0x2171, 0x2172, 0xA270, 0x5C, 0xA243, 0x2178,
- 0x212F, 0x00FD, 0xA26C, 0, 0x224C, 0, 0xA26E, 0xA234,
- 0x216B, 0x215E, 0, 0, 0x212D, 0, 0x2279, 0,
- 0xA231, 0, 0xA26B, 0, 0, 0, 0, 0xA244,
-};
-static const unsigned short utf8_to_euc_C2_932[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x21, 0x2171, 0x2172, 0, 0x5C, 0x7C, 0x2178,
- 0x212F, 0x63, 0x61, 0x2263, 0x224C, 0x2D, 0x52, 0x2131,
- 0x216B, 0x215E, 0x32, 0x33, 0x212D, 0x264C, 0x2279, 0x2126,
- 0x2124, 0x31, 0x6F, 0x2264, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_C2_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2922, 0x2923, 0x2171, 0x2172, 0x2924, 0x216F, 0x2925, 0x2178,
- 0x212F, 0x2926, 0x2927, 0x2928, 0x224C, 0x2929, 0x292A, 0x292B,
- 0x216B, 0x215E, 0x292C, 0x292D, 0x212D, 0, 0x2279, 0x292E,
- 0x292F, 0x2930, 0x2931, 0x2932, 0x2933, 0x2934, 0x2935, 0x2936,
-};
-static const unsigned short utf8_to_euc_C3[] = {
- 0xAA22, 0xAA21, 0xAA24, 0xAA2A, 0xAA23, 0xAA29, 0xA921, 0xAA2E,
- 0xAA32, 0xAA31, 0xAA34, 0xAA33, 0xAA40, 0xAA3F, 0xAA42, 0xAA41,
- 0, 0xAA50, 0xAA52, 0xAA51, 0xAA54, 0xAA58, 0xAA53, 0x215F,
- 0xA92C, 0xAA63, 0xAA62, 0xAA65, 0xAA64, 0xAA72, 0xA930, 0xA94E,
- 0xAB22, 0xAB21, 0xAB24, 0xAB2A, 0xAB23, 0xAB29, 0xA941, 0xAB2E,
- 0xAB32, 0xAB31, 0xAB34, 0xAB33, 0xAB40, 0xAB3F, 0xAB42, 0xAB41,
- 0xA943, 0xAB50, 0xAB52, 0xAB51, 0xAB54, 0xAB58, 0xAB53, 0x2160,
- 0xA94C, 0xAB63, 0xAB62, 0xAB65, 0xAB64, 0xAB72, 0xA950, 0xAB73,
-};
-static const unsigned short utf8_to_euc_C3_932[] = {
- 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x43,
- 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49,
- 0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x215F,
- 0x4F, 0x55, 0x55, 0x55, 0x55, 0x59, 0x54, 0x73,
- 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x63,
- 0x65, 0x65, 0x65, 0x65, 0x69, 0x69, 0x69, 0x69,
- 0x64, 0x6E, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x2160,
- 0x6F, 0x75, 0x75, 0x75, 0x75, 0x79, 0x74, 0x79,
-};
-static const unsigned short utf8_to_euc_C3_x0213[] = {
- 0x2937, 0x2938, 0x2939, 0x293A, 0x293B, 0x293C, 0x293D, 0x293E,
- 0x293F, 0x2940, 0x2941, 0x2942, 0x2943, 0x2944, 0x2945, 0x2946,
- 0x2947, 0x2948, 0x2949, 0x294A, 0x294B, 0x294C, 0x294D, 0x215F,
- 0x294E, 0x294F, 0x2950, 0x2951, 0x2952, 0x2953, 0x2954, 0x2955,
- 0x2956, 0x2957, 0x2958, 0x2959, 0x295A, 0x295B, 0x295C, 0x295D,
- 0x295E, 0x295F, 0x2960, 0x2961, 0x2962, 0x2963, 0x2964, 0x2965,
- 0x2966, 0x2967, 0x2968, 0x2969, 0x296A, 0x296B, 0x296C, 0x2160,
- 0x296D, 0x296E, 0x296F, 0x2970, 0x2971, 0x2972, 0x2973, 0x2974,
-};
-static const unsigned short utf8_to_euc_C4[] = {
- 0xAA27, 0xAB27, 0xAA25, 0xAB25, 0xAA28, 0xAB28, 0xAA2B, 0xAB2B,
- 0xAA2C, 0xAB2C, 0xAA2F, 0xAB2F, 0xAA2D, 0xAB2D, 0xAA30, 0xAB30,
- 0xA922, 0xA942, 0xAA37, 0xAB37, 0, 0, 0xAA36, 0xAB36,
- 0xAA38, 0xAB38, 0xAA35, 0xAB35, 0xAA3A, 0xAB3A, 0xAA3B, 0xAB3B,
- 0xAA3D, 0xAB3D, 0xAA3C, 0, 0xAA3E, 0xAB3E, 0xA924, 0xA944,
- 0xAA47, 0xAB47, 0xAA45, 0xAB45, 0, 0, 0xAA46, 0xAB46,
- 0xAA44, 0xA945, 0xA926, 0xA946, 0xAA48, 0xAB48, 0xAA49, 0xAB49,
- 0xA947, 0xAA4A, 0xAB4A, 0xAA4C, 0xAB4C, 0xAA4B, 0xAB4B, 0xA929,
-};
-static const unsigned short utf8_to_euc_C4_x0213[] = {
- 0x2975, 0x297A, 0x2A3A, 0x2A49, 0x2A21, 0x2A2C, 0x2A3C, 0x2A4B,
- 0x2A59, 0x2A5F, 0xAA2F, 0xAB2F, 0x2A3D, 0x2A4C, 0x2A40, 0x2A4F,
- 0xA922, 0x2A50, 0x2978, 0x297D, 0, 0, 0xAA36, 0xAB36,
- 0x2A3E, 0x2A4D, 0x2A3F, 0x2A4E, 0x2A5A, 0x2A60, 0xAA3B, 0xAB3B,
- 0xAA3D, 0xAB3D, 0xAA3C, 0, 0x2A5B, 0x2A61, 0xA924, 0x2A7D,
- 0xAA47, 0xAB47, 0x2976, 0x297B, 0, 0, 0xAA46, 0xAB46,
- 0xAA44, 0xA945, 0xA926, 0xA946, 0x2A5C, 0x2A62, 0xAA49, 0xAB49,
- 0xA947, 0x2A3B, 0x2A4A, 0xAA4C, 0xAB4C, 0x2A24, 0x2A2F, 0xA929,
-};
-static const unsigned short utf8_to_euc_C5[] = {
- 0xA949, 0xA928, 0xA948, 0xAA4D, 0xAB4D, 0xAA4F, 0xAB4F, 0xAA4E,
- 0xAB4E, 0xA94A, 0xA92B, 0xA94B, 0xAA57, 0xAB57, 0, 0,
- 0xAA56, 0xAB56, 0xA92D, 0xA94D, 0xAA59, 0xAB59, 0xAA5B, 0xAB5B,
- 0xAA5A, 0xAB5A, 0xAA5C, 0xAB5C, 0xAA5D, 0xAB5D, 0xAA5F, 0xAB5F,
- 0xAA5E, 0xAB5E, 0xAA61, 0xAB61, 0xAA60, 0xAB60, 0xA92F, 0xA94F,
- 0xAA6C, 0xAB6C, 0xAA69, 0xAB69, 0xAA66, 0xAB66, 0xAA6B, 0xAB6B,
- 0xAA68, 0xAB68, 0xAA6A, 0xAB6A, 0xAA71, 0xAB71, 0xAA74, 0xAB74,
- 0xAA73, 0xAA75, 0xAB75, 0xAA77, 0xAB77, 0xAA76, 0xAB76, 0,
-};
-static const unsigned short utf8_to_euc_C5_x0213[] = {
- 0xA949, 0x2A23, 0x2A2E, 0x2A41, 0x2A51, 0xAA4F, 0xAB4F, 0x2A42,
- 0x2A52, 0xA94A, 0xA92B, 0x2A7A, 0x2979, 0x297E, 0, 0,
- 0x2A43, 0x2A53, 0x2B2B, 0x2B2A, 0x2A39, 0x2A48, 0xAA5B, 0xAB5B,
- 0x2A44, 0x2A54, 0x2A25, 0x2A30, 0x2A5D, 0x2A63, 0x2A27, 0x2A33,
- 0x2A26, 0x2A32, 0x2A47, 0x2A57, 0x2A28, 0x2A34, 0xA92F, 0xA94F,
- 0xAA6C, 0xAB6C, 0x2977, 0x297C, 0x2A5E, 0x2A64, 0x2A45, 0x2A55,
- 0x2A46, 0x2A56, 0xAA6A, 0xAB6A, 0xAA71, 0xAB71, 0xAA74, 0xAB74,
- 0xAA73, 0x2A29, 0x2A35, 0x2A2B, 0x2A38, 0x2A2A, 0x2A37, 0,
-};
-static const unsigned short utf8_to_euc_C6_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x2B29, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_C7[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xAA26, 0xAB26, 0xAA43,
- 0xAB43, 0xAA55, 0xAB55, 0xAA67, 0xAB67, 0xAA70, 0xAB70, 0xAA6D,
- 0xAB6D, 0xAA6F, 0xAB6F, 0xAA6E, 0xAB6E, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xAB39, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_C7_x0213[] = {
- 0, 0, 0x2B24, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x286F, 0x2870, 0xAA43,
- 0x2871, 0x2876, 0x2877, 0xAA67, 0x2878, 0xAA70, 0x2879, 0xAA6D,
- 0x287A, 0xAA6F, 0x287B, 0xAA6E, 0x287C, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xAB39, 0, 0,
- 0x2874, 0x2875, 0, 0, 0, 0x2B45, 0, 0,
-};
-static const unsigned short utf8_to_euc_C9_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2B33, 0x2B39, 0x2B3A, 0x2B25, 0x2B38, 0x2B3F, 0x2A6E, 0x2B26,
- 0x2B2E, 0x2B30, 0x2B43, 0, 0x2B31, 0, 0x2B32, 0x2A75,
- 0x2B28, 0x2A79, 0, 0, 0x2B36, 0x2B3C, 0x2B22, 0x2B42,
- 0x2B2C, 0, 0, 0, 0x2A6A, 0x2A74, 0x2A6B, 0x2B34,
- 0x2A7B, 0x2A65, 0x2A76, 0x2A6F, 0, 0x2B2F, 0, 0,
- 0, 0x2A6C, 0x2B41, 0x2A73, 0, 0x2A70, 0x2A67, 0,
-};
-static const unsigned short utf8_to_euc_CA_x0213[] = {
- 0, 0x2A7C, 0x2A71, 0x2A68, 0x2B27, 0, 0, 0,
- 0x2A6D, 0x2B2D, 0x2B35, 0x2A66, 0x2B37, 0x2B3B, 0x2A78, 0,
- 0x2A72, 0x2B40, 0x2A69, 0, 0x2B21, 0x2A7E, 0, 0,
- 0x2B23, 0, 0, 0, 0, 0x2A77, 0, 0,
- 0, 0x2B3E, 0x2B3D, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_CB[] = {
- 0, 0, 0, 0, 0, 0, 0, 0xA230,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xA22F, 0xA232, 0xA236, 0xA235, 0, 0xA233, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_CB_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0x2A31,
- 0x2B53, 0, 0, 0, 0x2B54, 0, 0, 0,
- 0x2B55, 0x2B56, 0, 0, 0, 0, 0, 0,
- 0x2A22, 0x2A58, 0xA236, 0x2A2D, 0, 0x2A36, 0x2B71, 0,
- 0, 0, 0, 0, 0, 0x2B60, 0x2B61, 0x2B62,
- 0x2B63, 0x2B64, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_CC_x0213[] = {
- 0x2B5C, 0x2B5A, 0x2B5F, 0x2B7D, 0x2B5B, 0, 0x2B57, 0,
- 0x2B6D, 0, 0, 0x2B59, 0x2B5E, 0, 0, 0x2B5D,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2B78, 0x2B79, 0x2B7E, 0, 0x2B6A, 0x2B76, 0x2B77, 0x2B6B,
- 0x2B6C, 0, 0, 0, 0x2B72, 0x2B67, 0, 0,
- 0, 0x2B6F, 0x2B7A, 0, 0x2B68, 0, 0, 0x2B70,
- 0x2B73, 0, 0, 0, 0x2B75, 0, 0, 0,
- 0, 0x2B69, 0x2B7B, 0x2B7C, 0x2B74, 0x2B6E, 0, 0,
-};
-static const unsigned short utf8_to_euc_CD_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x2B52, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_CE[] = {
- 0, 0, 0, 0, 0xA238, 0xA239, 0xA661, 0,
- 0xA662, 0xA663, 0xA664, 0, 0xA667, 0, 0xA669, 0xA66C,
- 0xA676, 0x2621, 0x2622, 0x2623, 0x2624, 0x2625, 0x2626, 0x2627,
- 0x2628, 0x2629, 0x262A, 0x262B, 0x262C, 0x262D, 0x262E, 0x262F,
- 0x2630, 0x2631, 0, 0x2632, 0x2633, 0x2634, 0x2635, 0x2636,
- 0x2637, 0x2638, 0xA665, 0xA66A, 0xA671, 0xA672, 0xA673, 0xA674,
- 0xA67B, 0x2641, 0x2642, 0x2643, 0x2644, 0x2645, 0x2646, 0x2647,
- 0x2648, 0x2649, 0x264A, 0x264B, 0x264C, 0x264D, 0x264E, 0x264F,
-};
-static const unsigned short utf8_to_euc_CF[] = {
- 0x2650, 0x2651, 0xA678, 0x2652, 0x2653, 0x2654, 0x2655, 0x2656,
- 0x2657, 0x2658, 0xA675, 0xA67A, 0xA677, 0xA679, 0xA67C, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_CF_x0213[] = {
- 0x2650, 0x2651, 0x2659, 0x2652, 0x2653, 0x2654, 0x2655, 0x2656,
- 0x2657, 0x2658, 0xA675, 0xA67A, 0xA677, 0xA679, 0xA67C, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_D0[] = {
- 0, 0x2727, 0xA742, 0xA743, 0xA744, 0xA745, 0xA746, 0xA747,
- 0xA748, 0xA749, 0xA74A, 0xA74B, 0xA74C, 0, 0xA74D, 0xA74E,
- 0x2721, 0x2722, 0x2723, 0x2724, 0x2725, 0x2726, 0x2728, 0x2729,
- 0x272A, 0x272B, 0x272C, 0x272D, 0x272E, 0x272F, 0x2730, 0x2731,
- 0x2732, 0x2733, 0x2734, 0x2735, 0x2736, 0x2737, 0x2738, 0x2739,
- 0x273A, 0x273B, 0x273C, 0x273D, 0x273E, 0x273F, 0x2740, 0x2741,
- 0x2751, 0x2752, 0x2753, 0x2754, 0x2755, 0x2756, 0x2758, 0x2759,
- 0x275A, 0x275B, 0x275C, 0x275D, 0x275E, 0x275F, 0x2760, 0x2761,
-};
-static const unsigned short utf8_to_euc_D1[] = {
- 0x2762, 0x2763, 0x2764, 0x2765, 0x2766, 0x2767, 0x2768, 0x2769,
- 0x276A, 0x276B, 0x276C, 0x276D, 0x276E, 0x276F, 0x2770, 0x2771,
- 0, 0x2757, 0xA772, 0xA773, 0xA774, 0xA775, 0xA776, 0xA777,
- 0xA778, 0xA779, 0xA77A, 0xA77B, 0xA77C, 0, 0xA77D, 0xA77E,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E1B8_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x2872, 0x2873,
-};
-static const unsigned short utf8_to_euc_E1BD_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2B46, 0x2B47, 0x2B50, 0x2B51, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E280[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x213E, 0, 0, 0, 0x213D, 0x213D, 0x2142, 0,
- 0x2146, 0x2147, 0, 0, 0x2148, 0x2149, 0, 0,
- 0x2277, 0x2278, 0, 0, 0, 0x2145, 0x2144, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2273, 0, 0x216C, 0x216D, 0, 0, 0, 0,
- 0, 0, 0, 0x2228, 0, 0, 0x2131, 0,
-};
-static const unsigned short utf8_to_euc_E280_ms[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x213E, 0, 0, 0, 0x213D, 0x213D, 0x2142, 0,
- 0x2146, 0x2147, 0, 0, 0x2148, 0x2149, 0, 0,
- 0x2277, 0x2278, 0, 0, 0, 0x2145, 0x2144, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2273, 0, 0x216C, 0x216D, 0, 0, 0, 0,
- 0, 0, 0, 0x2228, 0, 0, 0x7E, 0,
-};
-static const unsigned short utf8_to_euc_E280_932[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x213E, 0, 0, 0, 0, 0x213D, 0, 0,
- 0x2146, 0x2147, 0, 0, 0x2148, 0x2149, 0, 0,
- 0x2277, 0x2278, 0, 0, 0, 0x2145, 0x2144, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2273, 0, 0x216C, 0x216D, 0, 0, 0, 0,
- 0, 0, 0, 0x2228, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E280_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x213E, 0, 0, 0x237C, 0x213D, 0x213D, 0x2142, 0,
- 0x2146, 0x2147, 0, 0, 0x2148, 0x2149, 0, 0,
- 0x2277, 0x2278, 0x2340, 0, 0, 0x2145, 0x2144, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2273, 0, 0x216C, 0x216D, 0, 0, 0, 0,
- 0, 0, 0, 0x2228, 0x286B, 0, 0x2131, 0x2B58,
-};
-static const unsigned short utf8_to_euc_E281_x0213[] = {
- 0, 0, 0x2C7E, 0, 0, 0, 0, 0x286C,
- 0x286D, 0x286E, 0, 0, 0, 0, 0, 0,
- 0, 0x2C7D, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E282_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x2921, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E284[] = {
- 0, 0, 0, 0x216E, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x2D62, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x2D64, 0xA26F, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x2272, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E284_mac[] = {
- 0, 0, 0, 0x216E, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x2B7B, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x2B7D, 0x00FE, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x2272, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E284_x0213[] = {
- 0, 0, 0, 0x216E, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x235D,
- 0, 0, 0, 0x235F, 0, 0, 0x2D62, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x2D64, 0xA26F, 0, 0, 0, 0, 0x2360,
- 0, 0, 0, 0x2272, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x235C, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E285[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2D35, 0x2D36, 0x2D37, 0x2D38, 0x2D39, 0x2D3A, 0x2D3B, 0x2D3C,
- 0x2D3D, 0x2D3E, 0, 0, 0, 0, 0, 0,
- 0xF373, 0xF374, 0xF375, 0xF376, 0xF377, 0xF378, 0xF379, 0xF37A,
- 0xF37B, 0xF37C, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E285_mac[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2A21, 0x2A22, 0x2A23, 0x2A24, 0x2A25, 0x2A26, 0x2A27, 0x2A28,
- 0x2A29, 0x2A2A, 0, 0, 0, 0, 0, 0,
- 0x2A35, 0x2A36, 0x2A37, 0x2A38, 0x2A39, 0x2A3A, 0x2A3B, 0x2A3C,
- 0x2A3D, 0x2A3E, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E285_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x2778, 0x2779, 0x277A, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2D35, 0x2D36, 0x2D37, 0x2D38, 0x2D39, 0x2D3A, 0x2D3B, 0x2D3C,
- 0x2D3D, 0x2D3E, 0x2D3F, 0x2D57, 0, 0, 0, 0,
- 0x2C35, 0x2C36, 0x2C37, 0x2C38, 0x2C39, 0x2C3A, 0x2C3B, 0x2C3C,
- 0x2C3D, 0x2C3E, 0x2C3F, 0x2C40, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E286[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x222B, 0x222C, 0x222A, 0x222D, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E286_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x222B, 0x222C, 0x222A, 0x222D, 0x2271, 0, 0x2327, 0x2325,
- 0x2326, 0x2328, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E287[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x224D, 0, 0x224E, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E287_x0213[] = {
- 0, 0, 0, 0, 0x2329, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x224D, 0, 0x224E, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x232B, 0x232C,
- 0x232A, 0x232D, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E288[] = {
- 0x224F, 0, 0x225F, 0x2250, 0, 0, 0, 0x2260,
- 0x223A, 0, 0, 0x223B, 0, 0, 0, 0,
- 0, 0x2D74, 0x215D, 0, 0, 0, 0, 0,
- 0, 0, 0x2265, 0, 0, 0x2267, 0x2167, 0x2D78,
- 0x225C, 0, 0, 0, 0, 0x2142, 0, 0x224A,
- 0x224B, 0x2241, 0x2240, 0x2269, 0x226A, 0, 0x2D73, 0,
- 0, 0, 0, 0, 0x2168, 0x2268, 0, 0,
- 0, 0, 0, 0, 0, 0x2266, 0, 0,
-};
-static const unsigned short utf8_to_euc_E288_932[] = {
- 0x224F, 0, 0x225F, 0x2250, 0, 0, 0, 0x2260,
- 0x223A, 0, 0, 0x223B, 0, 0, 0, 0,
- 0, 0x2D74, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x2265, 0, 0, 0x2267, 0x2167, 0x2D78,
- 0x225C, 0, 0, 0, 0, 0x2142, 0, 0x224A,
- 0x224B, 0x2241, 0x2240, 0x2269, 0x226A, 0, 0x2D73, 0,
- 0, 0, 0, 0, 0x2168, 0x2268, 0, 0,
- 0, 0, 0, 0, 0, 0x2266, 0, 0,
-};
-static const unsigned short utf8_to_euc_E288_mac[] = {
- 0x224F, 0, 0x225F, 0x2250, 0, 0, 0, 0x2260,
- 0x223A, 0, 0, 0x223B, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x2265, 0, 0, 0x2267, 0x2167, 0x2F22,
- 0x225C, 0, 0, 0, 0, 0x2142, 0, 0x224A,
- 0x224B, 0x2241, 0x2240, 0x2269, 0x226A, 0, 0x2F21, 0,
- 0, 0, 0, 0, 0x2168, 0x2268, 0, 0,
- 0, 0, 0, 0, 0, 0x2266, 0, 0,
-};
-static const unsigned short utf8_to_euc_E288_x0213[] = {
- 0x224F, 0, 0x225F, 0x2250, 0, 0x2247, 0, 0x2260,
- 0x223A, 0x2246, 0, 0x223B, 0, 0, 0, 0,
- 0, 0x2D74, 0x215D, 0x235B, 0, 0, 0, 0,
- 0, 0, 0x2265, 0, 0, 0x2267, 0x2167, 0x2D78,
- 0x225C, 0, 0, 0, 0, 0x2254, 0x2255, 0x224A,
- 0x224B, 0x2241, 0x2240, 0x2269, 0x226A, 0, 0x2D73, 0,
- 0, 0, 0, 0, 0x2168, 0x2268, 0, 0,
- 0, 0, 0, 0, 0, 0x2266, 0, 0,
-};
-static const unsigned short utf8_to_euc_E289[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x2262, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2162, 0x2261, 0, 0, 0, 0, 0x2165, 0x2166,
- 0, 0, 0x2263, 0x2264, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E289_x0213[] = {
- 0, 0, 0, 0x226C, 0, 0x226D, 0, 0,
- 0x226E, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x2262, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2162, 0x2261, 0x226B, 0, 0, 0, 0x2165, 0x2166,
- 0, 0, 0x2263, 0x2264, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x226F, 0x2270,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E28A[] = {
- 0, 0, 0x223E, 0x223F, 0, 0, 0x223C, 0x223D,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x225D, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x2D79,
-};
-static const unsigned short utf8_to_euc_E28A_mac[] = {
- 0, 0, 0x223E, 0x223F, 0, 0, 0x223C, 0x223D,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x225D, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x2F23,
-};
-static const unsigned short utf8_to_euc_E28A_x0213[] = {
- 0, 0, 0x223E, 0x223F, 0x2242, 0x2243, 0x223C, 0x223D,
- 0, 0, 0x2244, 0x2245, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x2251, 0x2252, 0x2253,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x225D, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x2D79,
-};
-static const unsigned short utf8_to_euc_E28B_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x2776, 0x2777, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E28C[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x225E, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E28C_x0213[] = {
- 0, 0, 0, 0, 0, 0x2248, 0x2249, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x225E, 0, 0, 0, 0, 0,
- 0x277C, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E28E_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x2742, 0x2743,
-};
-static const unsigned short utf8_to_euc_E28F_x0213[] = {
- 0x2744, 0x2745, 0x2746, 0x2747, 0x2748, 0x2749, 0x274A, 0x274B,
- 0x274C, 0x274D, 0x274E, 0x274F, 0x2750, 0, 0x277E, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E290_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x277D, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E291[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2D21, 0x2D22, 0x2D23, 0x2D24, 0x2D25, 0x2D26, 0x2D27, 0x2D28,
- 0x2D29, 0x2D2A, 0x2D2B, 0x2D2C, 0x2D2D, 0x2D2E, 0x2D2F, 0x2D30,
- 0x2D31, 0x2D32, 0x2D33, 0x2D34, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E291_mac[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2921, 0x2922, 0x2923, 0x2924, 0x2925, 0x2926, 0x2927, 0x2928,
- 0x2929, 0x292A, 0x292B, 0x292C, 0x292D, 0x292E, 0x292F, 0x2930,
- 0x2931, 0x2932, 0x2933, 0x2934, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E293_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2C41, 0x2C42, 0x2C43, 0x2C44, 0x2C45, 0x2C46, 0x2C47, 0x2C48,
- 0x2C49, 0x2C4A, 0x2C4B, 0x2C4C, 0x2C4D, 0x2C4E, 0x2C4F, 0x2C50,
- 0x2C51, 0x2C52, 0x2C53, 0x2C54, 0x2C55, 0x2C56, 0x2C57, 0x2C58,
- 0x2C59, 0x2C5A, 0, 0x2C2B, 0x2C2C, 0x2C2D, 0x2C2E, 0x2C2F,
- 0x2C30, 0x2C31, 0x2C32, 0x2C33, 0x2C34, 0x265A, 0x265B, 0x265C,
- 0x265D, 0x265E, 0x265F, 0x2660, 0x2661, 0x2662, 0x2663, 0,
-};
-static const unsigned short utf8_to_euc_E294[] = {
- 0x2821, 0x282C, 0x2822, 0x282D, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x2823, 0, 0, 0x282E,
- 0x2824, 0, 0, 0x282F, 0x2826, 0, 0, 0x2831,
- 0x2825, 0, 0, 0x2830, 0x2827, 0x283C, 0, 0,
- 0x2837, 0, 0, 0x2832, 0x2829, 0x283E, 0, 0,
- 0x2839, 0, 0, 0x2834, 0x2828, 0, 0, 0x2838,
- 0x283D, 0, 0, 0x2833, 0x282A, 0, 0, 0x283A,
- 0x283F, 0, 0, 0x2835, 0x282B, 0, 0, 0x283B,
-};
-static const unsigned short utf8_to_euc_E295[] = {
- 0, 0, 0x2840, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x2836, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E296[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2223, 0x2222, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x2225, 0x2224, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x2227, 0x2226, 0, 0,
-};
-static const unsigned short utf8_to_euc_E296_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2223, 0x2222, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x266D, 0x2225, 0x2224, 0, 0, 0x2322, 0x2321,
- 0, 0, 0, 0, 0x2227, 0x2226, 0, 0,
-};
-static const unsigned short utf8_to_euc_E297[] = {
- 0, 0, 0, 0, 0, 0, 0x2221, 0x217E,
- 0, 0, 0, 0x217B, 0, 0, 0x217D, 0x217C,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x227E,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E297_x0213[] = {
- 0x2324, 0x2323, 0, 0, 0, 0, 0x2221, 0x217E,
- 0, 0x233B, 0, 0x217B, 0, 0, 0x217D, 0x217C,
- 0x2867, 0x2868, 0x2869, 0x286A, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x233F, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x227E,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E298[] = {
- 0, 0, 0, 0, 0, 0x217A, 0x2179, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E298_x0213[] = {
- 0x2668, 0x2669, 0x266A, 0x266B, 0, 0x217A, 0x2179, 0,
- 0, 0, 0, 0, 0, 0, 0x2667, 0,
- 0, 0, 0, 0, 0, 0, 0x2664, 0x2665,
- 0, 0, 0, 0, 0, 0, 0x2D7E, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E299[] = {
- 0x216A, 0, 0x2169, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x2276, 0, 0, 0x2275, 0, 0x2274,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E299_x0213[] = {
- 0x216A, 0, 0x2169, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x263A, 0x263D, 0x263B, 0x2640, 0x2639, 0x263E, 0x263C, 0x263F,
- 0x266C, 0x227D, 0x2276, 0x227B, 0x227C, 0x2275, 0x227A, 0x2274,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E29C_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x277B, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E29D_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x2D7D, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x2C21, 0x2C22,
- 0x2C23, 0x2C24, 0x2C25, 0x2C26, 0x2C27, 0x2C28, 0x2C29, 0x2C2A,
-};
-static const unsigned short utf8_to_euc_E2A4_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x232E, 0x232F, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E2A6_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x233A,
-};
-static const unsigned short utf8_to_euc_E2A7_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x237D, 0x237E, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E380[] = {
- 0x2121, 0x2122, 0x2123, 0x2137, 0, 0x2139, 0x213A, 0x213B,
- 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159,
- 0x215A, 0x215B, 0x2229, 0x222E, 0x214C, 0x214D, 0, 0,
- 0, 0, 0, 0, 0x2141, 0x2D60, 0, 0x2D61,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E380_932[] = {
- 0x2121, 0x2122, 0x2123, 0x2137, 0, 0x2139, 0x213A, 0x213B,
- 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159,
- 0x215A, 0x215B, 0x2229, 0x222E, 0x214C, 0x214D, 0, 0,
- 0, 0, 0, 0, 0, 0x2D60, 0, 0x2D61,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E380_x0213[] = {
- 0x2121, 0x2122, 0x2123, 0x2137, 0, 0x2139, 0x213A, 0x213B,
- 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159,
- 0x215A, 0x215B, 0x2229, 0x222E, 0x214C, 0x214D, 0x225A, 0x225B,
- 0x2258, 0x2259, 0, 0, 0x2141, 0x2D60, 0, 0x2D61,
- 0x2666, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x2233, 0x2234, 0x2235, 0, 0,
- 0, 0, 0, 0x2236, 0x2237, 0x233C, 0, 0,
-};
-static const unsigned short utf8_to_euc_E381[] = {
- 0, 0x2421, 0x2422, 0x2423, 0x2424, 0x2425, 0x2426, 0x2427,
- 0x2428, 0x2429, 0x242A, 0x242B, 0x242C, 0x242D, 0x242E, 0x242F,
- 0x2430, 0x2431, 0x2432, 0x2433, 0x2434, 0x2435, 0x2436, 0x2437,
- 0x2438, 0x2439, 0x243A, 0x243B, 0x243C, 0x243D, 0x243E, 0x243F,
- 0x2440, 0x2441, 0x2442, 0x2443, 0x2444, 0x2445, 0x2446, 0x2447,
- 0x2448, 0x2449, 0x244A, 0x244B, 0x244C, 0x244D, 0x244E, 0x244F,
- 0x2450, 0x2451, 0x2452, 0x2453, 0x2454, 0x2455, 0x2456, 0x2457,
- 0x2458, 0x2459, 0x245A, 0x245B, 0x245C, 0x245D, 0x245E, 0x245F,
-};
-static const unsigned short utf8_to_euc_E382[] = {
- 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467,
- 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E, 0x246F,
- 0x2470, 0x2471, 0x2472, 0x2473, 0, 0, 0, 0,
- 0, 0, 0, 0x212B, 0x212C, 0x2135, 0x2136, 0,
- 0, 0x2521, 0x2522, 0x2523, 0x2524, 0x2525, 0x2526, 0x2527,
- 0x2528, 0x2529, 0x252A, 0x252B, 0x252C, 0x252D, 0x252E, 0x252F,
- 0x2530, 0x2531, 0x2532, 0x2533, 0x2534, 0x2535, 0x2536, 0x2537,
- 0x2538, 0x2539, 0x253A, 0x253B, 0x253C, 0x253D, 0x253E, 0x253F,
-};
-static const unsigned short utf8_to_euc_E382_932[] = {
- 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467,
- 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E, 0x246F,
- 0x2470, 0x2471, 0x2472, 0x2473, 0x2574, 0, 0, 0,
- 0, 0, 0, 0x212B, 0x212C, 0x2135, 0x2136, 0,
- 0, 0x2521, 0x2522, 0x2523, 0x2524, 0x2525, 0x2526, 0x2527,
- 0x2528, 0x2529, 0x252A, 0x252B, 0x252C, 0x252D, 0x252E, 0x252F,
- 0x2530, 0x2531, 0x2532, 0x2533, 0x2534, 0x2535, 0x2536, 0x2537,
- 0x2538, 0x2539, 0x253A, 0x253B, 0x253C, 0x253D, 0x253E, 0x253F,
-};
-static const unsigned short utf8_to_euc_E382_x0213[] = {
- 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467,
- 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E, 0x246F,
- 0x2470, 0x2471, 0x2472, 0x2473, 0x2474, 0x2475, 0x2476, 0,
- 0, 0, 0, 0x212B, 0x212C, 0x2135, 0x2136, 0x2239,
- 0x237B, 0x2521, 0x2522, 0x2523, 0x2524, 0x2525, 0x2526, 0x2527,
- 0x2528, 0x2529, 0x252A, 0x252B, 0x252C, 0x252D, 0x252E, 0x252F,
- 0x2530, 0x2531, 0x2532, 0x2533, 0x2534, 0x2535, 0x2536, 0x2537,
- 0x2538, 0x2539, 0x253A, 0x253B, 0x253C, 0x253D, 0x253E, 0x253F,
-};
-static const unsigned short utf8_to_euc_E383[] = {
- 0x2540, 0x2541, 0x2542, 0x2543, 0x2544, 0x2545, 0x2546, 0x2547,
- 0x2548, 0x2549, 0x254A, 0x254B, 0x254C, 0x254D, 0x254E, 0x254F,
- 0x2550, 0x2551, 0x2552, 0x2553, 0x2554, 0x2555, 0x2556, 0x2557,
- 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255D, 0x255E, 0x255F,
- 0x2560, 0x2561, 0x2562, 0x2563, 0x2564, 0x2565, 0x2566, 0x2567,
- 0x2568, 0x2569, 0x256A, 0x256B, 0x256C, 0x256D, 0x256E, 0x256F,
- 0x2570, 0x2571, 0x2572, 0x2573, 0x2574, 0x2575, 0x2576, 0,
- 0, 0, 0, 0x2126, 0x213C, 0x2133, 0x2134, 0,
-};
-static const unsigned short utf8_to_euc_E383_x0213[] = {
- 0x2540, 0x2541, 0x2542, 0x2543, 0x2544, 0x2545, 0x2546, 0x2547,
- 0x2548, 0x2549, 0x254A, 0x254B, 0x254C, 0x254D, 0x254E, 0x254F,
- 0x2550, 0x2551, 0x2552, 0x2553, 0x2554, 0x2555, 0x2556, 0x2557,
- 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255D, 0x255E, 0x255F,
- 0x2560, 0x2561, 0x2562, 0x2563, 0x2564, 0x2565, 0x2566, 0x2567,
- 0x2568, 0x2569, 0x256A, 0x256B, 0x256C, 0x256D, 0x256E, 0x256F,
- 0x2570, 0x2571, 0x2572, 0x2573, 0x2574, 0x2575, 0x2576, 0x2772,
- 0x2773, 0x2774, 0x2775, 0x2126, 0x213C, 0x2133, 0x2134, 0x2238,
-};
-static const unsigned short utf8_to_euc_E387_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x266E, 0x266F, 0x2670, 0x2671, 0x2672, 0x2673, 0x2674, 0x2675,
- 0x2676, 0x2677, 0x2679, 0x267A, 0x267B, 0x267C, 0x267D, 0x267E,
-};
-static const unsigned short utf8_to_euc_E388[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x2D6A, 0x2D6B, 0, 0, 0, 0, 0,
- 0, 0x2D6C, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E388_mac[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x2D2E, 0x2D31, 0, 0, 0, 0, 0,
- 0, 0x2D2C, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E389_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x2841, 0x2842, 0x2843, 0x2844, 0x2845, 0x2846, 0x2847,
- 0x2848, 0x2849, 0x284A, 0x284B, 0x284C, 0x284D, 0x284E, 0x284F,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E38A[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x2D65, 0x2D66, 0x2D67, 0x2D68,
- 0x2D69, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E38A_mac[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x2D73, 0x2D74, 0x2D75, 0x2D76,
- 0x2D77, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E38A_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x2D65, 0x2D66, 0x2D67, 0x2D68,
- 0x2D69, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x2850, 0x2851, 0x2852, 0x2853, 0x2854, 0x2855, 0x2856,
- 0x2857, 0x2858, 0x2859, 0x285A, 0x285B, 0x285C, 0x285D, 0x285E,
-};
-static const unsigned short utf8_to_euc_E38B_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2C5B, 0x2C5C, 0x2C5D, 0x2C5E, 0x2C5F, 0x2C60, 0x2C61, 0x2C62,
- 0x2C63, 0x2C64, 0x2C65, 0x2C66, 0x2C67, 0x2C68, 0x2C69, 0x2C6A,
- 0x2C6B, 0x2C6C, 0x2C6D, 0x2C6E, 0, 0x2C71, 0, 0,
- 0, 0x2C70, 0, 0, 0x2C73, 0x2C72, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x2C6F, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E38C[] = {
- 0, 0, 0, 0x2D46, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x2D4A, 0, 0,
- 0, 0, 0, 0, 0x2D41, 0, 0, 0,
- 0x2D44, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x2D42, 0x2D4C, 0, 0, 0x2D4B, 0x2D45,
- 0, 0, 0, 0x2D4D, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x2D47, 0,
- 0, 0, 0, 0x2D4F, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E38C_mac[] = {
- 0, 0, 0, 0x2E29, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x2E32, 0, 0,
- 0, 0, 0, 0, 0x2E24, 0, 0, 0,
- 0x2E2B, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x2E22, 0x2E34, 0, 0, 0x2E35, 0x2E2D,
- 0, 0, 0, 0x2E37, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x2E2A, 0,
- 0, 0, 0, 0x2E36, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E38D[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x2D40, 0x2D4E, 0, 0, 0x2D43, 0, 0,
- 0, 0x2D48, 0, 0, 0, 0, 0, 0x2D49,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x2D5F, 0x2D6F, 0x2D6E, 0x2D6D, 0,
-};
-static const unsigned short utf8_to_euc_E38D_mac[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x2E21, 0x2E2F, 0, 0, 0x2E23, 0, 0,
- 0, 0x2E2E, 0, 0, 0, 0, 0, 0x2E31,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x2E6A, 0x2E69, 0x2E68, 0x2E67, 0,
-};
-static const unsigned short utf8_to_euc_E38E[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x2D53, 0x2D54,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x2D50, 0x2D51, 0x2D52, 0,
- 0, 0x2D56, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E38E_mac[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x2B2B, 0x2B2D,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x2B21, 0x2B23, 0x2B29, 0,
- 0, 0x2B27, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E38F[] = {
- 0, 0, 0, 0, 0x2D55, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x2D63, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E38F_mac[] = {
- 0, 0, 0, 0, 0x2B2E, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x2B7C, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E38F_x0213[] = {
- 0, 0, 0, 0, 0x2D55, 0, 0, 0,
- 0, 0, 0, 0x235E, 0, 0x2D63, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E390_x0213[] = {
- 0, 0, 0x2E23, 0, 0, 0, 0xA12D, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xA132, 0, 0xA133, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E391_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xA15E, 0, 0xA156, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E392_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xA17E, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x2E53, 0, 0,
- 0, 0, 0, 0, 0xA32B, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E393_x0213[] = {
- 0, 0xF468, 0, 0, 0, 0, 0, 0xA32F,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x2E5B, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E394_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xA348,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E395_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xA35D, 0xA35E, 0,
- 0, 0, 0, 0xA361, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xA367, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E396_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xA423, 0,
- 0xA426, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E397_x0213[] = {
- 0, 0, 0, 0, 0, 0xA42F, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xA438, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xA442, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E398_x0213[] = {
- 0, 0, 0, 0, 0, 0xA44A, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E399_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xA479, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E39A_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xA53F, 0, 0, 0, 0, 0xA543, 0,
- 0, 0xA541, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E39B_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xA557,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E39D_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xA823, 0xA825, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xA829, 0xA828, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xA82C, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E39E_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x4F5F, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E39F_x0213[] = {
- 0, 0xA83E, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x4F6F, 0, 0, 0, 0, 0,
- 0xA856, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xA859, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xA85C, 0, 0,
-};
-static const unsigned short utf8_to_euc_E3A0_x0213[] = {
- 0xA85E, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xA86F,
- 0, 0, 0, 0, 0, 0, 0xA871, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E3A1_x0213[] = {
- 0xA874, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xA879, 0, 0, 0,
- 0, 0xA87B, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E3A3_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xAC3B, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E3A4_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xAC46,
- 0, 0, 0xAC4A, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E3A5_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xAC60,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E3A9_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xAD5B, 0,
- 0, 0, 0, 0xAD5F, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E3AB_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xAD71, 0xAE36,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xAD7C, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E3AC_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xAE2E, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xAE32, 0, 0xAE34, 0, 0, 0,
- 0, 0, 0x7549, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E3AD_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xAE6D, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xAE65,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E3AE_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0xAF28,
- 0xAF29, 0, 0, 0, 0, 0xAF2C, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xAF34, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x757E, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E3AF_x0213[] = {
- 0, 0, 0, 0x7621, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xAF48, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xAF5D, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E3B0_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x763A,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xAF77, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E3B3_x0213[] = {
- 0, 0, 0, 0xEE3B, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xEE42, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E3B4_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xEE71, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xEE7E, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E3B5_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xEF40, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E3B6_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xEF54, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E3B7_x0213[] = {
- 0xEF70, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xEF77, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E3B8_x0213[] = {
- 0, 0, 0, 0, 0, 0xF028, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x7766,
-};
-static const unsigned short utf8_to_euc_E3B9_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xF03F, 0, 0, 0, 0, 0, 0xF041, 0,
- 0xF042, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E3BA_x0213[] = {
- 0, 0, 0, 0xF049, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xF050, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E3BD_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xF134,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x784D, 0, 0, 0xF146, 0, 0xF148,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E3BE_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xF15C, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E3BF_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xF167, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xF16C,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E480_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xF222, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E481_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xF22D, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E482_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xF239, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E484_x0213[] = {
- 0, 0, 0, 0, 0, 0xF264, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E485_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xF274, 0, 0, 0, 0, 0, 0, 0xF277,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xF27D, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E486_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xF333, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xF337,
-};
-static const unsigned short utf8_to_euc_E487_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xF347, 0,
- 0, 0, 0, 0, 0, 0, 0xF34B, 0,
- 0, 0, 0, 0xF348, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E488_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0xF353,
- 0, 0, 0, 0, 0, 0, 0xF357, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E489_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x796D, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E48B_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0xF42B, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xF436, 0,
- 0, 0, 0, 0, 0, 0xF43B, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E48C_x0213[] = {
- 0, 0, 0xF44E, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xF45D, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E48D_x0213[] = {
- 0, 0, 0, 0xF461, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E48F_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xF53E, 0,
- 0xF542, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E490_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xF548, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xF54A,
- 0, 0, 0, 0, 0xF54C, 0, 0, 0,
- 0, 0, 0xF54F, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E491_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x7A59, 0, 0, 0, 0,
- 0, 0, 0, 0x7A5A, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xF56C, 0,
- 0, 0, 0xF56E, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E492_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xF577, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xF635, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xF632, 0,
-};
-static const unsigned short utf8_to_euc_E493_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xF634, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E494_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xF659, 0, 0, 0, 0, 0xF654, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xF66D, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E495_x0213[] = {
- 0, 0, 0, 0xF66E, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E496_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x7B51, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xF74F, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E497_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xF76C, 0, 0,
- 0, 0, 0x7B60, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E498_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xF824,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E499_x0213[] = {
- 0, 0xF83A, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xF843, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E49A_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xF84E, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xF853,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E49C_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xF86B, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E49D_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xF929, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E49F_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xF93F, 0, 0,
-};
-static const unsigned short utf8_to_euc_E4A0_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xF949, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E4A1_x0213[] = {
- 0, 0, 0, 0, 0x7C4B, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xF95C, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E4A2_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFA27, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E4A6_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x7D58, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E4A7_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xFB6A,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFB70, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E4A8_x0213[] = {
- 0, 0, 0, 0, 0xFB75, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFB78, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E4AA_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFC37, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E4AC_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFC55, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E4AF_x0213[] = {
- 0, 0, 0xFD26, 0, 0, 0, 0, 0,
- 0, 0, 0xFD28, 0, 0, 0, 0, 0,
- 0, 0, 0xFD2A, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFD31, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E4B0_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x7E3E,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFD3F, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E4B3_x0213[] = {
- 0, 0, 0, 0, 0xFE2A, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFE2D, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E4B4_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0xFE4B,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E4B5_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xFE60,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E4B8[] = {
- 0x306C, 0x437A, 0xB021, 0x3C37, 0xB022, 0xB023, 0, 0x4B7C,
- 0x3E66, 0x3B30, 0x3E65, 0x323C, 0xB024, 0x4954, 0x4D3F, 0,
- 0x5022, 0x312F, 0xB025, 0, 0x336E, 0x5023, 0x4024, 0x5242,
- 0x3556, 0x4A3A, 0, 0, 0, 0, 0x3E67, 0xB026,
- 0, 0x4E3E, 0, 0xB027, 0xB028, 0, 0x4A42, 0,
- 0xB029, 0, 0x5024, 0xB02A, 0, 0x4366, 0xB02B, 0xB02C,
- 0xB02D, 0x5025, 0x367A, 0, 0, 0xB02E, 0x5026, 0,
- 0x345D, 0x4330, 0, 0x3C67, 0x5027, 0, 0, 0x5028,
-};
-static const unsigned short utf8_to_euc_E4B8_x0213[] = {
- 0x306C, 0x437A, 0xA122, 0x3C37, 0xB022, 0xB023, 0, 0x4B7C,
- 0x3E66, 0x3B30, 0x3E65, 0x323C, 0xB024, 0x4954, 0x4D3F, 0xA123,
- 0x5022, 0x312F, 0xA124, 0, 0x336E, 0x5023, 0x4024, 0x5242,
- 0x3556, 0x4A3A, 0, 0, 0, 0, 0x3E67, 0xB026,
- 0, 0x4E3E, 0, 0xB027, 0xB028, 0, 0x4A42, 0,
- 0x2E24, 0xA125, 0x5024, 0xA126, 0xF02E, 0x4366, 0xA127, 0x2E25,
- 0x2E26, 0x5025, 0x367A, 0, 0, 0xB02E, 0x5026, 0,
- 0x345D, 0x4330, 0, 0x3C67, 0x5027, 0, 0, 0x5028,
-};
-static const unsigned short utf8_to_euc_E4B9[] = {
- 0xB02F, 0xB030, 0x5029, 0x4735, 0xB031, 0x3557, 0, 0xB032,
- 0, 0, 0, 0x4737, 0, 0x4663, 0x3843, 0x4B33,
- 0, 0xB033, 0, 0, 0, 0x6949, 0x502A, 0x3E68,
- 0x502B, 0x3235, 0xB034, 0, 0xB035, 0x3665, 0x3870, 0x4C69,
- 0, 0, 0x5626, 0xB036, 0, 0, 0, 0,
- 0xB037, 0xB038, 0, 0, 0, 0, 0, 0,
- 0, 0x4D70, 0, 0x467D, 0xB039, 0xB03A, 0, 0,
- 0, 0xB03B, 0, 0, 0, 0, 0x3425, 0xB03C,
-};
-static const unsigned short utf8_to_euc_E4B9_x0213[] = {
- 0xA128, 0xB030, 0x5029, 0x4735, 0xB031, 0x3557, 0, 0xA129,
- 0xA12A, 0, 0, 0x4737, 0, 0x4663, 0x3843, 0x4B33,
- 0, 0xA12C, 0, 0, 0, 0x6949, 0x502A, 0x3E68,
- 0x502B, 0x3235, 0xA12F, 0, 0xB035, 0x3665, 0x3870, 0x4C69,
- 0, 0, 0x5626, 0xB036, 0, 0, 0, 0,
- 0xB037, 0xA130, 0, 0, 0, 0, 0, 0,
- 0, 0x4D70, 0, 0x467D, 0xB039, 0xB03A, 0, 0,
- 0, 0xB03B, 0, 0, 0, 0, 0x3425, 0xB03C,
-};
-static const unsigned short utf8_to_euc_E4BA[] = {
- 0x3535, 0, 0x502C, 0, 0, 0x502D, 0x4E3B, 0,
- 0x4D3D, 0x4168, 0x502F, 0x3B76, 0x4673, 0xB03D, 0x5032, 0,
- 0, 0x313E, 0x385F, 0, 0x385E, 0x3066, 0xB03E, 0xB03F,
- 0x4F4B, 0x4F4A, 0, 0x3A33, 0x3021, 0xB040, 0x5033, 0x5034,
- 0x5035, 0x4B34, 0x5036, 0, 0x3872, 0x3067, 0x4B72, 0,
- 0x357C, 0, 0, 0x357D, 0x357E, 0x4462, 0x4E3C, 0xB041,
- 0x5037, 0, 0, 0x5038, 0, 0, 0x5039, 0,
- 0, 0xB042, 0x3F4D, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E4BA_x0213[] = {
- 0x3535, 0, 0x502C, 0, 0, 0x502D, 0x4E3B, 0,
- 0x4D3D, 0x4168, 0x502F, 0x3B76, 0x4673, 0x2E27, 0x5032, 0,
- 0, 0x313E, 0x385F, 0, 0x385E, 0x3066, 0xB03E, 0xB03F,
- 0x4F4B, 0x4F4A, 0, 0x3A33, 0x3021, 0xA131, 0x5033, 0x5034,
- 0x5035, 0x4B34, 0x5036, 0, 0x3872, 0x3067, 0x4B72, 0,
- 0x357C, 0, 0, 0x357D, 0x357E, 0x4462, 0x4E3C, 0xB041,
- 0x5037, 0, 0, 0x5038, 0, 0, 0x5039, 0,
- 0, 0xA134, 0x3F4D, 0xA135, 0xA137, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E4BB[] = {
- 0x3D3A, 0x3F4E, 0x503E, 0xB043, 0x503C, 0, 0x503D, 0x3558,
- 0, 0, 0x3A23, 0x3270, 0, 0x503B, 0x503A, 0x4A29,
- 0xB044, 0, 0, 0, 0x3B46, 0x3B45, 0x423E, 0x503F,
- 0x4955, 0x4067, 0xB045, 0xB046, 0, 0x2138, 0x5040, 0x5042,
- 0xB047, 0xB048, 0xB049, 0x4265, 0x4E61, 0x304A, 0, 0,
- 0xB04A, 0, 0, 0, 0, 0x5041, 0x323E, 0xB04B,
- 0x3644, 0xB04C, 0x4367, 0xB04D, 0, 0xB04E, 0x376F, 0x5043,
- 0, 0, 0, 0x4724, 0xF42F, 0xB04F, 0xB050, 0xB051,
-};
-static const unsigned short utf8_to_euc_E4BB_x0213[] = {
- 0x3D3A, 0x3F4E, 0x503E, 0xA138, 0x503C, 0, 0x503D, 0x3558,
- 0xA139, 0, 0x3A23, 0x3270, 0, 0x503B, 0x503A, 0x4A29,
- 0xA13A, 0, 0, 0, 0x3B46, 0x3B45, 0x423E, 0x503F,
- 0x4955, 0x4067, 0xA13C, 0xB046, 0, 0x2138, 0x5040, 0x5042,
- 0xB047, 0x2E28, 0xB049, 0x4265, 0x4E61, 0x304A, 0, 0,
- 0xB04A, 0, 0, 0xA13B, 0, 0x5041, 0x323E, 0xB04B,
- 0x3644, 0xA13D, 0x4367, 0xB04D, 0, 0xA13E, 0x376F, 0x5043,
- 0, 0, 0, 0x4724, 0, 0x2E29, 0xB050, 0x2E2A,
-};
-static const unsigned short utf8_to_euc_E4BC[] = {
- 0xB052, 0x346B, 0xB053, 0xB054, 0, 0, 0, 0,
- 0xB055, 0x5044, 0x304B, 0xB056, 0xB057, 0x3860, 0x346C, 0x497A,
- 0x4832, 0x3559, 0xB058, 0, 0, 0xB059, 0xB05A, 0xB05B,
- 0, 0xB05C, 0x3271, 0, 0x5067, 0x4541, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xB05D, 0x476C,
- 0x5046, 0xB05E, 0, 0xB060, 0x483C, 0xB061, 0x4E62, 0xB062,
- 0x3F2D, 0xB063, 0x3B47, 0xB064, 0x3B77, 0x3240, 0xB065, 0,
-};
-static const unsigned short utf8_to_euc_E4BC_x0213[] = {
- 0xA13F, 0x346B, 0xB053, 0x2E2B, 0, 0, 0, 0,
- 0xB055, 0x5044, 0x304B, 0x2E2C, 0xB057, 0x3860, 0x346C, 0x497A,
- 0x4832, 0x3559, 0xB058, 0, 0, 0xB059, 0xA140, 0xB05B,
- 0, 0xB05C, 0x3271, 0, 0x5067, 0x4541, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xB05D, 0x476C,
- 0x5046, 0xB05E, 0, 0xB060, 0x483C, 0xB061, 0x4E62, 0xA142,
- 0x3F2D, 0, 0x3B47, 0xB064, 0x3B77, 0x3240, 0xA143, 0,
-};
-static const unsigned short utf8_to_euc_E4BD[] = {
- 0xB066, 0, 0xB067, 0x4451, 0, 0, 0x4322, 0x504A,
- 0xB068, 0xB069, 0, 0xB06A, 0xB06B, 0x304C, 0x4463, 0x3D3B,
- 0x3A34, 0x4D24, 0xB06C, 0x424E, 0xB06D, 0x323F, 0xB06E, 0x5049,
- 0xB06F, 0x4D3E, 0x5045, 0x5047, 0x3A6E, 0x5048, 0x5524, 0xB070,
- 0xB05F, 0, 0, 0xB071, 0, 0, 0, 0,
- 0, 0x5050, 0xB072, 0, 0xB073, 0, 0xB074, 0x5053,
- 0x5051, 0xB075, 0, 0x3242, 0, 0x4A3B, 0x504B, 0xB076,
- 0xB077, 0xB078, 0xB079, 0x504F, 0x3873, 0xB07A, 0xB07B, 0x3B48,
-};
-static const unsigned short utf8_to_euc_E4BD_x0213[] = {
- 0xB066, 0, 0xB067, 0x4451, 0, 0, 0x4322, 0x504A,
- 0x2E2E, 0x2E2F, 0, 0xB06A, 0xB06B, 0x304C, 0x4463, 0x3D3B,
- 0x3A34, 0x4D24, 0xB06C, 0x424E, 0xA144, 0x323F, 0x2E30, 0x5049,
- 0xA145, 0x4D3E, 0x5045, 0x5047, 0x3A6E, 0x5048, 0x5524, 0x2E31,
- 0x2E2D, 0, 0, 0xB071, 0xA141, 0, 0, 0,
- 0, 0x5050, 0x2E32, 0, 0x2E33, 0, 0xB074, 0x5053,
- 0x5051, 0xB075, 0, 0x3242, 0, 0x4A3B, 0x504B, 0xA147,
- 0xA148, 0xB078, 0xA149, 0x504F, 0x3873, 0xA14A, 0x2E34, 0x3B48,
-};
-static const unsigned short utf8_to_euc_E4BE[] = {
- 0, 0xB07C, 0xB07D, 0x3426, 0xB07E, 0xB121, 0x5054, 0,
- 0x504C, 0xB122, 0xB123, 0x4E63, 0xB124, 0x3B78, 0xB125, 0x504D,
- 0xB126, 0x5052, 0xB127, 0xB128, 0xB129, 0, 0x5055, 0xB12A,
- 0x504E, 0xB12B, 0xB12C, 0x3621, 0, 0x304D, 0xB12D, 0xB12E,
- 0x3622, 0x3241, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x5525, 0, 0x4B79, 0x496E, 0x3874,
- 0, 0, 0xB12F, 0, 0, 0x3F2F, 0x4E37, 0xB130,
- 0, 0xB131, 0, 0xB132, 0xB133, 0xB134, 0xB135, 0x4A58,
-};
-static const unsigned short utf8_to_euc_E4BE_x0213[] = {
- 0, 0xB07C, 0xA14B, 0x3426, 0xB07E, 0xA14C, 0x5054, 0,
- 0x504C, 0xB122, 0x2E35, 0x4E63, 0xB124, 0x3B78, 0xB125, 0x504D,
- 0xB126, 0x5052, 0xA14D, 0xB128, 0x2E36, 0, 0x5055, 0x2E37,
- 0x504E, 0xB12B, 0xA14E, 0x3621, 0, 0x304D, 0xB12D, 0xB12E,
- 0x3622, 0x3241, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x5525, 0, 0x4B79, 0x496E, 0x3874,
- 0, 0, 0xA150, 0, 0, 0x3F2F, 0x4E37, 0xB130,
- 0, 0xB131, 0, 0xB132, 0xB133, 0xB134, 0xA151, 0x4A58,
-};
-static const unsigned short utf8_to_euc_E4BF[] = {
- 0xB136, 0xB137, 0x3738, 0x4225, 0x3264, 0xB138, 0xB139, 0,
- 0xB13A, 0xB13B, 0x3D53, 0xB13C, 0xB13D, 0xB13E, 0x5059, 0xB13F,
- 0x505E, 0x505C, 0xB140, 0, 0x5057, 0, 0, 0x422F,
- 0x505A, 0, 0x505D, 0x505B, 0xB141, 0x4A5D, 0, 0x5058,
- 0xB142, 0x3F2E, 0xB143, 0x4B73, 0x505F, 0x5060, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x3D24, 0x506D,
- 0xB144, 0, 0xB145, 0x4750, 0, 0x4936, 0x5068, 0,
- 0x4A70, 0, 0x3236, 0, 0xB146, 0xB147, 0x506C, 0xB148,
-};
-static const unsigned short utf8_to_euc_E4BF_x0213[] = {
- 0xB136, 0xB137, 0x3738, 0x4225, 0x3264, 0xA152, 0xB139, 0,
- 0xB13A, 0x2E39, 0x3D53, 0xA153, 0xB13D, 0, 0x5059, 0xA154,
- 0x505E, 0x505C, 0xA155, 0, 0x5057, 0, 0, 0x422F,
- 0x505A, 0, 0x505D, 0x505B, 0xB141, 0x4A5D, 0, 0x5058,
- 0x2E3A, 0x3F2E, 0xB143, 0x4B73, 0x505F, 0x5060, 0xA14F, 0,
- 0, 0, 0, 0, 0, 0, 0x3D24, 0x506D,
- 0xB144, 0x2E21, 0xA157, 0x4750, 0, 0x4936, 0x5068, 0,
- 0x4A70, 0, 0x3236, 0, 0xB146, 0xB147, 0x506C, 0,
-};
-static const unsigned short utf8_to_euc_E580[] = {
- 0xB149, 0xB14A, 0, 0, 0xB14B, 0x5066, 0x506F, 0xB14C,
- 0, 0x4152, 0xB14D, 0x3844, 0xB14E, 0x475C, 0xB14F, 0x6047,
- 0xB150, 0x506E, 0x455D, 0xB151, 0x5063, 0, 0x3876, 0xB152,
- 0xB153, 0x3875, 0x5061, 0xB154, 0xB155, 0xB156, 0xB157, 0x3C5A,
- 0, 0x5069, 0xB158, 0x4A6F, 0x434D, 0x5065, 0x3771, 0xB159,
- 0x5062, 0x506A, 0x5064, 0x4E51, 0x506B, 0x4F41, 0xB15A, 0,
- 0xB15B, 0, 0xB15C, 0xB15D, 0, 0xB15E, 0x3666, 0,
- 0, 0x3770, 0, 0xB176, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E580_x0213[] = {
- 0xA158, 0x2E3B, 0x2E3C, 0, 0xB14B, 0x5066, 0x506F, 0xB14C,
- 0, 0x4152, 0xB14D, 0x3844, 0xB14E, 0x475C, 0x2E3D, 0x6047,
- 0xA159, 0x506E, 0x455D, 0xA15A, 0x5063, 0, 0x3876, 0xB152,
- 0x2E3E, 0x3875, 0x5061, 0xB154, 0xA15B, 0xB156, 0xA15C, 0x3C5A,
- 0, 0x5069, 0xA15D, 0x4A6F, 0x434D, 0x5065, 0x3771, 0x2E3F,
- 0x5062, 0x506A, 0x5064, 0x4E51, 0x506B, 0x4F41, 0x2E40, 0,
- 0xB15B, 0, 0xB15C, 0xB15D, 0, 0xB15E, 0x3666, 0,
- 0, 0x3770, 0, 0x2E42, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E581[] = {
- 0xB15F, 0xB160, 0xB161, 0x5070, 0, 0xB162, 0xB163, 0x5071,
- 0x5075, 0x304E, 0xB164, 0, 0xB165, 0, 0xB166, 0x4A50,
- 0x5074, 0xB167, 0xB168, 0xB169, 0, 0x5073, 0x5077, 0xB16A,
- 0, 0xB16B, 0x5076, 0, 0x4464, 0, 0, 0xB16C,
- 0xB16D, 0, 0xB16E, 0xB16F, 0, 0x3772, 0xB170, 0xB171,
- 0, 0, 0xB172, 0, 0x5078, 0xB173, 0, 0,
- 0xB174, 0xB175, 0x3C45, 0, 0x4226, 0x4465, 0x3676, 0,
- 0x5079, 0, 0, 0, 0, 0x3536, 0, 0,
-};
-static const unsigned short utf8_to_euc_E581_x0213[] = {
- 0x2E41, 0x2E43, 0xA15F, 0x5070, 0, 0xB162, 0xA160, 0x5071,
- 0x5075, 0x304E, 0xB164, 0, 0xB165, 0, 0xA161, 0x4A50,
- 0x5074, 0xB167, 0xB168, 0xA162, 0, 0x5073, 0x5077, 0xA163,
- 0, 0xB16B, 0x5076, 0, 0x4464, 0, 0, 0xB16C,
- 0xB16D, 0, 0xB16E, 0xA164, 0, 0x3772, 0xA165, 0xB171,
- 0, 0, 0xA166, 0, 0x5078, 0xB173, 0, 0,
- 0xA167, 0xB175, 0x3C45, 0, 0x4226, 0x4465, 0x3676, 0,
- 0x5079, 0, 0, 0, 0, 0x3536, 0, 0,
-};
-static const unsigned short utf8_to_euc_E582[] = {
- 0x507A, 0xB177, 0, 0xB178, 0xB179, 0x507C, 0xB17A, 0,
- 0, 0, 0xB17B, 0, 0, 0x4B35, 0xB17C, 0xB17D,
- 0xB17E, 0x3766, 0xB221, 0xB222, 0xB223, 0, 0xB224, 0,
- 0x3B31, 0x4877, 0x507B, 0xB225, 0xB226, 0, 0xB227, 0xB228,
- 0xB229, 0xB22A, 0xB22B, 0, 0, 0, 0, 0,
- 0, 0, 0xB22C, 0, 0x3A45, 0x4D43, 0, 0xB22D,
- 0xB22E, 0, 0x507E, 0x5123, 0x507D, 0x3A44, 0, 0x3D7D,
- 0, 0xB22F, 0xB230, 0, 0, 0xB231, 0x3739, 0,
-};
-static const unsigned short utf8_to_euc_E582_x0213[] = {
- 0x507A, 0xB177, 0, 0xB178, 0xB179, 0x507C, 0xB17A, 0,
- 0xA169, 0, 0xB17B, 0, 0, 0x4B35, 0xB17C, 0xB17D,
- 0xB17E, 0x3766, 0xA16A, 0xA16B, 0x2E44, 0xA16C, 0xA16D, 0,
- 0x3B31, 0x4877, 0x507B, 0xB225, 0xA16E, 0, 0xB227, 0xB228,
- 0xB229, 0xB22A, 0xB22B, 0xA168, 0, 0, 0, 0,
- 0, 0, 0xA16F, 0, 0x3A45, 0x4D43, 0, 0xB22D,
- 0xB22E, 0xA171, 0x507E, 0x5123, 0x507D, 0x3A44, 0, 0x3D7D,
- 0, 0xB22F, 0xA172, 0xA173, 0, 0xB231, 0x3739, 0,
-};
-static const unsigned short utf8_to_euc_E583[] = {
- 0xB232, 0, 0x5124, 0xB233, 0xB234, 0x364F, 0, 0xB235,
- 0, 0x5121, 0x5122, 0, 0xB236, 0x462F, 0xB237, 0x417C,
- 0xB238, 0x3623, 0, 0xB239, 0xB23A, 0x4B4D, 0x5125, 0,
- 0xB23B, 0, 0x4E3D, 0, 0xB23C, 0xB23D, 0x5126, 0xB23E,
- 0, 0, 0xB23F, 0x5129, 0xB240, 0x5127, 0xB241, 0x414E,
- 0xB242, 0xB243, 0, 0, 0, 0x5128, 0x512A, 0xB244,
- 0, 0xB245, 0xB251, 0, 0xF430, 0x512C, 0xB246, 0,
- 0, 0x512B, 0xB247, 0x4A48, 0, 0, 0xB248, 0,
-};
-static const unsigned short utf8_to_euc_E583_x0213[] = {
- 0xB232, 0, 0x5124, 0xB233, 0xA174, 0x364F, 0, 0xA175,
- 0, 0x5121, 0x5122, 0, 0x2E45, 0x462F, 0xA178, 0x417C,
- 0x2E47, 0x3623, 0, 0xB239, 0xA17A, 0x4B4D, 0x5125, 0,
- 0, 0xA17B, 0x4E3D, 0, 0xB23C, 0xB23D, 0x5126, 0xB23E,
- 0, 0xA17C, 0xB23F, 0x5129, 0xB240, 0x5127, 0x2E48, 0x414E,
- 0xB242, 0xA17D, 0, 0, 0, 0x5128, 0x512A, 0xB244,
- 0, 0xB245, 0x2E46, 0xA176, 0, 0x512C, 0xB246, 0,
- 0, 0x512B, 0xB247, 0x4A48, 0, 0, 0xB248, 0,
-};
-static const unsigned short utf8_to_euc_E584[] = {
- 0x3537, 0x512E, 0x512F, 0xB249, 0x322F, 0, 0xB24A, 0xB24B,
- 0xB24C, 0x512D, 0, 0xB24D, 0xB24E, 0xB24F, 0xB250, 0,
- 0xB252, 0, 0x3C74, 0, 0x5132, 0x5131, 0x5130, 0xB253,
- 0x5056, 0xB254, 0x5133, 0xB255, 0xB256, 0xB257, 0xB258, 0x3D7E,
- 0, 0x5134, 0, 0xB259, 0, 0, 0, 0xB25A,
- 0xB25B, 0, 0x4D25, 0, 0xB25C, 0xB25D, 0, 0xB25E,
- 0, 0xB25F, 0x4C59, 0xB260, 0xB261, 0xB262, 0, 0x5136,
- 0xB263, 0xB264, 0x5135, 0x5138, 0x5137, 0, 0, 0x5139,
-};
-static const unsigned short utf8_to_euc_E584_x0213[] = {
- 0x3537, 0x512E, 0x512F, 0x2E4B, 0x322F, 0, 0x2E4A, 0xB24B,
- 0xA321, 0x512D, 0, 0x2E4C, 0xB24E, 0xB24F, 0xB250, 0,
- 0xB252, 0, 0x3C74, 0, 0x5132, 0x5131, 0x5130, 0xA323,
- 0x5056, 0xB254, 0x5133, 0xA324, 0xB256, 0xB257, 0x2E4D, 0x3D7E,
- 0, 0x5134, 0, 0xB259, 0, 0, 0, 0xB25A,
- 0xB25B, 0, 0x4D25, 0, 0xB25C, 0xB25D, 0, 0xB25E,
- 0, 0xB25F, 0x4C59, 0xB260, 0xB261, 0x2E4E, 0, 0x5136,
- 0xB263, 0xB264, 0x5135, 0x5138, 0x5137, 0, 0, 0x5139,
-};
-static const unsigned short utf8_to_euc_E585[] = {
- 0x513A, 0x3074, 0xB265, 0x3835, 0x373B, 0x3D3C, 0x437B, 0x3624,
- 0x4068, 0x3877, 0xB266, 0x396E, 0x513C, 0x4C48, 0x4546, 0xB267,
- 0x3B79, 0, 0x513B, 0xB268, 0x513D, 0xB269, 0, 0xB26A,
- 0xB26B, 0, 0x455E, 0, 0x3375, 0, 0, 0xB26C,
- 0, 0, 0x513E, 0, 0xB26D, 0x467E, 0xB26E, 0,
- 0x4134, 0x5140, 0x5141, 0x482C, 0x3878, 0x4F3B, 0x5142, 0,
- 0, 0x3626, 0, 0, 0, 0x4A3C, 0x4236, 0x3671,
- 0x4535, 0, 0, 0, 0x3773, 0, 0xB26F, 0,
-};
-static const unsigned short utf8_to_euc_E585_x0213[] = {
- 0x513A, 0x3074, 0xB265, 0x3835, 0x373B, 0x3D3C, 0x437B, 0x3624,
- 0x4068, 0x3877, 0x2E4F, 0x396E, 0x513C, 0x4C48, 0x4546, 0xB267,
- 0x3B79, 0, 0x513B, 0xB268, 0x513D, 0x2E51, 0, 0x2E52,
- 0xB26B, 0, 0x455E, 0, 0x3375, 0, 0, 0xB26C,
- 0xA326, 0, 0x513E, 0, 0, 0x467E, 0xB26E, 0,
- 0x4134, 0x5140, 0x5141, 0x482C, 0x3878, 0x4F3B, 0x5142, 0,
- 0, 0x3626, 0, 0xA328, 0, 0x4A3C, 0x4236, 0x3671,
- 0x4535, 0, 0, 0xF474, 0x3773, 0, 0xB26F, 0,
-};
-static const unsigned short utf8_to_euc_E586[] = {
- 0x5143, 0, 0x5144, 0xB270, 0xB271, 0x4662, 0x315F, 0,
- 0, 0x5147, 0x3A7D, 0xB272, 0x5146, 0x3A46, 0xB273, 0x5148,
- 0x666E, 0x5149, 0x4B41, 0x514A, 0, 0x514B, 0x514C, 0x3E69,
- 0xB274, 0x3C4C, 0, 0, 0, 0xB275, 0, 0,
- 0x3427, 0xB276, 0x514F, 0xB277, 0x514D, 0x4C3D, 0x514E, 0,
- 0x495A, 0x5150, 0x5151, 0x5152, 0x455F, 0xB278, 0, 0,
- 0x5156, 0x5154, 0x5155, 0x5153, 0x3A63, 0x5157, 0x4C6A, 0x4E64,
- 0xB279, 0, 0xB27A, 0, 0xB27B, 0x5158, 0xB27C, 0xB27D,
-};
-static const unsigned short utf8_to_euc_E586_x0213[] = {
- 0x5143, 0, 0x5144, 0xA329, 0xB271, 0x4662, 0x315F, 0,
- 0, 0x5147, 0x3A7D, 0xA32A, 0x5146, 0x3A46, 0xB273, 0x5148,
- 0x666E, 0x5149, 0x4B41, 0x514A, 0, 0x514B, 0x514C, 0x3E69,
- 0xA32C, 0x3C4C, 0, 0, 0, 0x2E54, 0, 0,
- 0x3427, 0xB276, 0x514F, 0xA32D, 0x514D, 0x4C3D, 0x514E, 0,
- 0x495A, 0x5150, 0x5151, 0x5152, 0x455F, 0xA32E, 0, 0,
- 0x5156, 0x5154, 0x5155, 0x5153, 0x3A63, 0x5157, 0x4C6A, 0x4E64,
- 0xB279, 0, 0xB27A, 0, 0xA330, 0x5158, 0, 0xB27D,
-};
-static const unsigned short utf8_to_euc_E587[] = {
- 0, 0, 0xB27E, 0, 0x4028, 0x5159, 0x3D5A, 0,
- 0xB321, 0x515A, 0, 0x437C, 0x4E3F, 0x4560, 0, 0xB322,
- 0, 0xB323, 0xB324, 0xB325, 0, 0xB326, 0x5245, 0,
- 0xB327, 0, 0, 0x515B, 0x7425, 0x3645, 0xB328, 0,
- 0x515C, 0x4B5E, 0xB329, 0, 0, 0xB32A, 0x3D68, 0x427C,
- 0, 0x515E, 0x4664, 0, 0xF431, 0x515F, 0xB32B, 0,
- 0x5160, 0x332E, 0xB32C, 0xB32D, 0xB32E, 0x5161, 0x3627, 0xB32F,
- 0x464C, 0x317A, 0x3D50, 0, 0, 0x4821, 0x5162, 0,
-};
-static const unsigned short utf8_to_euc_E587_x0213[] = {
- 0, 0, 0xB27E, 0x2E55, 0x4028, 0x5159, 0x3D5A, 0,
- 0xB321, 0x515A, 0x2E56, 0x437C, 0x4E3F, 0x4560, 0, 0xB322,
- 0, 0xB323, 0xB324, 0xB325, 0, 0xB326, 0x5245, 0,
- 0xB327, 0, 0, 0x515B, 0x7425, 0x3645, 0x2E57, 0,
- 0x515C, 0x4B5E, 0x2E58, 0, 0, 0xB32A, 0x3D68, 0x427C,
- 0, 0x515E, 0x4664, 0, 0, 0x515F, 0x2E59, 0,
- 0x5160, 0x332E, 0xB32C, 0xA333, 0xA334, 0x5161, 0x3627, 0xB32F,
- 0x464C, 0x317A, 0x3D50, 0, 0, 0x4821, 0x5162, 0,
-};
-static const unsigned short utf8_to_euc_E588[] = {
- 0x4561, 0xB330, 0xB331, 0x3F4F, 0x5163, 0xB332, 0x4A2C, 0x405A,
- 0x3422, 0, 0x3429, 0x5164, 0, 0, 0x5166, 0,
- 0, 0x373A, 0xB333, 0xB334, 0x5165, 0xB335, 0xB336, 0x4E73,
- 0xB337, 0, 0, 0, 0, 0x3D69, 0, 0,
- 0, 0, 0xB338, 0, 0x483D, 0x4A4C, 0, 0x5167,
- 0xB339, 0x4D78, 0x5168, 0, 0, 0, 0x5169, 0,
- 0x457E, 0xB33A, 0xB33B, 0x516A, 0, 0xB33C, 0x4029, 0x3A7E,
- 0x3774, 0x516B, 0x3B49, 0x396F, 0xB33D, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E588_x0213[] = {
- 0x4561, 0x2E5A, 0xA335, 0x3F4F, 0x5163, 0xB332, 0x4A2C, 0x405A,
- 0x3422, 0, 0x3429, 0x5164, 0, 0, 0x5166, 0,
- 0, 0x373A, 0xA336, 0x2E5C, 0x5165, 0x2E5D, 0xA337, 0x4E73,
- 0xB337, 0, 0, 0, 0, 0x3D69, 0, 0,
- 0, 0, 0xB338, 0, 0x483D, 0x4A4C, 0, 0x5167,
- 0xB339, 0x4D78, 0x5168, 0, 0, 0, 0x5169, 0,
- 0x457E, 0xB33A, 0xB33B, 0x516A, 0, 0xB33C, 0x4029, 0x3A7E,
- 0x3774, 0x516B, 0x3B49, 0x396F, 0xB33D, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E589[] = {
- 0, 0, 0, 0x4466, 0x516D, 0xB33E, 0, 0x4227,
- 0, 0xB33F, 0x3A6F, 0x516E, 0x516F, 0x4130, 0, 0x516C,
- 0, 0, 0, 0, 0x5171, 0xB340, 0x4B36, 0xB341,
- 0xB342, 0, 0xB343, 0x3964, 0xB344, 0, 0x5170, 0xB345,
- 0xB346, 0xB347, 0, 0x3775, 0x3A5E, 0x476D, 0xB348, 0,
- 0, 0x5174, 0x5172, 0, 0, 0, 0xB349, 0x497B,
- 0x3E6A, 0x517B, 0x3364, 0x5175, 0x5173, 0x414F, 0, 0xB34A,
- 0xB34B, 0xB34C, 0, 0, 0, 0x5177, 0, 0x5176,
-};
-static const unsigned short utf8_to_euc_E589_x0213[] = {
- 0, 0, 0, 0x4466, 0x516D, 0xB33E, 0, 0x4227,
- 0, 0x2E5E, 0x3A6F, 0x516E, 0x516F, 0x4130, 0, 0x516C,
- 0, 0, 0, 0, 0x5171, 0xA339, 0x4B36, 0x2E5F,
- 0xB342, 0, 0xB343, 0x3964, 0xA33A, 0x2F7E, 0x5170, 0xB345,
- 0xB346, 0x2E60, 0, 0x3775, 0x3A5E, 0x476D, 0xB348, 0,
- 0, 0x5174, 0x5172, 0, 0xA33B, 0, 0xB349, 0x497B,
- 0x3E6A, 0x517B, 0x3364, 0x5175, 0x5173, 0x414F, 0, 0xA33C,
- 0xB34B, 0xB34C, 0, 0, 0, 0x5177, 0, 0x5176,
-};
-static const unsigned short utf8_to_euc_E58A[] = {
- 0xB34D, 0, 0xB34E, 0x3344, 0, 0xB34F, 0, 0x3760,
- 0x517C, 0x4E2D, 0xB350, 0, 0xB351, 0x5178, 0, 0,
- 0, 0x517D, 0x517A, 0xB352, 0x5179, 0xB353, 0xB354, 0xB355,
- 0xB356, 0, 0xB357, 0x4E4F, 0xB358, 0, 0, 0x3879,
- 0x3243, 0, 0, 0x4E74, 0xB359, 0xB35A, 0xB35B, 0xB35C,
- 0, 0x3D75, 0x4558, 0x3965, 0x5222, 0x5223, 0, 0xB35D,
- 0xB35E, 0x4E65, 0, 0, 0x4F2B, 0x5225, 0xB35F, 0xB360,
- 0xB361, 0x387A, 0xB362, 0xB363, 0x5224, 0xB364, 0x332F, 0,
-};
-static const unsigned short utf8_to_euc_E58A_x0213[] = {
- 0xB34D, 0, 0xA33E, 0x3344, 0xA33D, 0xB34F, 0, 0x3760,
- 0x517C, 0x4E2D, 0xB350, 0, 0xB351, 0x5178, 0, 0,
- 0, 0x517D, 0x517A, 0x2E61, 0x5179, 0xB353, 0xB354, 0xB355,
- 0xA340, 0, 0xB357, 0x4E4F, 0, 0, 0, 0x3879,
- 0x3243, 0, 0, 0x4E74, 0xA342, 0xB35A, 0xA343, 0xB35C,
- 0, 0x3D75, 0x4558, 0x3965, 0x5222, 0x5223, 0, 0xA344,
- 0xB35E, 0x4E65, 0, 0, 0x4F2B, 0x5225, 0xB35F, 0xB360,
- 0xB361, 0x387A, 0xA345, 0xA346, 0x5224, 0xB364, 0x332F, 0,
-};
-static const unsigned short utf8_to_euc_E58B[] = {
- 0xB365, 0x5226, 0, 0x4B56, 0xB366, 0x443C, 0xB367, 0x4D26,
- 0xB368, 0x4A59, 0, 0, 0xB369, 0x5227, 0, 0xB36A,
- 0, 0xB36B, 0x7055, 0, 0xB36C, 0x4630, 0xB36D, 0x5228,
- 0x342A, 0x4C33, 0, 0xB36E, 0xB36F, 0x3E21, 0x5229, 0x4A67,
- 0x522D, 0xB370, 0x402A, 0x522A, 0x3650, 0xB371, 0x522B, 0x342B,
- 0xB372, 0xB373, 0xB374, 0, 0xB375, 0, 0, 0,
- 0xB376, 0xB377, 0x372E, 0x522E, 0xB378, 0x522F, 0xB379, 0xB37A,
- 0x5230, 0x5231, 0x3C5B, 0, 0, 0, 0x387B, 0x4C5E,
-};
-static const unsigned short utf8_to_euc_E58B_x0213[] = {
- 0, 0x5226, 0, 0x4B56, 0xB366, 0x443C, 0xB367, 0x4D26,
- 0x2E62, 0x4A59, 0xA347, 0, 0x2E64, 0x5227, 0, 0xB36A,
- 0x2E65, 0xA349, 0x7055, 0, 0xB36C, 0x4630, 0x2E66, 0x5228,
- 0x342A, 0x4C33, 0, 0x2E67, 0xB36F, 0x3E21, 0x5229, 0x4A67,
- 0x522D, 0xB370, 0x402A, 0x522A, 0x3650, 0xB371, 0x522B, 0x342B,
- 0xB372, 0xB373, 0xB374, 0, 0xB375, 0, 0, 0,
- 0x2E69, 0xB377, 0x372E, 0x522E, 0xB378, 0x522F, 0xB379, 0xA34B,
- 0x5230, 0x5231, 0x3C5B, 0x2E6A, 0, 0, 0x387B, 0x4C5E,
-};
-static const unsigned short utf8_to_euc_E58C[] = {
- 0xB37B, 0x4C68, 0x4677, 0xB37C, 0, 0x4A71, 0x5232, 0xF432,
- 0x5233, 0, 0xB37D, 0xB37E, 0xB421, 0x5235, 0, 0x5237,
- 0x5236, 0xB422, 0, 0xB423, 0, 0x5238, 0x323D, 0x4B4C,
- 0xB424, 0x3A7C, 0x5239, 0xB425, 0xB426, 0x4159, 0xB427, 0xB428,
- 0x3E22, 0x3629, 0, 0x523A, 0xF433, 0xB429, 0, 0xB42A,
- 0xB42B, 0xB42C, 0x485B, 0xB42D, 0xB42E, 0xB42F, 0, 0x523B,
- 0xB430, 0x523C, 0xB431, 0x523D, 0, 0xB432, 0, 0,
- 0x523E, 0x4924, 0x3668, 0x3065, 0xB433, 0xB434, 0xB435, 0x463F,
-};
-static const unsigned short utf8_to_euc_E58C_x0213[] = {
- 0x2E6B, 0x4C68, 0x4677, 0xB37C, 0, 0x4A71, 0x5232, 0x2E6C,
- 0x5233, 0, 0xA34C, 0xA34D, 0xB421, 0x5235, 0, 0x5237,
- 0x5236, 0xB422, 0, 0xB423, 0, 0x5238, 0x323D, 0x4B4C,
- 0xB424, 0x3A7C, 0x5239, 0xB425, 0x2E6D, 0x4159, 0xB427, 0xB428,
- 0x3E22, 0x3629, 0, 0x523A, 0xA34E, 0xB429, 0, 0xB42A,
- 0xB42B, 0xB42C, 0x485B, 0xB42D, 0xB42E, 0xB42F, 0, 0x523B,
- 0xB430, 0x523C, 0xB431, 0x523D, 0, 0xA34F, 0, 0,
- 0x523E, 0x4924, 0x3668, 0x3065, 0xB433, 0xB434, 0xA350, 0x463F,
-};
-static const unsigned short utf8_to_euc_E58D[] = {
- 0x523F, 0x3D3D, 0xB436, 0x4069, 0, 0x5241, 0x5240, 0x3E23,
- 0x3861, 0x5243, 0x483E, 0xB438, 0xB437, 0x5244, 0, 0,
- 0, 0x485C, 0x4234, 0x426E, 0x3628, 0, 0, 0x466E,
- 0x4331, 0xB439, 0x476E, 0xB43A, 0x4B4E, 0, 0x5246, 0,
- 0x406A, 0xB43B, 0, 0xB43C, 0, 0xB43D, 0x3735, 0,
- 0, 0x5247, 0, 0, 0xB43E, 0xB43F, 0x5248, 0x312C,
- 0x3075, 0x346D, 0xB440, 0x4228, 0x3551, 0x4D71, 0, 0x524B,
- 0x3237, 0xB441, 0, 0x524A, 0, 0, 0xB442, 0x362A,
-};
-static const unsigned short utf8_to_euc_E58D_x0213[] = {
- 0x523F, 0x3D3D, 0xA351, 0x4069, 0, 0x5241, 0x5240, 0x3E23,
- 0x3861, 0x5243, 0x483E, 0xB438, 0xB437, 0x5244, 0, 0,
- 0, 0x485C, 0x4234, 0x426E, 0x3628, 0, 0, 0x466E,
- 0x4331, 0xB439, 0x476E, 0xB43A, 0x4B4E, 0, 0x5246, 0,
- 0x406A, 0x2E6F, 0, 0x2E70, 0, 0xB43D, 0x3735, 0xA354,
- 0, 0x5247, 0, 0, 0xA355, 0xB43F, 0x5248, 0x312C,
- 0x3075, 0x346D, 0, 0x4228, 0x3551, 0x4D71, 0, 0x524B,
- 0x3237, 0xB441, 0xA356, 0x524A, 0, 0x2E71, 0xB442, 0x362A,
-};
-static const unsigned short utf8_to_euc_E58E[] = {
- 0, 0, 0x524C, 0xB443, 0x4C71, 0, 0, 0xB444,
- 0xB445, 0, 0, 0, 0, 0, 0xB446, 0,
- 0, 0, 0, 0xB447, 0xB448, 0, 0x524D, 0,
- 0x4E52, 0xB449, 0x387C, 0, 0, 0xB44A, 0, 0x3836,
- 0x524E, 0xB44B, 0, 0, 0xB44C, 0x5250, 0x524F, 0,
- 0x3F5F, 0x3139, 0xB44D, 0xB44E, 0, 0x315E, 0x5251, 0xB44F,
- 0x5252, 0, 0xB450, 0x3837, 0xB451, 0xB452, 0x5253, 0xB453,
- 0xB454, 0, 0xB455, 0x356E, 0, 0xB456, 0, 0,
-};
-static const unsigned short utf8_to_euc_E58E_x0213[] = {
- 0, 0, 0x524C, 0xB443, 0x4C71, 0, 0, 0xB444,
- 0xB445, 0, 0, 0, 0, 0, 0xB446, 0,
- 0, 0, 0, 0x2E72, 0xB448, 0, 0x524D, 0,
- 0x4E52, 0xB449, 0x387C, 0, 0, 0x2E73, 0, 0x3836,
- 0x524E, 0xB44B, 0, 0, 0xA357, 0x5250, 0x524F, 0,
- 0x3F5F, 0x3139, 0xB44D, 0xB44E, 0, 0x315E, 0x5251, 0xB44F,
- 0x5252, 0, 0x2E74, 0x3837, 0xA358, 0xB452, 0x5253, 0xA35A,
- 0xB454, 0, 0xB455, 0x356E, 0, 0xB456, 0, 0,
-};
-static const unsigned short utf8_to_euc_E58F[] = {
- 0xB457, 0, 0x3B32, 0x5254, 0, 0xB458, 0, 0,
- 0x4B74, 0x3A35, 0x355A, 0x4D27, 0x4150, 0x483F, 0x3C7D, 0xB459,
- 0, 0, 0xB45A, 0xB45B, 0x3D47, 0xB45C, 0x3C68, 0x3C75,
- 0, 0x3D76, 0xB45D, 0x4840, 0, 0xB45E, 0xB45F, 0x5257,
- 0xB460, 0x3143, 0x4151, 0x387D, 0x3845, 0x3667, 0xB461, 0xB462,
- 0x525B, 0x4321, 0x427E, 0x362B, 0x3E24, 0x525C, 0x525A, 0x3244,
- 0x4266, 0x3C38, 0x3B4B, 0x3126, 0, 0xB463, 0x3370, 0x3966,
- 0x3B4A, 0, 0x525D, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E58F_x0213[] = {
- 0xA35B, 0, 0x3B32, 0x5254, 0, 0xB458, 0, 0,
- 0x4B74, 0x3A35, 0x355A, 0x4D27, 0x4150, 0x483F, 0x3C7D, 0xB459,
- 0, 0, 0xB45A, 0xB45B, 0x3D47, 0xA35F, 0x3C68, 0x3C75,
- 0, 0x3D76, 0xA360, 0x4840, 0, 0, 0xB45F, 0x5257,
- 0xB460, 0x3143, 0x4151, 0x387D, 0x3845, 0x3667, 0xB461, 0xB462,
- 0x525B, 0x4321, 0x427E, 0x362B, 0x3E24, 0x525C, 0x525A, 0x3244,
- 0x4266, 0x3C38, 0x3B4B, 0x3126, 0xA362, 0xA363, 0x3370, 0x3966,
- 0x3B4A, 0, 0x525D, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E590[] = {
- 0, 0x525E, 0xB464, 0x3549, 0x3346, 0, 0, 0,
- 0x3967, 0x3548, 0x445F, 0x3125, 0x4631, 0x4C3E, 0x3921, 0x4D79,
- 0x4547, 0x387E, 0, 0xB465, 0, 0, 0, 0,
- 0, 0, 0xB466, 0x372F, 0, 0x5267, 0, 0x3663,
- 0x4B4A, 0xB467, 0, 0, 0, 0, 0x485D, 0xB468,
- 0xB469, 0x5266, 0xB46A, 0x345E, 0x5261, 0x5262, 0x5264, 0xB46B,
- 0, 0xB46C, 0, 0, 0xB46D, 0xB46E, 0x5265, 0,
- 0x355B, 0x3F61, 0, 0x4A2D, 0x5263, 0x525F, 0x3863, 0,
-};
-static const unsigned short utf8_to_euc_E590_x0213[] = {
- 0, 0x525E, 0xB464, 0x3549, 0x3346, 0, 0, 0,
- 0x3967, 0x3548, 0x445F, 0x3125, 0x4631, 0x4C3E, 0x3921, 0x4D79,
- 0x4547, 0x387E, 0x2E75, 0xB465, 0, 0, 0, 0,
- 0, 0, 0xB466, 0x372F, 0, 0x5267, 0x4F7E, 0x3663,
- 0x4B4A, 0xB467, 0, 0, 0xA365, 0, 0x485D, 0x2E76,
- 0xA366, 0x5266, 0xB46A, 0x345E, 0x5261, 0x5262, 0x5264, 0xB46B,
- 0, 0xB46C, 0, 0, 0xB46D, 0xB46E, 0x5265, 0,
- 0x355B, 0x3F61, 0, 0x4A2D, 0x5263, 0x525F, 0x3863, 0,
-};
-static const unsigned short utf8_to_euc_E591[] = {
- 0x5260, 0, 0x4F24, 0xB46F, 0xB470, 0, 0x4A72, 0xB471,
- 0x4468, 0x3862, 0x3970, 0, 0, 0xB472, 0x5268, 0xB473,
- 0, 0x465D, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xB474, 0x526C,
- 0, 0, 0xB475, 0, 0xB476, 0, 0xB477, 0xB478,
- 0x3C7E, 0xB479, 0x3C76, 0xB47A, 0, 0xB47B, 0xB47C, 0,
- 0x526F, 0x526D, 0, 0x4C23, 0xB47D, 0x526A, 0x5273, 0x526E,
- 0, 0, 0, 0x5271, 0x3846, 0x4C3F, 0, 0xB47E,
-};
-static const unsigned short utf8_to_euc_E591_x0213[] = {
- 0x5260, 0, 0x4F24, 0xA368, 0xB470, 0, 0x4A72, 0xB471,
- 0x4468, 0x3862, 0x3970, 0, 0, 0x2E77, 0x5268, 0xB473,
- 0, 0x465D, 0, 0, 0, 0xA364, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xB474, 0x526C,
- 0, 0, 0xA369, 0, 0xB476, 0, 0xA36A, 0xB478,
- 0x3C7E, 0xB479, 0x3C76, 0x2E79, 0xA36B, 0xB47B, 0xB47C, 0,
- 0x526F, 0x526D, 0, 0x4C23, 0x2E7A, 0x526A, 0x5273, 0x526E,
- 0, 0, 0, 0x5271, 0x3846, 0x4C3F, 0, 0x2E7B,
-};
-static const unsigned short utf8_to_euc_E592[] = {
- 0x5272, 0xB521, 0, 0xB522, 0x5274, 0xB523, 0x5276, 0,
- 0xB524, 0xB525, 0xF435, 0x3A70, 0x4F42, 0xB526, 0x526B, 0x5269,
- 0x5275, 0xB527, 0x5270, 0, 0, 0xB528, 0xB529, 0,
- 0, 0, 0, 0, 0xB52A, 0, 0, 0xB52B,
- 0, 0xB52C, 0x5278, 0, 0x5323, 0x527A, 0xB52D, 0xB52E,
- 0x527E, 0xB52F, 0xB530, 0x5321, 0x527B, 0xB531, 0xB532, 0x533E,
- 0, 0xB533, 0x3A69, 0x3331, 0, 0, 0, 0xB534,
- 0x5279, 0xB535, 0xB536, 0xB537, 0x5325, 0x3076, 0x5324, 0xB538,
-};
-static const unsigned short utf8_to_euc_E592_x0213[] = {
- 0x5272, 0xB521, 0, 0xB522, 0x5274, 0xB523, 0x5276, 0,
- 0x2E7C, 0xB525, 0xA36C, 0x3A70, 0x4F42, 0xA36D, 0x526B, 0x5269,
- 0x5275, 0xB527, 0x5270, 0, 0, 0xA36E, 0x2E7D, 0,
- 0, 0, 0, 0, 0x2E78, 0, 0, 0xB52B,
- 0xA36F, 0x2E7E, 0x5278, 0, 0x5323, 0x527A, 0xA370, 0xB52E,
- 0x527E, 0x2F21, 0xB530, 0x5321, 0x527B, 0xA371, 0xA372, 0x533E,
- 0, 0xB533, 0x3A69, 0x3331, 0, 0, 0, 0xA373,
- 0x5279, 0xB535, 0xA374, 0xB537, 0x5325, 0x3076, 0x5324, 0xA375,
-};
-static const unsigned short utf8_to_euc_E593[] = {
- 0x3025, 0x494A, 0x5322, 0, 0x527C, 0, 0xB539, 0x5277,
- 0x527D, 0x3A48, 0xB53A, 0, 0, 0xB53B, 0xB53C, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x5326, 0, 0, 0, 0, 0, 0, 0,
- 0xB53D, 0x3077, 0x532F, 0, 0, 0x5327, 0x5328, 0,
- 0x3E25, 0x4B69, 0xB53E, 0, 0xB53F, 0x532D, 0x532C, 0xB540,
- 0, 0, 0x452F, 0, 0, 0, 0xB541, 0,
- 0, 0, 0x532E, 0, 0xB542, 0x532B, 0xB543, 0xB544,
-};
-static const unsigned short utf8_to_euc_E593_x0213[] = {
- 0x3025, 0x494A, 0x5322, 0xA376, 0x527C, 0, 0x2F22, 0x5277,
- 0x527D, 0x3A48, 0xB53A, 0, 0, 0xB53B, 0xB53C, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x5326, 0, 0, 0, 0, 0, 0, 0,
- 0xB53D, 0x3077, 0x532F, 0, 0, 0x5327, 0x5328, 0,
- 0x3E25, 0x4B69, 0xB53E, 0, 0xA378, 0x532D, 0x532C, 0xA379,
- 0, 0xA37A, 0x452F, 0xA37B, 0, 0, 0xB541, 0,
- 0, 0, 0x532E, 0, 0xB542, 0x532B, 0xB543, 0x2F23,
-};
-static const unsigned short utf8_to_euc_E594[] = {
- 0xB545, 0xB546, 0, 0, 0x3134, 0xB547, 0x3A36, 0x3F30,
- 0xB548, 0xB549, 0, 0, 0xB54A, 0xB54B, 0xB54C, 0x5329,
- 0x4562, 0, 0, 0, 0x532A, 0xB54D, 0x3022, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xB54E, 0xB54F, 0, 0, 0x5334, 0x4D23,
- 0, 0x3E27, 0xB550, 0x533A, 0, 0xB551, 0xB552, 0,
- 0x5339, 0x5330, 0, 0xB553, 0xB554, 0xB555, 0x4243, 0,
-};
-static const unsigned short utf8_to_euc_E594_x0213[] = {
- 0xA37C, 0xA37D, 0, 0, 0x3134, 0xB547, 0x3A36, 0x3F30,
- 0xB548, 0xA37E, 0, 0, 0xB54A, 0xB54B, 0x2F24, 0x5329,
- 0x4562, 0, 0, 0, 0x532A, 0xB54D, 0x3022, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xB54E, 0x2F25, 0, 0, 0x5334, 0x4D23,
- 0, 0x3E27, 0xB550, 0x533A, 0, 0x2F26, 0xB552, 0,
- 0x5339, 0x5330, 0, 0xB553, 0xA421, 0xB555, 0x4243, 0,
-};
-static const unsigned short utf8_to_euc_E595[] = {
- 0x5331, 0xB556, 0, 0, 0x426F, 0x5336, 0x3E26, 0xB557,
- 0, 0xB558, 0xB559, 0, 0x5333, 0xB55A, 0, 0x4C64,
- 0xB55B, 0xB55C, 0, 0x373C, 0, 0, 0x5337, 0x5338,
- 0xB55D, 0, 0xB55E, 0xB55F, 0x5335, 0x533B, 0xB560, 0,
- 0xB561, 0xB562, 0, 0x5332, 0xB563, 0, 0xB564, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x5341, 0x5346, 0, 0x5342, 0xB565,
-};
-static const unsigned short utf8_to_euc_E595_x0213[] = {
- 0x5331, 0xA422, 0, 0, 0x426F, 0x5336, 0x3E26, 0xA424,
- 0, 0xB558, 0xA425, 0, 0x5333, 0xB55A, 0, 0x4C64,
- 0x2F27, 0xB55C, 0, 0x373C, 0, 0, 0x5337, 0x5338,
- 0xB55D, 0, 0xB55E, 0xB55F, 0x5335, 0x533B, 0x2F28, 0,
- 0xA427, 0xA428, 0, 0x5332, 0xA429, 0, 0xB564, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x5341, 0x5346, 0xA42B, 0x5342, 0xB565,
-};
-static const unsigned short utf8_to_euc_E596[] = {
- 0x533D, 0xB566, 0xB567, 0x5347, 0x4131, 0, 0xB568, 0x5349,
- 0xB569, 0x3922, 0x533F, 0x437D, 0, 0, 0xB56A, 0xB56B,
- 0, 0xB56C, 0xB56D, 0xB56E, 0xB56F, 0, 0, 0xB570,
- 0x5343, 0x533C, 0x342D, 0, 0x346E, 0x3365, 0x5344, 0x5340,
- 0, 0, 0, 0xB571, 0xB572, 0, 0, 0x3776,
- 0x534A, 0x5348, 0x4153, 0x354A, 0x362C, 0xB573, 0x5345, 0,
- 0x3674, 0, 0xB574, 0, 0, 0, 0x3144, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xB575,
-};
-static const unsigned short utf8_to_euc_E596_x0213[] = {
- 0x533D, 0x2F29, 0xA42C, 0x5347, 0x4131, 0, 0x2F2A, 0x5349,
- 0xA42D, 0x3922, 0x533F, 0x437D, 0, 0, 0x2F2B, 0xB56B,
- 0, 0xA42E, 0xB56D, 0xB56E, 0xB56F, 0, 0, 0xB570,
- 0x5343, 0x533C, 0x342D, 0, 0x346E, 0x3365, 0x5344, 0x5340,
- 0, 0, 0, 0xB571, 0xB572, 0, 0, 0x3776,
- 0x534A, 0x5348, 0x4153, 0x354A, 0x362C, 0x2F2D, 0x5345, 0,
- 0x3674, 0, 0xB574, 0, 0, 0, 0x3144, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xA433,
-};
-static const unsigned short utf8_to_euc_E597[] = {
- 0, 0xB576, 0, 0xB577, 0x534E, 0x534C, 0xB578, 0x5427,
- 0, 0xB579, 0, 0xB57A, 0xB57B, 0, 0xB57C, 0,
- 0, 0xB57D, 0xB57E, 0xB621, 0x5351, 0, 0, 0xB622,
- 0xB623, 0, 0x534B, 0xB624, 0x534F, 0, 0xB625, 0x534D,
- 0, 0, 0xB626, 0x3B4C, 0x5350, 0, 0, 0,
- 0, 0xB627, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xB628, 0x5353,
- 0, 0x5358, 0, 0, 0, 0x5356, 0x5355, 0xB629,
-};
-static const unsigned short utf8_to_euc_E597_x0213[] = {
- 0, 0xB576, 0, 0xB577, 0x534E, 0x534C, 0xB578, 0x5427,
- 0, 0xA434, 0, 0xB57A, 0xA435, 0, 0x2F2E, 0,
- 0, 0xA436, 0xA430, 0xB621, 0x5351, 0, 0, 0xB622,
- 0xB623, 0, 0x534B, 0xB624, 0x534F, 0xA437, 0xB625, 0x534D,
- 0, 0, 0xA439, 0x3B4C, 0x5350, 0, 0, 0,
- 0, 0xA43B, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xB628, 0x5353,
- 0, 0x5358, 0, 0, 0, 0x5356, 0x5355, 0xB629,
-};
-static const unsigned short utf8_to_euc_E598[] = {
- 0, 0, 0, 0, 0, 0xB62A, 0x4332, 0,
- 0xB62B, 0x3245, 0xB62C, 0, 0, 0xB62D, 0xB62E, 0xB62F,
- 0xB630, 0xB631, 0xB632, 0, 0x5352, 0, 0x5354, 0x3E28,
- 0x3133, 0xB633, 0, 0x5357, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x325E, 0, 0, 0xB634, 0, 0, 0x5362,
- 0xB635, 0x3E7C, 0x535E, 0xB636, 0x535C, 0xB637, 0x535D, 0xB638,
- 0x535F, 0xB639, 0, 0xB63A, 0xB63B, 0xB63C, 0, 0xB63D,
-};
-static const unsigned short utf8_to_euc_E598_x0213[] = {
- 0, 0, 0, 0, 0, 0xB62A, 0x4332, 0xA43E,
- 0x2F30, 0x3245, 0xB62C, 0, 0, 0xB62D, 0x2F31, 0xB62F,
- 0xA43F, 0xB631, 0xB632, 0, 0x5352, 0, 0x5354, 0x3E28,
- 0x3133, 0xB633, 0, 0x5357, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xA43C, 0x325E, 0, 0, 0xB634, 0, 0, 0x5362,
- 0xA440, 0x3E7C, 0x535E, 0xB636, 0x535C, 0xB637, 0x535D, 0xA441,
- 0x535F, 0xB639, 0, 0x2F32, 0xB63B, 0xA443, 0, 0xA444,
-};
-static const unsigned short utf8_to_euc_E599[] = {
- 0xB63E, 0xB63F, 0x313D, 0xB640, 0xB641, 0, 0xB642, 0,
- 0, 0xB643, 0, 0xB644, 0x4139, 0xB645, 0x5359, 0xB646,
- 0x535A, 0, 0, 0, 0xB647, 0, 0, 0,
- 0, 0, 0, 0x337A, 0, 0, 0xB648, 0,
- 0xB649, 0xB64A, 0xB64B, 0xB64C, 0x5361, 0, 0xB64D, 0,
- 0x346F, 0xB64E, 0x5364, 0x5360, 0x5363, 0xB64F, 0, 0xB650,
- 0, 0xB651, 0xB652, 0, 0x4A2E, 0xB653, 0, 0,
- 0x4655, 0, 0x4838, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E599_x0213[] = {
- 0xA445, 0xB63F, 0x313D, 0xB640, 0xB641, 0, 0xB642, 0xA446,
- 0, 0x2F33, 0, 0xB644, 0x4139, 0xB645, 0x5359, 0xB646,
- 0x535A, 0, 0, 0x7427, 0xB647, 0, 0, 0,
- 0, 0, 0, 0x337A, 0, 0, 0xA447, 0,
- 0xA448, 0xB64A, 0xB64B, 0xB64C, 0x5361, 0, 0x2F35, 0,
- 0x346F, 0xB64E, 0x5364, 0x5360, 0x5363, 0xA449, 0, 0x2F37,
- 0, 0x2F38, 0x2F39, 0, 0x4A2E, 0xB653, 0x2F34, 0,
- 0x4655, 0, 0x4838, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E59A[] = {
- 0x5366, 0, 0, 0, 0xB654, 0xB655, 0x5365, 0x3345,
- 0xB656, 0, 0x5367, 0xB657, 0xB658, 0, 0, 0x536A,
- 0, 0, 0, 0, 0x5369, 0xB659, 0, 0,
- 0, 0xB65A, 0xB65B, 0, 0, 0xB65C, 0xB65D, 0xB65E,
- 0x5368, 0, 0x4739, 0, 0, 0x536B, 0xB65F, 0xB660,
- 0xB661, 0xB662, 0, 0xB663, 0xB664, 0xB665, 0x536C, 0,
- 0, 0xB666, 0, 0xB667, 0x536E, 0, 0x536D, 0xB668,
- 0, 0, 0, 0, 0x5370, 0, 0xB669, 0,
-};
-static const unsigned short utf8_to_euc_E59A_x0213[] = {
- 0x5366, 0, 0, 0, 0xB654, 0xB655, 0x5365, 0x3345,
- 0xA44B, 0, 0x5367, 0xB657, 0xA44C, 0, 0, 0x536A,
- 0, 0, 0, 0, 0x5369, 0xA44D, 0, 0,
- 0, 0x2F3A, 0xA44E, 0, 0, 0xA44F, 0x2F3B, 0xB65E,
- 0x5368, 0, 0x4739, 0, 0, 0x536B, 0xB65F, 0xB660,
- 0xA450, 0x2F3C, 0, 0xB663, 0x2F3D, 0xA451, 0x536C, 0,
- 0, 0xB666, 0xA452, 0x2F3E, 0x536E, 0, 0x536D, 0xB668,
- 0, 0, 0, 0, 0x5370, 0, 0xB669, 0,
-};
-static const unsigned short utf8_to_euc_E59B[] = {
- 0x5373, 0x5371, 0x536F, 0x5372, 0, 0xB66A, 0, 0,
- 0x5374, 0xB66B, 0xB66C, 0xB66D, 0xB670, 0xB671, 0x5375, 0xB66E,
- 0xB66F, 0x5376, 0, 0x5377, 0, 0, 0, 0x5378,
- 0x5145, 0xB672, 0x3C7C, 0x3B4D, 0xB673, 0xB674, 0x3273, 0xB675,
- 0x3078, 0xB676, 0, 0x4344, 0xB677, 0xB678, 0xB679, 0xB67A,
- 0xB67B, 0, 0, 0xB67D, 0, 0xB67E, 0x5379, 0,
- 0x3A24, 0xB67C, 0x304F, 0x3F5E, 0, 0, 0xB721, 0xB722,
- 0, 0x537A, 0x3847, 0, 0, 0x3971, 0, 0x537C,
-};
-static const unsigned short utf8_to_euc_E59B_x0213[] = {
- 0x5373, 0x5371, 0x536F, 0x5372, 0, 0xA453, 0, 0,
- 0x5374, 0x2F3F, 0x2F40, 0xB66D, 0xB670, 0xA454, 0x5375, 0xB66E,
- 0xB66F, 0x5376, 0, 0x5377, 0, 0, 0, 0x5378,
- 0x5145, 0xB672, 0x3C7C, 0x3B4D, 0xB673, 0xB674, 0x3273, 0xA455,
- 0x3078, 0xB676, 0, 0x4344, 0xB677, 0xB678, 0xB679, 0xB67A,
- 0xA456, 0, 0, 0xB67D, 0, 0xB67E, 0x5379, 0,
- 0x3A24, 0xB67C, 0x304F, 0x3F5E, 0, 0, 0xA457, 0xA458,
- 0, 0x537A, 0x3847, 0, 0, 0x3971, 0, 0x537C,
-};
-static const unsigned short utf8_to_euc_E59C[] = {
- 0x537B, 0xB723, 0xB724, 0x4A60, 0x537D, 0, 0, 0xB725,
- 0x5421, 0x537E, 0xB726, 0x5422, 0xB727, 0x5423, 0, 0x3777,
- 0, 0xB728, 0x3160, 0x5424, 0, 0xB729, 0x5426, 0,
- 0x5425, 0, 0xB72A, 0xB72B, 0x5428, 0xB72C, 0, 0x455A,
- 0xB72D, 0, 0xB72E, 0xB72F, 0xB730, 0xB731, 0x5429, 0x3035,
- 0x3A5F, 0xB732, 0xB733, 0, 0xB734, 0x373D, 0xB735, 0xB736,
- 0x434F, 0, 0, 0xB737, 0xB738, 0, 0, 0x542A,
- 0x542B, 0, 0, 0x542D, 0, 0xB739, 0xB73A, 0xB73B,
-};
-static const unsigned short utf8_to_euc_E59C_x0213[] = {
- 0x537B, 0xB723, 0xB724, 0x4A60, 0x537D, 0, 0, 0xB725,
- 0x5421, 0x537E, 0x2F41, 0x5422, 0xB727, 0x5423, 0, 0x3777,
- 0, 0xB728, 0x3160, 0x5424, 0, 0xA45A, 0x5426, 0,
- 0x5425, 0, 0xB72A, 0xB72B, 0x5428, 0xB72C, 0, 0x455A,
- 0xB72D, 0x2F43, 0xB72E, 0xA45B, 0xB730, 0xB731, 0x5429, 0x3035,
- 0x3A5F, 0xA45D, 0xB733, 0, 0xB734, 0x373D, 0xB735, 0x2F44,
- 0x434F, 0, 0, 0x2F45, 0x2F46, 0, 0, 0x542A,
- 0x542B, 0, 0, 0x542D, 0, 0xB739, 0xB73A, 0xB73B,
-};
-static const unsigned short utf8_to_euc_E59D[] = {
- 0x542E, 0, 0x3A64, 0, 0, 0xB73C, 0xB73D, 0x3651,
- 0, 0, 0x4B37, 0, 0xB73E, 0xB73F, 0x542C, 0x542F,
- 0x3A41, 0x3923, 0xB740, 0, 0, 0, 0, 0,
- 0, 0xF436, 0, 0, 0, 0, 0, 0,
- 0, 0x5433, 0xB741, 0, 0x3A25, 0xB742, 0x4333, 0xB743,
- 0xB744, 0x5430, 0x445A, 0xB745, 0, 0xB746, 0xB747, 0xB748,
- 0xB749, 0xB74A, 0, 0xB74B, 0xB74C, 0xB74D, 0, 0xB74E,
- 0, 0xB74F, 0xB750, 0xB751, 0xB752, 0, 0xB753, 0x5434,
-};
-static const unsigned short utf8_to_euc_E59D_x0213[] = {
- 0x542E, 0, 0x3A64, 0, 0, 0xA45F, 0xA460, 0x3651,
- 0, 0, 0x4B37, 0, 0xA461, 0xA462, 0x542C, 0x542F,
- 0x3A41, 0x3923, 0xB740, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x5433, 0xB741, 0, 0x3A25, 0, 0x4333, 0xB743,
- 0xA464, 0x5430, 0x445A, 0xB745, 0, 0xB746, 0xB747, 0xA465,
- 0x2F47, 0xB74A, 0, 0xA466, 0xA467, 0xA468, 0, 0x2F48,
- 0, 0xB74F, 0xB750, 0xA469, 0x2F49, 0, 0xB753, 0x5434,
-};
-static const unsigned short utf8_to_euc_E59E[] = {
- 0, 0xB754, 0x3F62, 0xB755, 0, 0, 0, 0,
- 0x5432, 0x5435, 0, 0x373F, 0xB756, 0, 0, 0,
- 0, 0, 0, 0x5436, 0xB757, 0xB760, 0, 0xB758,
- 0, 0xB759, 0xB75A, 0, 0xB75B, 0xB75C, 0xB75D, 0xB75E,
- 0x5437, 0xB75F, 0x3924, 0x3340, 0x5439, 0, 0, 0xB761,
- 0xB762, 0xB763, 0x543A, 0, 0xB764, 0, 0, 0,
- 0x543B, 0, 0, 0x5438, 0, 0, 0, 0,
- 0xB765, 0, 0, 0, 0, 0xB766, 0, 0,
-};
-static const unsigned short utf8_to_euc_E59E_x0213[] = {
- 0, 0xB754, 0x3F62, 0xB755, 0, 0, 0, 0,
- 0x5432, 0x5435, 0, 0x373F, 0xB756, 0, 0, 0,
- 0, 0, 0, 0x5436, 0xB757, 0xB760, 0, 0xB758,
- 0, 0xB759, 0xA46D, 0, 0x2F4A, 0xA46E, 0xA46F, 0xB75E,
- 0x5437, 0xB75F, 0x3924, 0x3340, 0x5439, 0, 0, 0xB761,
- 0xA470, 0xB763, 0x543A, 0, 0xA46C, 0, 0, 0,
- 0x543B, 0, 0, 0x5438, 0, 0, 0, 0,
- 0x2F4D, 0, 0, 0, 0, 0xB766, 0, 0,
-};
-static const unsigned short utf8_to_euc_E59F[] = {
- 0x5431, 0, 0, 0x543C, 0, 0, 0x543D, 0xB767,
- 0xB768, 0, 0, 0x4B64, 0xB769, 0, 0x3E6B, 0xB76A,
- 0, 0, 0x543F, 0x5440, 0x543E, 0xB76B, 0x5442, 0,
- 0, 0, 0, 0, 0x4738, 0xB76C, 0xB76D, 0x3068,
- 0x4956, 0xB77E, 0, 0x5443, 0xB76E, 0, 0xB76F, 0xB770,
- 0, 0xB771, 0, 0, 0, 0xB772, 0, 0,
- 0xB773, 0, 0, 0, 0x3E7D, 0xB774, 0xB775, 0x3C39,
- 0xB776, 0x475D, 0x3470, 0, 0x3A6B, 0xB777, 0xB778, 0xB779,
-};
-static const unsigned short utf8_to_euc_E59F_x0213[] = {
- 0x5431, 0, 0, 0x543C, 0, 0, 0x543D, 0x2F4E,
- 0x2F4F, 0, 0, 0x4B64, 0xA473, 0, 0x3E6B, 0x2F50,
- 0, 0, 0x543F, 0x5440, 0x543E, 0xB76B, 0x5442, 0xA471,
- 0, 0, 0, 0, 0x4738, 0xB76C, 0xA476, 0x3068,
- 0x4956, 0xB77E, 0, 0x5443, 0x2F51, 0, 0xA477, 0xB770,
- 0, 0xB771, 0, 0, 0, 0x2F52, 0, 0,
- 0xA478, 0, 0, 0, 0x3E7D, 0x2F53, 0x2F54, 0x3C39,
- 0xA47A, 0x475D, 0x3470, 0xA47B, 0x3A6B, 0xA47C, 0xB778, 0x2F55,
-};
-static const unsigned short utf8_to_euc_E5A0[] = {
- 0x4B59, 0, 0x4632, 0xB77A, 0xB77B, 0x3778, 0x424F, 0,
- 0xB77C, 0xB77D, 0x5441, 0x5444, 0xB821, 0xB822, 0, 0,
- 0, 0, 0, 0, 0, 0x4244, 0, 0,
- 0, 0x5445, 0, 0xB823, 0, 0x5446, 0xB824, 0xB825,
- 0xB826, 0x5448, 0, 0, 0x4469, 0, 0xB827, 0xB828,
- 0, 0, 0x342E, 0, 0, 0xB829, 0, 0x7421,
- 0x3161, 0x4A73, 0xB82A, 0, 0x3E6C, 0x4548, 0, 0,
- 0, 0xB82B, 0x3A66, 0, 0, 0x544E, 0, 0xB82C,
-};
-static const unsigned short utf8_to_euc_E5A0_x0213[] = {
- 0x4B59, 0, 0x4632, 0xB77A, 0xA47D, 0x3778, 0x424F, 0,
- 0xB77C, 0x2F56, 0x5441, 0x5444, 0xB821, 0xB822, 0, 0,
- 0, 0, 0, 0, 0, 0x4244, 0, 0,
- 0, 0x5445, 0, 0xB823, 0, 0x5446, 0xA47E, 0xB825,
- 0xA521, 0x5448, 0, 0, 0x4469, 0, 0xB827, 0xA522,
- 0, 0, 0x342E, 0, 0, 0xB829, 0, 0x7421,
- 0x3161, 0x4A73, 0xA523, 0, 0x3E6C, 0x4548, 0, 0,
- 0, 0xA524, 0x3A66, 0, 0, 0x544E, 0, 0xB82C,
-};
-static const unsigned short utf8_to_euc_E5A1[] = {
- 0x4A3D, 0x4E5D, 0, 0, 0, 0, 0, 0,
- 0, 0xB82D, 0x3274, 0x544A, 0xB82E, 0xB82F, 0, 0xB830,
- 0xB831, 0x413A, 0x544D, 0, 0x4563, 0xB832, 0, 0x4549,
- 0x4564, 0x4839, 0x444D, 0, 0, 0, 0x3A49, 0xB833,
- 0, 0xB834, 0x5449, 0, 0xB835, 0, 0, 0xB836,
- 0xB837, 0x3176, 0, 0x4536, 0, 0, 0, 0,
- 0x544B, 0, 0x5447, 0, 0, 0x3F50, 0, 0,
- 0xB838, 0x544F, 0, 0, 0xB839, 0, 0x3D4E, 0xB83A,
-};
-static const unsigned short utf8_to_euc_E5A1_x0213[] = {
- 0x4A3D, 0x4E5D, 0, 0, 0, 0, 0, 0,
- 0, 0xA526, 0x3274, 0x544A, 0xA527, 0xB82F, 0, 0xB830,
- 0xB831, 0x413A, 0x544D, 0, 0x4563, 0xB832, 0, 0x4549,
- 0x4564, 0x4839, 0x444D, 0, 0, 0, 0x3A49, 0xB833,
- 0, 0x2F58, 0x5449, 0, 0x2F59, 0, 0, 0xA528,
- 0xB837, 0x3176, 0, 0x4536, 0, 0, 0, 0,
- 0x544B, 0, 0x5447, 0, 0, 0x3F50, 0, 0,
- 0xB838, 0x544F, 0, 0, 0x2F5B, 0, 0x3D4E, 0xB83A,
-};
-static const unsigned short utf8_to_euc_E5A2[] = {
- 0xB83B, 0xB83C, 0, 0x362D, 0, 0x5450, 0, 0xB83D,
- 0xB83E, 0xB83F, 0xB840, 0, 0xB841, 0xB842, 0, 0xB843,
- 0xB844, 0, 0, 0x4A68, 0xB845, 0, 0xB846, 0x417D,
- 0, 0, 0, 0, 0x4446, 0xB847, 0xF439, 0x5452,
- 0xB848, 0xB849, 0xB84A, 0, 0, 0, 0xB84B, 0,
- 0x4B4F, 0xB84C, 0, 0x5453, 0, 0, 0x5458, 0,
- 0, 0xB84D, 0xB84E, 0x4A2F, 0, 0, 0, 0,
- 0x5457, 0x5451, 0x5454, 0x5456, 0xB850, 0, 0x3A26, 0,
-};
-static const unsigned short utf8_to_euc_E5A2_x0213[] = {
- 0xB83B, 0xB83C, 0, 0x362D, 0, 0x5450, 0, 0xB83D,
- 0xB83E, 0x2F5C, 0xA529, 0xA52A, 0xB841, 0xA52B, 0, 0xA52C,
- 0xA52D, 0, 0, 0x4A68, 0xA52E, 0, 0xB846, 0x417D,
- 0, 0, 0, 0, 0x4446, 0xA52F, 0x2F5D, 0x5452,
- 0xB848, 0xB849, 0xB84A, 0, 0, 0, 0xB84B, 0,
- 0x4B4F, 0x2F5F, 0xA530, 0x5453, 0, 0, 0x5458, 0,
- 0, 0xA531, 0, 0x4A2F, 0, 0, 0, 0,
- 0x5457, 0x5451, 0x5454, 0x5456, 0xB850, 0, 0x3A26, 0,
-};
-static const unsigned short utf8_to_euc_E5A3[] = {
- 0, 0x4A49, 0xB851, 0, 0xB84F, 0x5459, 0, 0x4345,
- 0xB852, 0, 0x3275, 0, 0x3E6D, 0xB853, 0xB854, 0,
- 0xB855, 0x545B, 0xB856, 0x545A, 0xB857, 0x3968, 0xB858, 0x545C,
- 0x545E, 0x545D, 0xB859, 0, 0x5460, 0xB85A, 0x5455, 0x5462,
- 0, 0xB85B, 0xB85C, 0, 0x5461, 0x545F, 0, 0,
- 0, 0xB85D, 0, 0x3B4E, 0x3F51, 0, 0x4154, 0x5463,
- 0x403C, 0x306D, 0x4764, 0xB85E, 0, 0, 0, 0x445B,
- 0, 0x5465, 0x5464, 0x5466, 0x5467, 0x5468, 0, 0,
-};
-static const unsigned short utf8_to_euc_E5A3_x0213[] = {
- 0, 0x4A49, 0xB851, 0xA533, 0xB84F, 0x5459, 0, 0x4345,
- 0xB852, 0, 0x3275, 0, 0x3E6D, 0xA534, 0x2F62, 0,
- 0xB855, 0x545B, 0x2F61, 0x545A, 0x2F63, 0x3968, 0xB858, 0x545C,
- 0x545E, 0x545D, 0x2F64, 0, 0x5460, 0xB85A, 0x5455, 0x5462,
- 0x2F65, 0xB85B, 0xA535, 0, 0x5461, 0x545F, 0, 0,
- 0, 0x2F66, 0, 0x3B4E, 0x3F51, 0, 0x4154, 0x5463,
- 0x403C, 0x306D, 0x4764, 0xA536, 0xA537, 0, 0, 0x445B,
- 0, 0x5465, 0x5464, 0x5466, 0x5467, 0x5468, 0, 0,
-};
-static const unsigned short utf8_to_euc_E5A4[] = {
- 0, 0, 0x5469, 0, 0, 0xB85F, 0xB860, 0,
- 0, 0x4A51, 0x546A, 0xB861, 0xB862, 0, 0, 0x3246,
- 0x546B, 0, 0xB863, 0xB864, 0xB865, 0x4D3C, 0x3330, 0,
- 0x5249, 0x3D48, 0x423F, 0x546C, 0x4C6B, 0xB867, 0, 0,
- 0, 0xB868, 0x4C34, 0xB869, 0xB86A, 0x546E, 0, 0x4267,
- 0xB86B, 0x4537, 0x4240, 0x4957, 0x546F, 0x5470, 0x317B, 0xB86C,
- 0xB86D, 0x3C3A, 0x5471, 0xB86E, 0, 0xB86F, 0xB870, 0x3050,
- 0x5472, 0, 0, 0, 0, 0, 0x5473, 0xB871,
-};
-static const unsigned short utf8_to_euc_E5A4_x0213[] = {
- 0, 0, 0x5469, 0, 0, 0xA538, 0xA539, 0,
- 0, 0x4A51, 0x546A, 0xA53A, 0x2F67, 0xA53B, 0, 0x3246,
- 0x546B, 0, 0xB863, 0xB864, 0xA53C, 0x4D3C, 0x3330, 0,
- 0x5249, 0x3D48, 0x423F, 0x546C, 0x4C6B, 0xB867, 0, 0,
- 0, 0xB868, 0x4C34, 0xB869, 0xA53D, 0x546E, 0, 0x4267,
- 0xB86B, 0x4537, 0x4240, 0x4957, 0x546F, 0x5470, 0x317B, 0xB86C,
- 0xB86D, 0x3C3A, 0x5471, 0xB86E, 0, 0xB86F, 0xB870, 0x3050,
- 0x5472, 0, 0, 0, 0, 0xA540, 0x5473, 0xB871,
-};
-static const unsigned short utf8_to_euc_E5A5[] = {
- 0, 0, 0, 0xB872, 0x3162, 0, 0xB873, 0x3471,
- 0x4660, 0x4A74, 0, 0, 0, 0, 0x5477, 0x4155,
- 0x5476, 0x3740, 0xB874, 0xB875, 0x4B5B, 0x5475, 0, 0x4565,
- 0x5479, 0xB876, 0x5478, 0xB877, 0, 0xB878, 0xB879, 0xB87A,
- 0x547B, 0xB87B, 0x547A, 0xB87C, 0, 0x317C, 0, 0x547C,
- 0x3E29, 0x547E, 0x4325, 0xB87D, 0x547D, 0xB87E, 0x4A33, 0xB921,
- 0, 0, 0xB922, 0x3D77, 0x455B, 0xB923, 0xB924, 0,
- 0x5521, 0xB925, 0, 0xB926, 0xB927, 0x3925, 0, 0,
-};
-static const unsigned short utf8_to_euc_E5A5_x0213[] = {
- 0, 0, 0, 0xB872, 0x3162, 0, 0xA542, 0x3471,
- 0x4660, 0x4A74, 0, 0, 0, 0, 0x5477, 0x4155,
- 0x5476, 0x3740, 0xB874, 0, 0x4B5B, 0x5475, 0, 0x4565,
- 0x5479, 0xB876, 0x5478, 0xA545, 0, 0x2F69, 0xB879, 0xA546,
- 0x547B, 0xB87B, 0x547A, 0, 0, 0x317C, 0, 0x547C,
- 0x3E29, 0x547E, 0x4325, 0xB87D, 0x547D, 0x2F6A, 0x4A33, 0xB921,
- 0, 0, 0xB922, 0x3D77, 0x455B, 0xA548, 0xA549, 0,
- 0x5521, 0xB925, 0, 0xB926, 0xA54A, 0x3925, 0, 0,
-};
-static const unsigned short utf8_to_euc_E5A6[] = {
- 0, 0x5522, 0x4721, 0x485E, 0x4C51, 0, 0, 0,
- 0, 0, 0x4725, 0xB928, 0xB929, 0x552B, 0xB92A, 0,
- 0, 0, 0xB92B, 0x3538, 0, 0xB92C, 0x4D45, 0xB92D,
- 0, 0x4C2F, 0, 0x562C, 0, 0x5523, 0, 0xB92E,
- 0, 0, 0, 0x5526, 0xB92F, 0x4245, 0, 0xB930,
- 0x4B38, 0, 0, 0, 0x454A, 0xB931, 0xB932, 0xB933,
- 0xB934, 0, 0x5527, 0xB935, 0, 0, 0, 0xB936,
- 0, 0x4B65, 0xB937, 0x3A4A, 0xB938, 0, 0x3E2A, 0,
-};
-static const unsigned short utf8_to_euc_E5A6_x0213[] = {
- 0, 0x5522, 0x4721, 0x485E, 0x4C51, 0, 0, 0,
- 0, 0, 0x4725, 0x2F6B, 0xB929, 0x552B, 0xB92A, 0,
- 0, 0, 0x2F6C, 0x3538, 0, 0xB92C, 0x4D45, 0xB92D,
- 0, 0x4C2F, 0, 0x562C, 0, 0x5523, 0, 0xA54B,
- 0, 0, 0, 0x5526, 0x2F6D, 0x4245, 0, 0xB930,
- 0x4B38, 0, 0, 0, 0x454A, 0xB931, 0xA54C, 0xB933,
- 0xB934, 0, 0x5527, 0xB935, 0, 0, 0, 0xB936,
- 0, 0x4B65, 0, 0x3A4A, 0xA54D, 0, 0x3E2A, 0,
-};
-static const unsigned short utf8_to_euc_E5A7[] = {
- 0, 0xB939, 0, 0xB93A, 0xB93B, 0, 0x5528, 0,
- 0xB93C, 0x3B50, 0xB93D, 0x3B4F, 0, 0xB93E, 0, 0,
- 0x3039, 0x3848, 0xB93F, 0x402B, 0x3051, 0, 0, 0,
- 0, 0x552C, 0x552D, 0, 0x552A, 0xB940, 0xB941, 0xB942,
- 0, 0, 0, 0xB943, 0xB944, 0x3138, 0x342F, 0xB945,
- 0x5529, 0, 0x4C45, 0x4931, 0, 0, 0xB946, 0xB947,
- 0, 0xB948, 0xB949, 0, 0xB94A, 0, 0x3028, 0xB94B,
- 0, 0, 0, 0x3079, 0, 0, 0, 0x3B51,
-};
-static const unsigned short utf8_to_euc_E5A7_x0213[] = {
- 0, 0xB939, 0, 0x2F6E, 0xB93B, 0, 0x5528, 0,
- 0xA54E, 0x3B50, 0xB93D, 0x3B4F, 0, 0xA54F, 0, 0,
- 0x3039, 0x3848, 0x2F6F, 0x402B, 0x3051, 0, 0, 0,
- 0, 0x552C, 0x552D, 0, 0x552A, 0x2F70, 0xA550, 0xB942,
- 0, 0, 0, 0xA551, 0xA552, 0x3138, 0x342F, 0xA553,
- 0x5529, 0, 0x4C45, 0x4931, 0, 0, 0xA554, 0xB947,
- 0, 0xB948, 0xB949, 0, 0xB94A, 0, 0x3028, 0xB94B,
- 0x7E7A, 0, 0, 0x3079, 0, 0, 0, 0x3B51,
-};
-static const unsigned short utf8_to_euc_E5A8[] = {
- 0xB94C, 0x3052, 0, 0x3023, 0xB94D, 0, 0, 0,
- 0, 0x5532, 0, 0, 0xB94E, 0xB94F, 0xB950, 0,
- 0, 0x5530, 0xB951, 0xB952, 0, 0, 0, 0,
- 0x4C3C, 0, 0x5533, 0, 0x5531, 0, 0xB953, 0x552F,
- 0x3F31, 0, 0, 0xB954, 0xB955, 0x552E, 0, 0xB956,
- 0xB957, 0x4A5A, 0xB958, 0, 0, 0xB959, 0, 0x3864,
- 0xB95A, 0, 0, 0, 0, 0x5537, 0x5538, 0,
- 0, 0, 0, 0, 0x3E2B, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E5A8_x0213[] = {
- 0xB94C, 0x3052, 0, 0x3023, 0xB94D, 0, 0, 0,
- 0, 0x5532, 0, 0, 0xA558, 0xA559, 0xB950, 0,
- 0, 0x5530, 0xB951, 0x2F71, 0, 0, 0, 0xA55A,
- 0x4C3C, 0, 0x5533, 0, 0x5531, 0, 0xB953, 0x552F,
- 0x3F31, 0, 0, 0x2F72, 0xB955, 0x552E, 0, 0xA55B,
- 0xB957, 0x4A5A, 0xB958, 0, 0, 0xA55C, 0, 0x3864,
- 0xB95A, 0, 0, 0, 0, 0x5537, 0x5538, 0,
- 0, 0, 0, 0, 0x3E2B, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E5A9[] = {
- 0x5534, 0x4F2C, 0, 0, 0xB95B, 0xB95C, 0x474C, 0xB95D,
- 0xB95E, 0x5536, 0, 0, 0xB95F, 0, 0, 0,
- 0xB960, 0, 0, 0, 0, 0xB961, 0, 0,
- 0, 0, 0x3A27, 0, 0, 0, 0xB962, 0,
- 0, 0, 0x5539, 0xB963, 0, 0xB964, 0x4958, 0xB965,
- 0, 0, 0x553A, 0, 0x5535, 0xB966, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xB967,
- 0, 0, 0xB968, 0xB969, 0, 0, 0xB96A, 0x4C3B,
-};
-static const unsigned short utf8_to_euc_E5A9_x0213[] = {
- 0x5534, 0x4F2C, 0, 0, 0xB95B, 0xB95C, 0x474C, 0xB95D,
- 0xB95E, 0x5536, 0, 0, 0xB95F, 0, 0, 0,
- 0xB960, 0, 0, 0, 0, 0xA55D, 0, 0,
- 0, 0, 0x3A27, 0, 0, 0, 0xB962, 0,
- 0, 0, 0x5539, 0xB963, 0, 0xA55E, 0x4958, 0x2F73,
- 0, 0, 0x553A, 0, 0x5535, 0x2F74, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x2F75,
- 0, 0, 0xA55F, 0xB969, 0, 0, 0x2F76, 0x4C3B,
-};
-static const unsigned short utf8_to_euc_E5AA[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xB96B, 0, 0, 0, 0,
- 0xB96C, 0, 0x475E, 0xB96D, 0, 0, 0xB96E, 0,
- 0, 0xB96F, 0x553B, 0x4932, 0xB970, 0, 0xB971, 0xB972,
- 0xB973, 0, 0xB974, 0, 0, 0, 0, 0xB975,
- 0, 0, 0, 0, 0xB976, 0, 0, 0,
- 0, 0xB977, 0xB978, 0xB979, 0, 0xB97A, 0, 0,
- 0xB97B, 0, 0xB97C, 0xB97D, 0x553C, 0x5540, 0x553D, 0xB97E,
-};
-static const unsigned short utf8_to_euc_E5AA_x0213[] = {
- 0, 0, 0, 0, 0x2F77, 0, 0, 0,
- 0, 0, 0, 0xA560, 0, 0, 0, 0,
- 0xB96C, 0, 0x475E, 0xB96D, 0, 0, 0xB96E, 0,
- 0, 0xB96F, 0x553B, 0x4932, 0xA561, 0, 0x2F78, 0xA562,
- 0xA563, 0, 0xA564, 0, 0, 0, 0, 0x2F79,
- 0, 0, 0, 0, 0xB976, 0, 0, 0,
- 0, 0xA565, 0xB978, 0xA566, 0, 0xA567, 0, 0,
- 0xB97B, 0, 0xA568, 0xB97D, 0x553C, 0x5540, 0x553D, 0xA569,
-};
-static const unsigned short utf8_to_euc_E5AB[] = {
- 0, 0x3247, 0x553F, 0, 0xBA21, 0, 0xBA22, 0,
- 0xBA23, 0x3C3B, 0, 0x553E, 0x3779, 0, 0, 0xBA24,
- 0x554C, 0, 0, 0, 0, 0, 0x5545, 0x5542,
- 0, 0, 0xBA25, 0, 0xBA26, 0, 0, 0,
- 0xBA27, 0x4364, 0, 0x5541, 0, 0xBA28, 0x5543, 0,
- 0, 0x5544, 0xBA29, 0, 0, 0, 0xBA2A, 0,
- 0, 0, 0, 0, 0, 0xBA2B, 0xBA2C, 0,
- 0, 0, 0x5546, 0x5547, 0, 0xBA2D, 0, 0,
-};
-static const unsigned short utf8_to_euc_E5AB_x0213[] = {
- 0, 0x3247, 0x553F, 0, 0x2F7A, 0, 0xBA22, 0,
- 0xBA23, 0x3C3B, 0, 0x553E, 0x3779, 0, 0, 0xBA24,
- 0x554C, 0, 0, 0, 0, 0, 0x5545, 0x5542,
- 0, 0, 0xA56A, 0, 0xA56B, 0, 0, 0,
- 0xA56C, 0x4364, 0, 0x5541, 0, 0xA56D, 0x5543, 0,
- 0, 0x5544, 0xBA29, 0, 0, 0, 0xA56F, 0,
- 0xA56E, 0, 0, 0, 0, 0xA570, 0xBA2C, 0,
- 0, 0, 0x5546, 0x5547, 0, 0xBA2D, 0, 0,
-};
-static const unsigned short utf8_to_euc_E5AC[] = {
- 0xBA2E, 0xBA2F, 0, 0, 0, 0, 0, 0,
- 0xBA30, 0x3472, 0, 0x5549, 0x5548, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x554A, 0xBA31,
- 0, 0xBA33, 0, 0xBA34, 0, 0xBA35, 0, 0,
- 0, 0xBA36, 0x3E6E, 0, 0, 0xBA37, 0, 0,
- 0, 0, 0x554D, 0, 0x445C, 0xBA38, 0, 0,
- 0x3145, 0, 0x554B, 0, 0xBA32, 0, 0x554E, 0,
- 0xBA39, 0, 0, 0, 0, 0, 0x554F, 0,
-};
-static const unsigned short utf8_to_euc_E5AC_x0213[] = {
- 0xA571, 0xBA2F, 0, 0, 0, 0, 0, 0,
- 0xA572, 0x3472, 0, 0x5549, 0x5548, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x554A, 0xA573,
- 0, 0x2F7C, 0, 0xBA34, 0, 0xBA35, 0, 0,
- 0, 0xBA36, 0x3E6E, 0, 0, 0x2F7D, 0, 0,
- 0, 0, 0x554D, 0, 0x445C, 0xA575, 0, 0,
- 0x3145, 0, 0x554B, 0, 0xA574, 0, 0x554E, 0,
- 0xBA39, 0, 0, 0, 0, 0, 0x554F, 0,
-};
-static const unsigned short utf8_to_euc_E5AD[] = {
- 0x5552, 0xBA3A, 0, 0x5550, 0, 0x5551, 0, 0,
- 0, 0, 0, 0xBA3B, 0xBA3C, 0, 0, 0,
- 0x3B52, 0x5553, 0xBA3D, 0, 0x3926, 0x5554, 0xBA3E, 0x3B7A,
- 0x4238, 0, 0x5555, 0x5556, 0x3B5A, 0x3927, 0xBA3F, 0x4C52,
- 0, 0, 0, 0x3528, 0x3849, 0x5557, 0x3358, 0,
- 0xBA40, 0x5558, 0, 0x4239, 0, 0, 0xBA41, 0xBA42,
- 0x5559, 0x5623, 0, 0x555A, 0, 0x555B, 0, 0,
- 0x555C, 0, 0x555E, 0, 0xBA43, 0xBA44, 0xBA45, 0xBA46,
-};
-static const unsigned short utf8_to_euc_E5AD_x0213[] = {
- 0x5552, 0x4F55, 0, 0x5550, 0, 0x5551, 0, 0,
- 0, 0, 0, 0xBA3B, 0xA576, 0, 0, 0,
- 0x3B52, 0x5553, 0xA577, 0, 0x3926, 0x5554, 0x4F56, 0x3B7A,
- 0x4238, 0, 0x5555, 0x5556, 0x3B5A, 0x3927, 0xBA3F, 0x4C52,
- 0, 0, 0, 0x3528, 0x3849, 0x5557, 0x3358, 0,
- 0xA578, 0x5558, 0, 0x4239, 0, 0, 0xBA41, 0xA579,
- 0x5559, 0x5623, 0, 0x555A, 0, 0x555B, 0, 0,
- 0x555C, 0, 0x555E, 0, 0xA57A, 0x4F57, 0xBA45, 0xA57B,
-};
-static const unsigned short utf8_to_euc_E5AE[] = {
- 0x555F, 0xBA47, 0, 0x5560, 0xBA48, 0x4270, 0xBA49, 0x3127,
- 0x3C69, 0x3042, 0xBA4A, 0x4157, 0x3430, 0x3C35, 0xBA4B, 0x3928,
- 0xBA4C, 0xBA4D, 0, 0xBA4E, 0xBA4F, 0x4566, 0xBA50, 0x3D21,
- 0x3431, 0x4368, 0x446A, 0x3038, 0x3539, 0x4A75, 0, 0x3C42,
- 0, 0, 0x3552, 0x406B, 0x3C3C, 0x4D28, 0x5561, 0,
- 0xBA51, 0xBA52, 0, 0, 0xBA53, 0xBA54, 0x355C, 0xBA55,
- 0x3A4B, 0xBA56, 0xBA57, 0x3332, 0x3163, 0x3E2C, 0x3248, 0xBA58,
- 0x5562, 0x4D46, 0xBA59, 0, 0xBA5A, 0, 0, 0x3D49,
-};
-static const unsigned short utf8_to_euc_E5AE_x0213[] = {
- 0x555F, 0xA57C, 0, 0x5560, 0xA57D, 0x4270, 0xBA49, 0x3127,
- 0x3C69, 0x3042, 0xBA4A, 0x4157, 0x3430, 0x3C35, 0xBA4B, 0x3928,
- 0xBA4C, 0xBA4D, 0, 0x4F58, 0xBA4F, 0x4566, 0xA821, 0x3D21,
- 0x3431, 0x4368, 0x446A, 0x3038, 0x3539, 0x4A75, 0, 0x3C42,
- 0, 0, 0x3552, 0x406B, 0x3C3C, 0x4D28, 0x5561, 0,
- 0xBA51, 0xBA52, 0, 0, 0xA822, 0xBA54, 0x355C, 0xBA55,
- 0x3A4B, 0xBA56, 0xBA57, 0x3332, 0x3163, 0x3E2C, 0x3248, 0xBA58,
- 0x5562, 0x4D46, 0xBA59, 0, 0xBA5A, 0, 0, 0x3D49,
-};
-static const unsigned short utf8_to_euc_E5AF[] = {
- 0xBA5B, 0xBA5C, 0x3C64, 0x5563, 0x3473, 0x4652, 0x4C29, 0x5564,
- 0, 0x5565, 0, 0, 0x4959, 0xBA5D, 0, 0xBA5E,
- 0x5567, 0, 0x3428, 0x3677, 0x5566, 0, 0xBA5F, 0xBA60,
- 0xBA61, 0xBA62, 0xBA63, 0x3432, 0, 0x3F32, 0x556B, 0x3B21,
- 0xBA64, 0x3249, 0x556A, 0, 0x5568, 0x556C, 0x5569, 0x472B,
- 0x5C4D, 0x3F33, 0, 0x556D, 0xF43A, 0, 0x4E40, 0xBA65,
- 0x556E, 0xBA66, 0, 0x5570, 0xBA67, 0x437E, 0x556F, 0,
- 0x4023, 0, 0x3B7B, 0, 0, 0xBA68, 0x4250, 0x3C77,
-};
-static const unsigned short utf8_to_euc_E5AF_x0213[] = {
- 0xA824, 0xBA5C, 0x3C64, 0x5563, 0x3473, 0x4652, 0x4C29, 0x5564,
- 0, 0x5565, 0, 0, 0x4959, 0xBA5D, 0xA826, 0xBA5E,
- 0x5567, 0, 0x3428, 0x3677, 0x5566, 0, 0xA827, 0xBA60,
- 0x4F59, 0xBA62, 0xBA63, 0x3432, 0, 0x3F32, 0x556B, 0x3B21,
- 0xBA64, 0x3249, 0x556A, 0, 0x5568, 0x556C, 0x5569, 0x472B,
- 0x5C4D, 0x3F33, 0, 0x556D, 0x4F5A, 0, 0x4E40, 0xBA65,
- 0x556E, 0xA82A, 0, 0x5570, 0xBA67, 0x437E, 0x556F, 0,
- 0x4023, 0, 0x3B7B, 0, 0, 0xA82B, 0x4250, 0x3C77,
-};
-static const unsigned short utf8_to_euc_E5B0[] = {
- 0, 0x4975, 0x406C, 0, 0x3C4D, 0x5571, 0x3E2D, 0x5572,
- 0x5573, 0x3053, 0x423A, 0x3F52, 0xBA69, 0x5574, 0x4633, 0x3E2E,
- 0, 0x3E2F, 0, 0x5575, 0, 0, 0x406D, 0xBA6A,
- 0, 0, 0x3E30, 0, 0, 0, 0xBA6B, 0xBA6C,
- 0x5576, 0, 0x5577, 0xBA6D, 0x4C60, 0, 0xBA6E, 0,
- 0x5578, 0xBA6F, 0, 0xBA70, 0xBA71, 0x3646, 0xBA72, 0,
- 0xBA73, 0x3D22, 0xBA74, 0, 0, 0xBA75, 0xBA76, 0,
- 0x5579, 0x557A, 0x3C5C, 0x3F2C, 0x4674, 0x3F54, 0x4878, 0x4722,
-};
-static const unsigned short utf8_to_euc_E5B0_x0213[] = {
- 0, 0x4975, 0x406C, 0xA82D, 0x3C4D, 0x5571, 0x3E2D, 0x5572,
- 0x5573, 0x3053, 0x423A, 0x3F52, 0xBA69, 0x5574, 0x4633, 0x3E2E,
- 0, 0x3E2F, 0x4F5B, 0x5575, 0, 0, 0x406D, 0xBA6A,
- 0, 0, 0x3E30, 0, 0, 0, 0x4F5C, 0xBA6C,
- 0x5576, 0, 0x5577, 0x4F5D, 0x4C60, 0, 0xBA6E, 0,
- 0x5578, 0xA82E, 0, 0x4F5E, 0xBA71, 0x3646, 0xBA72, 0,
- 0xA82F, 0x3D22, 0xBA74, 0, 0, 0xBA75, 0xBA76, 0,
- 0x5579, 0x557A, 0x3C5C, 0x3F2C, 0x4674, 0x3F54, 0x4878, 0x4722,
-};
-static const unsigned short utf8_to_euc_E5B1[] = {
- 0x3649, 0x557B, 0, 0, 0, 0x356F, 0x557C, 0,
- 0x367E, 0, 0x464F, 0x3230, 0, 0x3B53, 0x557D, 0x5622,
- 0x5621, 0x367D, 0, 0x557E, 0, 0x4538, 0, 0,
- 0, 0xBA77, 0xBA78, 0, 0xBA79, 0, 0x4230, 0,
- 0x454B, 0x3C48, 0xBA7A, 0xBA7B, 0x4158, 0x4D7A, 0, 0xBA7C,
- 0xBA7D, 0xBA7E, 0, 0, 0x5624, 0xBB21, 0x5625, 0x4656,
- 0xBB22, 0x3B33, 0, 0, 0xBB23, 0xBB24, 0x5627, 0,
- 0, 0x5628, 0xBB25, 0xBB26, 0xBB27, 0xBB28, 0, 0,
-};
-static const unsigned short utf8_to_euc_E5B1_x0213[] = {
- 0x3649, 0x557B, 0, 0, 0, 0x356F, 0x557C, 0,
- 0x367E, 0, 0x464F, 0x3230, 0, 0x3B53, 0x557D, 0x5622,
- 0x5621, 0x367D, 0, 0x557E, 0, 0x4538, 0, 0,
- 0, 0xBA77, 0xBA78, 0x7E7B, 0xBA79, 0, 0x4230, 0xA831,
- 0x454B, 0x3C48, 0x4F60, 0xA832, 0x4158, 0x4D7A, 0, 0xA833,
- 0xA834, 0xA835, 0, 0, 0x5624, 0xBB21, 0x5625, 0x4656,
- 0xA836, 0x3B33, 0, 0, 0xBB23, 0xBB24, 0x5627, 0,
- 0, 0x5628, 0x4F64, 0xBB26, 0xA839, 0xBB28, 0, 0,
-};
-static const unsigned short utf8_to_euc_E5B2[] = {
- 0, 0, 0, 0, 0, 0, 0, 0xBB29,
- 0xBB2A, 0, 0xBB2B, 0, 0x5629, 0, 0, 0xBB2C,
- 0x3474, 0x562A, 0xBB2D, 0, 0x562B, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xBB2E, 0, 0xBB2F,
- 0xBB30, 0x322C, 0xBB31, 0xBB32, 0, 0, 0xBB33, 0,
- 0x413B, 0x3464, 0xBB34, 0x562D, 0x4C28, 0, 0, 0,
- 0, 0x4252, 0xBB35, 0x3359, 0xBB36, 0xBB37, 0x562F, 0x5631,
- 0x345F, 0, 0xBB38, 0x562E, 0x5630, 0, 0x5633, 0,
-};
-static const unsigned short utf8_to_euc_E5B2_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0xBB29,
- 0xA83C, 0, 0xA83D, 0, 0x5629, 0, 0, 0x4F65,
- 0x3474, 0x562A, 0xBB2D, 0, 0x562B, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xBB2E, 0, 0x4F66,
- 0xA841, 0x322C, 0xA842, 0x4F67, 0, 0, 0xA843, 0xA844,
- 0x413B, 0x3464, 0x4F68, 0x562D, 0x4C28, 0xA846, 0, 0,
- 0, 0x4252, 0xBB35, 0x3359, 0xBB36, 0xA847, 0x562F, 0x5631,
- 0x345F, 0, 0x4F69, 0x562E, 0x5630, 0, 0x5633, 0,
-};
-static const unsigned short utf8_to_euc_E5B3[] = {
- 0, 0, 0, 0, 0, 0x5632, 0, 0x5634,
- 0, 0xBB39, 0, 0xBB3A, 0, 0, 0, 0,
- 0, 0, 0xBB3B, 0, 0, 0, 0, 0xBB3D,
- 0, 0x5635, 0, 0, 0, 0xBB3C, 0, 0,
- 0x463D, 0x362E, 0, 0, 0, 0, 0, 0,
- 0x3265, 0x5636, 0x563B, 0, 0, 0x5639, 0xBB3E, 0x4A77,
- 0x4A76, 0xBB3F, 0xBB40, 0, 0xBB41, 0xF43B, 0x4567, 0,
- 0, 0, 0x5638, 0x3D54, 0, 0x5637, 0, 0,
-};
-static const unsigned short utf8_to_euc_E5B3_x0213[] = {
- 0, 0, 0, 0, 0, 0x5632, 0, 0x5634,
- 0, 0xA849, 0, 0x4F6A, 0, 0, 0, 0,
- 0x4F6B, 0, 0x4F6C, 0, 0, 0, 0, 0xBB3D,
- 0, 0x5635, 0, 0, 0, 0xBB3C, 0, 0,
- 0x463D, 0x362E, 0, 0, 0, 0, 0, 0,
- 0x3265, 0x5636, 0x563B, 0, 0, 0x5639, 0xBB3E, 0x4A77,
- 0x4A76, 0xBB3F, 0xBB40, 0, 0x4F6D, 0, 0x4567, 0,
- 0, 0, 0x5638, 0x3D54, 0, 0x5637, 0, 0,
-};
-static const unsigned short utf8_to_euc_E5B4[] = {
- 0, 0xBB42, 0, 0, 0, 0, 0xBB43, 0x3F72,
- 0, 0, 0, 0x563C, 0, 0xBB44, 0x3A6A, 0,
- 0, 0x5642, 0xBB45, 0, 0x5643, 0x563D, 0x3333, 0x563E,
- 0x5647, 0x5646, 0x5645, 0x5641, 0, 0, 0, 0x5640,
- 0, 0, 0x5644, 0xBB47, 0xBB48, 0, 0xBB49, 0xBB4A,
- 0, 0x4A78, 0, 0xBB46, 0, 0, 0, 0,
- 0, 0xBB4B, 0, 0, 0xBB4C, 0, 0, 0,
- 0, 0xBB4D, 0, 0, 0, 0xBB4E, 0, 0xBB4F,
-};
-static const unsigned short utf8_to_euc_E5B4_x0213[] = {
- 0, 0xBB42, 0, 0, 0, 0, 0xA84C, 0x3F72,
- 0, 0, 0, 0x563C, 0, 0x4F70, 0x3A6A, 0,
- 0xA84D, 0x5642, 0xBB45, 0, 0x5643, 0x563D, 0x3333, 0x563E,
- 0x5647, 0x5646, 0x5645, 0x5641, 0, 0xA84F, 0, 0x5640,
- 0xA850, 0, 0x5644, 0xBB47, 0xA851, 0, 0xA852, 0x4F71,
- 0, 0x4A78, 0, 0xA84E, 0, 0, 0, 0,
- 0, 0xA853, 0, 0, 0xBB4C, 0, 0, 0,
- 0, 0xA854, 0, 0, 0, 0xBB4E, 0, 0xBB4F,
-};
-static const unsigned short utf8_to_euc_E5B5[] = {
- 0, 0, 0xBB50, 0xBB51, 0, 0, 0xBB52, 0,
- 0xBB53, 0, 0xBB57, 0x564B, 0x5648, 0, 0x564A, 0,
- 0x4D72, 0xBB55, 0x5649, 0xF43C, 0, 0xBB54, 0, 0,
- 0, 0xBB56, 0, 0, 0x563F, 0, 0, 0xBB58,
- 0xBB59, 0xBB5A, 0xBB5B, 0, 0xBB5C, 0, 0, 0,
- 0, 0x3F73, 0xBB5D, 0, 0x564C, 0xBB5E, 0, 0x3A37,
- 0xBB5F, 0, 0, 0x564D, 0, 0, 0x564E, 0,
- 0, 0xBB60, 0xBB61, 0, 0, 0, 0xBB62, 0xBB63,
-};
-static const unsigned short utf8_to_euc_E5B5_x0213[] = {
- 0, 0, 0xA855, 0xBB51, 0, 0, 0x4F73, 0x4F74,
- 0xBB53, 0, 0x4F76, 0x564B, 0x5648, 0, 0x564A, 0,
- 0x4D72, 0xBB55, 0x5649, 0x4F75, 0, 0xBB54, 0, 0,
- 0, 0xBB56, 0, 0, 0x563F, 0, 0, 0xBB58,
- 0xBB59, 0xA857, 0xBB5B, 0, 0xBB5C, 0, 0, 0,
- 0, 0x3F73, 0xA858, 0, 0x564C, 0x4F77, 0, 0x3A37,
- 0xA85A, 0, 0, 0x564D, 0, 0, 0x564E, 0,
- 0, 0xBB60, 0xBB61, 0, 0, 0, 0xBB62, 0xBB63,
-};
-static const unsigned short utf8_to_euc_E5B6[] = {
- 0, 0xBB64, 0x5651, 0xBB65, 0x5650, 0, 0, 0x564F,
- 0xBB66, 0, 0xBB67, 0x4568, 0x563A, 0, 0, 0,
- 0x5657, 0, 0xBB68, 0xBB69, 0xBB6A, 0xBB6B, 0, 0,
- 0, 0xBB6C, 0, 0xBB6D, 0, 0x5653, 0, 0xBB6E,
- 0xBB6F, 0, 0x5652, 0, 0, 0, 0, 0xBB70,
- 0, 0, 0, 0xBB71, 0x5654, 0, 0x5655, 0,
- 0xBB72, 0, 0xE674, 0, 0xBB73, 0, 0, 0x5658,
- 0xBB74, 0xBB75, 0x4E66, 0, 0x5659, 0x5656, 0, 0,
-};
-static const unsigned short utf8_to_euc_E5B6_x0213[] = {
- 0, 0x4F78, 0x5651, 0xBB65, 0x5650, 0, 0, 0x564F,
- 0xA85D, 0, 0xBB67, 0x4568, 0x563A, 0, 0, 0,
- 0x5657, 0, 0xA85F, 0xBB69, 0xA860, 0xBB6B, 0, 0xA861,
- 0, 0xA862, 0, 0xBB6D, 0, 0x5653, 0, 0xBB6E,
- 0x4F79, 0, 0x5652, 0, 0x4F7A, 0, 0, 0x4F7B,
- 0, 0, 0, 0xBB71, 0x5654, 0, 0x5655, 0,
- 0xA863, 0, 0xA864, 0, 0xA865, 0, 0, 0x5658,
- 0x4F7C, 0xA867, 0x4E66, 0, 0x5659, 0x5656, 0, 0,
-};
-static const unsigned short utf8_to_euc_E5B7[] = {
- 0, 0, 0, 0xBB76, 0, 0, 0, 0xBB77,
- 0, 0x565A, 0, 0xBB78, 0x3460, 0x565B, 0xBB7A, 0,
- 0xBB79, 0, 0x565D, 0x565C, 0, 0, 0x565E, 0,
- 0xBB7B, 0xBB7C, 0, 0x565F, 0, 0x406E, 0x3D23, 0,
- 0xBB7D, 0x3D64, 0, 0x4163, 0xBB7E, 0x3929, 0x3A38, 0x392A,
- 0x3570, 0xBC21, 0, 0x5660, 0, 0, 0x3A39, 0,
- 0, 0x384A, 0x5661, 0x4C26, 0x4743, 0x5662, 0, 0x392B,
- 0xBC22, 0xBC23, 0, 0x342C, 0, 0x4327, 0x3652, 0,
-};
-static const unsigned short utf8_to_euc_E5B7_x0213[] = {
- 0, 0, 0, 0xBB76, 0, 0, 0, 0xBB77,
- 0, 0x565A, 0, 0x4F7D, 0x3460, 0x565B, 0xBB7A, 0,
- 0, 0xA868, 0x565D, 0x565C, 0, 0, 0x565E, 0xA869,
- 0xA86A, 0xBB7C, 0, 0x565F, 0, 0x406E, 0x3D23, 0,
- 0xA86B, 0x3D64, 0x7428, 0x4163, 0xA86D, 0x3929, 0x3A38, 0x392A,
- 0x3570, 0xA86E, 0, 0x5660, 0, 0, 0x3A39, 0,
- 0, 0x384A, 0x5661, 0x4C26, 0x4743, 0x5662, 0, 0x392B,
- 0xBC22, 0xBC23, 0, 0x342C, 0, 0x4327, 0x3652, 0,
-};
-static const unsigned short utf8_to_euc_E5B8[] = {
- 0xBC24, 0, 0x3B54, 0x495B, 0, 0, 0x4841, 0xBC25,
- 0, 0, 0, 0x5663, 0x3475, 0xBC26, 0, 0,
- 0, 0x5666, 0xBC27, 0, 0xBC28, 0xBC29, 0x4421, 0,
- 0xBC2A, 0x5665, 0x5664, 0x5667, 0, 0x446B, 0, 0xBC2B,
- 0xBC2C, 0, 0, 0, 0, 0x3F63, 0, 0,
- 0xBC2E, 0, 0, 0x3B55, 0, 0x404A, 0xBC2D, 0x4253,
- 0x3522, 0, 0xBC2F, 0x4422, 0, 0xBC30, 0x5668, 0x5669,
- 0x3E6F, 0, 0, 0, 0, 0x4B39, 0xBC31, 0,
-};
-static const unsigned short utf8_to_euc_E5B8_x0213[] = {
- 0xA870, 0, 0x3B54, 0x495B, 0, 0, 0x4841, 0xBC25,
- 0, 0, 0, 0x5663, 0x3475, 0xBC26, 0, 0,
- 0, 0x5666, 0xA872, 0, 0x7429, 0xA873, 0x4421, 0,
- 0x742A, 0x5665, 0x5664, 0x5667, 0, 0x446B, 0, 0xA875,
- 0xBC2C, 0, 0, 0, 0, 0x3F63, 0, 0,
- 0xBC2E, 0, 0, 0x3B55, 0, 0x404A, 0xA876, 0x4253,
- 0x3522, 0, 0xBC2F, 0x4422, 0, 0xBC30, 0x5668, 0x5669,
- 0x3E6F, 0, 0, 0, 0, 0x4B39, 0xA877, 0,
-};
-static const unsigned short utf8_to_euc_E5B9[] = {
- 0x566C, 0, 0, 0x566B, 0x566A, 0x497D, 0, 0x5673,
- 0, 0xBC34, 0, 0xBC32, 0x4B5A, 0, 0x566D, 0,
- 0xBC33, 0xBC35, 0, 0, 0x566F, 0x4B6B, 0xBC36, 0x566E,
- 0xBC37, 0, 0, 0xBC38, 0xBC39, 0, 0xBC3A, 0x5670,
- 0, 0x4828, 0x5671, 0x4A3E, 0x5672, 0, 0, 0,
- 0xBC3B, 0, 0xBC3C, 0xBC3D, 0xBC3E, 0xBC3F, 0xBC40, 0,
- 0xBC41, 0, 0x3433, 0x4A3F, 0x472F, 0x5674, 0x5675, 0,
- 0x392C, 0x3434, 0x5676, 0x3838, 0x4D44, 0x4D29, 0x3476, 0x5678,
-};
-static const unsigned short utf8_to_euc_E5B9_x0213[] = {
- 0x566C, 0, 0, 0x566B, 0x566A, 0x497D, 0, 0x5673,
- 0, 0xA878, 0, 0xBC32, 0x4B5A, 0, 0x566D, 0,
- 0xBC33, 0xBC35, 0, 0, 0x566F, 0x4B6B, 0xA87A, 0x566E,
- 0x742B, 0, 0, 0xBC38, 0xBC39, 0, 0x742C, 0x5670,
- 0, 0x4828, 0x5671, 0x4A3E, 0x5672, 0, 0, 0,
- 0xBC3B, 0, 0xBC3C, 0xA87C, 0xA87D, 0xA87E, 0xAC21, 0,
- 0xBC41, 0, 0x3433, 0x4A3F, 0x472F, 0x5674, 0x5675, 0x7E7C,
- 0x392C, 0x3434, 0x5676, 0x3838, 0x4D44, 0x4D29, 0x3476, 0x5678,
-};
-static const unsigned short utf8_to_euc_E5BA[] = {
- 0xBC42, 0x4423, 0, 0x392D, 0x3E31, 0, 0, 0x485F,
- 0, 0, 0x3E32, 0xBC43, 0, 0, 0xBC44, 0x3D78,
- 0, 0, 0, 0, 0, 0x446C, 0x4A79, 0x4539,
- 0, 0, 0x392E, 0, 0x495C, 0, 0, 0,
- 0x5679, 0, 0xBC45, 0, 0xBC46, 0xBC47, 0x4559, 0x3A42,
- 0xBC48, 0, 0xBC49, 0x384B, 0xBC4A, 0x446D, 0, 0,
- 0, 0xBC4B, 0, 0xBC4C, 0, 0x3043, 0x3D6E, 0x392F,
- 0x4D47, 0, 0, 0, 0, 0xBC4D, 0xBC4E, 0xBC4F,
-};
-static const unsigned short utf8_to_euc_E5BA_x0213[] = {
- 0xBC42, 0x4423, 0, 0x392D, 0x3E31, 0, 0, 0x485F,
- 0, 0, 0x3E32, 0xBC43, 0, 0, 0xBC44, 0x3D78,
- 0, 0, 0, 0, 0, 0x446C, 0x4A79, 0x4539,
- 0, 0, 0x392E, 0, 0x495C, 0, 0, 0,
- 0x5679, 0, 0xBC45, 0, 0xBC46, 0xAC23, 0x4559, 0x3A42,
- 0xBC48, 0, 0xAC24, 0x384B, 0xAC25, 0x446D, 0, 0,
- 0, 0xBC4B, 0, 0xBC4C, 0, 0x3043, 0x3D6E, 0x392F,
- 0x4D47, 0xAC26, 0, 0, 0, 0xBC4D, 0x742D, 0xAC27,
-};
-static const unsigned short utf8_to_euc_E5BB[] = {
- 0, 0x567A, 0x567B, 0x4751, 0, 0, 0xBC50, 0,
- 0x567C, 0x4E77, 0x4F2D, 0xBC52, 0xBC51, 0, 0xBC53, 0x567E,
- 0x567D, 0xBC54, 0xBC55, 0x3347, 0xBC56, 0xBC57, 0x5721, 0,
- 0, 0, 0x5724, 0x5725, 0xBC58, 0x5723, 0xBC59, 0x4940,
- 0x3E33, 0x5727, 0x5726, 0x5722, 0, 0xBC5A, 0, 0,
- 0x5728, 0x5729, 0, 0xBC5B, 0x572A, 0, 0, 0,
- 0x572D, 0x572B, 0, 0x572C, 0x572E, 0, 0x3164, 0x446E,
- 0x572F, 0, 0x377A, 0x3276, 0x4736, 0, 0x5730, 0x467B,
-};
-static const unsigned short utf8_to_euc_E5BB_x0213[] = {
- 0, 0x567A, 0x567B, 0x4751, 0, 0, 0xAC28, 0,
- 0x567C, 0x4E77, 0x4F2D, 0x742F, 0xBC51, 0, 0xBC53, 0x567E,
- 0x567D, 0xBC54, 0xAC29, 0x3347, 0xBC56, 0xBC57, 0x5721, 0,
- 0, 0xAC2A, 0x5724, 0x5725, 0xBC58, 0x5723, 0xBC59, 0x4940,
- 0x3E33, 0x5727, 0x5726, 0x5722, 0, 0xBC5A, 0, 0,
- 0x5728, 0x5729, 0, 0xBC5B, 0x572A, 0, 0, 0,
- 0x572D, 0x572B, 0, 0x572C, 0x572E, 0, 0x3164, 0x446E,
- 0x572F, 0x7430, 0x377A, 0x3276, 0x4736, 0xAC2C, 0x5730, 0x467B,
-};
-static const unsigned short utf8_to_euc_E5BC[] = {
- 0, 0x4A5B, 0xBC5C, 0x5731, 0x4F2E, 0, 0xBC5D, 0xBC5E,
- 0xBC5F, 0x5732, 0x4A40, 0x5735, 0x5021, 0x5031, 0xBC60, 0x3C30,
- 0x4675, 0x5736, 0, 0x355D, 0x4424, 0x307A, 0x5737, 0x4A26,
- 0x3930, 0xBC61, 0, 0x4350, 0xBC62, 0xBC63, 0, 0x446F,
- 0, 0xBC64, 0xBC65, 0xBC66, 0xBC67, 0x4C6F, 0x3839, 0x384C,
- 0xBC68, 0x5738, 0, 0xBC69, 0xBC6A, 0x5739, 0xBC6B, 0x573F,
- 0xBC6C, 0x3C65, 0, 0, 0xBC6D, 0x4425, 0xBC6E, 0x362F,
- 0x573A, 0, 0, 0xBC6F, 0x492B, 0xBC70, 0x4346, 0xBC71,
-};
-static const unsigned short utf8_to_euc_E5BC_x0213[] = {
- 0x7431, 0x4A5B, 0x7432, 0x5731, 0x4F2E, 0, 0xBC5D, 0x7433,
- 0xAC2D, 0x5732, 0x4A40, 0x5735, 0x5021, 0x5031, 0xAC2E, 0x3C30,
- 0x4675, 0x5736, 0, 0x355D, 0x4424, 0x307A, 0x5737, 0x4A26,
- 0x3930, 0xBC61, 0, 0x4350, 0xAC2F, 0x7434, 0xAC31, 0x446F,
- 0, 0, 0xBC65, 0x7435, 0xBC67, 0x4C6F, 0x3839, 0x384C,
- 0xBC68, 0x5738, 0, 0xBC69, 0xBC6A, 0x5739, 0xBC6B, 0x573F,
- 0xBC6C, 0x3C65, 0, 0, 0x7436, 0x4425, 0x7437, 0x362F,
- 0x573A, 0, 0, 0xBC6F, 0x492B, 0x7438, 0x4346, 0xBC71,
-};
-static const unsigned short utf8_to_euc_E5BD[] = {
- 0xBC72, 0x573B, 0, 0, 0xBC73, 0xBC74, 0, 0xBC75,
- 0x573C, 0, 0x3630, 0, 0x573D, 0xBC76, 0x573E, 0,
- 0xBC77, 0x5740, 0, 0x4576, 0xBC78, 0, 0x5741, 0x5742,
- 0xBC79, 0x5743, 0, 0xBC7A, 0x5734, 0x5733, 0, 0,
- 0xBC7B, 0x5744, 0x3741, 0xBC7C, 0xBC7D, 0, 0x4927, 0xBC7E,
- 0, 0x3A4C, 0x4937, 0x4426, 0x494B, 0x5745, 0, 0xBD21,
- 0x3E34, 0x3146, 0xBD22, 0x5746, 0xBD23, 0xBD24, 0, 0x5747,
- 0xBD25, 0x4C72, 0xBD26, 0, 0x4860, 0xBD27, 0xBD28, 0x574A,
-};
-static const unsigned short utf8_to_euc_E5BD_x0213[] = {
- 0x7439, 0x573B, 0, 0, 0xBC73, 0x743A, 0, 0xAC32,
- 0x573C, 0, 0x3630, 0, 0x573D, 0xBC76, 0x573E, 0,
- 0xBC77, 0x5740, 0, 0x4576, 0x743B, 0, 0x5741, 0x5742,
- 0x743C, 0x5743, 0, 0xBC7A, 0x5734, 0x5733, 0, 0,
- 0xBC7B, 0x5744, 0x3741, 0xAC33, 0x743D, 0, 0x4927, 0x743E,
- 0, 0x3A4C, 0x4937, 0x4426, 0x494B, 0x5745, 0, 0xBD21,
- 0x3E34, 0x3146, 0xAC34, 0x5746, 0xBD23, 0xBD24, 0, 0x5747,
- 0xBD25, 0x4C72, 0xBD26, 0, 0x4860, 0x743F, 0xAC35, 0x574A,
-};
-static const unsigned short utf8_to_euc_E5BE[] = {
- 0x317D, 0x402C, 0x5749, 0x5748, 0x3742, 0x4254, 0, 0x574E,
- 0x574C, 0xBD29, 0x574B, 0x4E27, 0x3865, 0xBD2A, 0, 0xBD2B,
- 0x3D79, 0x574D, 0x454C, 0x3D3E, 0, 0, 0xBD2C, 0x4640,
- 0x5751, 0x5750, 0, 0, 0xBD2D, 0xBD2E, 0x574F, 0,
- 0x5752, 0x3866, 0xBD2F, 0, 0xBD32, 0, 0, 0xBD30,
- 0x5753, 0x497C, 0x3D5B, 0xBD31, 0xBD33, 0x5754, 0x4879, 0xBD34,
- 0xBD35, 0xBD36, 0, 0x4641, 0x4427, 0, 0, 0xF43E,
- 0xBD37, 0x4530, 0, 0, 0x5755, 0x352B, 0, 0,
-};
-static const unsigned short utf8_to_euc_E5BE_x0213[] = {
- 0x317D, 0x402C, 0x5749, 0x5748, 0x3742, 0x4254, 0, 0x574E,
- 0x574C, 0x7440, 0x574B, 0x4E27, 0x3865, 0xBD2A, 0, 0xAC36,
- 0x3D79, 0x574D, 0x454C, 0x3D3E, 0, 0, 0xBD2C, 0x4640,
- 0x5751, 0x5750, 0, 0, 0x7441, 0xBD2E, 0x574F, 0,
- 0x5752, 0x3866, 0xAC37, 0, 0xAC38, 0, 0, 0x7442,
- 0x5753, 0x497C, 0x3D5B, 0xBD31, 0xBD33, 0x5754, 0x4879, 0x7443,
- 0xBD35, 0xBD36, 0, 0x4641, 0x4427, 0x7444, 0, 0x7445,
- 0xAC39, 0x4530, 0, 0, 0x5755, 0x352B, 0, 0,
-};
-static const unsigned short utf8_to_euc_E5BF[] = {
- 0, 0, 0, 0x3F34, 0xBD38, 0x492C, 0, 0xBD39,
- 0xBD3A, 0xBD3B, 0, 0xBD3C, 0x3477, 0x4726, 0, 0,
- 0xBD3D, 0xBD3E, 0xBD3F, 0xBD40, 0xBD41, 0, 0x5756, 0x3B56,
- 0x4B3A, 0x4B3B, 0, 0, 0x317E, 0x575B, 0xBD42, 0,
- 0x4369, 0xBD43, 0xBD44, 0, 0x5758, 0, 0, 0,
- 0xBD45, 0xBD46, 0xBD47, 0x3277, 0xBD48, 0xBD49, 0xBD4A, 0xBD4B,
- 0x582D, 0x575A, 0xBD4C, 0xBD4D, 0, 0x4730, 0xBD4E, 0,
- 0x5759, 0, 0xBD4F, 0x5757, 0xBD50, 0x397A, 0, 0x575D,
-};
-static const unsigned short utf8_to_euc_E5BF_x0213[] = {
- 0, 0, 0, 0x3F34, 0xAC3A, 0x492C, 0, 0xAC3C,
- 0xBD3A, 0x7446, 0, 0xAC3D, 0x3477, 0x4726, 0, 0,
- 0xBD3D, 0xBD3E, 0xAC3E, 0xAC3F, 0xAC40, 0, 0x5756, 0x3B56,
- 0x4B3A, 0x4B3B, 0, 0, 0x317E, 0x575B, 0x7447, 0,
- 0x4369, 0x7448, 0xAC41, 0, 0x5758, 0, 0, 0,
- 0xBD45, 0x7449, 0xBD47, 0x3277, 0xBD48, 0xBD49, 0xAC42, 0xAC43,
- 0x582D, 0x575A, 0xBD4C, 0xAC44, 0, 0x4730, 0xBD4E, 0,
- 0x5759, 0, 0xBD4F, 0x5757, 0xAC45, 0x397A, 0, 0x575D,
-};
-static const unsigned short utf8_to_euc_E680[] = {
- 0, 0, 0, 0, 0, 0, 0, 0xBD51,
- 0, 0, 0xBD52, 0, 0, 0xBD53, 0x5763, 0x5769,
- 0x5761, 0, 0x455C, 0xBD54, 0xBD55, 0x5766, 0x495D, 0xBD56,
- 0xBD57, 0x5760, 0xBD58, 0x5765, 0x4E67, 0x3B57, 0, 0xBD59,
- 0x4255, 0x575E, 0, 0, 0xBD5A, 0x355E, 0x5768, 0x402D,
- 0x3165, 0x5762, 0x3278, 0x5767, 0, 0xBD5B, 0, 0x3631,
- 0, 0x5764, 0, 0xBD5C, 0, 0xBD5D, 0, 0,
- 0, 0, 0x576A, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E680_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0xBD51,
- 0, 0, 0xBD52, 0, 0, 0x744A, 0x5763, 0x5769,
- 0x5761, 0, 0x455C, 0xBD54, 0x744B, 0x5766, 0x495D, 0xAC47,
- 0x744C, 0x5760, 0xBD58, 0x5765, 0x4E67, 0x3B57, 0, 0xBD59,
- 0x4255, 0x575E, 0xAC48, 0, 0xAC49, 0x355E, 0x5768, 0x402D,
- 0x3165, 0x5762, 0x3278, 0x5767, 0, 0xBD5B, 0, 0x3631,
- 0, 0x5764, 0, 0x744D, 0, 0x744E, 0, 0,
- 0, 0, 0x576A, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E681[] = {
- 0xBD5E, 0x576C, 0x5776, 0x5774, 0, 0, 0x5771, 0xBD5F,
- 0xBD60, 0xBD61, 0x5770, 0x4E78, 0xBD62, 0x5772, 0, 0,
- 0x3632, 0xBD63, 0x3931, 0, 0xBD64, 0x3D7A, 0xBD65, 0xBD66,
- 0, 0x5779, 0x576B, 0, 0, 0xBD67, 0, 0x576F,
- 0x575F, 0xBD68, 0x327A, 0x5773, 0x5775, 0x4351, 0, 0xBD69,
- 0x3A28, 0x3238, 0x576D, 0x5778, 0x5777, 0x3633, 0, 0x4229,
- 0x3366, 0xBD6A, 0, 0, 0, 0x3743, 0, 0x576E,
- 0, 0, 0, 0, 0, 0, 0xBD6B, 0xBD6C,
-};
-static const unsigned short utf8_to_euc_E681_x0213[] = {
- 0xBD5E, 0x576C, 0x5776, 0x5774, 0, 0, 0x5771, 0x744F,
- 0xBD60, 0xBD61, 0x5770, 0x4E78, 0xAC4B, 0x5772, 0, 0,
- 0x3632, 0xBD63, 0x3931, 0, 0xBD64, 0x3D7A, 0xBD65, 0xBD66,
- 0, 0x5779, 0x576B, 0, 0, 0, 0, 0x576F,
- 0x575F, 0xBD68, 0x327A, 0x5773, 0x5775, 0x4351, 0, 0xBD69,
- 0x3A28, 0x3238, 0x576D, 0x5778, 0x5777, 0x3633, 0, 0x4229,
- 0x3366, 0xBD6A, 0, 0, 0, 0x3743, 0, 0x576E,
- 0, 0, 0, 0, 0, 0, 0xBD6B, 0xAC4C,
-};
-static const unsigned short utf8_to_euc_E682[] = {
- 0, 0x577A, 0xBD6D, 0x577D, 0x5821, 0xF43F, 0xBD6E, 0,
- 0xBD6F, 0x3C3D, 0xBD70, 0x5827, 0x4470, 0x577B, 0xBD71, 0,
- 0, 0xBD72, 0x5825, 0xBD73, 0x3279, 0xBD74, 0x5823, 0x5824,
- 0xBD75, 0, 0x577E, 0x5822, 0, 0xBD76, 0xBD77, 0x3867,
- 0x4D2A, 0, 0xBD78, 0x3435, 0xBD79, 0xBD7A, 0x3159, 0x5826,
- 0xBD7B, 0x473A, 0x302D, 0, 0, 0, 0, 0,
- 0xBD7C, 0xBD7D, 0x4861, 0x575C, 0x582C, 0x5830, 0x4C65, 0xBD7E,
- 0x5829, 0, 0, 0xBE21, 0x4569, 0x582E, 0xBE22, 0,
-};
-static const unsigned short utf8_to_euc_E682_x0213[] = {
- 0, 0x577A, 0xBD6D, 0x577D, 0x5821, 0, 0xBD6E, 0,
- 0xBD6F, 0x3C3D, 0xAC4D, 0x5827, 0x4470, 0x577B, 0xBD71, 0,
- 0, 0xBD72, 0x5825, 0xBD73, 0x3279, 0xAC4E, 0x5823, 0x5824,
- 0xBD75, 0, 0x577E, 0x5822, 0, 0x7451, 0x7452, 0x3867,
- 0x4D2A, 0, 0xBD78, 0x3435, 0xBD79, 0xBD7A, 0x3159, 0x5826,
- 0xAC4F, 0x473A, 0x302D, 0, 0, 0, 0, 0,
- 0xAC51, 0xAC52, 0x4861, 0x575C, 0x582C, 0x5830, 0x4C65, 0xBD7E,
- 0x5829, 0, 0, 0xBE21, 0x4569, 0x582E, 0xAC53, 0,
-};
-static const unsigned short utf8_to_euc_E683[] = {
- 0, 0, 0xBE23, 0, 0xBE24, 0x3E70, 0x582F, 0x4657,
- 0xBE25, 0xBE26, 0xBE27, 0xBE28, 0, 0, 0xBE29, 0xBE2A,
- 0, 0x4F47, 0, 0x582B, 0xBE2B, 0xBE2C, 0, 0,
- 0x5831, 0xBE2D, 0x397B, 0xBE2E, 0x404B, 0xBE2F, 0xBE30, 0x3054,
- 0x582A, 0x5828, 0xBE31, 0x415A, 0, 0xBE32, 0, 0x577C,
- 0x3B34, 0, 0, 0, 0, 0, 0, 0,
- 0x4246, 0x583D, 0xBE33, 0x415B, 0x5838, 0xBE34, 0x5835, 0x5836,
- 0xBE35, 0x3C66, 0x5839, 0x583C, 0xBE36, 0xBE37, 0, 0,
-};
-static const unsigned short utf8_to_euc_E683_x0213[] = {
- 0, 0, 0xBE23, 0, 0xBE24, 0x3E70, 0x582F, 0x4657,
- 0xAC54, 0xBE26, 0xBE27, 0x7453, 0, 0, 0xBE29, 0xBE2A,
- 0, 0x4F47, 0, 0x582B, 0x7454, 0x7455, 0, 0,
- 0x5831, 0xAC55, 0x397B, 0xAC56, 0x404B, 0x7456, 0, 0x3054,
- 0x582A, 0x5828, 0xBE31, 0x415A, 0, 0xBE32, 0, 0x577C,
- 0x3B34, 0, 0, 0, 0, 0, 0xAC57, 0,
- 0x4246, 0x583D, 0xAC58, 0x415B, 0x5838, 0xAC59, 0x5835, 0x5836,
- 0x7457, 0x3C66, 0x5839, 0x583C, 0xBE36, 0xBE37, 0, 0,
-};
-static const unsigned short utf8_to_euc_E684[] = {
- 0x5837, 0x3D25, 0xBE38, 0x583A, 0, 0, 0x5834, 0xBE39,
- 0x4C7C, 0x4C7B, 0xBE3A, 0, 0xBE3B, 0x583E, 0x583F, 0x3055,
- 0xBE3C, 0xBE3D, 0xBE3E, 0xBE3F, 0xBE40, 0x5833, 0xBE41, 0xBE42,
- 0, 0xBE43, 0x3672, 0x3026, 0xBE44, 0, 0xBE45, 0x3436,
- 0xF440, 0x583B, 0xBE46, 0, 0, 0, 0, 0x5843,
- 0x5842, 0, 0xBE47, 0xBE48, 0x5847, 0, 0, 0,
- 0xBE49, 0xBE4A, 0, 0, 0x5848, 0xBE4B, 0xBE4C, 0xBE4D,
- 0, 0xBE4E, 0, 0, 0x5846, 0x5849, 0x5841, 0x5845,
-};
-static const unsigned short utf8_to_euc_E684_x0213[] = {
- 0x5837, 0x3D25, 0xBE38, 0x583A, 0, 0, 0x5834, 0xBE39,
- 0x4C7C, 0x4C7B, 0xBE3A, 0, 0xBE3B, 0x583E, 0x583F, 0x3055,
- 0xAC5A, 0, 0xAC5B, 0xAC5C, 0xBE40, 0x5833, 0xBE41, 0xBE42,
- 0, 0xAC5D, 0x3672, 0x3026, 0x7458, 0, 0xAC5E, 0x3436,
- 0, 0x583B, 0xBE46, 0, 0, 0, 0, 0x5843,
- 0x5842, 0, 0xBE47, 0x7459, 0x5847, 0, 0, 0,
- 0x745A, 0xBE4A, 0, 0, 0x5848, 0xBE4B, 0xBE4C, 0x745B,
- 0, 0xBE4E, 0xAC5F, 0, 0x5846, 0x5849, 0x5841, 0x5845,
-};
-static const unsigned short utf8_to_euc_E685[] = {
- 0, 0xBE4F, 0x584A, 0, 0x584B, 0xBE50, 0xBE51, 0x5840,
- 0x3B7C, 0xBE52, 0x5844, 0x4256, 0x3932, 0x5832, 0x3F35, 0,
- 0, 0, 0, 0x5858, 0, 0x4A69, 0, 0,
- 0x584E, 0x584F, 0x5850, 0, 0, 0x5857, 0xBE53, 0x5856,
- 0xBE54, 0, 0x4B7D, 0x3437, 0, 0x5854, 0, 0x3745,
- 0x3334, 0, 0, 0x5851, 0xBE55, 0, 0x4E38, 0x5853,
- 0x3056, 0x5855, 0xBE56, 0x584C, 0x5852, 0x5859, 0x3744, 0x584D,
- 0xBE57, 0, 0, 0xBE58, 0xBE59, 0, 0x4D5D, 0xBE5A,
-};
-static const unsigned short utf8_to_euc_E685_x0213[] = {
- 0, 0xAC61, 0x584A, 0, 0x584B, 0xBE50, 0xAC62, 0x5840,
- 0x3B7C, 0xBE52, 0x5844, 0x4256, 0x3932, 0x5832, 0x3F35, 0,
- 0, 0, 0, 0x5858, 0, 0x4A69, 0, 0,
- 0x584E, 0x584F, 0x5850, 0, 0, 0x5857, 0xBE53, 0x5856,
- 0xAC63, 0, 0x4B7D, 0x3437, 0, 0x5854, 0, 0x3745,
- 0x3334, 0, 0, 0x5851, 0xBE55, 0, 0x4E38, 0x5853,
- 0x3056, 0x5855, 0xBE56, 0x584C, 0x5852, 0x5859, 0x3744, 0x584D,
- 0xBE57, 0, 0, 0xBE58, 0xAC64, 0, 0x4D5D, 0xBE5A,
-};
-static const unsigned short utf8_to_euc_E686[] = {
- 0xBE5B, 0xBE5C, 0x4D2B, 0xBE5D, 0xBE5E, 0, 0, 0x585C,
- 0, 0, 0x5860, 0xBE5F, 0, 0xBE60, 0x417E, 0,
- 0x4E79, 0x5861, 0xBE61, 0xBE62, 0x585E, 0, 0x585B, 0xBE63,
- 0xBE64, 0x585A, 0x585F, 0, 0xBE65, 0xBE66, 0, 0xBE67,
- 0xBE68, 0, 0, 0, 0x4A30, 0xBE69, 0, 0x4634,
- 0xBE6A, 0x3746, 0xBE6B, 0x5862, 0x585D, 0xBE6C, 0x5863, 0,
- 0, 0, 0x377B, 0, 0, 0, 0x3231, 0,
- 0xBE6D, 0xBE6E, 0x586B, 0, 0xBE6F, 0, 0x3438, 0,
-};
-static const unsigned short utf8_to_euc_E686_x0213[] = {
- 0xBE5B, 0xBE5C, 0x4D2B, 0xBE5D, 0xBE5E, 0, 0, 0x585C,
- 0, 0, 0x5860, 0xBE5F, 0, 0x745D, 0x417E, 0,
- 0x4E79, 0x5861, 0xAC66, 0xAC67, 0x585E, 0, 0x585B, 0xAC68,
- 0xAC69, 0x585A, 0x585F, 0, 0xBE65, 0xBE66, 0, 0xBE67,
- 0xBE68, 0, 0, 0, 0x4A30, 0xAC6A, 0, 0x4634,
- 0xAC6B, 0x3746, 0xBE6B, 0x5862, 0x585D, 0xAC6C, 0x5863, 0,
- 0, 0, 0x377B, 0, 0, 0, 0x3231, 0,
- 0xBE6D, 0x7460, 0x586B, 0, 0x745F, 0, 0x3438, 0,
-};
-static const unsigned short utf8_to_euc_E687[] = {
- 0xBE70, 0xBE71, 0xBE72, 0x5869, 0, 0, 0x586A, 0x3A29,
- 0x5868, 0x5866, 0x5865, 0x586C, 0x5864, 0x586E, 0xBE73, 0xBE74,
- 0x327B, 0, 0, 0, 0, 0xBE75, 0, 0,
- 0, 0, 0, 0, 0xBE76, 0xBE77, 0xBE78, 0xBE79,
- 0, 0xBE7A, 0xBE7B, 0x5870, 0, 0xBE7E, 0x586F, 0xBE7C,
- 0, 0xBE7D, 0, 0, 0xBF21, 0xBF22, 0, 0xBF23,
- 0, 0, 0x4428, 0, 0x5873, 0, 0x5871, 0x5867,
- 0x377C, 0, 0x5872, 0, 0x5876, 0x5875, 0x5877, 0x5874,
-};
-static const unsigned short utf8_to_euc_E687_x0213[] = {
- 0xBE70, 0xBE71, 0xBE72, 0x5869, 0, 0, 0x586A, 0x3A29,
- 0x5868, 0x5866, 0x5865, 0x586C, 0x5864, 0x586E, 0xBE73, 0xBE74,
- 0x327B, 0, 0, 0, 0, 0xAC6E, 0, 0,
- 0, 0, 0, 0, 0xBE76, 0xAC6F, 0xBE78, 0xAC70,
- 0, 0xBE7A, 0xBE7B, 0x5870, 0, 0xBE7E, 0x586F, 0xBE7C,
- 0, 0xBE7D, 0, 0, 0xBF21, 0xBF22, 0, 0xBF23,
- 0, 0, 0x4428, 0, 0x5873, 0xAC71, 0x5871, 0x5867,
- 0x377C, 0, 0x5872, 0, 0x5876, 0x5875, 0x5877, 0x5874,
-};
-static const unsigned short utf8_to_euc_E688[] = {
- 0x5878, 0xBF24, 0, 0xBF25, 0xBF26, 0, 0, 0xBF27,
- 0x5879, 0x587A, 0x4A6A, 0, 0x587C, 0x587B, 0x3D3F, 0,
- 0x402E, 0x3266, 0x327C, 0xBF28, 0x587D, 0xBF29, 0x303F, 0,
- 0, 0, 0x404C, 0x587E, 0xBF2A, 0x6C43, 0x5921, 0x3761,
- 0xBF2B, 0x5922, 0xBF2C, 0xBF2D, 0, 0, 0x406F, 0xBF2E,
- 0, 0xBF2F, 0x5923, 0xBF30, 0, 0, 0x5924, 0x353A,
- 0x5925, 0, 0x5926, 0x5927, 0x4257, 0, 0, 0,
- 0x384D, 0xBF31, 0, 0x4C61, 0, 0xBF32, 0, 0x4B3C,
-};
-static const unsigned short utf8_to_euc_E688_x0213[] = {
- 0x5878, 0xBF24, 0, 0xBF25, 0xBF26, 0, 0, 0xBF27,
- 0x5879, 0x587A, 0x4A6A, 0, 0x587C, 0x587B, 0x3D3F, 0,
- 0x402E, 0x3266, 0x327C, 0, 0x587D, 0xAC73, 0x303F, 0,
- 0, 0, 0x404C, 0x587E, 0xBF2A, 0x6C43, 0x5921, 0x3761,
- 0xBF2B, 0x5922, 0x7462, 0xAC74, 0, 0, 0x406F, 0xBF2E,
- 0, 0xAC75, 0x5923, 0xBF30, 0, 0, 0x5924, 0x353A,
- 0x5925, 0, 0x5926, 0x5927, 0x4257, 0, 0, 0,
- 0x384D, 0xBF31, 0, 0x4C61, 0, 0xBF32, 0x7463, 0x4B3C,
-};
-static const unsigned short utf8_to_euc_E689[] = {
- 0x3D6A, 0x5928, 0xBF33, 0xBF34, 0xBF35, 0, 0xBF36, 0x4070,
- 0x6E3D, 0x4862, 0, 0x3C6A, 0xBF37, 0x3A4D, 0x5929, 0,
- 0xBF38, 0xBF39, 0xBF3A, 0x4247, 0xBF3B, 0x4A27, 0xBF3C, 0,
- 0x4271, 0, 0xBF3D, 0x592C, 0xBF3E, 0, 0x592A, 0,
- 0x592D, 0, 0, 0x592B, 0xBF3F, 0, 0, 0,
- 0x592E, 0, 0, 0, 0, 0xBF40, 0x4A31, 0xBF41,
- 0, 0x3037, 0, 0xBF42, 0, 0, 0x495E, 0,
- 0, 0x4863, 0xBF43, 0, 0x592F, 0xBF44, 0x5932, 0x3E35,
-};
-static const unsigned short utf8_to_euc_E689_x0213[] = {
- 0x3D6A, 0x5928, 0xBF33, 0x7464, 0xBF35, 0, 0xAC76, 0x4070,
- 0x6E3D, 0x4862, 0, 0x3C6A, 0xAC77, 0x3A4D, 0x5929, 0,
- 0xBF38, 0xAC78, 0xAC79, 0x4247, 0xBF3B, 0x4A27, 0x7465, 0,
- 0x4271, 0, 0x7466, 0x592C, 0xBF3E, 0, 0x592A, 0,
- 0x592D, 0xAC7A, 0, 0x592B, 0xAC7B, 0, 0, 0,
- 0x592E, 0, 0, 0, 0, 0xAC7D, 0x4A31, 0x7467,
- 0, 0x3037, 0, 0xAC7E, 0, 0, 0x495E, 0,
- 0, 0x4863, 0xBF43, 0xAC7C, 0x592F, 0xBF44, 0x5932, 0x3E35,
-};
-static const unsigned short utf8_to_euc_E68A[] = {
- 0x353B, 0, 0x5930, 0x5937, 0x3E36, 0, 0, 0,
- 0, 0x5931, 0x4744, 0, 0, 0xBF45, 0xBF46, 0xBF47,
- 0xBF48, 0x4D5E, 0x5933, 0x5934, 0x5938, 0x456A, 0x5935, 0x3933,
- 0x405E, 0, 0, 0x5946, 0x4834, 0, 0x4272, 0,
- 0, 0, 0, 0, 0, 0, 0xBF49, 0,
- 0xBF4A, 0, 0, 0x4864, 0x5A2D, 0, 0, 0,
- 0, 0x4A7A, 0, 0xBF4B, 0, 0x4471, 0xBF4C, 0xBF4D,
- 0, 0x4B75, 0xBF4E, 0x593B, 0x3221, 0x436A, 0xBF4F, 0xBF50,
-};
-static const unsigned short utf8_to_euc_E68A_x0213[] = {
- 0x353B, 0, 0x5930, 0x5937, 0x3E36, 0x7468, 0, 0,
- 0, 0x5931, 0x4744, 0, 0, 0xBF45, 0xBF46, 0xBF47,
- 0xBF48, 0x4D5E, 0x5933, 0x5934, 0x5938, 0x456A, 0x5935, 0x3933,
- 0x405E, 0xAD21, 0, 0x5946, 0x4834, 0, 0x4272, 0,
- 0, 0, 0, 0, 0, 0, 0xAD22, 0,
- 0xBF4A, 0, 0, 0x4864, 0x5A2D, 0, 0, 0,
- 0, 0x4A7A, 0, 0xBF4B, 0, 0x4471, 0xBF4C, 0xBF4D,
- 0, 0x4B75, 0xBF4E, 0x593B, 0x3221, 0x436A, 0xBF4F, 0xBF50,
-};
-static const unsigned short utf8_to_euc_E68B[] = {
- 0, 0, 0x5944, 0, 0xBF51, 0x4334, 0x593E, 0x5945,
- 0x5940, 0x5947, 0x5943, 0, 0x5942, 0x476F, 0xBF52, 0x593C,
- 0x327D, 0x593A, 0x3571, 0x4273, 0x5936, 0xBF53, 0xBF54, 0x5939,
- 0x3934, 0x405B, 0xBF55, 0x3E37, 0x5941, 0x4752, 0, 0,
- 0x3572, 0x3348, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xBF56, 0, 0x3367, 0x3F21, 0x5949, 0x594E,
- 0, 0x594A, 0xBF57, 0x377D, 0xBF58, 0x594F, 0x3B22, 0x3969,
- 0, 0, 0, 0, 0xBF59, 0xBF5A, 0x3D26, 0x593D,
-};
-static const unsigned short utf8_to_euc_E68B_x0213[] = {
- 0, 0, 0x5944, 0, 0x7469, 0x4334, 0x593E, 0x5945,
- 0x5940, 0x5947, 0x5943, 0, 0x5942, 0x476F, 0xBF52, 0x593C,
- 0x327D, 0x593A, 0x3571, 0x4273, 0x5936, 0xAD23, 0x746A, 0x5939,
- 0x3934, 0x405B, 0xBF55, 0x3E37, 0x5941, 0x4752, 0, 0,
- 0x3572, 0x3348, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xBF56, 0, 0x3367, 0x3F21, 0x5949, 0x594E,
- 0, 0x594A, 0xBF57, 0x377D, 0xBF58, 0x594F, 0x3B22, 0x3969,
- 0, 0, 0, 0, 0x746B, 0xAD25, 0x3D26, 0x593D,
-};
-static const unsigned short utf8_to_euc_E68C[] = {
- 0, 0x3B7D, 0x594C, 0xBF5B, 0xBF5C, 0, 0, 0x3B58,
- 0x594D, 0x3044, 0xBF5D, 0xBF5E, 0x5948, 0xBF5F, 0, 0,
- 0xBF60, 0x4429, 0, 0xBF61, 0, 0, 0xBF62, 0,
- 0xBF63, 0x3573, 0, 0, 0, 0, 0, 0x3634,
- 0, 0, 0, 0, 0, 0, 0, 0x594B,
- 0x3027, 0xBF64, 0xBF65, 0x3A43, 0, 0xBF66, 0, 0x3F36,
- 0, 0, 0, 0, 0, 0xBF67, 0xBF68, 0,
- 0, 0xBF69, 0x4472, 0, 0xBF6A, 0x4854, 0x5951, 0x415E,
-};
-static const unsigned short utf8_to_euc_E68C_x0213[] = {
- 0, 0x3B7D, 0x594C, 0xAD26, 0xBF5C, 0, 0, 0x3B58,
- 0x594D, 0x3044, 0x746C, 0xBF5E, 0x5948, 0xAD27, 0, 0,
- 0xAD28, 0x4429, 0, 0xBF61, 0, 0, 0xBF62, 0,
- 0x746D, 0x3573, 0, 0, 0, 0, 0, 0x3634,
- 0, 0, 0, 0, 0, 0, 0, 0x594B,
- 0x3027, 0xBF64, 0xBF65, 0x3A43, 0, 0xBF66, 0, 0x3F36,
- 0, 0, 0xAD2B, 0, 0, 0xAD2C, 0xBF68, 0,
- 0, 0x746E, 0x4472, 0xAD2D, 0xAD2E, 0x4854, 0x5951, 0x415E,
-};
-static const unsigned short utf8_to_euc_E68D[] = {
- 0, 0xBF6B, 0xBF6C, 0xBF6D, 0xBF6E, 0, 0xBF6F, 0,
- 0, 0x422A, 0xBF70, 0xBF71, 0x3B2B, 0x5952, 0xBF72, 0x5954,
- 0x5950, 0, 0xBF73, 0xBF74, 0xBF75, 0x4A61, 0, 0x443D,
- 0xBF76, 0, 0, 0xBF77, 0x415C, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xBF78, 0xBF79, 0x4A7B,
- 0x3C4E, 0x5960, 0, 0x595F, 0xBF7A, 0xBF7B, 0x3F78, 0,
- 0, 0xBF7C, 0x377E, 0, 0xBF7D, 0xBF7E, 0x5959, 0x3E39,
- 0xC021, 0, 0x4668, 0x4731, 0xC022, 0xC023, 0, 0xC024,
-};
-static const unsigned short utf8_to_euc_E68D_x0213[] = {
- 0, 0xAD2F, 0xBF6C, 0x746F, 0xAD30, 0, 0xBF6F, 0,
- 0, 0x422A, 0xBF70, 0xBF71, 0x3B2B, 0x5952, 0xAD31, 0x5954,
- 0x5950, 0, 0xBF73, 0xBF74, 0xBF75, 0x4A61, 0, 0x443D,
- 0xBF76, 0xAD33, 0, 0xBF77, 0x415C, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x7470, 0xBF79, 0x4A7B,
- 0x3C4E, 0x5960, 0, 0x595F, 0xAD36, 0xBF7B, 0x3F78, 0,
- 0, 0xBF7C, 0x377E, 0, 0xBF7D, 0xBF7E, 0x5959, 0x3E39,
- 0xC021, 0, 0x4668, 0x4731, 0x7471, 0xC023, 0, 0xC024,
-};
-static const unsigned short utf8_to_euc_E68E[] = {
- 0x5957, 0, 0xC025, 0x415D, 0xC026, 0, 0, 0xC027,
- 0x3C78, 0x595C, 0xC028, 0, 0x3E38, 0, 0x5956, 0x595B,
- 0xC029, 0, 0x4753, 0, 0xC02A, 0xC02B, 0x5955, 0,
- 0x3721, 0xC02C, 0xC02D, 0x335D, 0, 0, 0xC02E, 0x595D,
- 0x4E2B, 0x3A4E, 0x4335, 0x595A, 0xC02F, 0x405C, 0xC030, 0x3935,
- 0x3F64, 0x3166, 0x413C, 0x5958, 0x3545, 0xC031, 0xC032, 0xC033,
- 0, 0, 0x3747, 0, 0x444F, 0x595E, 0, 0,
- 0, 0, 0, 0x415F, 0, 0xC034, 0x5961, 0,
-};
-static const unsigned short utf8_to_euc_E68E_x0213[] = {
- 0x5957, 0, 0xC025, 0x415D, 0xAD37, 0, 0, 0xC027,
- 0x3C78, 0x595C, 0xC028, 0, 0x3E38, 0, 0x5956, 0x595B,
- 0xC029, 0, 0x4753, 0, 0xAD3A, 0xC02B, 0x5955, 0,
- 0x3721, 0xAD38, 0xC02D, 0x335D, 0, 0, 0xC02E, 0x595D,
- 0x4E2B, 0x3A4E, 0x4335, 0x595A, 0xC02F, 0x405C, 0xC030, 0x3935,
- 0x3F64, 0x3166, 0x413C, 0x5958, 0x3545, 0xC031, 0xC032, 0xC033,
- 0, 0, 0x3747, 0, 0x444F, 0x595E, 0, 0,
- 0, 0, 0, 0x415F, 0, 0xAD3B, 0x5961, 0,
-};
-static const unsigned short utf8_to_euc_E68F[] = {
- 0x5963, 0xC035, 0, 0x4237, 0x5969, 0xC036, 0x5964, 0,
- 0xC037, 0x5966, 0, 0, 0, 0, 0xC038, 0x4941,
- 0x4473, 0xC039, 0x5967, 0xC03A, 0xC03B, 0xC03C, 0x4D2C, 0,
- 0, 0, 0x4D48, 0x3439, 0xC03D, 0, 0, 0,
- 0xC03E, 0x302E, 0, 0x5965, 0, 0xC03F, 0, 0,
- 0, 0x5962, 0xC040, 0, 0xC041, 0, 0x3478, 0,
- 0, 0, 0xC042, 0xC043, 0x3167, 0xC044, 0x5968, 0,
- 0xC045, 0xC046, 0x4D49, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E68F_x0213[] = {
- 0x5963, 0xC035, 0, 0x4237, 0x5969, 0xC036, 0x5964, 0,
- 0xC037, 0x5966, 0, 0, 0, 0, 0xC038, 0x4941,
- 0x4473, 0xC039, 0x5967, 0xC03A, 0xAD3D, 0xAD3E, 0x4D2C, 0,
- 0, 0, 0x4D48, 0x3439, 0xAD3F, 0, 0, 0,
- 0xAD40, 0x302E, 0, 0x5965, 0, 0x7472, 0, 0,
- 0, 0x5962, 0xC040, 0xAD41, 0xAD42, 0x7473, 0x3478, 0,
- 0, 0, 0xAD43, 0xC043, 0x3167, 0x7474, 0x5968, 0xAD3C,
- 0xC045, 0xC046, 0x4D49, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E690[] = {
- 0, 0, 0, 0, 0, 0, 0x596C, 0,
- 0, 0xC047, 0xC048, 0, 0, 0x423B, 0, 0x5973,
- 0xC049, 0, 0xC04A, 0x596D, 0xC04B, 0, 0x596A, 0x5971,
- 0xC04C, 0, 0, 0, 0x5953, 0, 0xC04D, 0,
- 0xC04E, 0, 0xC04F, 0, 0xC050, 0xC051, 0x596E, 0,
- 0x5972, 0xC052, 0xC053, 0, 0x4842, 0x456B, 0, 0xC054,
- 0xC055, 0, 0, 0, 0x596B, 0xC056, 0x596F, 0,
- 0, 0, 0x3748, 0, 0, 0xC057, 0x3A71, 0xC058,
-};
-static const unsigned short utf8_to_euc_E690_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0x596C, 0,
- 0, 0xAD44, 0xC048, 0, 0, 0x423B, 0, 0x5973,
- 0x7475, 0, 0xC04A, 0x596D, 0x7476, 0, 0x596A, 0x5971,
- 0xC04C, 0, 0, 0, 0x5953, 0, 0xAD45, 0,
- 0xC04E, 0, 0x7477, 0, 0xC050, 0xAD46, 0x596E, 0,
- 0x5972, 0xAD47, 0xC053, 0, 0x4842, 0x456B, 0, 0xAD48,
- 0xC055, 0, 0, 0, 0x596B, 0xC056, 0x596F, 0,
- 0, 0, 0x3748, 0, 0, 0xC057, 0x3A71, 0xC058,
-};
-static const unsigned short utf8_to_euc_E691[] = {
- 0, 0, 0x405D, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xC059, 0, 0, 0x5977, 0xC05A,
- 0, 0xC05B, 0xC05C, 0xC05D, 0xC05E, 0, 0, 0,
- 0x4526, 0, 0xC05F, 0xC060, 0xC061, 0xC062, 0, 0xC063,
- 0xC064, 0xC065, 0, 0xC066, 0, 0, 0, 0x5974,
- 0, 0x4B60, 0, 0, 0, 0xC067, 0, 0x5975,
- 0, 0, 0, 0xC068, 0xC069, 0, 0x5976, 0,
- 0x4C4E, 0, 0x4022, 0xC06A, 0, 0xC06B, 0, 0,
-};
-static const unsigned short utf8_to_euc_E691_x0213[] = {
- 0, 0, 0x405D, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xC059, 0, 0, 0x5977, 0xC05A,
- 0, 0x7479, 0xC05C, 0xC05D, 0xC05E, 0, 0, 0,
- 0x4526, 0, 0xAD49, 0xAD4A, 0xC061, 0xAD4B, 0, 0xC063,
- 0x747A, 0xC065, 0, 0xC066, 0, 0, 0, 0x5974,
- 0, 0x4B60, 0, 0, 0, 0x747B, 0, 0x5975,
- 0, 0, 0, 0xAD4C, 0xC069, 0, 0x5976, 0,
- 0x4C4E, 0x7478, 0x4022, 0xC06A, 0, 0xAD4D, 0, 0,
-};
-static const unsigned short utf8_to_euc_E692[] = {
- 0, 0, 0, 0x3762, 0, 0xC06C, 0, 0xC06D,
- 0x597D, 0, 0, 0, 0, 0, 0, 0xC06E,
- 0xC06F, 0xC070, 0x3B35, 0x597A, 0, 0x5979, 0, 0,
- 0xC071, 0xC072, 0x4732, 0xC073, 0, 0xC074, 0x4635, 0xC075,
- 0, 0xC076, 0, 0xC077, 0x4531, 0x597B, 0xC078, 0,
- 0xC079, 0x597C, 0, 0x496F, 0xC07A, 0x4745, 0x3B23, 0,
- 0x4071, 0, 0x4B50, 0xC07B, 0, 0, 0, 0,
- 0, 0x3349, 0, 0x5A25, 0x597E, 0xC07C, 0xC07D, 0xC07E,
-};
-static const unsigned short utf8_to_euc_E692_x0213[] = {
- 0, 0, 0, 0x3762, 0, 0xC06C, 0, 0xAD4E,
- 0x597D, 0, 0, 0, 0, 0, 0, 0xC06E,
- 0xC06F, 0xAD4F, 0x3B35, 0x597A, 0, 0x5979, 0, 0,
- 0xC071, 0xC072, 0x4732, 0xC073, 0, 0xAD50, 0x4635, 0xAD51,
- 0, 0xC076, 0, 0xC077, 0x4531, 0x597B, 0xC078, 0,
- 0xC079, 0x597C, 0, 0x496F, 0xC07A, 0x4745, 0x3B23, 0,
- 0x4071, 0, 0x4B50, 0xC07B, 0, 0, 0, 0,
- 0, 0x3349, 0, 0x5A25, 0x597E, 0xC07C, 0x747D, 0x747E,
-};
-static const unsigned short utf8_to_euc_E693[] = {
- 0, 0x4D4A, 0x5A27, 0, 0xC121, 0x5A23, 0, 0x5A24,
- 0, 0xC122, 0xC123, 0xC124, 0xC125, 0x4160, 0xC126, 0,
- 0xC127, 0xC128, 0x5A22, 0, 0x593F, 0xC129, 0, 0xC12A,
- 0x5A26, 0, 0x5A21, 0, 0, 0, 0, 0,
- 0x5A2B, 0x5A2C, 0x4527, 0x5A2E, 0xC12B, 0xC12C, 0x3B24, 0x5A29,
- 0, 0xC12D, 0xC12E, 0, 0x353C, 0xC12F, 0, 0x5A2F,
- 0xC130, 0x5A28, 0x5A33, 0, 0x5A32, 0xC131, 0x5A31, 0xC132,
- 0, 0, 0x5A34, 0xC133, 0, 0x5A36, 0x3E71, 0xC134,
-};
-static const unsigned short utf8_to_euc_E693_x0213[] = {
- 0, 0x4D4A, 0x5A27, 0, 0x7521, 0x5A23, 0, 0x5A24,
- 0, 0xC122, 0x7522, 0xAD52, 0xAD53, 0x4160, 0x747C, 0,
- 0x7523, 0xC128, 0x5A22, 0, 0x593F, 0xAD54, 0, 0xAD55,
- 0x5A26, 0, 0x5A21, 0, 0, 0, 0, 0,
- 0x5A2B, 0x5A2C, 0x4527, 0x5A2E, 0xAD57, 0xAD58, 0x3B24, 0x5A29,
- 0, 0xC12D, 0xC12E, 0, 0x353C, 0xC12F, 0, 0x5A2F,
- 0xC130, 0x5A28, 0x5A33, 0, 0x5A32, 0xC131, 0x5A31, 0x7524,
- 0, 0, 0x5A34, 0x7525, 0, 0x5A36, 0x3E71, 0xAD59,
-};
-static const unsigned short utf8_to_euc_E694[] = {
- 0x5A35, 0xC135, 0, 0, 0xC136, 0x5A39, 0, 0,
- 0xC137, 0xC138, 0xC139, 0, 0, 0, 0, 0xC13A,
- 0, 0, 0, 0xC13B, 0xC13C, 0, 0xC13D, 0,
- 0x5A37, 0xC13E, 0, 0xC13F, 0x5A38, 0x5970, 0xC140, 0xC141,
- 0, 0, 0xC142, 0x5A3B, 0x5A3A, 0, 0xC143, 0,
- 0, 0xC144, 0x5978, 0x5A3C, 0x5A30, 0, 0xC145, 0x3B59,
- 0, 0xC146, 0, 0, 0x5A3D, 0x5A3E, 0x5A40, 0x5A3F,
- 0x5A41, 0x327E, 0xC147, 0x3936, 0xC148, 0xC149, 0x4A7C, 0x402F,
-};
-static const unsigned short utf8_to_euc_E694_x0213[] = {
- 0x5A35, 0xC135, 0, 0, 0xAD5A, 0x5A39, 0, 0,
- 0xC137, 0xC138, 0xC139, 0, 0, 0, 0, 0xAD5C,
- 0, 0, 0, 0xC13B, 0xAD5D, 0, 0xAD5E, 0,
- 0x5A37, 0xC13E, 0, 0xC13F, 0x5A38, 0x5970, 0xAD60, 0xC141,
- 0, 0, 0x7526, 0x5A3B, 0x5A3A, 0, 0xC143, 0,
- 0, 0x7527, 0x5978, 0x5A3C, 0x5A30, 0, 0xC145, 0x3B59,
- 0, 0xC146, 0xAD61, 0, 0x5A3D, 0x5A3E, 0x5A40, 0x5A3F,
- 0x5A41, 0x327E, 0xC147, 0x3936, 0xC148, 0xC149, 0x4A7C, 0x402F,
-};
-static const unsigned short utf8_to_euc_E695[] = {
- 0, 0, 0, 0xC14A, 0, 0x384E, 0, 0xC14B,
- 0x5A43, 0xC14C, 0, 0, 0, 0x5A46, 0xF441, 0x4952,
- 0xC14D, 0x355F, 0xC14E, 0, 0xC14F, 0x5A45, 0x5A44, 0x4754,
- 0x5A47, 0x3635, 0, 0, 0, 0x5A49, 0x5A48, 0xC150,
- 0xC151, 0, 0x343A, 0x3B36, 0, 0, 0x4658, 0xC152,
- 0, 0, 0, 0xC153, 0x3749, 0, 0, 0,
- 0x3F74, 0, 0x5A4A, 0, 0x4030, 0x4528, 0, 0x495F,
- 0x5A4B, 0, 0xC154, 0, 0, 0xC155, 0, 0,
-};
-static const unsigned short utf8_to_euc_E695_x0213[] = {
- 0, 0, 0, 0xC14A, 0xAD62, 0x384E, 0, 0xC14B,
- 0x5A43, 0xC14C, 0, 0, 0, 0x5A46, 0, 0x4952,
- 0xC14D, 0x355F, 0xC14E, 0, 0xAD63, 0x5A45, 0x5A44, 0x4754,
- 0x5A47, 0x3635, 0, 0, 0, 0x5A49, 0x5A48, 0xC150,
- 0xC151, 0, 0x343A, 0x3B36, 0, 0, 0x4658, 0x7529,
- 0, 0, 0, 0xAD64, 0x3749, 0, 0, 0,
- 0x3F74, 0, 0x5A4A, 0, 0x4030, 0x4528, 0, 0x495F,
- 0x5A4B, 0, 0xAD65, 0, 0, 0xC155, 0, 0,
-};
-static const unsigned short utf8_to_euc_E696[] = {
- 0, 0xC156, 0x5A4C, 0x5A4D, 0, 0xC157, 0, 0x4A38,
- 0x555D, 0x4046, 0xC158, 0, 0x494C, 0, 0x3A58, 0,
- 0x4865, 0x4843, 0xC159, 0, 0, 0xC15A, 0, 0x454D,
- 0xC15B, 0x4E41, 0, 0x5A4F, 0x3C50, 0xC15C, 0, 0x5A50,
- 0xC15D, 0x3036, 0, 0xC15E, 0x3654, 0x404D, 0xC15F, 0x4960,
- 0, 0, 0, 0x5A51, 0x3B42, 0x4347, 0xC160, 0x3B5B,
- 0x3F37, 0, 0xC161, 0xC162, 0xC163, 0, 0, 0x5A52,
- 0, 0x4A7D, 0, 0, 0x3177, 0x3B5C, 0, 0xC164,
-};
-static const unsigned short utf8_to_euc_E696_x0213[] = {
- 0, 0xAD66, 0x5A4C, 0x5A4D, 0xAD67, 0xAD68, 0, 0x4A38,
- 0x555D, 0x4046, 0xAD69, 0, 0x494C, 0, 0x3A58, 0,
- 0x4865, 0x4843, 0xC159, 0, 0, 0xC15A, 0, 0x454D,
- 0xC15B, 0x4E41, 0, 0x5A4F, 0x3C50, 0x752A, 0, 0x5A50,
- 0xC15D, 0x3036, 0, 0xC15E, 0x3654, 0x404D, 0xC15F, 0x4960,
- 0, 0, 0, 0x5A51, 0x3B42, 0x4347, 0xC160, 0x3B5B,
- 0x3F37, 0, 0xAD6A, 0xC162, 0xC163, 0xAD6B, 0, 0x5A52,
- 0xAD6C, 0x4A7D, 0, 0, 0x3177, 0x3B5C, 0, 0xAD6D,
-};
-static const unsigned short utf8_to_euc_E697[] = {
- 0, 0x5A55, 0xC165, 0x5A53, 0x5A56, 0x4E39, 0x5A54, 0,
- 0xC166, 0xC167, 0, 0x407B, 0x5A57, 0, 0xC168, 0x4232,
- 0xC169, 0, 0x5A58, 0, 0xC16A, 0, 0xC16B, 0x347A,
- 0xC16C, 0x5A5A, 0, 0x5A59, 0, 0, 0, 0xC16D,
- 0x5A5B, 0x5A5C, 0x347B, 0, 0, 0x467C, 0x4336, 0x356C,
- 0x3B5D, 0x4161, 0, 0, 0x3D5C, 0x3030, 0, 0,
- 0xC16E, 0x5A5D, 0xC16F, 0, 0xC170, 0xC171, 0, 0,
- 0, 0xC172, 0x3222, 0x5A61, 0, 0, 0xC173, 0xC174,
-};
-static const unsigned short utf8_to_euc_E697_x0213[] = {
- 0, 0x5A55, 0xAD6E, 0x5A53, 0x5A56, 0x4E39, 0x5A54, 0,
- 0xC166, 0xAD6F, 0, 0x407B, 0x5A57, 0, 0xC168, 0x4232,
- 0xC169, 0, 0x5A58, 0, 0xAD70, 0, 0xC16B, 0x347A,
- 0xC16C, 0x5A5A, 0, 0x5A59, 0, 0, 0, 0xC16D,
- 0x5A5B, 0x5A5C, 0x347B, 0, 0, 0x467C, 0x4336, 0x356C,
- 0x3B5D, 0x4161, 0, 0, 0x3D5C, 0x3030, 0, 0,
- 0xC16E, 0x5A5D, 0xAD72, 0, 0xC170, 0xC171, 0, 0,
- 0, 0xAD73, 0x3222, 0x5A61, 0xAD74, 0, 0xC173, 0xC174,
-};
-static const unsigned short utf8_to_euc_E698[] = {
- 0xC175, 0, 0x3937, 0x5A60, 0xC176, 0, 0x3A2B, 0x3E3A,
- 0xC177, 0xC178, 0x5A5F, 0, 0x3E3B, 0xC179, 0x4C40, 0x3A2A,
- 0, 0xC17A, 0xC17B, 0x3057, 0x404E, 0xC17C, 0xC17D, 0,
- 0, 0, 0, 0, 0x5A66, 0xC17E, 0xC221, 0x4031,
- 0x3147, 0xC222, 0xC223, 0xC224, 0xC225, 0x3D55, 0xC226, 0x4B66,
- 0x3A72, 0xC227, 0xC228, 0xC229, 0xC22A, 0x3E3C, 0xC22B, 0x4027,
- 0xC22C, 0xC22D, 0, 0xC22E, 0x5A65, 0x5A63, 0x5A64, 0xC230,
- 0, 0xC22F, 0, 0xF442, 0x436B, 0, 0, 0x5B26,
-};
-static const unsigned short utf8_to_euc_E698_x0213[] = {
- 0x752C, 0, 0x3937, 0x5A60, 0xAD75, 0, 0x3A2B, 0x3E3A,
- 0xAD76, 0x752D, 0x5A5F, 0, 0x3E3B, 0xC179, 0x4C40, 0x3A2A,
- 0, 0xC17A, 0xC17B, 0x3057, 0x404E, 0x752E, 0xC17D, 0,
- 0, 0, 0, 0, 0x5A66, 0xC17E, 0x752F, 0x4031,
- 0x3147, 0xAD77, 0x7531, 0xC224, 0x7532, 0x3D55, 0xC226, 0x4B66,
- 0x3A72, 0xC227, 0xAD78, 0x7533, 0xC22A, 0x3E3C, 0, 0x4027,
- 0x7534, 0x7535, 0, 0x7536, 0x5A65, 0x5A63, 0x5A64, 0xC230,
- 0, 0xC22F, 0x7530, 0, 0x436B, 0, 0, 0x5B26,
-};
-static const unsigned short utf8_to_euc_E699[] = {
- 0xC231, 0x5A6A, 0x3B7E, 0x3938, 0x5A68, 0xC232, 0xC233, 0,
- 0, 0x5A69, 0xC234, 0x3F38, 0xC235, 0, 0xC237, 0x5A67,
- 0, 0xC236, 0x3B2F, 0, 0, 0, 0, 0xC238,
- 0xC239, 0xC23A, 0, 0xC23B, 0xC23C, 0x5A6C, 0x5A6B, 0x5A70,
- 0xC23D, 0xC23E, 0x5A71, 0, 0x5A6D, 0xF443, 0x3322, 0x5A6E,
- 0x5A6F, 0x4855, 0xC240, 0xC241, 0xC242, 0, 0x4961, 0x374A,
- 0x5A72, 0, 0, 0xC244, 0x4032, 0xC245, 0x3E3D, 0xC247,
- 0xC248, 0xC249, 0x4352, 0xC24A, 0xC24C, 0, 0xC243, 0xC246,
-};
-static const unsigned short utf8_to_euc_E699_x0213[] = {
- 0xC231, 0x5A6A, 0x3B7E, 0x3938, 0x5A68, 0xAD79, 0xC233, 0,
- 0x7538, 0x5A69, 0xC234, 0x3F38, 0x7539, 0, 0xAD7B, 0x5A67,
- 0, 0xAD7A, 0x3B2F, 0, 0, 0, 0, 0xAD7E,
- 0xC239, 0x753B, 0x753C, 0xAE21, 0xC23C, 0x5A6C, 0x5A6B, 0x5A70,
- 0xC23D, 0x753D, 0x5A71, 0xAE22, 0x5A6D, 0x753E, 0x3322, 0x5A6E,
- 0x5A6F, 0x4855, 0xAE25, 0xAE26, 0xAE27, 0xAE28, 0x4961, 0x374A,
- 0x5A72, 0, 0, 0x753F, 0x4032, 0xC245, 0x3E3D, 0x7540,
- 0x7541, 0xC249, 0x4352, 0xAE29, 0xC24C, 0, 0xC243, 0xC246,
-};
-static const unsigned short utf8_to_euc_E69A[] = {
- 0xC24B, 0x3647, 0, 0x5A73, 0x5A77, 0, 0, 0x324B,
- 0x5A74, 0x5A76, 0, 0xC24D, 0xC24E, 0xC24F, 0x5A75, 0,
- 0xC250, 0x3D6B, 0xC251, 0, 0, 0, 0x4348, 0x3045,
- 0x5A78, 0xC252, 0xC253, 0xC254, 0xC255, 0x5A79, 0, 0xC256,
- 0xC257, 0, 0x442A, 0, 0xC258, 0, 0x4E71, 0,
- 0, 0, 0, 0x3B43, 0, 0xC259, 0x4A6B, 0,
- 0, 0xC25A, 0xC25B, 0, 0x4B3D, 0xC25C, 0, 0,
- 0x5B22, 0x5A7B, 0, 0xC25D, 0x5A7E, 0, 0x5A7D, 0xC25E,
-};
-static const unsigned short utf8_to_euc_E69A_x0213[] = {
- 0xAE2A, 0x3647, 0, 0x5A73, 0x5A77, 0, 0, 0x324B,
- 0x5A74, 0x5A76, 0, 0xC24D, 0xC24E, 0x7542, 0x5A75, 0,
- 0xAE2B, 0x3D6B, 0xAE2C, 0, 0, 0, 0x4348, 0x3045,
- 0x5A78, 0xAE2D, 0xC253, 0xC254, 0xC255, 0x5A79, 0, 0xC256,
- 0x7544, 0, 0x442A, 0, 0xC258, 0, 0x4E71, 0,
- 0, 0, 0, 0x3B43, 0, 0xAE2F, 0x4A6B, 0,
- 0, 0xAE30, 0x7545, 0, 0x4B3D, 0xAE31, 0, 0,
- 0x5B22, 0x5A7B, 0, 0x7546, 0x5A7E, 0, 0x5A7D, 0xAE33,
-};
-static const unsigned short utf8_to_euc_E69B[] = {
- 0xC25F, 0x5A7A, 0xC260, 0xC261, 0x5B21, 0, 0, 0x465E,
- 0xC262, 0x5A7C, 0, 0, 0xC263, 0, 0xC264, 0xC265,
- 0, 0, 0, 0, 0xC266, 0, 0x5B23, 0,
- 0, 0x3D6C, 0x5B24, 0xC267, 0x4D4B, 0x4778, 0, 0xC268,
- 0x5B25, 0, 0, 0, 0, 0, 0x5B27, 0,
- 0xC269, 0x5B28, 0, 0xC26A, 0xC26B, 0, 0xC26C, 0,
- 0x5B29, 0, 0x364A, 0x3148, 0x3939, 0x5B2A, 0, 0x5B2B,
- 0x3D71, 0x4162, 0xC26D, 0xC23F, 0x5258, 0x413E, 0x413D, 0x4258,
-};
-static const unsigned short utf8_to_euc_E69B_x0213[] = {
- 0xC25F, 0x5A7A, 0xC260, 0xC261, 0x5B21, 0, 0x7547, 0x465E,
- 0x7548, 0x5A7C, 0, 0, 0xC263, 0, 0xC264, 0xC265,
- 0, 0, 0, 0, 0xC266, 0, 0x5B23, 0,
- 0, 0x3D6C, 0x5B24, 0x754A, 0x4D4B, 0x4778, 0, 0xC268,
- 0x5B25, 0, 0, 0, 0, 0, 0x5B27, 0,
- 0x754B, 0x5B28, 0, 0xC26A, 0xAE35, 0, 0xC26C, 0,
- 0x5B29, 0, 0x364A, 0x3148, 0x3939, 0x5B2A, 0, 0x5B2B,
- 0x3D71, 0x4162, 0x754C, 0x7537, 0x5258, 0x413E, 0x413D, 0x4258,
-};
-static const unsigned short utf8_to_euc_E69C[] = {
- 0x3A47, 0, 0, 0x5072, 0, 0xC26E, 0, 0xC26F,
- 0x376E, 0x4D2D, 0, 0x4A7E, 0, 0x497E, 0xC270, 0x5B2C,
- 0, 0, 0, 0xC271, 0x3A73, 0x443F, 0x5B2D, 0x4F2F,
- 0, 0xC272, 0, 0x4B3E, 0xC273, 0x442B, 0x5B2E, 0x347C,
- 0xC274, 0, 0xC275, 0, 0, 0, 0x5B2F, 0x5B30,
- 0x4C5A, 0, 0x4C24, 0x4B76, 0x4B5C, 0x3B25, 0x5B32, 0,
- 0, 0x3C6B, 0, 0xC276, 0x4B51, 0, 0x5B34, 0x5B37,
- 0x5B36, 0, 0x3479, 0, 0, 0x3560, 0xC277, 0x5B33,
-};
-static const unsigned short utf8_to_euc_E69C_x0213[] = {
- 0x3A47, 0xAE37, 0, 0x5072, 0, 0xAE38, 0, 0xC26F,
- 0x376E, 0x4D2D, 0, 0x4A7E, 0, 0x497E, 0, 0x5B2C,
- 0, 0, 0xAE39, 0x754D, 0x3A73, 0x443F, 0x5B2D, 0x4F2F,
- 0, 0xAE3B, 0, 0x4B3E, 0xC273, 0x442B, 0x5B2E, 0x347C,
- 0xC274, 0, 0xC275, 0, 0, 0, 0x5B2F, 0x5B30,
- 0x4C5A, 0, 0x4C24, 0x4B76, 0x4B5C, 0x3B25, 0x5B32, 0,
- 0, 0x3C6B, 0, 0x754F, 0x4B51, 0, 0x5B34, 0x5B37,
- 0x5B36, 0, 0x3479, 0, 0, 0x3560, 0xC277, 0x5B33,
-};
-static const unsigned short utf8_to_euc_E69D[] = {
- 0, 0x5B35, 0, 0, 0, 0xC278, 0x5B38, 0xC279,
- 0xC27A, 0x3F79, 0, 0, 0xC27B, 0, 0x4D7B, 0x3049,
- 0x3A60, 0x423C, 0, 0x3C5D, 0xC27C, 0xC27D, 0x3E73, 0,
- 0, 0x5B3B, 0, 0, 0x454E, 0xC27E, 0x5B39, 0x422B,
- 0x5B3A, 0x3E72, 0x4C5D, 0x5B3C, 0x5B3D, 0x4D68, 0xC321, 0,
- 0, 0, 0x5B42, 0, 0xC322, 0x393A, 0xC323, 0x4755,
- 0x5B3F, 0x456C, 0x5A5E, 0x5A62, 0xC324, 0x354F, 0xC325, 0x4747,
- 0, 0, 0, 0xC326, 0x5B41, 0, 0x3E3E, 0x4844,
-};
-static const unsigned short utf8_to_euc_E69D_x0213[] = {
- 0, 0x5B35, 0, 0, 0, 0xC278, 0x5B38, 0x7551,
- 0x7552, 0x3F79, 0, 0, 0xAE3E, 0xAE3F, 0x4D7B, 0x3049,
- 0x3A60, 0x423C, 0, 0x3C5D, 0xAE40, 0xC27D, 0x3E73, 0,
- 0, 0x5B3B, 0, 0, 0x454E, 0xAE41, 0x5B39, 0x422B,
- 0x5B3A, 0x3E72, 0x4C5D, 0x5B3C, 0x5B3D, 0x4D68, 0x7550, 0,
- 0, 0, 0x5B42, 0, 0xC322, 0x393A, 0xC323, 0x4755,
- 0x5B3F, 0x456C, 0x5A5E, 0x5A62, 0xAE45, 0x354F, 0xAE46, 0x4747,
- 0, 0, 0, 0x7553, 0x5B41, 0, 0x3E3E, 0x4844,
-};
-static const unsigned short utf8_to_euc_E69E[] = {
- 0, 0xC327, 0, 0, 0xC328, 0x5B47, 0, 0x487A,
- 0, 0x5B3E, 0, 0x5B44, 0x5B43, 0, 0xC329, 0xC32A,
- 0x404F, 0xC32B, 0, 0xC32C, 0, 0x4B6D, 0xC32D, 0x4E53,
- 0xC32E, 0xC32F, 0x4B67, 0xC330, 0x324C, 0x3B5E, 0, 0,
- 0x4F48, 0x5B46, 0x3F75, 0, 0, 0, 0x5B45, 0,
- 0, 0x5B40, 0, 0, 0, 0, 0, 0x384F,
- 0xC331, 0xC332, 0xC333, 0x5B4C, 0x5B4A, 0xC334, 0x324D, 0x5B48,
- 0x5B4E, 0x5B54, 0, 0xC335, 0xC336, 0xC337, 0, 0,
-};
-static const unsigned short utf8_to_euc_E69E_x0213[] = {
- 0, 0x7554, 0, 0, 0xC328, 0x5B47, 0, 0x487A,
- 0, 0x5B3E, 0, 0x5B44, 0x5B43, 0, 0xC329, 0xC32A,
- 0x404F, 0xC32B, 0xAE48, 0x7555, 0, 0x4B6D, 0xC32D, 0x4E53,
- 0x7556, 0xC32F, 0x4B67, 0x7557, 0x324C, 0x3B5E, 0, 0,
- 0x4F48, 0x5B46, 0x3F75, 0, 0, 0, 0x5B45, 0,
- 0, 0x5B40, 0, 0, 0, 0, 0, 0x384F,
- 0xAE4C, 0xC332, 0xAE4D, 0x5B4C, 0x5B4A, 0xC334, 0x324D, 0x5B48,
- 0x5B4E, 0x5B54, 0, 0x7558, 0xC336, 0xC337, 0, 0,
-};
-static const unsigned short utf8_to_euc_E69F[] = {
- 0xC339, 0x4248, 0xC33A, 0xC33B, 0x4A41, 0xC33C, 0x5B56, 0,
- 0xC33D, 0xC33E, 0x4922, 0, 0, 0, 0x5B55, 0x4770,
- 0x4B3F, 0x343B, 0xC33F, 0x4077, 0x3D40, 0, 0, 0xC340,
- 0x4453, 0xC341, 0x4D2E, 0, 0xC342, 0x5B51, 0x5B50, 0,
- 0, 0xC343, 0x5B52, 0, 0x5B4F, 0, 0xC344, 0x5B57,
- 0, 0x5B4D, 0, 0, 0x5B4B, 0, 0x5B53, 0x5B49,
- 0xC345, 0x436C, 0xC346, 0x4C78, 0x3C46, 0x3A74, 0xC347, 0xC348,
- 0, 0xC338, 0, 0x3A3A, 0, 0, 0x4B6F, 0x3341,
-};
-static const unsigned short utf8_to_euc_E69F_x0213[] = {
- 0x755A, 0x4248, 0xC33A, 0xAE4E, 0x4A41, 0xC33C, 0x5B56, 0,
- 0xAE4F, 0xC33E, 0x4922, 0, 0, 0, 0x5B55, 0x4770,
- 0x4B3F, 0x343B, 0xAE50, 0x4077, 0x3D40, 0, 0, 0x755B,
- 0x4453, 0xAE51, 0x4D2E, 0xAE52, 0xC342, 0x5B51, 0x5B50, 0,
- 0, 0xC343, 0x5B52, 0, 0x5B4F, 0, 0xC344, 0x5B57,
- 0, 0x5B4D, 0, 0, 0x5B4B, 0, 0x5B53, 0x5B49,
- 0xAE53, 0x436C, 0xC346, 0x4C78, 0x3C46, 0x3A74, 0xC347, 0xAE54,
- 0, 0x7559, 0, 0x3A3A, 0x755C, 0, 0x4B6F, 0x3341,
-};
-static const unsigned short utf8_to_euc_E6A0[] = {
- 0, 0xF446, 0x444E, 0x464A, 0x3149, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x4072, 0xC34A, 0, 0x4034, 0x372A,
- 0, 0xC34B, 0, 0, 0, 0xC34C, 0x5B59, 0xC34D,
- 0, 0x393B, 0x337C, 0, 0, 0, 0, 0xC34F,
- 0xC34E, 0x5B5B, 0x3374, 0x5B61, 0xC350, 0xC351, 0, 0xC352,
- 0xC353, 0xC354, 0x5B5E, 0xC355, 0x4073, 0, 0, 0,
- 0x334B, 0x3A2C, 0, 0xC356, 0x334A, 0x3A4F, 0, 0xC357,
-};
-static const unsigned short utf8_to_euc_E6A0_x0213[] = {
- 0, 0x755D, 0x444E, 0x464A, 0x3149, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xAE4B, 0, 0, 0x4072, 0xC34A, 0, 0x4034, 0x372A,
- 0xAE58, 0xC34B, 0, 0, 0, 0x755F, 0x5B59, 0xAE59,
- 0, 0x393B, 0x337C, 0, 0, 0, 0, 0xC34F,
- 0xC34E, 0x5B5B, 0x3374, 0x5B61, 0x7560, 0xAE5A, 0, 0xC352,
- 0xC353, 0x7561, 0x5B5E, 0xAE5C, 0x4073, 0, 0, 0,
- 0x334B, 0x3A2C, 0, 0xAE5D, 0x334A, 0x3A4F, 0xAE5E, 0xC357,
-};
-static const unsigned short utf8_to_euc_E6A1[] = {
- 0x5B5C, 0x3765, 0x374B, 0x456D, 0xC358, 0xC359, 0x5B5A, 0,
- 0x3046, 0, 0xC35A, 0, 0xC35B, 0x5B5D, 0x5B5F, 0,
- 0x364D, 0x372C, 0xC349, 0x343C, 0x354B, 0xC35C, 0, 0xC35D,
- 0xC35E, 0x5B62, 0, 0xC35F, 0x3A79, 0x4B71, 0, 0x3B37,
- 0, 0, 0, 0x5B63, 0, 0, 0, 0x4930,
- 0, 0, 0, 0xC360, 0, 0, 0xC361, 0xC362,
- 0xC363, 0xC364, 0xC365, 0, 0x5B6F, 0xC366, 0x3233, 0x5B64,
- 0, 0xC367, 0xC368, 0xC369, 0xC36A, 0, 0x5B75, 0x5B65,
-};
-static const unsigned short utf8_to_euc_E6A1_x0213[] = {
- 0x5B5C, 0x3765, 0x374B, 0x456D, 0xAE5F, 0xAE60, 0x5B5A, 0,
- 0x3046, 0xAE61, 0xC35A, 0, 0xAE62, 0x5B5D, 0x5B5F, 0,
- 0x364D, 0x372C, 0x755E, 0x343C, 0x354B, 0xAE63, 0, 0xAE64,
- 0xC35E, 0x5B62, 0, 0x7562, 0x3A79, 0x4B71, 0, 0x3B37,
- 0, 0, 0, 0x5B63, 0, 0, 0, 0x4930,
- 0, 0, 0, 0xAE66, 0, 0, 0xAE67, 0xC362,
- 0xC363, 0xC364, 0x7563, 0, 0x5B6F, 0x7564, 0x3233, 0x5B64,
- 0, 0xC367, 0xAE68, 0xC369, 0xAE69, 0, 0x5B75, 0x5B65,
-};
-static const unsigned short utf8_to_euc_E6A2[] = {
- 0, 0x4E42, 0xC36B, 0x5B6C, 0xC36C, 0x475F, 0xC36D, 0,
- 0xC36E, 0, 0, 0, 0, 0x5B74, 0, 0x5B67,
- 0, 0, 0, 0x3034, 0x5B69, 0, 0xC36F, 0x393C,
- 0xC370, 0, 0xC371, 0x5B6B, 0xC372, 0x5B6A, 0, 0x5B66,
- 0x5B71, 0xC373, 0x3E3F, 0xC374, 0, 0xC375, 0x546D, 0x3868,
- 0x4D7C, 0xC376, 0xC377, 0, 0, 0x5B68, 0xC378, 0x4474,
- 0x3323, 0x3A2D, 0xC379, 0x5B60, 0, 0x5B70, 0x3361, 0,
- 0, 0x5B6E, 0x5B72, 0xC37A, 0x456E, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E6A2_x0213[] = {
- 0, 0x4E42, 0xAE6A, 0x5B6C, 0xC36C, 0x475F, 0xC36D, 0,
- 0xC36E, 0, 0, 0, 0, 0x5B74, 0, 0x5B67,
- 0xAE6B, 0, 0, 0x3034, 0x5B69, 0, 0xAE6C, 0x393C,
- 0xAE6E, 0xAE6F, 0xAE70, 0x5B6B, 0xAE71, 0x5B6A, 0, 0x5B66,
- 0x5B71, 0xC373, 0x3E3F, 0x7566, 0, 0x7567, 0x546D, 0x3868,
- 0x4D7C, 0xC376, 0xAE72, 0xAE73, 0, 0x5B68, 0xC378, 0x4474,
- 0x3323, 0x3A2D, 0x7568, 0x5B60, 0xAE74, 0x5B70, 0x3361, 0,
- 0, 0x5B6E, 0x5B72, 0xAE75, 0x456E, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E6A3[] = {
- 0, 0, 0, 0, 0x347E, 0xC37B, 0x5C32, 0,
- 0xC37C, 0x4C49, 0x5B77, 0x347D, 0xC37D, 0x5B7E, 0, 0xC37E,
- 0xC421, 0xC422, 0x4B40, 0xC423, 0x5C21, 0x5C23, 0xC424, 0x5C27,
- 0x5B79, 0xC425, 0x432A, 0, 0xC426, 0xC427, 0, 0x456F,
- 0x5C2B, 0x5B7C, 0, 0x5C28, 0, 0xC428, 0, 0x5C22,
- 0xC429, 0, 0xC42A, 0xC42B, 0xC42C, 0xC42D, 0x3F39, 0x5C2C,
- 0xC42E, 0xC42F, 0x4033, 0, 0, 0xC430, 0xC431, 0,
- 0, 0x5C2A, 0x343D, 0xC432, 0xC433, 0xC434, 0, 0,
-};
-static const unsigned short utf8_to_euc_E6A3_x0213[] = {
- 0, 0, 0, 0xAE7A, 0x347E, 0xAE7B, 0x5C32, 0,
- 0x7569, 0x4C49, 0x5B77, 0x347D, 0xAE7C, 0x5B7E, 0, 0xAE7D,
- 0x756A, 0xC422, 0x4B40, 0xC423, 0x5C21, 0x5C23, 0xAE7E, 0x5C27,
- 0x5B79, 0xAF21, 0x432A, 0, 0xC426, 0xC427, 0, 0x456F,
- 0x5C2B, 0x5B7C, 0, 0x5C28, 0xAF22, 0xAF23, 0, 0x5C22,
- 0x756B, 0, 0xC42A, 0xC42B, 0xAF24, 0x756C, 0x3F39, 0x5C2C,
- 0x756D, 0x756E, 0x4033, 0, 0, 0xC430, 0xC431, 0xAF25,
- 0, 0x5C2A, 0x343D, 0xAE76, 0x756F, 0xC434, 0, 0,
-};
-static const unsigned short utf8_to_euc_E6A4[] = {
- 0x4F50, 0x5B76, 0, 0, 0x5C26, 0x3058, 0xC435, 0,
- 0x5B78, 0xC436, 0xC437, 0x4C3A, 0x5B7D, 0x3F22, 0x4447, 0x5B73,
- 0xC438, 0xC439, 0x5C25, 0xC43A, 0, 0, 0xC43B, 0xC43C,
- 0, 0x3F7A, 0x5C2F, 0x3371, 0x3821, 0, 0, 0,
- 0, 0x5C31, 0x5B7A, 0x5C30, 0, 0x5C29, 0x5B7B, 0,
- 0x5C2D, 0, 0x5C2E, 0, 0, 0, 0, 0,
- 0x5C3F, 0xC43D, 0, 0xC43E, 0x464E, 0xC43F, 0x5C24, 0,
- 0xC440, 0x5C3B, 0, 0xC441, 0, 0x5C3D, 0, 0x4458,
-};
-static const unsigned short utf8_to_euc_E6A4_x0213[] = {
- 0x4F50, 0x5B76, 0, 0xAF26, 0x5C26, 0x3058, 0xC435, 0xAF27,
- 0x5B78, 0xC436, 0x7570, 0x4C3A, 0x5B7D, 0x3F22, 0x4447, 0x5B73,
- 0xC438, 0xC439, 0x5C25, 0xC43A, 0, 0, 0xC43B, 0xC43C,
- 0, 0x3F7A, 0x5C2F, 0x3371, 0x3821, 0, 0, 0,
- 0, 0x5C31, 0x5B7A, 0x5C30, 0, 0x5C29, 0x5B7B, 0,
- 0x5C2D, 0, 0x5C2E, 0, 0, 0, 0, 0,
- 0x5C3F, 0xC43D, 0, 0xC43E, 0x464E, 0x7573, 0x5C24, 0,
- 0xC440, 0x5C3B, 0, 0xAF2B, 0, 0x5C3D, 0, 0x4458,
-};
-static const unsigned short utf8_to_euc_E6A5[] = {
- 0, 0, 0xC442, 0, 0, 0xC443, 0, 0,
- 0, 0xC444, 0x4D4C, 0, 0, 0, 0xC445, 0,
- 0, 0, 0, 0x4976, 0x5C38, 0x424A, 0, 0xC446,
- 0, 0x5C3E, 0x413F, 0xC447, 0x5C35, 0x5C42, 0x5C41, 0,
- 0x466F, 0x5C40, 0x466A, 0xC448, 0xC449, 0xC44A, 0xC44B, 0,
- 0xC44C, 0xC44D, 0x5C44, 0x5C37, 0xC44E, 0x3648, 0x5C3A, 0x3D5D,
- 0xC44F, 0xC450, 0xC451, 0x4760, 0x5C3C, 0x364B, 0, 0x5C34,
- 0x5C36, 0x5C33, 0xC452, 0xC453, 0x4F30, 0x335A, 0x5C39, 0xC454,
-};
-static const unsigned short utf8_to_euc_E6A5_x0213[] = {
- 0, 0, 0x7574, 0, 0, 0xC443, 0xAF2D, 0,
- 0, 0x7571, 0x4D4C, 0, 0, 0, 0xC445, 0,
- 0, 0, 0, 0x4976, 0x5C38, 0x424A, 0, 0x7575,
- 0, 0x5C3E, 0x413F, 0xC447, 0x5C35, 0x5C42, 0x5C41, 0,
- 0x466F, 0x5C40, 0x466A, 0x7576, 0x7577, 0xC44A, 0xC44B, 0,
- 0x7578, 0xAF2E, 0x5C44, 0x5C37, 0xAF2F, 0x3648, 0x5C3A, 0x3D5D,
- 0xC44F, 0xC450, 0xAF30, 0x4760, 0x5C3C, 0x364B, 0, 0x5C34,
- 0x5C36, 0x5C33, 0xAF31, 0xC453, 0x4F30, 0x335A, 0x5C39, 0xAF32,
-};
-static const unsigned short utf8_to_euc_E6A6[] = {
- 0xC455, 0x5C43, 0x3335, 0, 0, 0, 0, 0,
- 0, 0, 0x3A67, 0, 0, 0xC456, 0x315D, 0,
- 0, 0x5C54, 0xC457, 0, 0x4F31, 0x5C57, 0xC458, 0,
- 0xC459, 0, 0, 0x3F3A, 0x5C56, 0, 0, 0,
- 0x5C55, 0xC45A, 0, 0, 0, 0xC45B, 0xC45C, 0x5C52,
- 0xC45D, 0, 0, 0xC45E, 0, 0xC45F, 0x5C46, 0xC460,
- 0, 0x5C63, 0x5C45, 0, 0x5C58, 0, 0, 0xC461,
- 0xC462, 0, 0xC463, 0x5C50, 0xC464, 0, 0x5C4B, 0x5C48,
-};
-static const unsigned short utf8_to_euc_E6A6_x0213[] = {
- 0x7579, 0x5C43, 0x3335, 0, 0, 0, 0, 0,
- 0, 0, 0x3A67, 0, 0, 0xC456, 0x315D, 0,
- 0, 0x5C54, 0xAF33, 0, 0x4F31, 0x5C57, 0xAF35, 0,
- 0xAF36, 0, 0, 0x3F3A, 0x5C56, 0, 0, 0,
- 0x5C55, 0xC45A, 0, 0, 0, 0x757B, 0xAF37, 0x5C52,
- 0xC45D, 0, 0, 0xC45E, 0, 0x757C, 0x5C46, 0xC460,
- 0xAF38, 0x5C63, 0x5C45, 0, 0x5C58, 0, 0, 0xAF39,
- 0xC462, 0, 0xAF3A, 0x5C50, 0xAF3B, 0, 0x5C4B, 0x5C48,
-};
-static const unsigned short utf8_to_euc_E6A7[] = {
- 0, 0x5C49, 0, 0x5C51, 0, 0xC465, 0, 0x7422,
- 0xC466, 0, 0x5C4E, 0x393D, 0x4448, 0x4164, 0x5C4C, 0,
- 0x5C47, 0xC467, 0, 0x5C4A, 0, 0, 0xC468, 0xC469,
- 0x4D4D, 0x4B6A, 0, 0, 0, 0x5C4F, 0x5C59, 0,
- 0, 0, 0xC46A, 0, 0, 0xC46B, 0, 0x5C61,
- 0x5C5A, 0, 0, 0x5C67, 0, 0x5C65, 0xC46C, 0xC46D,
- 0, 0xC46E, 0x5C60, 0xC46F, 0, 0xC470, 0, 0,
- 0, 0x5C5F, 0, 0x4450, 0, 0x4165, 0xC471, 0x5C5D,
-};
-static const unsigned short utf8_to_euc_E6A7_x0213[] = {
- 0xAF3C, 0x5C49, 0, 0x5C51, 0, 0xC465, 0, 0x7422,
- 0xC466, 0, 0x5C4E, 0x393D, 0x4448, 0x4164, 0x5C4C, 0x757D,
- 0x5C47, 0xAF3D, 0, 0x5C4A, 0, 0, 0xAF3E, 0xC469,
- 0x4D4D, 0x4B6A, 0, 0, 0, 0x5C4F, 0x5C59, 0,
- 0, 0, 0x7622, 0xAF44, 0, 0xC46B, 0, 0x5C61,
- 0x5C5A, 0x7623, 0x7624, 0x5C67, 0, 0x5C65, 0xAF45, 0xAF46,
- 0, 0xC46E, 0x5C60, 0xAF47, 0xAF49, 0x7625, 0x7626, 0,
- 0, 0x5C5F, 0, 0x4450, 0, 0x4165, 0xAF4A, 0x5C5D,
-};
-static const unsigned short utf8_to_euc_E6A8[] = {
- 0xC472, 0xC473, 0x5C5B, 0xC474, 0, 0x5C62, 0, 0,
- 0, 0, 0x5C68, 0x4875, 0x5C6E, 0, 0, 0xC475,
- 0, 0xC476, 0x5C69, 0x5C6C, 0x5C66, 0xC477, 0, 0x4374,
- 0, 0x4938, 0xC478, 0x5C5C, 0, 0xC479, 0x5C64, 0x3E40,
- 0xC47A, 0x4C4F, 0x5C78, 0x5C6B, 0xC47B, 0, 0, 0,
- 0xC47C, 0x3822, 0x3223, 0x335F, 0, 0, 0x5C53, 0,
- 0xC47D, 0, 0xC47E, 0, 0xC521, 0x3E41, 0x5C70, 0xC522,
- 0x5C77, 0x3C79, 0x3372, 0xC523, 0, 0x432E, 0xC524, 0xC525,
-};
-static const unsigned short utf8_to_euc_E6A8_x0213[] = {
- 0xC472, 0xC473, 0x5C5B, 0xC474, 0, 0x5C62, 0, 0,
- 0, 0, 0x5C68, 0x4875, 0x5C6E, 0, 0, 0x7627,
- 0, 0xAF4B, 0x5C69, 0x5C6C, 0x5C66, 0x7628, 0, 0x4374,
- 0, 0x4938, 0xAF4C, 0x5C5C, 0, 0xAF4D, 0x5C64, 0x3E40,
- 0xC47A, 0x4C4F, 0x5C78, 0x5C6B, 0xC47B, 0, 0, 0,
- 0xC47C, 0x3822, 0x3223, 0x335F, 0, 0, 0x5C53, 0,
- 0xAF41, 0, 0xAF4F, 0xAF50, 0xAF51, 0x3E41, 0x5C70, 0xC522,
- 0x5C77, 0x3C79, 0x3372, 0x762A, 0, 0x432E, 0x762B, 0xAF52,
-};
-static const unsigned short utf8_to_euc_E6A9[] = {
- 0, 0, 0, 0, 0x5C6D, 0xC526, 0xC527, 0x5C72,
- 0x5C76, 0xC528, 0xC529, 0x3636, 0, 0, 0xC52A, 0,
- 0xC52B, 0xC52C, 0xC52D, 0, 0, 0xC52E, 0xC52F, 0,
- 0x354C, 0x5C74, 0, 0xC530, 0, 0, 0, 0x3521,
- 0, 0x464B, 0x5C73, 0, 0xC531, 0, 0x5C75, 0xC532,
- 0, 0, 0xC533, 0xF449, 0, 0, 0, 0,
- 0, 0xC534, 0x5C6F, 0xC535, 0, 0, 0, 0,
- 0x5C71, 0, 0, 0, 0, 0, 0xC536, 0x3360,
-};
-static const unsigned short utf8_to_euc_E6A9_x0213[] = {
- 0, 0, 0, 0, 0x5C6D, 0x762C, 0xAF53, 0x5C72,
- 0x5C76, 0xAF54, 0xC529, 0x3636, 0, 0, 0xAF56, 0,
- 0x762D, 0xC52C, 0xAF57, 0, 0, 0xC52E, 0x762E, 0,
- 0x354C, 0x5C74, 0, 0x762F, 0, 0, 0, 0x3521,
- 0, 0x464B, 0x5C73, 0, 0xAF58, 0, 0x5C75, 0xC532,
- 0, 0, 0xC533, 0x7630, 0, 0, 0, 0,
- 0, 0xC534, 0x5C6F, 0x7631, 0, 0, 0, 0,
- 0x5C71, 0, 0xAF55, 0, 0, 0, 0xAF5A, 0x3360,
-};
-static const unsigned short utf8_to_euc_E6AA[] = {
- 0x4349, 0xC537, 0, 0xC538, 0x5C7C, 0, 0xC539, 0xC53A,
- 0, 0xC53B, 0, 0xC53C, 0, 0x5C7A, 0x3869, 0,
- 0x5C79, 0xC53D, 0, 0, 0, 0, 0, 0x5D21,
- 0, 0, 0, 0xC53E, 0x5B58, 0xC53F, 0xC540, 0xC541,
- 0x5C7B, 0, 0x5C7D, 0x5C7E, 0, 0xC542, 0, 0,
- 0, 0, 0x5D2C, 0xC543, 0x5D28, 0, 0x5B6D, 0xC544,
- 0xC545, 0xC546, 0, 0x5D27, 0xC547, 0, 0, 0,
- 0x5D26, 0, 0, 0x5D23, 0, 0xC548, 0xC549, 0xC54A,
-};
-static const unsigned short utf8_to_euc_E6AA_x0213[] = {
- 0x4349, 0xC537, 0, 0xAF5B, 0x5C7C, 0, 0xC539, 0xC53A,
- 0, 0x7633, 0, 0xAF5C, 0, 0x5C7A, 0x3869, 0,
- 0x5C79, 0xAF5E, 0, 0, 0x7634, 0, 0, 0x5D21,
- 0, 0, 0, 0xC53E, 0x5B58, 0x7635, 0x7636, 0xAF5F,
- 0x5C7B, 0xAF60, 0x5C7D, 0x5C7E, 0, 0x7637, 0, 0,
- 0, 0, 0x5D2C, 0xAF62, 0x5D28, 0, 0x5B6D, 0xC544,
- 0xC545, 0xC546, 0, 0x5D27, 0xC547, 0, 0, 0,
- 0x5D26, 0, 0, 0x5D23, 0, 0xAF63, 0xC549, 0xC54A,
-};
-static const unsigned short utf8_to_euc_E6AB[] = {
- 0, 0x5C6A, 0x5D25, 0x5D24, 0, 0, 0xC54B, 0,
- 0xC54D, 0xC54C, 0, 0, 0xC54E, 0, 0, 0,
- 0xC54F, 0x5D2A, 0, 0x4F26, 0xC550, 0xC551, 0xC552, 0,
- 0, 0, 0x5D2D, 0x367B, 0xC553, 0xC554, 0x5D29, 0x5D2B,
- 0, 0, 0xF44A, 0, 0xC555, 0, 0, 0xC556,
- 0x4827, 0, 0x5D2E, 0, 0xC557, 0, 0, 0,
- 0xC558, 0xC559, 0xC55A, 0, 0, 0, 0, 0,
- 0, 0, 0x5D32, 0x5D2F, 0xC55B, 0xC55C, 0, 0,
-};
-static const unsigned short utf8_to_euc_E6AB_x0213[] = {
- 0, 0x5C6A, 0x5D25, 0x5D24, 0, 0, 0xAF64, 0,
- 0xC54D, 0xC54C, 0, 0, 0xC54E, 0, 0, 0,
- 0xAF66, 0x5D2A, 0, 0x4F26, 0xAF65, 0xC551, 0xC552, 0,
- 0, 0, 0x5D2D, 0x367B, 0xAF67, 0xAF68, 0x5D29, 0x5D2B,
- 0, 0, 0, 0, 0x7638, 0, 0, 0x7639,
- 0x4827, 0, 0x5D2E, 0, 0xAF6B, 0, 0, 0,
- 0xC558, 0xAF6C, 0xAF6D, 0xAF6E, 0, 0, 0, 0,
- 0, 0, 0x5D32, 0x5D2F, 0xC55B, 0xAF6F, 0, 0,
-};
-static const unsigned short utf8_to_euc_E6AC[] = {
- 0, 0, 0xC55D, 0xC55E, 0x4D73, 0x5D30, 0xC55F, 0xC560,
- 0, 0xC561, 0x5C5E, 0, 0, 0, 0, 0xC562,
- 0xC563, 0xC564, 0x5D33, 0, 0, 0, 0x5D34, 0xC565,
- 0, 0, 0, 0xC566, 0, 0x3135, 0xC567, 0x5D36,
- 0x3767, 0x3C21, 0, 0x3655, 0xC568, 0, 0, 0x3224,
- 0xC569, 0, 0, 0xC56A, 0xC56B, 0, 0, 0xC56C,
- 0, 0, 0x4D5F, 0, 0, 0xC56D, 0xC56E, 0x5D38,
- 0x5D37, 0x5D3A, 0x353D, 0xC56F, 0, 0x3656, 0x343E, 0xC570,
-};
-static const unsigned short utf8_to_euc_E6AC_x0213[] = {
- 0, 0, 0xC55D, 0xC55E, 0x4D73, 0x5D30, 0xC55F, 0xC560,
- 0, 0xC561, 0x5C5E, 0xAF71, 0, 0, 0, 0xAF72,
- 0xAF73, 0xAF74, 0x5D33, 0, 0, 0, 0x5D34, 0xAF76,
- 0, 0, 0, 0x763C, 0, 0x3135, 0x763D, 0x5D36,
- 0x3767, 0x3C21, 0, 0x3655, 0xC568, 0, 0, 0x3224,
- 0xC569, 0, 0, 0xC56A, 0x763E, 0, 0, 0xAF78,
- 0, 0, 0x4D5F, 0, 0, 0x763F, 0xC56E, 0x5D38,
- 0x5D37, 0x5D3A, 0x353D, 0xC56F, 0, 0x3656, 0x343E, 0xC570,
-};
-static const unsigned short utf8_to_euc_E6AD[] = {
- 0, 0, 0, 0x5D3D, 0, 0, 0xC571, 0x5D3C,
- 0, 0x5D3E, 0xC572, 0, 0x324E, 0xC573, 0x4337, 0,
- 0x5D3F, 0, 0xC574, 0x343F, 0x5D41, 0, 0xC575, 0,
- 0xC576, 0x5D40, 0, 0x5D42, 0, 0xC577, 0, 0x5D43,
- 0xC578, 0x5D44, 0x3B5F, 0x4035, 0x3A21, 0, 0x4970, 0xC579,
- 0, 0x4A62, 0x4F44, 0xC57A, 0, 0, 0xC57B, 0x3B75,
- 0xC57C, 0, 0, 0x3A50, 0x4E72, 0xC57D, 0, 0,
- 0x5D45, 0x5D46, 0, 0x3B60, 0, 0xC57E, 0xC621, 0x5D47,
-};
-static const unsigned short utf8_to_euc_E6AD_x0213[] = {
- 0, 0, 0, 0x5D3D, 0, 0, 0x7640, 0x5D3C,
- 0, 0x5D3E, 0xAF79, 0, 0x324E, 0xC573, 0x4337, 0,
- 0x5D3F, 0, 0xC574, 0x343F, 0x5D41, 0, 0x7641, 0,
- 0xAF7A, 0x5D40, 0, 0x5D42, 0, 0xC577, 0, 0x5D43,
- 0x7642, 0x5D44, 0x3B5F, 0x4035, 0x3A21, 0x7643, 0x4970, 0x7644,
- 0, 0x4A62, 0x4F44, 0xC57A, 0xAF7B, 0, 0xC57B, 0x3B75,
- 0xC57C, 0, 0, 0x3A50, 0x4E72, 0xAF7C, 0, 0x7645,
- 0x5D45, 0x5D46, 0xAF7D, 0x3B60, 0, 0xC57E, 0xC621, 0x5D47,
-};
-static const unsigned short utf8_to_euc_E6AE[] = {
- 0x5D48, 0, 0xC622, 0x5D4A, 0x5D49, 0xC623, 0x4B58, 0,
- 0, 0x3D5E, 0x3C6C, 0x3B44, 0, 0x5D4B, 0, 0,
- 0, 0, 0, 0, 0, 0x5D4D, 0x3F23, 0xC624,
- 0x5D4C, 0, 0, 0xC625, 0, 0, 0x5D4E, 0xC626,
- 0xC627, 0, 0xC628, 0xC629, 0x5D4F, 0, 0, 0,
- 0xC62A, 0xC62B, 0x5D50, 0x5D51, 0xC62C, 0xC62D, 0xC62E, 0x5D52,
- 0xC62F, 0x5D54, 0x5D53, 0x5D55, 0x3225, 0x434A, 0, 0x5D56,
- 0xC630, 0xC631, 0x3B26, 0x334C, 0x5D57, 0xC632, 0xC633, 0x4542,
-};
-static const unsigned short utf8_to_euc_E6AE_x0213[] = {
- 0x5D48, 0xAF7E, 0x7646, 0x5D4A, 0x5D49, 0xC623, 0x4B58, 0,
- 0, 0x3D5E, 0x3C6C, 0x3B44, 0, 0x5D4B, 0, 0,
- 0, 0, 0, 0, 0, 0x5D4D, 0x3F23, 0xC624,
- 0x5D4C, 0, 0, 0xEE21, 0, 0, 0x5D4E, 0xC626,
- 0xC627, 0, 0xC628, 0xC629, 0x5D4F, 0, 0, 0,
- 0xC62A, 0x7647, 0x5D50, 0x5D51, 0xC62C, 0x7648, 0xEE22, 0x5D52,
- 0xC62F, 0x5D54, 0x5D53, 0x5D55, 0x3225, 0x434A, 0, 0x5D56,
- 0xC630, 0xC631, 0x3B26, 0x334C, 0x5D57, 0xEE24, 0xEE25, 0x4542,
-};
-static const unsigned short utf8_to_euc_E6AF[] = {
- 0x544C, 0, 0, 0xC634, 0xC635, 0x3523, 0x5D58, 0,
- 0, 0xC636, 0, 0x5D59, 0xC637, 0x4A6C, 0x4B68, 0,
- 0, 0, 0x4647, 0x5D5A, 0x4866, 0, 0xC638, 0,
- 0x487B, 0, 0xC639, 0x4C53, 0, 0, 0, 0x5D5B,
- 0, 0xC63A, 0, 0xC63B, 0, 0, 0xC63C, 0xC63D,
- 0, 0, 0, 0x5D5D, 0x5D5C, 0, 0xC63E, 0x5D5F,
- 0, 0xC63F, 0, 0x5D5E, 0, 0, 0, 0xC640,
- 0, 0xC641, 0, 0, 0, 0, 0, 0xC642,
-};
-static const unsigned short utf8_to_euc_E6AF_x0213[] = {
- 0x544C, 0, 0, 0xC634, 0xC635, 0x3523, 0x5D58, 0xEE26,
- 0xEE27, 0xEE28, 0, 0x5D59, 0xC637, 0x4A6C, 0x4B68, 0x764A,
- 0, 0, 0x4647, 0x5D5A, 0x4866, 0, 0x764B, 0x764C,
- 0x487B, 0, 0xEE29, 0x4C53, 0, 0, 0, 0x5D5B,
- 0, 0xC63A, 0, 0xC63B, 0, 0, 0xEE2A, 0xEE2B,
- 0, 0, 0, 0x5D5D, 0x5D5C, 0, 0xEE2C, 0x5D5F,
- 0, 0xEE2D, 0, 0x5D5E, 0, 0, 0, 0xC640,
- 0, 0xC641, 0, 0, 0, 0, 0, 0x764D,
-};
-static const unsigned short utf8_to_euc_E6B0[] = {
- 0, 0, 0xC643, 0, 0xC644, 0xC645, 0, 0,
- 0x5D61, 0xC646, 0, 0, 0, 0xC647, 0xC648, 0x3B61,
- 0xC649, 0x4C31, 0xC64A, 0x5D62, 0x5D63, 0, 0, 0x3524,
- 0, 0xC64B, 0, 0x5D64, 0, 0, 0, 0xC64C,
- 0, 0, 0, 0x5D66, 0x5D65, 0, 0xC64D, 0xC64E,
- 0xC64F, 0, 0, 0, 0xC650, 0, 0xC651, 0,
- 0, 0, 0, 0xC652, 0x3F65, 0xC653, 0xC654, 0x4939,
- 0x314A, 0, 0xC655, 0xC656, 0, 0, 0x4845, 0xC657,
-};
-static const unsigned short utf8_to_euc_E6B0_x0213[] = {
- 0, 0, 0xEE2E, 0, 0xC644, 0x764E, 0, 0,
- 0x5D61, 0xC646, 0xEE2F, 0, 0, 0xC647, 0xEE30, 0x3B61,
- 0x764F, 0x4C31, 0xC64A, 0x5D62, 0x5D63, 0, 0, 0x3524,
- 0, 0xC64B, 0, 0x5D64, 0, 0, 0, 0xC64C,
- 0, 0, 0, 0x5D66, 0x5D65, 0, 0xC64D, 0xC64E,
- 0xC64F, 0, 0, 0, 0xC650, 0, 0xC651, 0,
- 0, 0, 0, 0x7650, 0x3F65, 0xEE31, 0xEE32, 0x4939,
- 0x314A, 0, 0xEE33, 0xC656, 0, 0, 0x4845, 0xEE35,
-};
-static const unsigned short utf8_to_euc_E6B1[] = {
- 0x4475, 0x3D41, 0x3561, 0, 0, 0, 0, 0,
- 0, 0, 0xC658, 0xC659, 0, 0xC65A, 0x4846, 0xC65B,
- 0x3C2E, 0, 0xC65C, 0, 0xC65D, 0x5D68, 0, 0x3440,
- 0, 0xC65E, 0x3178, 0xC65F, 0xC660, 0x4672, 0x5D67, 0x393E,
- 0x4353, 0, 0x5D69, 0, 0, 0, 0, 0xC736,
- 0x5D71, 0, 0x5D6A, 0xC661, 0, 0xC662, 0, 0xC663,
- 0x4241, 0, 0x3562, 0x5D72, 0xC664, 0, 0xC665, 0,
- 0xC666, 0xC667, 0x3768, 0xC668, 0, 0x3525, 0x5D70, 0,
-};
-static const unsigned short utf8_to_euc_E6B1_x0213[] = {
- 0x4475, 0x3D41, 0x3561, 0, 0, 0, 0, 0,
- 0, 0, 0xC658, 0xC659, 0, 0xEE36, 0x4846, 0xC65B,
- 0x3C2E, 0, 0xC65C, 0, 0xC65D, 0x5D68, 0, 0x3440,
- 0, 0x7651, 0x3178, 0xEE37, 0x7652, 0x4672, 0x5D67, 0x393E,
- 0x4353, 0, 0x5D69, 0, 0, 0, 0, 0xEE4F,
- 0x5D71, 0, 0x5D6A, 0xC661, 0, 0xEE38, 0, 0,
- 0x4241, 0, 0x3562, 0x5D72, 0x7654, 0, 0x7655, 0,
- 0xC666, 0xC667, 0x3768, 0xC668, 0, 0x3525, 0x5D70, 0,
-};
-static const unsigned short utf8_to_euc_E6B2[] = {
- 0, 0x5D6E, 0x5D6B, 0x4D60, 0, 0xC669, 0xC66A, 0xC66B,
- 0x4440, 0xC66C, 0, 0, 0x4659, 0x5D6C, 0, 0,
- 0x5D74, 0, 0x5D73, 0x3723, 0xC66D, 0xC66E, 0x322D, 0xC66F,
- 0xC670, 0x3A3B, 0x5D6D, 0x5D6F, 0xC671, 0, 0, 0xC672,
- 0, 0x4B57, 0x4274, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x4B77, 0, 0, 0x5D7C, 0,
- 0xC673, 0x5D7D, 0xC674, 0x324F, 0xC675, 0, 0, 0,
- 0x4A28, 0x4C7D, 0x5E21, 0x3C23, 0x3E42, 0x5D78, 0x5D7E, 0x3168,
-};
-static const unsigned short utf8_to_euc_E6B2_x0213[] = {
- 0, 0x5D6E, 0x5D6B, 0x4D60, 0xEE39, 0x7656, 0x7657, 0xC66B,
- 0x4440, 0xEE3A, 0, 0, 0x4659, 0x5D6C, 0, 0,
- 0x5D74, 0, 0x5D73, 0x3723, 0xEE3C, 0xEE3D, 0x322D, 0xEE3E,
- 0x7658, 0x3A3B, 0x5D6D, 0x5D6F, 0x7659, 0, 0, 0xC672,
- 0, 0x4B57, 0x4274, 0, 0, 0, 0, 0,
- 0, 0, 0x7653, 0x4B77, 0, 0xEE3F, 0x5D7C, 0,
- 0xC673, 0x5D7D, 0xC674, 0x324F, 0xC675, 0, 0, 0,
- 0x4A28, 0x4C7D, 0x5E21, 0x3C23, 0x3E42, 0x5D78, 0x5D7E, 0x3168,
-};
-static const unsigned short utf8_to_euc_E6B3[] = {
- 0, 0x3637, 0xC676, 0, 0x5D75, 0x5D7A, 0xC677, 0,
- 0, 0x4074, 0x4771, 0, 0x4867, 0xC678, 0, 0xC679,
- 0xC67A, 0xC67B, 0xC67C, 0x5D77, 0xC67D, 0x4B21, 0xC67E, 0x5D79,
- 0, 0x5E24, 0xC721, 0x5E22, 0xC722, 0x5D7B, 0, 0,
- 0xC723, 0x4B22, 0x4748, 0x3563, 0, 0x4525, 0, 0xC724,
- 0x436D, 0xC725, 0x5E25, 0xC726, 0xC727, 0, 0xC728, 0x5E23,
- 0x4259, 0x5D76, 0xC729, 0x314B, 0xC72A, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E6B3_x0213[] = {
- 0, 0x3637, 0xEE40, 0, 0x5D75, 0x5D7A, 0x765B, 0,
- 0, 0x4074, 0x4771, 0, 0x4867, 0xC678, 0, 0xC679,
- 0xEE41, 0xC67B, 0xC67C, 0x5D77, 0x765C, 0x4B21, 0xEE43, 0x5D79,
- 0, 0x5E24, 0xEE44, 0x5E22, 0xEE45, 0x5D7B, 0, 0,
- 0x765D, 0x4B22, 0x4748, 0x3563, 0, 0x4525, 0, 0xC724,
- 0x436D, 0xEE46, 0x5E25, 0x765E, 0xEE47, 0xEE48, 0x765F, 0x5E23,
- 0x4259, 0x5D76, 0xC729, 0x314B, 0xC72A, 0, 0, 0,
- 0, 0, 0, 0x765A, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E6B4[] = {
- 0, 0, 0, 0, 0xC72B, 0, 0, 0xC72C,
- 0, 0, 0xC72D, 0x4D4E, 0x5E30, 0, 0xC72E, 0xC72F,
- 0, 0xC730, 0x5E2F, 0xC731, 0, 0, 0, 0x4076,
- 0, 0x5E2C, 0xC732, 0x4D6C, 0, 0, 0x4636, 0x5E26,
- 0, 0, 0, 0, 0, 0x4445, 0xC733, 0xC734,
- 0xC735, 0x314C, 0x393F, 0x5E29, 0, 0, 0xC737, 0xC738,
- 0, 0xC739, 0x3D27, 0x5E2E, 0, 0x5E2D, 0x5E28, 0,
- 0x5E2B, 0xC73A, 0, 0x3368, 0xC73B, 0x5E2A, 0x4749, 0xC73C,
-};
-static const unsigned short utf8_to_euc_E6B4_x0213[] = {
- 0xEE4A, 0, 0, 0, 0x7661, 0, 0, 0xC72C,
- 0, 0, 0xEE4B, 0x4D4E, 0x5E30, 0, 0x7662, 0xC72F,
- 0, 0xC730, 0x5E2F, 0xC731, 0, 0, 0, 0x4076,
- 0, 0x5E2C, 0xC732, 0x4D6C, 0, 0, 0x4636, 0x5E26,
- 0, 0, 0, 0, 0xEE4C, 0x4445, 0xEE4D, 0xEE4E,
- 0xC735, 0x314C, 0x393F, 0x5E29, 0, 0, 0x7663, 0xEE50,
- 0, 0x7664, 0x3D27, 0x5E2E, 0xEE65, 0x5E2D, 0x5E28, 0,
- 0x5E2B, 0x7665, 0, 0x3368, 0xEE51, 0x5E2A, 0x4749, 0x7666,
-};
-static const unsigned short utf8_to_euc_E6B5[] = {
- 0, 0x4E2E, 0, 0, 0x3E74, 0x4075, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xC73D,
- 0, 0x5E36, 0x5E34, 0, 0x494D, 0, 0xC73E, 0xC73F,
- 0, 0xC740, 0, 0x5E31, 0x5E33, 0xC741, 0x313A, 0xC742,
- 0, 0x3940, 0x4F32, 0, 0x333D, 0, 0x4962, 0xC743,
- 0xC744, 0, 0, 0, 0x4D61, 0, 0, 0x3324,
- 0x3F3B, 0x5E35, 0, 0, 0xC745, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E6B5_x0213[] = {
- 0, 0x4E2E, 0, 0, 0x3E74, 0x4075, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xC73D,
- 0x7667, 0x5E36, 0x5E34, 0xEE52, 0x494D, 0, 0xEE53, 0xC73F,
- 0xEE54, 0xC740, 0, 0x5E31, 0x5E33, 0x7668, 0x313A, 0xC742,
- 0, 0x3940, 0x4F32, 0, 0x333D, 0, 0x4962, 0,
- 0xEE55, 0, 0, 0, 0x4D61, 0, 0, 0x3324,
- 0x3F3B, 0x5E35, 0, 0, 0xC745, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E6B6[] = {
- 0, 0, 0xC746, 0, 0, 0x5E3A, 0, 0xC747,
- 0x3E43, 0, 0, 0, 0x4D30, 0, 0x5E37, 0,
- 0, 0xC748, 0xC749, 0x5E32, 0xC74A, 0x5E38, 0xC74B, 0xC74C,
- 0xC74D, 0x4E5E, 0, 0x4573, 0x4642, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xC74E, 0, 0xC74F, 0, 0, 0x3336,
- 0, 0, 0x3155, 0, 0xC750, 0x5E3E, 0, 0xC751,
- 0x5E41, 0xC752, 0, 0, 0x4E43, 0xC753, 0, 0xC754,
-};
-static const unsigned short utf8_to_euc_E6B6_x0213[] = {
- 0xEE56, 0xEE57, 0x766A, 0, 0, 0x5E3A, 0, 0x766B,
- 0x3E43, 0x766C, 0xEE58, 0, 0x4D30, 0xEE59, 0x5E37, 0,
- 0, 0xEE5A, 0xC749, 0x5E32, 0x766D, 0x5E38, 0, 0xC74C,
- 0xEE5B, 0x4E5E, 0, 0x4573, 0x4642, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x766E, 0xEE61, 0x766F, 0, 0xEE62, 0x3336,
- 0, 0, 0x3155, 0, 0xEE63, 0x5E3E, 0, 0xC751,
- 0x5E41, 0xC752, 0, 0, 0x4E43, 0xC753, 0, 0x7670,
-};
-static const unsigned short utf8_to_euc_E6B7[] = {
- 0x4D64, 0, 0, 0, 0xC755, 0x5E48, 0x5E42, 0x5E3F,
- 0xC756, 0, 0xC757, 0x4E54, 0x5E45, 0, 0xC758, 0xC759,
- 0, 0x3D4A, 0x5E47, 0, 0, 0x5E4C, 0xC75A, 0,
- 0x4571, 0x5E4A, 0, 0xC75B, 0, 0xC75C, 0x5E44, 0xC75D,
- 0xC75E, 0x4338, 0xC75F, 0, 0x5E4B, 0xC760, 0x5E40, 0,
- 0x5E46, 0xC761, 0x5E4D, 0x307C, 0x5E43, 0, 0x5E4E, 0xC762,
- 0xC763, 0x3F3C, 0xF44C, 0x3D5F, 0xC764, 0x4A25, 0xC765, 0x3A2E,
- 0xF44B, 0x5E3B, 0x5E49, 0x453A, 0xC766, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E6B7_x0213[] = {
- 0x4D64, 0, 0xEE64, 0, 0x7671, 0x5E48, 0x5E42, 0x5E3F,
- 0xEE66, 0, 0xC757, 0x4E54, 0x5E45, 0, 0xEE67, 0xEE68,
- 0xEE69, 0x3D4A, 0x5E47, 0, 0, 0x5E4C, 0x7672, 0,
- 0x4571, 0x5E4A, 0x7673, 0x7674, 0, 0x7675, 0x5E44, 0xEE6A,
- 0xC75E, 0x4338, 0xC75F, 0, 0x5E4B, 0xC760, 0x5E40, 0,
- 0x5E46, 0xEE6B, 0x5E4D, 0x307C, 0x5E43, 0, 0x5E4E, 0xC762,
- 0xC763, 0x3F3C, 0, 0x3D5F, 0xC764, 0x4A25, 0xEE6C, 0x3A2E,
- 0, 0x5E3B, 0x5E49, 0x453A, 0x7676, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E6B8[] = {
- 0xC767, 0, 0, 0, 0xC768, 0x4036, 0, 0x3369,
- 0x3A51, 0x3E44, 0x5E3D, 0x3D42, 0, 0, 0, 0,
- 0, 0, 0, 0x374C, 0, 0x5E3C, 0, 0,
- 0, 0x5E52, 0x3D6D, 0x383A, 0, 0x5E61, 0xC769, 0x5E5B,
- 0x3574, 0x454F, 0xC76A, 0x5E56, 0x5E5F, 0x302F, 0x3132, 0xC76B,
- 0, 0x3239, 0, 0x5E58, 0x422C, 0x5E4F, 0x5E51, 0x3941,
- 0, 0, 0xC76C, 0, 0, 0, 0xC76D, 0,
- 0x5E62, 0xC76E, 0x5E5D, 0xC76F, 0xC770, 0, 0x5E55, 0,
-};
-static const unsigned short utf8_to_euc_E6B8_x0213[] = {
- 0xC767, 0, 0, 0, 0xC768, 0x4036, 0, 0x3369,
- 0x3A51, 0x3E44, 0x5E3D, 0x3D42, 0, 0, 0, 0,
- 0, 0, 0, 0x374C, 0, 0x5E3C, 0, 0xEE5D,
- 0, 0x5E52, 0x3D6D, 0x383A, 0, 0x5E61, 0xEE6E, 0x5E5B,
- 0x3574, 0x454F, 0xEE6F, 0x5E56, 0x5E5F, 0x302F, 0x3132, 0xEE70,
- 0, 0x3239, 0, 0x5E58, 0x422C, 0x5E4F, 0x5E51, 0x3941,
- 0, 0, 0xEE72, 0, 0x7678, 0, 0xEE6D, 0,
- 0x5E62, 0, 0x5E5D, 0xC76F, 0xEE73, 0, 0x5E55, 0,
-};
-static const unsigned short utf8_to_euc_E6B9[] = {
- 0, 0, 0, 0x5E5C, 0xC771, 0xC772, 0, 0,
- 0xC773, 0xC774, 0x4C2B, 0xC775, 0, 0x5E5A, 0x5E5E, 0xC776,
- 0, 0xC777, 0xC778, 0xC779, 0xC77A, 0, 0x3850, 0xC77B,
- 0x3E45, 0, 0, 0x4339, 0xC77C, 0xC77D, 0xC77E, 0x5E54,
- 0, 0, 0xC821, 0xC822, 0, 0, 0, 0x4D2F,
- 0xC823, 0, 0, 0x5E57, 0, 0, 0x5E50, 0x4572,
- 0, 0, 0x5E53, 0xC824, 0, 0, 0x5E59, 0,
- 0, 0, 0, 0xC825, 0, 0xC826, 0x4F51, 0x3C3E,
-};
-static const unsigned short utf8_to_euc_E6B9_x0213[] = {
- 0, 0, 0, 0x5E5C, 0x7679, 0xC772, 0, 0,
- 0xEE74, 0xEE75, 0x4C2B, 0xEE76, 0xEE77, 0x5E5A, 0x5E5E, 0xEE78,
- 0, 0xEE79, 0xC778, 0xEE7A, 0xEE7B, 0, 0x3850, 0xEE7C,
- 0x3E45, 0, 0, 0x4339, 0x767A, 0xC77D, 0x767B, 0x5E54,
- 0, 0, 0xC821, 0xEE7D, 0, 0, 0, 0x4D2F,
- 0xC823, 0, 0, 0x5E57, 0, 0, 0x5E50, 0x4572,
- 0, 0, 0x5E53, 0xC824, 0, 0, 0x5E59, 0,
- 0, 0, 0, 0xC825, 0, 0xC826, 0x4F51, 0x3C3E,
-};
-static const unsigned short utf8_to_euc_E6BA[] = {
- 0x4B7E, 0, 0x5E63, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x482E, 0xC827, 0, 0x5E6F,
- 0x383B, 0, 0, 0xC828, 0, 0, 0x3D60, 0,
- 0x5E65, 0xC829, 0, 0, 0x4E2F, 0x3942, 0, 0x5E72,
- 0xC82A, 0, 0x306E, 0, 0, 0x5E70, 0, 0xC82B,
- 0, 0, 0x5E64, 0, 0, 0xC82C, 0xC82D, 0x5E6A,
- 0, 0xC82E, 0x5E6C, 0xC82F, 0, 0, 0x4D4F, 0x5E67,
- 0, 0, 0x452E, 0xC830, 0, 0x5E69, 0, 0xC831,
-};
-static const unsigned short utf8_to_euc_E6BA_x0213[] = {
- 0x4B7E, 0, 0x5E63, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x482E, 0xC827, 0, 0x5E6F,
- 0x383B, 0, 0, 0xEF21, 0, 0, 0x3D60, 0,
- 0x5E65, 0xC829, 0, 0, 0x4E2F, 0x3942, 0, 0x5E72,
- 0xC82A, 0, 0x306E, 0, 0, 0x5E70, 0, 0xEF22,
- 0, 0, 0x5E64, 0x767C, 0, 0xC82C, 0xC82D, 0x5E6A,
- 0, 0x767D, 0x5E6C, 0xC82F, 0xEF23, 0, 0x4D4F, 0x5E67,
- 0, 0, 0x452E, 0xC830, 0, 0x5E69, 0, 0xEF24,
-};
-static const unsigned short utf8_to_euc_E6BB[] = {
- 0xC832, 0xC833, 0x5E71, 0xC834, 0x5E6B, 0x4C47, 0, 0xC835,
- 0xC836, 0x5E66, 0xC837, 0x3C22, 0x5E7E, 0xC838, 0xC839, 0xC83A,
- 0, 0x336A, 0, 0x5E68, 0x5E6D, 0x5E6E, 0, 0,
- 0, 0, 0, 0, 0, 0x426C, 0x425A, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xC83B, 0x5E76, 0xC83C, 0xC83D, 0x5E7C,
- 0, 0, 0x5E7A, 0, 0x4529, 0, 0, 0x5F23,
- 0x5E77, 0xC83E, 0, 0xC83F, 0, 0xC840, 0x5E78, 0x5E60,
-};
-static const unsigned short utf8_to_euc_E6BB_x0213[] = {
- 0xC832, 0x767E, 0x5E71, 0xEF25, 0x5E6B, 0x4C47, 0, 0x7721,
- 0xC836, 0x5E66, 0xEF26, 0x3C22, 0x5E7E, 0xC838, 0x7722, 0xC83A,
- 0, 0x336A, 0, 0x5E68, 0x5E6D, 0x5E6E, 0, 0,
- 0, 0xEF27, 0, 0, 0, 0x426C, 0x425A, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xEF29, 0x5E76, 0xC83C, 0xC83D, 0x5E7C,
- 0, 0, 0x5E7A, 0, 0x4529, 0, 0, 0x5F23,
- 0x5E77, 0xEF2A, 0, 0xEF2B, 0, 0xC840, 0x5E78, 0x5E60,
-};
-static const unsigned short utf8_to_euc_E6BC[] = {
- 0, 0x3579, 0x493A, 0, 0xC841, 0, 0x3C3F, 0,
- 0xC842, 0x3977, 0xC843, 0, 0xC844, 0xC845, 0, 0x4F33,
- 0, 0x5E74, 0, 0x5F22, 0x3169, 0x4166, 0xC846, 0,
- 0xC847, 0, 0xC848, 0xC849, 0, 0, 0, 0,
- 0x4779, 0, 0x3441, 0x4E7A, 0, 0, 0xC84A, 0,
- 0, 0xC84B, 0xC84C, 0x4C21, 0x4452, 0xC853, 0, 0xC84D,
- 0xC84E, 0x5E7B, 0x5E7D, 0xC84F, 0, 0, 0xC850, 0,
- 0x4132, 0, 0, 0xC851, 0xC852, 0, 0x5F21, 0x5E79,
-};
-static const unsigned short utf8_to_euc_E6BC_x0213[] = {
- 0, 0x3579, 0x493A, 0, 0xC841, 0, 0x3C3F, 0,
- 0xC842, 0x3977, 0xEF2C, 0, 0xEF2D, 0xC845, 0, 0x4F33,
- 0x7723, 0x5E74, 0, 0x5F22, 0x3169, 0x4166, 0xC846, 0,
- 0xEF2E, 0, 0x7724, 0xC849, 0, 0, 0, 0,
- 0x4779, 0, 0x3441, 0x4E7A, 0, 0xEF2F, 0xC84A, 0,
- 0, 0xC84B, 0x7726, 0x4C21, 0x4452, 0xC853, 0, 0x7727,
- 0xC84E, 0x5E7B, 0x5E7D, 0x7728, 0, 0xEF28, 0xEF30, 0,
- 0x4132, 0, 0, 0xC851, 0xEF31, 0, 0x5F21, 0x5E79,
-};
-static const unsigned short utf8_to_euc_E6BD[] = {
- 0, 0x5E73, 0, 0, 0, 0x3443, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xC854,
- 0, 0xC855, 0xC856, 0xC857, 0x3769, 0, 0, 0xC858,
- 0x5F2F, 0xC859, 0xC85A, 0x5F2A, 0x4078, 0xC85B, 0xC85C, 0x3363,
- 0, 0xC85D, 0xC85E, 0, 0x3D61, 0, 0x5F33, 0,
- 0xC85F, 0, 0, 0, 0xC860, 0x5F2C, 0x442C, 0x5F29,
- 0x4459, 0, 0, 0, 0x5F4C, 0, 0, 0,
- 0x5F26, 0, 0x5F25, 0, 0x5F2E, 0xC861, 0xC862, 0,
-};
-static const unsigned short utf8_to_euc_E6BD_x0213[] = {
- 0, 0x5E73, 0, 0, 0, 0x3443, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xC854,
- 0, 0x7729, 0xEF33, 0xC857, 0x3769, 0, 0, 0xEF34,
- 0x5F2F, 0x772A, 0xEF35, 0x5F2A, 0x4078, 0xC85B, 0x772B, 0x3363,
- 0xEF36, 0x772C, 0x772D, 0, 0x3D61, 0, 0x5F33, 0,
- 0xEF37, 0, 0, 0, 0xC860, 0x5F2C, 0x442C, 0x5F29,
- 0x4459, 0, 0, 0, 0x5F4C, 0, 0, 0,
- 0x5F26, 0, 0x5F25, 0, 0x5F2E, 0xEF39, 0x772E, 0,
-};
-static const unsigned short utf8_to_euc_E6BE[] = {
- 0x5F28, 0x5F27, 0x5F2D, 0xC863, 0x4021, 0, 0x5F24, 0xC864,
- 0xC865, 0, 0, 0xC866, 0xC867, 0xC868, 0x5F30, 0,
- 0xC869, 0x5F31, 0xC86A, 0xC86B, 0xC86C, 0, 0xC86D, 0x3442,
- 0, 0, 0xC86E, 0, 0, 0, 0, 0xC86F,
- 0xC870, 0x5F36, 0, 0x5F35, 0x5F37, 0xC871, 0xC872, 0xC873,
- 0xC874, 0, 0x5F3A, 0, 0, 0, 0xC875, 0xC876,
- 0xC877, 0x4543, 0, 0x5F34, 0, 0xC878, 0xC879, 0,
- 0, 0x5F38, 0, 0, 0xC87A, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E6BE_x0213[] = {
- 0x5F28, 0x5F27, 0x5F2D, 0xC863, 0x4021, 0, 0x5F24, 0xC864,
- 0x772F, 0, 0, 0xC866, 0x7730, 0x7731, 0x5F30, 0,
- 0xEF3A, 0x5F31, 0xC86A, 0xC86B, 0x7732, 0, 0xEF3B, 0x3442,
- 0xEF38, 0, 0xC86E, 0, 0, 0, 0, 0xEF3D,
- 0x7733, 0x5F36, 0, 0x5F35, 0x5F37, 0xEF3E, 0xC872, 0x7734,
- 0xC874, 0, 0x5F3A, 0, 0, 0, 0xC875, 0xEF3F,
- 0xC877, 0x4543, 0, 0x5F34, 0, 0xEF41, 0x7735, 0,
- 0, 0x5F38, 0, 0, 0x7736, 0, 0xEF3C, 0,
-};
-static const unsigned short utf8_to_euc_E6BF[] = {
- 0x3763, 0x4279, 0x5F32, 0x473B, 0, 0xC87B, 0x5F39, 0xC87C,
- 0xC87D, 0, 0xC87E, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x5F3E, 0x5F3C, 0, 0,
- 0x5F3F, 0, 0xC921, 0x5F42, 0, 0, 0xC922, 0x5F3B,
- 0x396A, 0x4728, 0, 0, 0x5E39, 0, 0, 0,
- 0xC923, 0xC924, 0, 0x4D74, 0x5F3D, 0, 0x5F41, 0x4275,
- 0xC925, 0x5F40, 0, 0x5F2B, 0, 0xC926, 0x6F69, 0,
- 0, 0xC927, 0x5F45, 0, 0xC928, 0xC929, 0x5F49, 0,
-};
-static const unsigned short utf8_to_euc_E6BF_x0213[] = {
- 0x3763, 0x4279, 0x5F32, 0x473B, 0, 0xC87B, 0x5F39, 0x7737,
- 0xEF42, 0xEF43, 0x7738, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x5F3E, 0x5F3C, 0, 0,
- 0x5F3F, 0, 0xEF44, 0x5F42, 0, 0, 0xEF45, 0x5F3B,
- 0x396A, 0x4728, 0, 0, 0x5E39, 0, 0, 0,
- 0xC923, 0xEF46, 0, 0x4D74, 0x5F3D, 0, 0x5F41, 0x4275,
- 0x773A, 0x5F40, 0, 0x5F2B, 0, 0x773B, 0x6F69, 0,
- 0, 0x7739, 0x5F45, 0, 0xEF48, 0xC929, 0x5F49, 0,
-};
-static const unsigned short utf8_to_euc_E780[] = {
- 0xC92A, 0x5F47, 0, 0, 0, 0xC92B, 0xC92C, 0xC92D,
- 0, 0x5F43, 0, 0x5F44, 0, 0xC92E, 0, 0x5F48,
- 0, 0x5F46, 0, 0, 0, 0x494E, 0, 0xC92F,
- 0x5F4E, 0, 0x5F4B, 0x5F4A, 0, 0x5F4D, 0x4654, 0x5F4F,
- 0xC930, 0, 0, 0xC931, 0, 0, 0x4375, 0x426D,
- 0xF44D, 0, 0, 0, 0x4025, 0, 0, 0xC932,
- 0x5F50, 0, 0x5F52, 0, 0xC933, 0, 0, 0xC934,
- 0, 0xC935, 0, 0, 0xC936, 0, 0x5F51, 0,
-};
-static const unsigned short utf8_to_euc_E780_x0213[] = {
- 0xEF49, 0x5F47, 0, 0, 0, 0x773C, 0x773D, 0xEF4A,
- 0, 0x5F43, 0xEF4B, 0x5F44, 0, 0xC92E, 0, 0x5F48,
- 0, 0x5F46, 0, 0, 0, 0x494E, 0, 0xC92F,
- 0x5F4E, 0, 0x5F4B, 0x5F4A, 0, 0x5F4D, 0x4654, 0x5F4F,
- 0xC930, 0, 0, 0xEF4C, 0, 0, 0x4375, 0x426D,
- 0x773E, 0, 0, 0, 0x4025, 0, 0, 0xC932,
- 0x5F50, 0, 0x5F52, 0, 0xC933, 0, 0, 0xC934,
- 0, 0xEF4E, 0xEF4F, 0, 0xEF50, 0, 0x5F51, 0,
-};
-static const unsigned short utf8_to_euc_E781[] = {
- 0, 0, 0, 0xC937, 0xC938, 0, 0, 0,
- 0xC939, 0xC93A, 0xC93B, 0xC93C, 0x5E75, 0, 0xC941, 0,
- 0, 0x5F53, 0, 0, 0xC93D, 0xC93E, 0, 0,
- 0x4667, 0, 0, 0, 0, 0xC93F, 0xC940, 0,
- 0, 0, 0, 0x5F54, 0xC942, 0xC943, 0, 0,
- 0, 0, 0, 0x3250, 0xC944, 0, 0xC945, 0x4574,
- 0x3325, 0, 0, 0, 0, 0xC946, 0xC947, 0,
- 0x3564, 0, 0, 0, 0x3C5E, 0x3A52, 0xC948, 0,
-};
-static const unsigned short utf8_to_euc_E781_x0213[] = {
- 0, 0, 0, 0xEF51, 0xC938, 0, 0, 0xEF52,
- 0xC939, 0xC93A, 0x773F, 0xEF53, 0x5E75, 0, 0x7742, 0,
- 0, 0x5F53, 0, 0, 0xEF55, 0xC93E, 0, 0,
- 0x4667, 0, 0, 0, 0, 0x7740, 0x7741, 0,
- 0, 0, 0, 0x5F54, 0x7743, 0xEF56, 0, 0,
- 0, 0xEF57, 0, 0x3250, 0xEF58, 0, 0xEF59, 0x4574,
- 0x3325, 0, 0, 0, 0, 0x7744, 0xEF5A, 0,
- 0x3564, 0, 0, 0, 0x3C5E, 0x3A52, 0xEF5B, 0,
-};
-static const unsigned short utf8_to_euc_E782[] = {
- 0, 0xC949, 0, 0, 0, 0xC94A, 0xC94B, 0,
- 0, 0x4F27, 0x3F66, 0, 0, 0, 0x316A, 0,
- 0, 0, 0x5F56, 0, 0xC94C, 0xC94D, 0xC94E, 0xC94F,
- 0xC950, 0x5F55, 0, 0xC951, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xC952, 0, 0, 0,
- 0, 0, 0, 0xC953, 0x5F59, 0x433A, 0x5F5C, 0x5F57,
- 0xC954, 0xC955, 0, 0x5F5B, 0xC956, 0, 0, 0xC957,
- 0x5F5A, 0x4540, 0x3059, 0xF42E, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E782_x0213[] = {
- 0, 0xEF5C, 0, 0, 0, 0x7745, 0xEF5D, 0,
- 0, 0x4F27, 0x3F66, 0, 0, 0, 0x316A, 0,
- 0, 0, 0x5F56, 0, 0xC94C, 0xEF5E, 0xC94E, 0xEF5F,
- 0xC950, 0x5F55, 0, 0xC951, 0, 0, 0, 0xEF62,
- 0, 0, 0, 0, 0x7746, 0, 0, 0,
- 0, 0, 0, 0x7747, 0x5F59, 0x433A, 0x5F5C, 0x5F57,
- 0xC954, 0xEF63, 0, 0x5F5B, 0xC956, 0, 0, 0x7748,
- 0x5F5A, 0x4540, 0x3059, 0xEF60, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E783[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x4E75, 0, 0xC958, 0x5F5E, 0, 0, 0, 0x3128,
- 0, 0xC959, 0, 0xC95A, 0xC95B, 0xC95C, 0xC95D, 0,
- 0xC95E, 0x5F60, 0, 0, 0xC95F, 0x5F5F, 0, 0x5F5D,
- 0, 0, 0, 0, 0xC960, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x5F58, 0, 0, 0, 0, 0, 0,
- 0, 0x4B23, 0xC961, 0, 0, 0x5F62, 0, 0,
-};
-static const unsigned short utf8_to_euc_E783_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x4E75, 0, 0xEF66, 0x5F5E, 0, 0, 0, 0x3128,
- 0, 0xEF67, 0, 0xEF68, 0x7749, 0xC95C, 0xC95D, 0,
- 0x774A, 0x5F60, 0, 0, 0xEF69, 0x5F5F, 0, 0x5F5D,
- 0, 0, 0, 0, 0x774B, 0, 0, 0,
- 0, 0, 0, 0, 0xEF65, 0, 0, 0,
- 0, 0x5F58, 0, 0, 0, 0, 0, 0,
- 0, 0x4B23, 0xC961, 0, 0, 0x5F62, 0, 0,
-};
-static const unsigned short utf8_to_euc_E784[] = {
- 0, 0, 0, 0xC962, 0xC963, 0xC964, 0xC965, 0xC966,
- 0, 0x5F61, 0, 0xC967, 0xC968, 0, 0, 0xC969,
- 0, 0, 0, 0, 0x316B, 0, 0, 0,
- 0, 0x5F64, 0x4A32, 0, 0x5F63, 0, 0xC96A, 0,
- 0xC96B, 0x4C35, 0, 0, 0, 0, 0x3E47, 0,
- 0, 0, 0, 0xC96C, 0, 0xC96D, 0, 0xC96E,
- 0xC96F, 0xC970, 0, 0, 0, 0, 0x4133, 0,
- 0xC971, 0, 0, 0, 0x3E46, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E784_x0213[] = {
- 0, 0, 0, 0xEF6A, 0xEF6B, 0xC964, 0xEF6C, 0xEF6D,
- 0xEF6E, 0x5F61, 0, 0xC967, 0xEF6F, 0, 0, 0x774C,
- 0, 0, 0, 0, 0x316B, 0, 0, 0,
- 0, 0x5F64, 0x4A32, 0, 0x5F63, 0, 0x774E, 0,
- 0x774F, 0x4C35, 0, 0, 0, 0, 0x3E47, 0,
- 0, 0, 0, 0x774D, 0, 0xC96D, 0x7750, 0xEF71,
- 0x7751, 0xEF72, 0, 0, 0, 0, 0x4133, 0,
- 0xC971, 0, 0, 0, 0x3E46, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E785[] = {
- 0, 0xC972, 0, 0, 0, 0xC973, 0xC974, 0xC975,
- 0, 0x4E7B, 0xC976, 0xC977, 0x5F6A, 0, 0x4079, 0,
- 0xC978, 0, 0xC979, 0, 0, 0x5F66, 0x5F6B, 0xC97A,
- 0, 0x316C, 0xC97B, 0, 0xC97C, 0, 0xC97D, 0,
- 0xC97E, 0, 0x5F69, 0, 0x4761, 0x5F65, 0x5F68, 0x3E48,
- 0xCA21, 0x4851, 0, 0, 0x5F6C, 0, 0x3C51, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xCA22, 0, 0, 0, 0x407A, 0, 0,
-};
-static const unsigned short utf8_to_euc_E785_x0213[] = {
- 0, 0xC972, 0, 0, 0, 0xC973, 0x7752, 0x7753,
- 0, 0x4E7B, 0xEF74, 0xC977, 0x5F6A, 0, 0x4079, 0,
- 0xEF73, 0x7754, 0x7756, 0xEF75, 0, 0x5F66, 0x5F6B, 0xC97A,
- 0, 0x316C, 0xC97B, 0, 0x7757, 0, 0xEF76, 0,
- 0x7758, 0, 0x5F69, 0, 0x4761, 0x5F65, 0x5F68, 0x3E48,
- 0x7759, 0x4851, 0, 0, 0x5F6C, 0, 0x3C51, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xCA22, 0, 0, 0, 0x407A, 0, 0,
-};
-static const unsigned short utf8_to_euc_E786[] = {
- 0xCA23, 0, 0, 0, 0x5F6F, 0xCA24, 0, 0xCA25,
- 0x5F67, 0, 0x3727, 0, 0xCA26, 0, 0, 0x5F6D,
- 0, 0, 0xCA27, 0, 0x4D50, 0x5F70, 0, 0,
- 0, 0x7426, 0xCA28, 0xCA29, 0, 0, 0, 0x3D4F,
- 0xCA2A, 0, 0xCA2B, 0, 0, 0, 0, 0,
- 0x5F71, 0, 0, 0, 0x5F72, 0, 0, 0xCA2C,
- 0xCA2D, 0x472E, 0xCA2E, 0xCA2F, 0, 0, 0, 0,
- 0, 0x5F74, 0xCA30, 0, 0, 0, 0x5F75, 0xCA31,
-};
-static const unsigned short utf8_to_euc_E786_x0213[] = {
- 0xEF79, 0, 0, 0, 0x5F6F, 0x775B, 0, 0x775C,
- 0x5F67, 0, 0x3727, 0, 0xCA26, 0, 0, 0x5F6D,
- 0, 0, 0x775D, 0, 0x4D50, 0x5F70, 0xEF78, 0,
- 0, 0x7426, 0xCA28, 0xEF7A, 0, 0, 0, 0x3D4F,
- 0xEF7B, 0, 0xEF7C, 0, 0, 0, 0, 0,
- 0x5F71, 0, 0, 0, 0x5F72, 0, 0xEF7D, 0xEF7E,
- 0xCA2D, 0x472E, 0xCA2E, 0xF021, 0, 0, 0, 0,
- 0, 0x5F74, 0x775F, 0, 0, 0, 0x5F75, 0xCA31,
-};
-static const unsigned short utf8_to_euc_E787[] = {
- 0xCA32, 0xCA33, 0, 0x4733, 0xCA34, 0, 0, 0,
- 0x4575, 0x5F77, 0, 0xCA35, 0xCA36, 0, 0x5F79, 0,
- 0x4E55, 0, 0x5F76, 0xCA37, 0x5F78, 0x316D, 0xCA38, 0x5F73,
- 0, 0xCA39, 0xCA3A, 0, 0xCA3B, 0, 0, 0x535B,
- 0x5F7A, 0, 0, 0, 0, 0x4167, 0x3B38, 0x5F7C,
- 0, 0, 0, 0, 0x5F7B, 0x3F24, 0x5259, 0,
- 0, 0, 0, 0, 0, 0x5F7D, 0, 0,
- 0xCA3C, 0x6021, 0, 0x5F6E, 0x5F7E, 0, 0xCA3D, 0x6022,
-};
-static const unsigned short utf8_to_euc_E787_x0213[] = {
- 0xCA32, 0x775E, 0, 0x4733, 0x7760, 0, 0, 0,
- 0x4575, 0x5F77, 0, 0xF023, 0xCA36, 0, 0x5F79, 0,
- 0x4E55, 0, 0x5F76, 0xF024, 0x5F78, 0x316D, 0xCA38, 0x5F73,
- 0, 0xF025, 0xCA3A, 0, 0xF026, 0, 0, 0x535B,
- 0x5F7A, 0, 0, 0, 0, 0x4167, 0x3B38, 0x5F7C,
- 0, 0, 0, 0, 0x5F7B, 0x3F24, 0x5259, 0,
- 0, 0, 0, 0, 0, 0x5F7D, 0, 0,
- 0xCA3C, 0x6021, 0, 0x5F6E, 0x5F7E, 0, 0x7761, 0x6022,
-};
-static const unsigned short utf8_to_euc_E788[] = {
- 0xCA3E, 0, 0, 0, 0, 0, 0x477A, 0xCA3F,
- 0xCA40, 0xCA41, 0, 0, 0, 0x6023, 0, 0,
- 0x6024, 0, 0, 0xCA42, 0, 0, 0, 0xCA43,
- 0, 0, 0xCA44, 0x6025, 0, 0xCA45, 0, 0xCA46,
- 0, 0, 0, 0, 0xCA47, 0, 0, 0,
- 0x6026, 0, 0x445E, 0xCA48, 0x6028, 0x6027, 0, 0xCA49,
- 0x6029, 0, 0x602A, 0, 0xCA4A, 0x3C5F, 0x4963, 0,
- 0xCA4B, 0xCA4C, 0x4C6C, 0x602B, 0x602C, 0x4156, 0x3C24, 0x602D,
-};
-static const unsigned short utf8_to_euc_E788_x0213[] = {
- 0x7762, 0, 0, 0, 0, 0, 0x477A, 0xF027,
- 0xCA40, 0xCA41, 0, 0, 0, 0x6023, 0, 0,
- 0x6024, 0, 0, 0xCA42, 0, 0x7763, 0, 0xCA43,
- 0, 0, 0xCA44, 0x6025, 0, 0xCA45, 0, 0xCA46,
- 0, 0, 0, 0, 0xCA47, 0, 0, 0,
- 0x6026, 0, 0x445E, 0xF02A, 0x6028, 0x6027, 0, 0xCA49,
- 0x6029, 0, 0x602A, 0, 0xF02B, 0x3C5F, 0x4963, 0,
- 0xF02C, 0xF02D, 0x4C6C, 0x602B, 0x602C, 0x4156, 0x3C24, 0x602D,
-};
-static const unsigned short utf8_to_euc_E789[] = {
- 0x602E, 0xCA4D, 0xCA4E, 0xCA4F, 0, 0xCA50, 0x602F, 0x4A52,
- 0x4847, 0, 0, 0x6030, 0x4757, 0, 0xCA51, 0xCA52,
- 0xCA53, 0, 0x442D, 0xCA54, 0, 0xCA55, 0xCA56, 0,
- 0x6031, 0x3267, 0xCA57, 0x356D, 0xCA58, 0x4C46, 0xCA59, 0x4C36,
- 0xCA5A, 0x3234, 0x4F34, 0xCA5B, 0, 0, 0, 0x4B52,
- 0xCA5C, 0x4A2A, 0, 0xCA5D, 0, 0, 0xCA5E, 0xCA5F,
- 0, 0xCA60, 0x4037, 0, 0x6032, 0, 0, 0xCA61,
- 0xCA62, 0x4643, 0, 0xCA63, 0xCA64, 0x3823, 0x6033, 0xCA65,
-};
-static const unsigned short utf8_to_euc_E789_x0213[] = {
- 0x602E, 0xCA4D, 0xF02F, 0xCA4F, 0, 0xCA50, 0x602F, 0x4A52,
- 0x4847, 0, 0, 0x6030, 0x4757, 0, 0xCA51, 0xCA52,
- 0xCA53, 0, 0x442D, 0xF030, 0, 0x7764, 0x7765, 0xF031,
- 0x6031, 0x3267, 0xCA57, 0x356D, 0xCA58, 0x4C46, 0xCA59, 0x4C36,
- 0xCA5A, 0x3234, 0x4F34, 0xF032, 0, 0, 0, 0x4B52,
- 0xCA5C, 0x4A2A, 0, 0xCA5D, 0, 0, 0xF034, 0xF035,
- 0, 0xCA60, 0x4037, 0, 0x6032, 0, 0, 0xCA61,
- 0xF036, 0x4643, 0, 0xCA63, 0xCA64, 0x3823, 0x6033, 0xF037,
-};
-static const unsigned short utf8_to_euc_E78A[] = {
- 0x3A54, 0x6035, 0x6034, 0, 0xCA66, 0, 0, 0x6036,
- 0, 0xCA67, 0, 0, 0, 0xCA68, 0xCA69, 0,
- 0, 0, 0x6037, 0xCA6A, 0, 0, 0x6038, 0,
- 0, 0, 0, 0xCA6B, 0, 0, 0, 0,
- 0x353E, 0, 0x6039, 0, 0, 0, 0, 0x603A,
- 0xCA6C, 0, 0, 0, 0x3824, 0xCA6D, 0xCA6E, 0x4848,
- 0, 0xCA6F, 0x603C, 0, 0xCA70, 0, 0x3E75, 0,
- 0, 0x603B, 0, 0, 0, 0, 0xCA71, 0,
-};
-static const unsigned short utf8_to_euc_E78A_x0213[] = {
- 0x3A54, 0x6035, 0x6034, 0, 0xCA66, 0, 0, 0x6036,
- 0, 0xCA67, 0, 0, 0, 0x7767, 0xF038, 0,
- 0, 0, 0x6037, 0xCA6A, 0, 0, 0x6038, 0,
- 0, 0, 0, 0x7768, 0, 0, 0, 0,
- 0x353E, 0, 0x6039, 0, 0, 0, 0, 0x603A,
- 0xCA6C, 0, 0, 0, 0x3824, 0xF03A, 0xF03B, 0x4848,
- 0xF03C, 0xF03D, 0x603C, 0, 0xCA70, 0, 0x3E75, 0,
- 0, 0x603B, 0, 0, 0, 0, 0x7769, 0,
-};
-static const unsigned short utf8_to_euc_E78B[] = {
- 0, 0xCA72, 0x3638, 0x603D, 0x603F, 0, 0x603E, 0xCA73,
- 0, 0xCA74, 0, 0, 0xCA75, 0, 0x6040, 0,
- 0x3851, 0, 0x6041, 0, 0, 0xCA76, 0xCA77, 0x3669,
- 0xCA78, 0x4140, 0, 0x397D, 0, 0, 0, 0xCA79,
- 0x6043, 0x6044, 0x6042, 0, 0, 0xCA7A, 0, 0,
- 0, 0x3C6D, 0, 0, 0x4648, 0x3639, 0, 0,
- 0, 0, 0, 0xCA7B, 0xCA7C, 0, 0, 0x6046,
- 0x432C, 0x6045, 0xCA7D, 0xCA7E, 0x4F35, 0x4762, 0xCB21, 0,
-};
-static const unsigned short utf8_to_euc_E78B_x0213[] = {
- 0x776A, 0xF03E, 0x3638, 0x603D, 0x603F, 0, 0x603E, 0xCA73,
- 0, 0xCA74, 0, 0, 0xF040, 0, 0x6040, 0,
- 0x3851, 0, 0x6041, 0, 0, 0xCA76, 0xCA77, 0x3669,
- 0xCA78, 0x4140, 0, 0x397D, 0, 0, 0, 0xCA79,
- 0x6043, 0x6044, 0x6042, 0, 0, 0xCA7A, 0, 0,
- 0, 0x3C6D, 0, 0, 0x4648, 0x3639, 0, 0,
- 0, 0, 0, 0xF043, 0xCA7C, 0, 0, 0x6046,
- 0x432C, 0x6045, 0xF044, 0x776B, 0x4F35, 0x4762, 0xCB21, 0,
-};
-static const unsigned short utf8_to_euc_E78C[] = {
- 0, 0, 0xCB22, 0, 0xCB23, 0xCB24, 0, 0xCB25,
- 0, 0, 0x6049, 0xCB26, 0, 0xCB27, 0, 0,
- 0, 0, 0xCB28, 0xCB29, 0, 0, 0x604B, 0x6048,
- 0xCB2A, 0xCB2B, 0, 0x4C54, 0x604A, 0x604C, 0xCB2C, 0x4E44,
- 0, 0, 0xCB2D, 0, 0xCB2E, 0x6050, 0, 0xCB2F,
- 0xCB30, 0x604F, 0x4376, 0x472D, 0xCB31, 0, 0x3825, 0x604E,
- 0, 0xCB32, 0xCB33, 0, 0x604D, 0xCB34, 0x4D31, 0x4D32,
- 0, 0, 0xCB35, 0xCB36, 0, 0xCB37, 0x6051, 0x316E,
-};
-static const unsigned short utf8_to_euc_E78C_x0213[] = {
- 0, 0, 0xCB22, 0, 0xCB23, 0xCB24, 0, 0xF045,
- 0, 0, 0x6049, 0xCB26, 0, 0xCB27, 0, 0,
- 0, 0, 0xF046, 0xCB29, 0, 0, 0x604B, 0x6048,
- 0xF047, 0xF048, 0, 0x4C54, 0x604A, 0x604C, 0xCB2C, 0x4E44,
- 0, 0, 0xCB2D, 0, 0, 0x6050, 0, 0x776D,
- 0x776E, 0x604F, 0x4376, 0x472D, 0xF04B, 0, 0x3825, 0x604E,
- 0, 0xF04C, 0xCB33, 0xF04D, 0x604D, 0xCB34, 0x4D31, 0x4D32,
- 0, 0xF04A, 0xCB35, 0xCB36, 0, 0xF04E, 0x6051, 0x316E,
-};
-static const unsigned short utf8_to_euc_E78D[] = {
- 0, 0, 0, 0xCB38, 0x3976, 0x3B62, 0, 0,
- 0, 0, 0, 0, 0, 0xCB39, 0x6052, 0x6053,
- 0xCB3A, 0, 0xCB3B, 0, 0, 0, 0xCB3C, 0x6055,
- 0xCB3D, 0, 0, 0, 0, 0xCB3E, 0xCB3F, 0xCB40,
- 0xCB41, 0, 0, 0x3D43, 0, 0, 0xCB42, 0xCB43,
- 0x6057, 0xCB44, 0x6056, 0xCB45, 0xCB46, 0, 0xCB47, 0xCB48,
- 0x6058, 0xCB49, 0x334D, 0, 0, 0x605A, 0, 0xCB4A,
- 0x6059, 0xCB4B, 0x605C, 0x605B, 0xCB4C, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E78D_x0213[] = {
- 0, 0, 0, 0xCB38, 0x3976, 0x3B62, 0, 0,
- 0, 0, 0, 0, 0, 0xCB39, 0x6052, 0x6053,
- 0x7770, 0, 0xF04F, 0, 0, 0, 0xCB3C, 0x6055,
- 0xCB3D, 0, 0, 0, 0, 0xCB3E, 0xCB3F, 0xCB40,
- 0xCB41, 0, 0, 0x3D43, 0, 0, 0x7771, 0xCB43,
- 0x6057, 0xCB44, 0x6056, 0xF051, 0xF052, 0, 0xF054, 0xF055,
- 0x6058, 0xF056, 0x334D, 0, 0, 0x605A, 0, 0xF057,
- 0x6059, 0xCB4B, 0x605C, 0x605B, 0x7772, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E78E[] = {
- 0xCB4D, 0xCB4E, 0, 0xCB4F, 0x383C, 0xCB50, 0xCB51, 0x4E28,
- 0, 0x364C, 0, 0x3226, 0, 0, 0xCB52, 0,
- 0xCB53, 0, 0, 0xCB54, 0, 0xCB55, 0x366A, 0xCB56,
- 0xCB57, 0, 0, 0, 0xCB58, 0, 0xCB59, 0xCB5A,
- 0xCB5B, 0, 0xCB5C, 0, 0, 0xCB5D, 0xCB5E, 0,
- 0, 0x3461, 0xCB5F, 0xCB60, 0, 0xCB61, 0, 0,
- 0, 0, 0x4E68, 0x605E, 0, 0xCB62, 0, 0xCB63,
- 0, 0xCB64, 0, 0x6060, 0xCB65, 0xCB66, 0, 0xCB67,
-};
-static const unsigned short utf8_to_euc_E78E_x0213[] = {
- 0xCB4D, 0xF058, 0, 0xCB4F, 0x383C, 0xF059, 0xCB51, 0x4E28,
- 0, 0x364C, 0xF05A, 0x3226, 0, 0, 0xCB52, 0,
- 0xCB53, 0, 0, 0xCB54, 0xF05B, 0x7773, 0x366A, 0xCB56,
- 0xF05C, 0, 0, 0, 0xF05D, 0, 0xF05E, 0x7774,
- 0x7775, 0, 0x7776, 0, 0, 0xF05F, 0x7777, 0,
- 0xF060, 0x3461, 0xCB5F, 0x7778, 0, 0xCB61, 0, 0,
- 0, 0, 0x4E68, 0x605E, 0, 0xF061, 0, 0xF062,
- 0, 0xF063, 0, 0x6060, 0xF064, 0, 0, 0xF065,
-};
-static const unsigned short utf8_to_euc_E78F[] = {
- 0x6061, 0, 0x3251, 0, 0, 0xCB68, 0xCB69, 0,
- 0x605D, 0xCB6A, 0x3B39, 0xCB6B, 0xCB6C, 0x4441, 0x605F, 0xCB6D,
- 0, 0, 0xCB6E, 0xCB6F, 0, 0, 0xCB70, 0,
- 0, 0xCB71, 0, 0, 0, 0xCB72, 0x6064, 0,
- 0x3C6E, 0xCB73, 0, 0xCB74, 0, 0x6062, 0xCB75, 0xCB76,
- 0, 0xCB77, 0x373E, 0, 0, 0x4849, 0x6063, 0,
- 0, 0x607E, 0, 0, 0xCB78, 0xCB79, 0, 0xCB7A,
- 0x6069, 0xCB7B, 0xCB7C, 0xCB7D, 0, 0xCB7E, 0x383D, 0xCC21,
-};
-static const unsigned short utf8_to_euc_E78F_x0213[] = {
- 0x6061, 0, 0x3251, 0, 0, 0xF066, 0xCB69, 0,
- 0x605D, 0x7779, 0x3B39, 0xF067, 0xCB6C, 0x4441, 0x605F, 0x777A,
- 0, 0, 0, 0xCB6F, 0, 0, 0x777B, 0,
- 0, 0x777C, 0, 0, 0, 0xCB72, 0x6064, 0,
- 0x3C6E, 0xF068, 0, 0x777D, 0, 0x6062, 0xCB75, 0xF069,
- 0, 0x777E, 0x373E, 0, 0, 0x4849, 0x6063, 0,
- 0, 0x607E, 0, 0, 0xCB78, 0, 0, 0xCB7A,
- 0x6069, 0xF06A, 0xF06C, 0xCB7D, 0, 0xCB7E, 0x383D, 0xCC21,
-};
-static const unsigned short utf8_to_euc_E790[] = {
- 0xCC22, 0xCC23, 0, 0x3565, 0xCC24, 0x6066, 0x4D7D, 0xCC25,
- 0, 0x4E30, 0xCC26, 0, 0, 0, 0, 0,
- 0, 0xCC27, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xCC28, 0xCC29, 0, 0, 0, 0,
- 0, 0, 0x4276, 0, 0xCC2A, 0x6068, 0xCC2B, 0,
- 0xCC2C, 0xCC2D, 0xCC2E, 0xCC2F, 0xCC30, 0xCC31, 0xCC32, 0xCC33,
- 0xCC34, 0xCC35, 0x606A, 0x4E56, 0x3657, 0x487C, 0x474A, 0,
- 0, 0xCC36, 0x606B, 0, 0, 0, 0, 0x606D,
-};
-static const unsigned short utf8_to_euc_E790_x0213[] = {
- 0xCC22, 0xF06D, 0, 0x3565, 0xCC24, 0x6066, 0x4D7D, 0x7821,
- 0, 0x4E30, 0x7822, 0, 0, 0, 0, 0,
- 0, 0xCC27, 0, 0xF06B, 0, 0, 0, 0,
- 0, 0, 0x7823, 0x7824, 0, 0, 0, 0,
- 0, 0, 0x4276, 0, 0xF06E, 0x6068, 0x7826, 0,
- 0x7827, 0, 0x7828, 0x7829, 0x782A, 0xCC31, 0x782B, 0x782C,
- 0x782D, 0xF06F, 0x606A, 0x4E56, 0x3657, 0x487C, 0x474A, 0,
- 0, 0xF070, 0x606B, 0, 0, 0, 0, 0x606D,
-};
-static const unsigned short utf8_to_euc_E791[] = {
- 0xCC37, 0x6070, 0, 0xCC38, 0xCC39, 0, 0xCC3A, 0xCC3B,
- 0, 0, 0, 0xCC3C, 0, 0xCC3D, 0, 0,
- 0, 0xCC3E, 0xCC3F, 0, 0, 0x606C, 0, 0xCC40,
- 0, 0x606F, 0x386A, 0x314D, 0x6071, 0xCC41, 0x3F70, 0x606E,
- 0x4E5C, 0, 0xCC42, 0x6074, 0x7424, 0, 0xCC43, 0xCC44,
- 0xCC45, 0x6072, 0x6075, 0xCC46, 0, 0xCC47, 0xCC48, 0x6067,
- 0x6073, 0xCC49, 0xCC4A, 0x3A3C, 0, 0, 0x6076, 0,
- 0, 0, 0, 0, 0, 0, 0x6077, 0,
-};
-static const unsigned short utf8_to_euc_E791_x0213[] = {
- 0xF072, 0x6070, 0, 0xF073, 0x782E, 0, 0x782F, 0x7830,
- 0, 0, 0, 0x7831, 0, 0xF074, 0, 0,
- 0, 0xCC3E, 0xF075, 0xF071, 0, 0x606C, 0, 0x7832,
- 0, 0x606F, 0x386A, 0x314D, 0x6071, 0xF076, 0x3F70, 0x606E,
- 0x4E5C, 0, 0x7833, 0x6074, 0x7424, 0, 0xCC43, 0xCC44,
- 0xCC45, 0x6072, 0x6075, 0x7834, 0, 0x7835, 0xCC48, 0x6067,
- 0x6073, 0xF077, 0xCC4A, 0x3A3C, 0, 0, 0x6076, 0,
- 0, 0, 0, 0, 0, 0, 0x6077, 0,
-};
-static const unsigned short utf8_to_euc_E792[] = {
- 0xCC4B, 0xCC4C, 0, 0x4D7E, 0, 0xCC4D, 0xCC4E, 0xCC4F,
- 0, 0xCC50, 0, 0x6078, 0, 0, 0, 0xCC51,
- 0xCC52, 0xCC53, 0xCC54, 0, 0, 0, 0, 0,
- 0xCC55, 0xCC56, 0xCC57, 0, 0xCC58, 0, 0x6079, 0xCC59,
- 0xCC5A, 0xCC5B, 0x6065, 0xCC5C, 0, 0, 0xCC5D, 0x607A,
- 0xCC5E, 0xCC5F, 0xCC60, 0xCC61, 0, 0, 0xCC62, 0xCC63,
- 0x3444, 0xCC64, 0xCC65, 0, 0, 0xCC66, 0, 0,
- 0, 0xCC67, 0, 0xCC68, 0, 0x3C25, 0, 0xCC69,
-};
-static const unsigned short utf8_to_euc_E792_x0213[] = {
- 0xCC4B, 0xF078, 0, 0x4D7E, 0, 0xF079, 0x7836, 0x7837,
- 0xF07A, 0x7838, 0, 0x6078, 0, 0, 0, 0xCC51,
- 0x783D, 0xCC53, 0xF07C, 0, 0, 0, 0, 0xF07D,
- 0x7839, 0xF07E, 0xCC57, 0, 0x783A, 0, 0x6079, 0x783B,
- 0xF121, 0xF122, 0x6065, 0x783C, 0, 0xF123, 0x783E, 0x607A,
- 0x783F, 0x7840, 0xF124, 0xF125, 0, 0, 0xCC62, 0xCC63,
- 0x3444, 0xCC64, 0xCC65, 0, 0, 0x7841, 0, 0,
- 0, 0xF126, 0xF128, 0xF127, 0, 0x3C25, 0, 0x7842,
-};
-static const unsigned short utf8_to_euc_E793[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xCC6A, 0xCC6B, 0x607B, 0, 0xCC6C, 0, 0, 0x607C,
- 0xCC6D, 0, 0, 0xCC6E, 0x607D, 0, 0, 0,
- 0xCC6F, 0, 0xCC70, 0xCC71, 0x313B, 0, 0xCC72, 0xCC73,
- 0x6121, 0, 0x493B, 0x6122, 0xCC74, 0, 0x3424, 0x6123,
- 0xCC75, 0x6124, 0xCC76, 0xCC77, 0, 0, 0x6125, 0xCC78,
- 0x6127, 0x6128, 0x6126, 0, 0xCC79, 0, 0x4953, 0x612A,
- 0x6129, 0, 0xCC7A, 0xCC7B, 0xCC7C, 0, 0, 0xCC7D,
-};
-static const unsigned short utf8_to_euc_E793_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x7843, 0x7844, 0x607B, 0, 0xCC6C, 0, 0, 0x607C,
- 0xCC6D, 0, 0, 0xCC6E, 0x607D, 0, 0xF129, 0,
- 0xF12A, 0, 0x7845, 0xCC71, 0x313B, 0, 0xF12B, 0xCC73,
- 0x6121, 0, 0x493B, 0x6122, 0xCC74, 0, 0x3424, 0x6123,
- 0xCC75, 0x6124, 0xCC76, 0xF12D, 0, 0, 0x6125, 0xF12C,
- 0x6127, 0x6128, 0x6126, 0, 0xCC79, 0, 0x4953, 0x612A,
- 0x6129, 0, 0xF12F, 0xCC7B, 0xCC7C, 0, 0, 0x7846,
-};
-static const unsigned short utf8_to_euc_E794[] = {
- 0, 0xF450, 0, 0x612C, 0x612B, 0x612D, 0xCC7E, 0,
- 0, 0, 0, 0, 0x612E, 0x6130, 0x612F, 0,
- 0, 0x3979, 0xCD21, 0x6132, 0, 0x6131, 0xCD22, 0xCD23,
- 0x3445, 0, 0x3F53, 0, 0x453C, 0, 0x6133, 0x4038,
- 0xCD24, 0xCD25, 0, 0x3B3A, 0xCD26, 0x3179, 0x6134, 0xCD27,
- 0x4D51, 0xCD28, 0xCD29, 0x4A63, 0x6135, 0, 0, 0xCD2A,
- 0x4544, 0x4D33, 0x3943, 0x3F3D, 0, 0, 0xCD2B, 0x434B,
- 0x5234, 0xCD2C, 0x442E, 0x3268, 0x6136, 0xCD2D, 0xCD2E, 0xCD2F,
-};
-static const unsigned short utf8_to_euc_E794_x0213[] = {
- 0, 0x7847, 0, 0x612C, 0x612B, 0x612D, 0xCC7E, 0,
- 0, 0, 0, 0, 0x612E, 0x6130, 0x612F, 0,
- 0, 0x3979, 0xCD21, 0x6132, 0, 0x6131, 0xCD22, 0x7848,
- 0x3445, 0, 0x3F53, 0, 0x453C, 0, 0x6133, 0x4038,
- 0xF131, 0xCD25, 0, 0x3B3A, 0xF132, 0x3179, 0x6134, 0xCD27,
- 0x4D51, 0xCD28, 0xF133, 0x4A63, 0x6135, 0, 0, 0x7849,
- 0x4544, 0x4D33, 0x3943, 0x3F3D, 0, 0, 0xCD2B, 0x434B,
- 0x5234, 0xCD2C, 0x442E, 0x3268, 0x6136, 0xF136, 0xF137, 0xCD2F,
-};
-static const unsigned short utf8_to_euc_E795[] = {
- 0xCD30, 0, 0, 0xCD31, 0x6137, 0, 0x613C, 0xCD32,
- 0xCD33, 0x613A, 0x6139, 0x5A42, 0x3326, 0x6138, 0xCD34, 0x305A,
- 0xCD35, 0x482A, 0xCD36, 0, 0x484A, 0, 0, 0xCD37,
- 0, 0x4E31, 0x613D, 0x613B, 0x435C, 0x4026, 0xCD38, 0xCD39,
- 0x482B, 0xCD3A, 0x492D, 0, 0x613F, 0x4E2C, 0x374D, 0x6140,
- 0, 0x613E, 0x4856, 0x6141, 0, 0x6142, 0, 0xCD3B,
- 0x305B, 0xCD3C, 0, 0x3E76, 0x6147, 0, 0x6144, 0x466D,
- 0x6143, 0xCD3D, 0xCD3E, 0xCD3F, 0xCD40, 0xCD41, 0xCD42, 0x3526,
-};
-static const unsigned short utf8_to_euc_E795_x0213[] = {
- 0xF138, 0, 0, 0xCD31, 0x6137, 0, 0x613C, 0xCD32,
- 0xF139, 0x613A, 0x6139, 0x5A42, 0x3326, 0x6138, 0xF13A, 0x305A,
- 0xF13B, 0x482A, 0xF13C, 0, 0x484A, 0, 0, 0xCD37,
- 0, 0x4E31, 0x613D, 0x613B, 0x435C, 0x4026, 0xCD38, 0xCD39,
- 0x482B, 0xCD3A, 0x492D, 0, 0x613F, 0x4E2C, 0x374D, 0x6140,
- 0, 0x613E, 0x4856, 0x6141, 0xF13D, 0x6142, 0, 0x784A,
- 0x305B, 0xF13F, 0xF13E, 0x3E76, 0x6147, 0, 0x6144, 0x466D,
- 0x6143, 0x784B, 0xF140, 0xCD3F, 0xCD40, 0xF141, 0xF142, 0x3526,
-};
-static const unsigned short utf8_to_euc_E796[] = {
- 0, 0xCD43, 0x614A, 0, 0, 0xCD44, 0x6145, 0x6146,
- 0, 0x6149, 0x6148, 0x4925, 0, 0, 0x4142, 0x4141,
- 0xCD45, 0x353F, 0xCD46, 0xCD47, 0x614B, 0xCD48, 0, 0,
- 0, 0xCD49, 0x614C, 0, 0xCD4A, 0x614D, 0, 0,
- 0, 0, 0xCD4B, 0x614F, 0xCD4C, 0x614E, 0, 0,
- 0, 0, 0, 0x3156, 0, 0, 0, 0,
- 0, 0x6157, 0x4868, 0x6151, 0xCD4D, 0x6153, 0, 0,
- 0x6155, 0x3F3E, 0xCD4E, 0, 0x6156, 0x6154, 0x3C40, 0xCD4F,
-};
-static const unsigned short utf8_to_euc_E796_x0213[] = {
- 0, 0xF143, 0x614A, 0, 0, 0xCD44, 0x6145, 0x6146,
- 0, 0x6149, 0x6148, 0x4925, 0xF145, 0, 0x4142, 0x4141,
- 0xCD45, 0x353F, 0x784C, 0xCD47, 0x614B, 0xCD48, 0, 0,
- 0, 0xCD49, 0x614C, 0, 0xCD4A, 0x614D, 0, 0,
- 0, 0, 0xF147, 0x614F, 0xCD4C, 0x614E, 0, 0,
- 0, 0, 0, 0x3156, 0, 0, 0, 0,
- 0xF149, 0x6157, 0x4868, 0x6151, 0xCD4D, 0x6153, 0, 0xF14A,
- 0x6155, 0x3F3E, 0xCD4E, 0, 0x6156, 0x6154, 0x3C40, 0xF14B,
-};
-static const unsigned short utf8_to_euc_E797[] = {
- 0xCD50, 0xCD51, 0x6150, 0x6152, 0xCD52, 0x4942, 0xCD53, 0x3E49,
- 0, 0, 0x6159, 0, 0xCD54, 0x6158, 0xCD55, 0xCD56,
- 0, 0, 0x615A, 0, 0x3C26, 0x3A2F, 0, 0xCD57,
- 0x4577, 0x615B, 0, 0x444B, 0xCD58, 0, 0x615D, 0xCD59,
- 0xCD5A, 0xCD5B, 0x4E21, 0x615C, 0xCD5C, 0, 0, 0xCD5D,
- 0, 0x4169, 0, 0, 0xCD5E, 0, 0xCD5F, 0xCD60,
- 0x6162, 0xCD61, 0x6164, 0x6165, 0x4354, 0, 0, 0,
- 0, 0xCD62, 0x6163, 0, 0x6160, 0, 0x615E, 0x615F,
-};
-static const unsigned short utf8_to_euc_E797_x0213[] = {
- 0xF14C, 0xCD51, 0x6150, 0x6152, 0xCD52, 0x4942, 0xF14D, 0x3E49,
- 0, 0, 0x6159, 0, 0xCD54, 0x6158, 0x784E, 0xF14E,
- 0, 0, 0x615A, 0xF14F, 0x3C26, 0x3A2F, 0, 0xCD57,
- 0x4577, 0x615B, 0, 0x444B, 0xCD58, 0xF150, 0x615D, 0xF151,
- 0xF152, 0xCD5B, 0x4E21, 0x615C, 0x784F, 0, 0, 0xF153,
- 0, 0x4169, 0, 0, 0xF154, 0, 0xF155, 0xCD60,
- 0x6162, 0xF156, 0x6164, 0x6165, 0x4354, 0, 0, 0,
- 0, 0xF157, 0x6163, 0, 0x6160, 0, 0x615E, 0x615F,
-};
-static const unsigned short utf8_to_euc_E798[] = {
- 0xCD63, 0x6161, 0xCD64, 0xCD65, 0xCD66, 0, 0, 0xCD67,
- 0xCD68, 0x6168, 0xCD69, 0x6166, 0xCD6A, 0x6167, 0, 0xCD6B,
- 0, 0, 0xCD6C, 0xCD6D, 0, 0xCD6E, 0xCD6F, 0,
- 0, 0xCD70, 0, 0xCD71, 0xCD72, 0xCD73, 0xCD74, 0x6169,
- 0x616B, 0x616C, 0x616D, 0xCD75, 0x616E, 0xCD76, 0xCD77, 0x616A,
- 0, 0xCD78, 0, 0, 0, 0xCD79, 0, 0,
- 0x6170, 0, 0xCD7A, 0xCD7B, 0x616F, 0xCD7C, 0, 0,
- 0xCD7D, 0xCD7E, 0xCE21, 0x6171, 0xCE22, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E798_x0213[] = {
- 0x7850, 0x6161, 0x7851, 0xF158, 0xCD66, 0, 0, 0xF15A,
- 0x7852, 0x6168, 0xCD69, 0x6166, 0xCD6A, 0x6167, 0, 0xF15B,
- 0, 0, 0xCD6C, 0xF15E, 0, 0x7853, 0x7854, 0,
- 0xF159, 0x7855, 0, 0xF15F, 0xF160, 0xCD73, 0x7856, 0x6169,
- 0x616B, 0x616C, 0x616D, 0xCD75, 0x616E, 0xF162, 0x7E7D, 0x616A,
- 0xF163, 0xCD78, 0, 0, 0, 0x7857, 0, 0,
- 0x6170, 0, 0xCD7A, 0xF165, 0x616F, 0x7858, 0, 0,
- 0xCD7D, 0xCD7E, 0xCE21, 0x6171, 0xF164, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E799[] = {
- 0xCE24, 0xCE25, 0x4E45, 0xCE26, 0xCE27, 0xCE28, 0x6174, 0x6172,
- 0x6173, 0xCE29, 0xCE23, 0xCE2A, 0x3462, 0, 0, 0,
- 0, 0, 0x4C7E, 0, 0, 0xCE2B, 0x4A4A, 0,
- 0x6176, 0xCE2C, 0, 0, 0x6175, 0, 0, 0xCE2D,
- 0, 0x6177, 0x6178, 0, 0xCE2E, 0xCE2F, 0, 0x617C,
- 0x6179, 0x617A, 0x617B, 0, 0x617D, 0xCE30, 0xCE31, 0xCE32,
- 0x617E, 0xCE33, 0x6221, 0, 0xCE34, 0, 0x6222, 0,
- 0x6223, 0, 0x482F, 0x4550, 0x6224, 0x4772, 0x4934, 0,
-};
-static const unsigned short utf8_to_euc_E799_x0213[] = {
- 0xCE24, 0xF168, 0x4E45, 0x7859, 0xCE27, 0xCE28, 0x6174, 0x6172,
- 0x6173, 0xF16A, 0xCE23, 0x785A, 0x3462, 0, 0, 0,
- 0, 0, 0x4C7E, 0, 0, 0xF16B, 0x4A4A, 0,
- 0x6176, 0xCE2C, 0, 0, 0x6175, 0, 0, 0xCE2D,
- 0, 0x6177, 0x6178, 0, 0x785B, 0x785C, 0, 0x617C,
- 0x6179, 0x617A, 0x617B, 0, 0x617D, 0x785D, 0xF16D, 0x785E,
- 0x617E, 0x785F, 0x6221, 0, 0xCE34, 0, 0x6222, 0,
- 0x6223, 0, 0x482F, 0x4550, 0x6224, 0x4772, 0x4934, 0,
-};
-static const unsigned short utf8_to_euc_E79A[] = {
- 0x6225, 0xCE35, 0xF451, 0x6226, 0x452A, 0xCE36, 0x3327, 0x3944,
- 0x6227, 0, 0, 0x6228, 0xCE37, 0xCE38, 0x6229, 0,
- 0x3B29, 0, 0, 0x622B, 0, 0xCE39, 0x622A, 0,
- 0, 0x622C, 0x622D, 0xCE3A, 0xCE3B, 0xCE3C, 0xF452, 0xCE3D,
- 0xCE3E, 0, 0xCE3F, 0xCE40, 0xCE41, 0xCE42, 0xCE43, 0xCE44,
- 0xCE45, 0, 0xCE46, 0, 0, 0xCE47, 0x4869, 0,
- 0x622E, 0, 0, 0, 0x622F, 0, 0, 0x7369,
- 0x6230, 0x6231, 0x6232, 0, 0, 0xCE48, 0, 0x3B2E,
-};
-static const unsigned short utf8_to_euc_E79A_x0213[] = {
- 0x6225, 0x7860, 0, 0x6226, 0x452A, 0xCE36, 0x3327, 0x3944,
- 0x6227, 0, 0, 0x6228, 0xCE37, 0xCE38, 0x6229, 0,
- 0x3B29, 0, 0, 0x622B, 0, 0xF16E, 0x622A, 0,
- 0, 0x622C, 0x622D, 0x7861, 0xF16F, 0x7862, 0x7863, 0xCE3D,
- 0xF171, 0xF170, 0xCE3F, 0xCE40, 0xCE41, 0xCE42, 0x7864, 0xF172,
- 0xF173, 0, 0x7865, 0, 0, 0xCE47, 0x4869, 0xF174,
- 0x622E, 0, 0, 0, 0x622F, 0, 0x7866, 0x7369,
- 0x6230, 0x6231, 0x6232, 0, 0, 0xCE48, 0, 0x3B2E,
-};
-static const unsigned short utf8_to_euc_E79B[] = {
- 0, 0xCE49, 0x6233, 0x4756, 0, 0xCE4A, 0x4B5F, 0,
- 0x314E, 0xCE4B, 0x3157, 0xCE4C, 0xCE4D, 0x6234, 0xCE4E, 0,
- 0, 0, 0x6236, 0, 0xCE4F, 0, 0x6235, 0x4570,
- 0, 0xCE50, 0, 0x4039, 0x5D39, 0, 0x6237, 0x4C41,
- 0xCE51, 0x6238, 0, 0x3446, 0x4857, 0x6239, 0xCE52, 0x623A,
- 0xCE53, 0, 0x623B, 0, 0xCE54, 0, 0x4C5C, 0,
- 0xCE55, 0xCE56, 0x4C55, 0, 0x443E, 0, 0xCE57, 0,
- 0x416A, 0xCE58, 0, 0x623D, 0xCE59, 0, 0x3D62, 0,
-};
-static const unsigned short utf8_to_euc_E79B_x0213[] = {
- 0, 0xCE49, 0x6233, 0x4756, 0, 0x7867, 0x4B5F, 0,
- 0x314E, 0xF176, 0x3157, 0xCE4C, 0x7868, 0x6234, 0x7869, 0,
- 0, 0, 0x6236, 0, 0x786A, 0, 0x6235, 0x4570,
- 0, 0xCE50, 0, 0x4039, 0x5D39, 0, 0x6237, 0x4C41,
- 0xCE51, 0x6238, 0, 0x3446, 0x4857, 0x6239, 0x786B, 0x623A,
- 0xF178, 0, 0x623B, 0, 0xF179, 0, 0x4C5C, 0,
- 0xCE55, 0x786C, 0x4C55, 0, 0x443E, 0, 0xCE57, 0,
- 0x416A, 0xCE58, 0, 0x623D, 0x786D, 0, 0x3D62, 0,
-};
-static const unsigned short utf8_to_euc_E79C[] = {
- 0xCE5A, 0x3E4A, 0, 0, 0x6240, 0, 0xCE5B, 0x623F,
- 0x623E, 0x487D, 0xCE5C, 0x3447, 0x3829, 0, 0xCE5D, 0,
- 0, 0, 0xCE5E, 0, 0xCE5F, 0xCE60, 0, 0xCE61,
- 0, 0xCE62, 0xCE63, 0x6246, 0xCE64, 0, 0x6243, 0x3F3F,
- 0x4C32, 0, 0xCE65, 0, 0x6242, 0x6244, 0x6245, 0,
- 0xCE66, 0x6241, 0, 0, 0, 0xCE67, 0xCE68, 0xCE69,
- 0, 0, 0, 0, 0xCE6A, 0xCE6B, 0xCE6C, 0x6247,
- 0x6248, 0xCE6D, 0x442F, 0, 0x3463, 0xCE6E, 0xCE6F, 0,
-};
-static const unsigned short utf8_to_euc_E79C_x0213[] = {
- 0xCE5A, 0x3E4A, 0, 0, 0x6240, 0, 0xCE5B, 0x623F,
- 0x623E, 0x487D, 0x786E, 0x3447, 0x3829, 0, 0xCE5D, 0,
- 0, 0, 0xCE5E, 0, 0xCE5F, 0xCE60, 0, 0xF17B,
- 0, 0x786F, 0xF17C, 0x6246, 0xCE64, 0, 0x6243, 0x3F3F,
- 0x4C32, 0, 0xCE65, 0, 0x6242, 0x6244, 0x6245, 0,
- 0xCE66, 0x6241, 0, 0, 0, 0xF17D, 0xCE68, 0xCE69,
- 0, 0, 0, 0, 0x7870, 0xF17E, 0x7871, 0x6247,
- 0x6248, 0xCE6D, 0x442F, 0, 0x3463, 0xCE6E, 0xCE6F, 0,
-};
-static const unsigned short utf8_to_euc_E79D[] = {
- 0x4365, 0, 0xCE70, 0, 0, 0xCE71, 0xCE72, 0x6249,
- 0, 0, 0xCE73, 0, 0, 0xCE74, 0xCE75, 0xCE76,
- 0, 0, 0xCE77, 0, 0, 0, 0xCE78, 0xCE79,
- 0, 0, 0x624A, 0x624D, 0xCE7A, 0, 0xCE7B, 0xCE7C,
- 0xCE7D, 0x3F67, 0xCE7E, 0x4644, 0xCF21, 0x624E, 0x4B53, 0xCF22,
- 0x624B, 0, 0xCF23, 0x624C, 0xCF24, 0, 0, 0,
- 0xCF25, 0, 0xCF26, 0xCF27, 0xCF28, 0, 0, 0,
- 0, 0x6251, 0xCF29, 0, 0, 0xCF2A, 0x6250, 0x624F,
-};
-static const unsigned short utf8_to_euc_E79D_x0213[] = {
- 0x4365, 0, 0xCE70, 0, 0, 0xCE71, 0x7872, 0x6249,
- 0, 0, 0xCE73, 0, 0, 0x7873, 0x7874, 0xCE76,
- 0, 0, 0xCE77, 0, 0, 0, 0xCE78, 0xCE79,
- 0xF225, 0, 0x624A, 0x624D, 0x7875, 0, 0xCE7B, 0x7876,
- 0xF226, 0x3F67, 0x7877, 0x4644, 0xCF21, 0x624E, 0x4B53, 0xCF22,
- 0x624B, 0, 0xF227, 0x624C, 0xCF24, 0, 0, 0,
- 0xCF25, 0, 0xF229, 0xCF27, 0xCF28, 0, 0, 0,
- 0, 0x6251, 0x7878, 0, 0xF22A, 0xF22B, 0x6250, 0x624F,
-};
-static const unsigned short utf8_to_euc_E79E[] = {
- 0xCF2B, 0, 0, 0, 0xCF2C, 0, 0, 0,
- 0, 0, 0, 0x6253, 0xCF2D, 0xCF2E, 0x6252, 0,
- 0, 0x6254, 0, 0, 0xCF2F, 0xCF30, 0xCF31, 0,
- 0, 0, 0xCF32, 0, 0, 0, 0x6256, 0xCF33,
- 0x6255, 0, 0xCF34, 0, 0, 0x4A4D, 0, 0xCF35,
- 0, 0, 0xCF36, 0, 0x3D56, 0x4E46, 0xCF37, 0xCF38,
- 0x6257, 0xCF39, 0, 0x4637, 0, 0xCF3A, 0x6258, 0,
- 0, 0x6259, 0, 0x625D, 0x625B, 0x625C, 0xCF3B, 0x625A,
-};
-static const unsigned short utf8_to_euc_E79E_x0213[] = {
- 0x7879, 0, 0, 0, 0xCF2C, 0, 0, 0,
- 0, 0, 0, 0x6253, 0xCF2D, 0xCF2E, 0x6252, 0,
- 0, 0x6254, 0, 0, 0x787A, 0xCF30, 0xCF31, 0,
- 0, 0, 0xF22E, 0, 0, 0, 0x6256, 0xF22F,
- 0x6255, 0, 0xF230, 0, 0xF231, 0x4A4D, 0, 0xCF35,
- 0, 0xF232, 0x787B, 0, 0x3D56, 0x4E46, 0xCF37, 0xCF38,
- 0x6257, 0xCF39, 0, 0x4637, 0, 0xCF3A, 0x6258, 0,
- 0, 0x6259, 0, 0x625D, 0x625B, 0x625C, 0xCF3B, 0x625A,
-};
-static const unsigned short utf8_to_euc_E79F[] = {
- 0, 0, 0, 0xCF3C, 0, 0, 0, 0x625E,
- 0, 0xCF3D, 0, 0, 0, 0x625F, 0, 0,
- 0, 0xCF3E, 0xCF3F, 0, 0, 0xCF40, 0, 0x6260,
- 0, 0xCF41, 0x6261, 0x4C37, 0x6262, 0, 0xCF42, 0xCF43,
- 0xCF44, 0, 0x4C70, 0x6263, 0xCF45, 0x434E, 0xCF46, 0x476A,
- 0, 0x366B, 0xCF47, 0, 0xCF48, 0x433B, 0x6264, 0x363A,
- 0xCF49, 0xCF4A, 0, 0x4050, 0xCF4B, 0, 0, 0,
- 0xCF4C, 0, 0, 0xCF4D, 0x6265, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E79F_x0213[] = {
- 0, 0, 0, 0xCF3C, 0, 0, 0, 0x625E,
- 0, 0xCF3D, 0, 0, 0, 0x625F, 0, 0,
- 0, 0xCF3E, 0xCF3F, 0, 0, 0xCF40, 0, 0x6260,
- 0, 0xCF41, 0x6261, 0x4C37, 0x6262, 0, 0xF233, 0xF234,
- 0x787C, 0, 0x4C70, 0x6263, 0xF235, 0x434E, 0xF236, 0x476A,
- 0, 0x366B, 0xF237, 0, 0xF238, 0x433B, 0x6264, 0x363A,
- 0xF23A, 0xCF4A, 0, 0x4050, 0xF23B, 0, 0, 0,
- 0xCF4C, 0, 0, 0xF23C, 0x6265, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E7A0[] = {
- 0, 0, 0x3A3D, 0, 0, 0xCF4E, 0xCF4F, 0,
- 0, 0xCF50, 0, 0, 0x6266, 0xCF51, 0xCF52, 0,
- 0, 0xCF53, 0x6267, 0, 0x3826, 0x3A55, 0, 0,
- 0, 0, 0, 0, 0, 0xCF54, 0, 0,
- 0x6269, 0xCF55, 0xCF56, 0xCF57, 0, 0x4556, 0x3A56, 0x354E,
- 0, 0, 0, 0, 0, 0xCF58, 0xCF59, 0,
- 0xCF5A, 0, 0x4B24, 0, 0x474B, 0xCF5B, 0, 0xCF5C,
- 0, 0, 0x4557, 0, 0, 0, 0, 0x395C,
-};
-static const unsigned short utf8_to_euc_E7A0_x0213[] = {
- 0, 0, 0x3A3D, 0, 0, 0xF23E, 0xF23F, 0,
- 0, 0xF240, 0, 0, 0x6266, 0xF241, 0xCF52, 0,
- 0, 0xCF53, 0x6267, 0, 0x3826, 0x3A55, 0, 0,
- 0, 0xF242, 0, 0, 0, 0xCF54, 0, 0,
- 0x6269, 0xF243, 0xCF56, 0xCF57, 0, 0x4556, 0x3A56, 0x354E,
- 0, 0, 0, 0, 0xF244, 0x787D, 0xCF59, 0,
- 0xCF5A, 0, 0x4B24, 0, 0x474B, 0xCF5B, 0, 0xCF5C,
- 0, 0, 0x4557, 0, 0, 0, 0, 0x395C,
-};
-static const unsigned short utf8_to_euc_E7A1[] = {
- 0, 0, 0, 0xCF5D, 0xCF5E, 0x626B, 0, 0xCF5F,
- 0xCF60, 0, 0, 0, 0xCF61, 0, 0xCF62, 0,
- 0, 0, 0xCF63, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xCF64, 0x3E4B, 0xCF65, 0,
- 0xCF66, 0xCF67, 0, 0xCF68, 0xCF69, 0, 0, 0,
- 0xCF6A, 0, 0xCF6B, 0x4E32, 0x3945, 0, 0xCF6C, 0x3827,
- 0, 0, 0x4823, 0, 0x626D, 0, 0, 0,
- 0, 0, 0xCF6D, 0, 0x626F, 0, 0xCF6E, 0,
-};
-static const unsigned short utf8_to_euc_E7A1_x0213[] = {
- 0, 0, 0, 0x7921, 0xCF5E, 0x626B, 0, 0xF245,
- 0xCF60, 0, 0, 0, 0xCF61, 0, 0x7922, 0x7923,
- 0, 0x7924, 0xCF63, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xCF64, 0x3E4B, 0xCF65, 0,
- 0xCF66, 0xCF67, 0, 0xCF68, 0xF246, 0, 0, 0,
- 0x7925, 0, 0xF247, 0x4E32, 0x3945, 0, 0x7926, 0x3827,
- 0, 0, 0x4823, 0, 0x626D, 0, 0, 0,
- 0, 0, 0, 0, 0x626F, 0, 0xCF6E, 0,
-};
-static const unsigned short utf8_to_euc_E7A2[] = {
- 0, 0x386B, 0, 0, 0, 0, 0x626E, 0x4476,
- 0, 0, 0xCF6F, 0, 0x6271, 0x3337, 0x626C, 0xCF70,
- 0, 0x486A, 0, 0x3130, 0xCF71, 0x3A6C, 0, 0x4F52,
- 0xCF72, 0, 0x6270, 0, 0, 0xCF74, 0xCF75, 0xCF76,
- 0, 0xCF73, 0, 0x6272, 0xCF77, 0, 0, 0x4A4B,
- 0xCF78, 0x4059, 0x6274, 0, 0xCF79, 0xCF7A, 0, 0x6275,
- 0xCF7B, 0xCF7C, 0xCF7D, 0xCF7E, 0, 0x6273, 0, 0,
- 0, 0, 0x334E, 0xD021, 0x627B, 0xD022, 0x627A, 0xD023,
-};
-static const unsigned short utf8_to_euc_E7A2_x0213[] = {
- 0, 0x386B, 0, 0, 0, 0, 0x626E, 0x4476,
- 0, 0, 0xF249, 0, 0x6271, 0x3337, 0x626C, 0xCF70,
- 0, 0x486A, 0, 0x3130, 0xF24A, 0x3A6C, 0, 0x4F52,
- 0xCF72, 0, 0x6270, 0, 0, 0xF24C, 0xF24D, 0xF24E,
- 0, 0xCF73, 0, 0x6272, 0xF24B, 0, 0, 0x4A4B,
- 0xCF78, 0x4059, 0x6274, 0, 0xCF79, 0x792A, 0, 0x6275,
- 0x7928, 0xCF7C, 0xCF7D, 0xCF7E, 0, 0x6273, 0, 0,
- 0, 0, 0x334E, 0xF24F, 0x627B, 0xD022, 0x627A, 0xD023,
-};
-static const unsigned short utf8_to_euc_E7A3[] = {
- 0, 0x3C27, 0, 0, 0, 0x627C, 0x6277, 0xD024,
- 0xD025, 0xD026, 0x627D, 0x6278, 0xD027, 0, 0xD028, 0,
- 0x4858, 0x6276, 0xD029, 0xD02A, 0x6279, 0xD02B, 0xD02C, 0,
- 0, 0, 0x6322, 0xD02E, 0, 0, 0, 0xD02F,
- 0xD030, 0xD031, 0, 0, 0xD02D, 0, 0xD032, 0x6321,
- 0x4B61, 0, 0xD033, 0, 0x627E, 0, 0, 0x306B,
- 0, 0, 0xD034, 0xD035, 0x6324, 0, 0xD037, 0xD038,
- 0, 0, 0xD039, 0xD03A, 0, 0x6323, 0, 0xD03B,
-};
-static const unsigned short utf8_to_euc_E7A3_x0213[] = {
- 0, 0x3C27, 0, 0, 0, 0x627C, 0x6277, 0xD024,
- 0xF250, 0xD026, 0x627D, 0x6278, 0xF251, 0, 0xF252, 0,
- 0x4858, 0x6276, 0xD029, 0xD02A, 0x6279, 0xF253, 0xD02C, 0,
- 0, 0, 0x6322, 0xD02E, 0, 0, 0, 0xD02F,
- 0xF254, 0xF255, 0, 0, 0x792B, 0, 0xF256, 0x6321,
- 0x4B61, 0, 0xD033, 0, 0x627E, 0, 0, 0x306B,
- 0, 0, 0x792C, 0xD035, 0x6324, 0, 0xD037, 0x792E,
- 0, 0xF257, 0xF258, 0xF259, 0, 0x6323, 0xF25A, 0xD03B,
-};
-static const unsigned short utf8_to_euc_E7A4[] = {
- 0xD036, 0x3E4C, 0, 0, 0, 0, 0xD03C, 0x6325,
- 0, 0, 0, 0, 0xD03D, 0, 0x4143, 0,
- 0xD03E, 0x6327, 0x6326, 0, 0, 0, 0, 0,
- 0, 0x6328, 0xD03F, 0, 0xD040, 0, 0xD041, 0xD042,
- 0xD043, 0, 0, 0, 0, 0xD044, 0x6268, 0xD045,
- 0, 0xD046, 0x626A, 0x632A, 0x6329, 0xD047, 0, 0,
- 0xF454, 0xD048, 0, 0, 0xD049, 0xD04A, 0, 0,
- 0, 0, 0x3C28, 0xD04B, 0x4E69, 0xD04C, 0x3C52, 0xD04D,
-};
-static const unsigned short utf8_to_euc_E7A4_x0213[] = {
- 0x792D, 0x3E4C, 0, 0, 0, 0, 0xD03C, 0x6325,
- 0, 0, 0, 0, 0xD03D, 0, 0x4143, 0,
- 0xF25C, 0x6327, 0x6326, 0, 0, 0, 0, 0,
- 0, 0x6328, 0xD03F, 0xF25D, 0x792F, 0, 0xD041, 0xD042,
- 0xD043, 0, 0, 0, 0, 0xF25F, 0x6268, 0xD045,
- 0, 0xD046, 0x626A, 0x632A, 0x6329, 0xD047, 0x7930, 0,
- 0xF25E, 0x7931, 0, 0, 0x7932, 0xD04A, 0, 0,
- 0, 0, 0x3C28, 0xF260, 0x4E69, 0xD04C, 0x3C52, 0xD04D,
-};
-static const unsigned short utf8_to_euc_E7A5[] = {
- 0x632B, 0x3737, 0, 0, 0xD04E, 0xD04F, 0xD050, 0x3540,
- 0x3527, 0x3B63, 0xD051, 0xD052, 0, 0, 0, 0xD053,
- 0x4D34, 0xD054, 0, 0x6331, 0xD055, 0x6330, 0x4144, 0x632D,
- 0xD056, 0, 0x632F, 0xD057, 0xD058, 0x3D4B, 0x3F40, 0x632E,
- 0x632C, 0, 0x472A, 0, 0, 0x3E4D, 0, 0xD059,
- 0x493C, 0xD05A, 0, 0xD05B, 0, 0x3A57, 0, 0,
- 0, 0, 0xD05C, 0, 0, 0, 0, 0x4578,
- 0, 0xD05D, 0x6332, 0xD05E, 0xD05F, 0, 0xD060, 0x6333,
-};
-static const unsigned short utf8_to_euc_E7A5_x0213[] = {
- 0x632B, 0x3737, 0, 0, 0xD04E, 0x7935, 0x7936, 0x3540,
- 0x3527, 0x3B63, 0xF261, 0xD052, 0, 0, 0, 0xD053,
- 0x4D34, 0xD054, 0, 0x6331, 0xD055, 0x6330, 0x4144, 0x632D,
- 0xF262, 0, 0x632F, 0xF263, 0x793A, 0x3D4B, 0x3F40, 0x632E,
- 0x632C, 0, 0x472A, 0, 0, 0x3E4D, 0, 0xF265,
- 0x493C, 0xD05A, 0, 0xD05B, 0, 0x3A57, 0, 0,
- 0, 0, 0xF266, 0, 0, 0, 0, 0x4578,
- 0, 0x793E, 0x6332, 0xD05E, 0xD05F, 0, 0xD060, 0x6333,
-};
-static const unsigned short utf8_to_euc_E7A6[] = {
- 0x6349, 0x3658, 0, 0, 0x4F3D, 0x4135, 0, 0,
- 0, 0, 0x6334, 0xD061, 0xD062, 0x3252, 0x4477, 0x4A21,
- 0, 0xD063, 0, 0xD064, 0xD065, 0xD066, 0xD067, 0,
- 0xD068, 0, 0, 0xD069, 0xD06A, 0x6335, 0, 0,
- 0, 0xD06B, 0, 0, 0, 0, 0x357A, 0x6336,
- 0xD06C, 0xD06D, 0x6338, 0xD06E, 0, 0, 0x6339, 0xD06F,
- 0x4729, 0xD070, 0, 0x633A, 0xD071, 0, 0, 0,
- 0xD072, 0x633B, 0x633C, 0xD073, 0, 0x3659, 0x3253, 0x4645,
-};
-static const unsigned short utf8_to_euc_E7A6_x0213[] = {
- 0x6349, 0x3658, 0, 0, 0x4F3D, 0x4135, 0, 0,
- 0, 0, 0x6334, 0xD061, 0xD062, 0x3252, 0x4477, 0x4A21,
- 0, 0xD063, 0, 0xD064, 0xF267, 0xF268, 0xF269, 0,
- 0x7942, 0, 0, 0xF26A, 0xD06A, 0x6335, 0, 0,
- 0, 0xF26B, 0, 0, 0, 0, 0x357A, 0x6336,
- 0xD06C, 0xF26C, 0x6338, 0xD06E, 0, 0, 0x6339, 0xD06F,
- 0x4729, 0x7943, 0, 0x633A, 0xF26D, 0, 0, 0,
- 0x7944, 0x633B, 0x633C, 0xF26E, 0, 0x3659, 0x3253, 0x4645,
-};
-static const unsigned short utf8_to_euc_E7A7[] = {
- 0x3D28, 0x3B64, 0xD074, 0, 0xD075, 0, 0, 0xD076,
- 0xD077, 0x633D, 0xD078, 0x3D29, 0, 0, 0, 0xD079,
- 0, 0x324A, 0x4943, 0, 0xD07A, 0x633E, 0xD07B, 0,
- 0x486B, 0, 0xD07C, 0, 0, 0xD07D, 0xD07E, 0x4145,
- 0xD121, 0x6341, 0xD122, 0x6342, 0x4769, 0xD123, 0x3F41, 0x633F,
- 0, 0x4361, 0xD124, 0xD125, 0x6340, 0xD126, 0, 0,
- 0x3E4E, 0xD127, 0, 0, 0, 0, 0, 0,
- 0xD128, 0, 0, 0x305C, 0xD129, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E7A7_x0213[] = {
- 0x3D28, 0x3B64, 0xF26F, 0, 0xD075, 0, 0, 0xF270,
- 0x7945, 0x633D, 0x7946, 0x3D29, 0xF271, 0xF272, 0, 0xD079,
- 0, 0x324A, 0x4943, 0, 0x7948, 0x633E, 0xF273, 0,
- 0x486B, 0, 0xD07C, 0, 0, 0xD07D, 0x7949, 0x4145,
- 0xD121, 0x6341, 0xD122, 0x6342, 0x4769, 0xD123, 0x3F41, 0x633F,
- 0, 0x4361, 0xD124, 0x794A, 0x6340, 0x794B, 0, 0,
- 0x3E4E, 0xD127, 0, 0, 0, 0, 0, 0,
- 0xD128, 0, 0, 0x305C, 0xD129, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E7A8[] = {
- 0x3529, 0, 0xD12A, 0xD12B, 0, 0, 0, 0xD12C,
- 0x6343, 0xD12D, 0xD12E, 0x4478, 0xD12F, 0x6344, 0x4047, 0,
- 0, 0xD130, 0, 0, 0x4C2D, 0xD131, 0, 0x4923,
- 0x6345, 0x6346, 0x4355, 0xD132, 0x4E47, 0, 0xD133, 0x6348,
- 0x6347, 0xD134, 0, 0, 0, 0, 0, 0xD135,
- 0, 0, 0, 0xD136, 0, 0xD137, 0x3C6F, 0xD138,
- 0xD139, 0x634A, 0x3070, 0, 0xD13A, 0xD13B, 0, 0x634D,
- 0xD13C, 0xD13D, 0xD13E, 0x634B, 0x3254, 0x374E, 0x634C, 0x3946,
-};
-static const unsigned short utf8_to_euc_E7A8_x0213[] = {
- 0x3529, 0, 0xD12A, 0x794C, 0, 0, 0, 0xD12C,
- 0x6343, 0xD12D, 0xF278, 0x4478, 0xD12F, 0x6344, 0x4047, 0,
- 0, 0xF279, 0, 0, 0x4C2D, 0xF27A, 0, 0x4923,
- 0x6345, 0x6346, 0x4355, 0xF27B, 0x4E47, 0, 0xF27C, 0x6348,
- 0x6347, 0xD134, 0, 0, 0, 0, 0, 0xD135,
- 0, 0, 0, 0xD136, 0, 0xF27E, 0x3C6F, 0xD138,
- 0xD139, 0x634A, 0x3070, 0, 0xD13A, 0xD13B, 0, 0x634D,
- 0xF321, 0x794E, 0xD13E, 0x634B, 0x3254, 0x374E, 0x634C, 0x3946,
-};
-static const unsigned short utf8_to_euc_E7A9[] = {
- 0x3972, 0, 0x4A66, 0x634E, 0xD13F, 0xD140, 0x4B54, 0xD141,
- 0xD142, 0x6350, 0, 0, 0xD143, 0x4051, 0x314F, 0x323A,
- 0x302C, 0, 0, 0, 0, 0xD144, 0xD145, 0x634F,
- 0, 0xD146, 0, 0, 0xD147, 0xD148, 0, 0xD149,
- 0xD14A, 0x6351, 0x6352, 0x3E77, 0, 0xD14B, 0, 0xD14C,
- 0, 0x6353, 0xD14D, 0x334F, 0, 0xD14E, 0, 0,
- 0x6355, 0, 0, 0, 0x376A, 0xD14F, 0x3566, 0,
- 0xD150, 0x6356, 0x3675, 0, 0, 0x6357, 0xD151, 0x407C,
-};
-static const unsigned short utf8_to_euc_E7A9_x0213[] = {
- 0x3972, 0, 0x4A66, 0x634E, 0xD13F, 0xD140, 0x4B54, 0xF322,
- 0xD142, 0x6350, 0, 0, 0xF323, 0x4051, 0x314F, 0x323A,
- 0x302C, 0, 0, 0, 0, 0xD144, 0xF324, 0x634F,
- 0, 0xF325, 0, 0, 0xF326, 0x794F, 0, 0xF327,
- 0xF328, 0x6351, 0x6352, 0x3E77, 0, 0xD14B, 0, 0xF329,
- 0, 0x6353, 0xF32A, 0x334F, 0, 0x7950, 0, 0,
- 0x6355, 0, 0, 0, 0x376A, 0xF32B, 0x3566, 0,
- 0xF32C, 0x6356, 0x3675, 0, 0, 0x6357, 0xD151, 0x407C,
-};
-static const unsigned short utf8_to_euc_E7AA[] = {
- 0xD152, 0x464D, 0xD153, 0x4060, 0x3A75, 0xD154, 0xD155, 0,
- 0x6358, 0, 0xD156, 0xD157, 0, 0, 0, 0,
- 0xD158, 0xD159, 0x4362, 0x416B, 0xD15A, 0x635A, 0x635C, 0x6359,
- 0x635B, 0, 0, 0, 0, 0, 0xD15B, 0x3722,
- 0xD15C, 0, 0, 0xD15D, 0, 0, 0, 0,
- 0, 0x635D, 0x3726, 0, 0xD15E, 0, 0x3567, 0x4D52,
- 0x635F, 0, 0, 0xD15F, 0, 0xD160, 0x6360, 0,
- 0, 0xD161, 0x312E, 0xD162, 0xD163, 0, 0, 0x6363,
-};
-static const unsigned short utf8_to_euc_E7AA_x0213[] = {
- 0xD152, 0x464D, 0xF32D, 0x4060, 0x3A75, 0x7952, 0xD155, 0,
- 0x6358, 0, 0xF32E, 0xD157, 0, 0, 0, 0,
- 0xF32F, 0xD159, 0x4362, 0x416B, 0xD15A, 0x635A, 0x635C, 0x6359,
- 0x635B, 0, 0, 0, 0, 0, 0xD15B, 0x3722,
- 0x7953, 0, 0, 0xF330, 0, 0, 0, 0,
- 0, 0x635D, 0x3726, 0, 0xF331, 0, 0x3567, 0x4D52,
- 0x635F, 0, 0, 0x7955, 0, 0xD160, 0x6360, 0,
- 0, 0xF334, 0x312E, 0x7956, 0xF335, 0, 0xF336, 0x6363,
-};
-static const unsigned short utf8_to_euc_E7AB[] = {
- 0, 0, 0, 0x3376, 0x6362, 0x6361, 0xD164, 0x6365,
- 0x635E, 0xD165, 0x6366, 0x4E29, 0xD166, 0x6367, 0xD167, 0x6368,
- 0, 0xD168, 0x5474, 0x636A, 0, 0x6369, 0, 0,
- 0, 0x636B, 0x636C, 0xD169, 0x4E35, 0x636D, 0, 0x706F,
- 0x3E4F, 0x636E, 0x636F, 0x3D57, 0, 0x4638, 0x6370, 0xF459,
- 0xD16A, 0xD16B, 0x4328, 0xD16C, 0xD16D, 0x6371, 0, 0x433C,
- 0x6372, 0xD16E, 0, 0, 0xD16F, 0, 0x3625, 0,
- 0x513F, 0x435D, 0x3C33, 0xD170, 0, 0xD171, 0xD172, 0x3448,
-};
-static const unsigned short utf8_to_euc_E7AB_x0213[] = {
- 0, 0, 0, 0x3376, 0x6362, 0x6361, 0xD164, 0x6365,
- 0x635E, 0xD165, 0x6366, 0x4E29, 0xF338, 0x6367, 0x7957, 0x6368,
- 0, 0xF339, 0x5474, 0x636A, 0, 0x6369, 0, 0,
- 0, 0x636B, 0x636C, 0xD169, 0x4E35, 0x636D, 0, 0x706F,
- 0x3E4F, 0x636E, 0x636F, 0x3D57, 0, 0x4638, 0x6370, 0xF33A,
- 0xF33B, 0xD16B, 0x4328, 0x7958, 0xD16D, 0x6371, 0, 0x433C,
- 0x6372, 0xD16E, 0, 0, 0xF33C, 0, 0x3625, 0,
- 0x513F, 0x435D, 0x3C33, 0xD170, 0, 0x7959, 0xD172, 0x3448,
-};
-static const unsigned short utf8_to_euc_E7AC[] = {
- 0, 0, 0x6373, 0, 0x6422, 0, 0x6376, 0xD173,
- 0x3568, 0, 0x6375, 0x6424, 0, 0, 0, 0x6374,
- 0, 0x3E50, 0, 0, 0xD174, 0, 0, 0,
- 0x6378, 0x6379, 0, 0x452B, 0, 0, 0x637A, 0xD175,
- 0x335E, 0, 0, 0xD176, 0, 0x3F5A, 0x4964, 0xD177,
- 0x637C, 0xD178, 0xD179, 0xD17A, 0x4268, 0xD17B, 0xD17C, 0xD17D,
- 0xD17E, 0xD221, 0, 0x6377, 0xD222, 0x637B, 0x637D, 0,
- 0, 0x3A7B, 0, 0, 0, 0xD223, 0, 0xD224,
-};
-static const unsigned short utf8_to_euc_E7AC_x0213[] = {
- 0, 0, 0x6373, 0, 0x6422, 0, 0x6376, 0xF33F,
- 0x3568, 0, 0x6375, 0x6424, 0, 0, 0, 0x6374,
- 0, 0x3E50, 0x795A, 0, 0xD174, 0, 0, 0,
- 0x6378, 0x6379, 0, 0x452B, 0, 0, 0x637A, 0xD175,
- 0x335E, 0, 0, 0xD176, 0, 0x3F5A, 0x4964, 0xF342,
- 0x637C, 0xD178, 0xF343, 0xD17A, 0x4268, 0x795B, 0xF344, 0xF345,
- 0xD17E, 0xF346, 0, 0x6377, 0xD222, 0x637B, 0x637D, 0,
- 0, 0x3A7B, 0, 0x795C, 0, 0xF341, 0, 0xD224,
-};
-static const unsigned short utf8_to_euc_E7AD[] = {
- 0xD225, 0xD226, 0, 0, 0, 0x6426, 0x492E, 0xD227,
- 0x4826, 0x4579, 0, 0x365A, 0x6425, 0x6423, 0xD228, 0x4835,
- 0x637E, 0x435E, 0x457B, 0, 0x457A, 0xD229, 0x3A76, 0,
- 0, 0, 0, 0, 0, 0x6438, 0, 0,
- 0xD22A, 0, 0, 0, 0xD22B, 0x6428, 0xD22C, 0x642A,
- 0, 0xD22D, 0xD22E, 0, 0x642D, 0xD22F, 0x642E, 0xD230,
- 0x642B, 0x642C, 0xD231, 0xD232, 0x6429, 0x6427, 0, 0xD233,
- 0, 0, 0x6421, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E7AD_x0213[] = {
- 0xD225, 0xF34A, 0, 0, 0, 0x6426, 0x492E, 0x795D,
- 0x4826, 0x4579, 0, 0x365A, 0x6425, 0x6423, 0x795E, 0x4835,
- 0x637E, 0x435E, 0x457B, 0, 0x457A, 0xF34C, 0x3A76, 0,
- 0, 0, 0, 0, 0, 0x6438, 0, 0,
- 0x795F, 0, 0, 0, 0xF34E, 0x6428, 0xF34F, 0x642A,
- 0, 0xF350, 0xD22E, 0, 0x642D, 0x7960, 0x642E, 0x7961,
- 0x642B, 0x642C, 0x7962, 0xF351, 0x6429, 0x6427, 0, 0xD233,
- 0, 0xF34D, 0x6421, 0, 0, 0, 0, 0xF349,
-};
-static const unsigned short utf8_to_euc_E7AE[] = {
- 0, 0, 0, 0, 0xD234, 0, 0x4A4F, 0x3255,
- 0, 0xD235, 0, 0x6435, 0, 0x6432, 0xD236, 0x6437,
- 0xD237, 0xD238, 0x6436, 0, 0x4773, 0x4C27, 0xD239, 0x3B3B,
- 0x6430, 0x6439, 0x6434, 0xD23A, 0x6433, 0x642F, 0xD23B, 0x6431,
- 0xD23C, 0x3449, 0, 0, 0, 0xD23D, 0, 0,
- 0, 0, 0x433D, 0, 0xD23E, 0x407D, 0, 0xD23F,
- 0xD240, 0x4822, 0xD241, 0, 0x643E, 0xD242, 0xD243, 0,
- 0x4824, 0, 0xD244, 0xD245, 0xD246, 0xD247, 0, 0,
-};
-static const unsigned short utf8_to_euc_E7AE_x0213[] = {
- 0, 0, 0, 0, 0xD234, 0, 0x4A4F, 0x3255,
- 0, 0xD235, 0, 0x6435, 0, 0x6432, 0xD236, 0x6437,
- 0xF354, 0xF355, 0x6436, 0, 0x4773, 0x4C27, 0xD239, 0x3B3B,
- 0x6430, 0x6439, 0x6434, 0xF356, 0x6433, 0x642F, 0x7963, 0x6431,
- 0xD23C, 0x3449, 0, 0, 0, 0xD23D, 0, 0,
- 0, 0, 0x433D, 0, 0xD23E, 0x407D, 0, 0xF358,
- 0xD240, 0x4822, 0xD241, 0, 0x643E, 0xF359, 0xD243, 0,
- 0x4824, 0, 0xD244, 0xD245, 0xF35A, 0xD247, 0, 0,
-};
-static const unsigned short utf8_to_euc_E7AF[] = {
- 0x4061, 0x643B, 0xD248, 0, 0x484F, 0xD249, 0x643F, 0x4A53,
- 0xD24A, 0x435B, 0xD24B, 0x643A, 0x643C, 0, 0, 0x643D,
- 0, 0, 0, 0, 0xD24C, 0, 0xD24D, 0xD24E,
- 0, 0xD24F, 0xD250, 0xD251, 0, 0x6440, 0, 0,
- 0x3C44, 0, 0, 0, 0x4646, 0x6445, 0x6444, 0,
- 0xD252, 0x6441, 0xD253, 0, 0, 0x4F36, 0, 0,
- 0, 0, 0xD254, 0x644A, 0xD255, 0xD256, 0x644E, 0x644B,
- 0xD257, 0xD258, 0xD259, 0, 0xD25A, 0, 0xD25B, 0,
-};
-static const unsigned short utf8_to_euc_E7AF_x0213[] = {
- 0x4061, 0x643B, 0xD248, 0, 0x484F, 0xF35B, 0x643F, 0x4A53,
- 0xD24A, 0x435B, 0xF35C, 0x643A, 0x643C, 0, 0, 0x643D,
- 0, 0, 0, 0, 0xF35F, 0, 0xF360, 0x7965,
- 0, 0x7966, 0xF361, 0xD251, 0, 0x6440, 0, 0,
- 0x3C44, 0, 0, 0, 0x4646, 0x6445, 0x6444, 0,
- 0xD252, 0x6441, 0xF362, 0, 0, 0x4F36, 0, 0,
- 0xF363, 0, 0xD254, 0x644A, 0xD255, 0xD256, 0x644E, 0x644B,
- 0xD257, 0xD258, 0xD259, 0, 0xD25A, 0, 0xD25B, 0,
-};
-static const unsigned short utf8_to_euc_E7B0[] = {
- 0x6447, 0xD25C, 0xD25D, 0xD25E, 0xD25F, 0, 0xD260, 0x6448,
- 0, 0xD261, 0, 0xD262, 0xD263, 0x644D, 0xD264, 0xD265,
- 0, 0x6442, 0x5255, 0x6449, 0x6443, 0, 0, 0x644C,
- 0, 0xD266, 0, 0xD267, 0, 0, 0, 0x6452,
- 0xD268, 0x344A, 0, 0x644F, 0, 0xD269, 0xD26A, 0x6450,
- 0xD26B, 0, 0x6451, 0x6454, 0xD26C, 0, 0, 0,
- 0, 0xD26D, 0, 0xD26E, 0xD26F, 0, 0xD270, 0x6453,
- 0x4876, 0xD271, 0xD272, 0, 0, 0x6455, 0x4E7C, 0x4A6D,
-};
-static const unsigned short utf8_to_euc_E7B0_x0213[] = {
- 0x6447, 0x7967, 0xD25D, 0xF364, 0xD25F, 0, 0xD260, 0x6448,
- 0, 0xD261, 0, 0xF365, 0xD263, 0x644D, 0xF366, 0xF367,
- 0, 0x6442, 0x5255, 0x6449, 0x6443, 0, 0, 0x644C,
- 0, 0xD266, 0, 0xD267, 0, 0, 0x7969, 0x6452,
- 0x796A, 0x344A, 0, 0x644F, 0, 0xD269, 0xF368, 0x6450,
- 0xD26B, 0, 0x6451, 0x6454, 0xD26C, 0, 0, 0,
- 0, 0x7968, 0, 0x796B, 0xD26F, 0, 0x796C, 0x6453,
- 0x4876, 0xD271, 0xD272, 0, 0, 0x6455, 0x4E7C, 0x4A6D,
-};
-static const unsigned short utf8_to_euc_E7B1[] = {
- 0x645A, 0, 0, 0x6457, 0, 0, 0xD273, 0,
- 0, 0, 0xD274, 0, 0x6456, 0x4052, 0, 0x6459,
- 0x645B, 0xD276, 0xD277, 0xD278, 0x6458, 0xD275, 0x645F, 0,
- 0x645C, 0xD279, 0xD27A, 0xD27B, 0xD27C, 0xD27D, 0xD27E, 0x645D,
- 0x6446, 0xD321, 0, 0xD322, 0x645E, 0x6460, 0, 0xD323,
- 0, 0xD324, 0, 0, 0x6461, 0xD325, 0xD326, 0,
- 0xD327, 0, 0xD328, 0x4A46, 0, 0x6462, 0, 0,
- 0, 0xD329, 0, 0, 0xD32A, 0xD32B, 0x4C62, 0,
-};
-static const unsigned short utf8_to_euc_E7B1_x0213[] = {
- 0x645A, 0, 0, 0x6457, 0, 0xF369, 0xD273, 0,
- 0, 0, 0xF36A, 0, 0x6456, 0x4052, 0, 0x6459,
- 0x645B, 0xF36B, 0xD277, 0xD278, 0x6458, 0xD275, 0x645F, 0xF36C,
- 0x645C, 0x796F, 0xD27A, 0xD27B, 0xD27C, 0xD27D, 0xF36D, 0x645D,
- 0x6446, 0xF36E, 0, 0xD322, 0x645E, 0x6460, 0, 0xD323,
- 0, 0xF36F, 0, 0, 0x6461, 0x7970, 0xF370, 0xF371,
- 0xF372, 0, 0xD328, 0x4A46, 0, 0x6462, 0, 0,
- 0, 0x7971, 0, 0, 0xD32A, 0xD32B, 0x4C62, 0,
-};
-static const unsigned short utf8_to_euc_E7B2[] = {
- 0, 0x364E, 0x3729, 0x6463, 0, 0, 0xD32C, 0xD32D,
- 0, 0x4A34, 0, 0x3F68, 0, 0x4C30, 0, 0xD32E,
- 0x6464, 0, 0x4E33, 0, 0xD32F, 0x4774, 0, 0x4146,
- 0x4734, 0, 0, 0x3D4D, 0, 0, 0xD330, 0x3040,
- 0xD331, 0x6469, 0x6467, 0, 0x6465, 0x3421, 0xD332, 0x3E51,
- 0x646A, 0, 0, 0x6468, 0, 0x6466, 0x646E, 0,
- 0xD333, 0x646D, 0x646C, 0x646B, 0, 0, 0xD334, 0xD335,
- 0, 0x646F, 0xD336, 0xD337, 0xD338, 0x6470, 0x403A, 0xD339,
-};
-static const unsigned short utf8_to_euc_E7B2_x0213[] = {
- 0, 0x364E, 0x3729, 0x6463, 0, 0, 0xD32C, 0xD32D,
- 0, 0x4A34, 0, 0x3F68, 0, 0x4C30, 0, 0x7972,
- 0x6464, 0, 0x4E33, 0, 0x7973, 0x4774, 0, 0x4146,
- 0x4734, 0, 0, 0x3D4D, 0, 0, 0xD330, 0x3040,
- 0x7974, 0x6469, 0x6467, 0, 0x6465, 0x3421, 0xF376, 0x3E51,
- 0x646A, 0, 0, 0x6468, 0, 0x6466, 0x646E, 0,
- 0xD333, 0x646D, 0x646C, 0x646B, 0, 0, 0xF378, 0xF379,
- 0, 0x646F, 0xD336, 0xD337, 0x7975, 0x6470, 0x403A, 0xF37A,
-};
-static const unsigned short utf8_to_euc_E7B3[] = {
- 0x6471, 0, 0x6473, 0, 0xD33A, 0x6472, 0, 0xD33B,
- 0xD33C, 0xD33D, 0x3852, 0, 0, 0xD33E, 0x4138, 0xD33F,
- 0, 0, 0x6475, 0xD340, 0xD341, 0xD342, 0x457C, 0xD343,
- 0x6474, 0xD344, 0xD345, 0, 0x6476, 0xD346, 0x4A35, 0x416C,
- 0x3947, 0, 0x6477, 0, 0, 0, 0xD347, 0x4E48,
- 0, 0xD348, 0, 0xD349, 0, 0, 0, 0x6479,
- 0, 0, 0x647A, 0, 0x647B, 0xD34A, 0x647C, 0,
- 0x3B65, 0, 0x647D, 0x374F, 0, 0, 0x356A, 0,
-};
-static const unsigned short utf8_to_euc_E7B3_x0213[] = {
- 0x6471, 0, 0x6473, 0, 0xF37C, 0x6472, 0, 0xD33B,
- 0xF37E, 0xD33D, 0x3852, 0, 0, 0xF421, 0x4138, 0xD33F,
- 0, 0, 0x6475, 0xD340, 0xD341, 0x7976, 0x457C, 0xF423,
- 0x6474, 0x7977, 0xD345, 0, 0x6476, 0x7978, 0x4A35, 0x416C,
- 0x3947, 0, 0x6477, 0, 0, 0, 0xF425, 0x4E48,
- 0, 0xD348, 0, 0xF426, 0, 0, 0, 0x6479,
- 0, 0, 0x647A, 0, 0x647B, 0xF428, 0x647C, 0,
- 0x3B65, 0, 0x647D, 0x374F, 0, 0, 0x356A, 0,
-};
-static const unsigned short utf8_to_euc_E7B4[] = {
- 0x352A, 0, 0x6521, 0xD34B, 0x4C73, 0x3948, 0x647E, 0xD34C,
- 0xD34D, 0xD34E, 0x6524, 0x4C66, 0, 0x473C, 0, 0xD34F,
- 0x4933, 0xD350, 0xD351, 0xD352, 0x3D63, 0x6523, 0xD353, 0x3C53,
- 0x3949, 0x3B66, 0x3569, 0x4A36, 0x6522, 0xD354, 0xD355, 0,
- 0x4147, 0x4B42, 0x3A77, 0xD356, 0, 0, 0xD357, 0,
- 0, 0, 0xD358, 0x3B67, 0x445D, 0xD359, 0x6527, 0x4E5F,
- 0x3A59, 0xD35A, 0x6528, 0x3F42, 0, 0x652A, 0, 0,
- 0, 0x3E52, 0x3A30, 0, 0xD35B, 0xD35C, 0xD35D, 0x6529,
-};
-static const unsigned short utf8_to_euc_E7B4_x0213[] = {
- 0x352A, 0, 0x6521, 0xF429, 0x4C73, 0x3948, 0x647E, 0x7979,
- 0x797A, 0xF42A, 0x6524, 0x4C66, 0, 0x473C, 0, 0xD34F,
- 0x4933, 0xD350, 0xF42C, 0x797B, 0x3D63, 0x6523, 0xD353, 0x3C53,
- 0x3949, 0x3B66, 0x3569, 0x4A36, 0x6522, 0x797C, 0xF42D, 0,
- 0x4147, 0x4B42, 0x3A77, 0x797D, 0, 0, 0xD357, 0,
- 0, 0, 0xD358, 0x3B67, 0x445D, 0xD359, 0x6527, 0x4E5F,
- 0x3A59, 0x797E, 0x6528, 0x3F42, 0, 0x652A, 0, 0,
- 0, 0x3E52, 0x3A30, 0, 0xD35B, 0xF430, 0xF431, 0x6529,
-};
-static const unsigned short utf8_to_euc_E7B5[] = {
- 0xD35E, 0xD35F, 0x3D2A, 0x383E, 0x4148, 0x6525, 0x652B, 0xD360,
- 0xD361, 0, 0, 0x6526, 0x3750, 0xD362, 0x652E, 0x6532,
- 0x376B, 0xD363, 0, 0xD364, 0, 0, 0x652D, 0xD365,
- 0, 0xD366, 0xD367, 0x6536, 0xD368, 0xD369, 0x394A, 0,
- 0, 0x4D6D, 0x303C, 0x6533, 0, 0xD36A, 0x356B, 0xD36B,
- 0x6530, 0, 0xD36C, 0, 0, 0, 0x6531, 0,
- 0xD36D, 0x457D, 0x652F, 0x652C, 0, 0x3328, 0x4064, 0,
- 0xD36E, 0x3828, 0xD36F, 0xD370, 0, 0x6538, 0, 0xD371,
-};
-static const unsigned short utf8_to_euc_E7B5_x0213[] = {
- 0xF432, 0x7A21, 0x3D2A, 0x383E, 0x4148, 0x6525, 0x652B, 0xF433,
- 0x7A22, 0, 0, 0x6526, 0x3750, 0xD362, 0x652E, 0x6532,
- 0x376B, 0xD363, 0, 0x7A23, 0, 0, 0x652D, 0xD365,
- 0, 0xF437, 0xF438, 0x6536, 0x7A24, 0xD369, 0x394A, 0,
- 0, 0x4D6D, 0x303C, 0x6533, 0, 0xD36A, 0x356B, 0xD36B,
- 0x6530, 0, 0xF439, 0, 0, 0, 0x6531, 0,
- 0xF43A, 0x457D, 0x652F, 0x652C, 0, 0x3328, 0x4064, 0,
- 0xD36E, 0x3828, 0x7A25, 0xD370, 0, 0x6538, 0, 0xF43C,
-};
-static const unsigned short utf8_to_euc_E7B6[] = {
- 0, 0xD372, 0xD373, 0xD374, 0, 0xD375, 0xD376, 0,
- 0xD377, 0x6535, 0, 0xD378, 0xD379, 0xD37A, 0, 0x6537,
- 0, 0xD37B, 0, 0x6534, 0, 0, 0xD37C, 0xD37D,
- 0, 0x3751, 0x4233, 0x6539, 0x416E, 0xD37E, 0xD421, 0x6546,
- 0xF45C, 0, 0x6542, 0x653C, 0, 0, 0xD422, 0xD423,
- 0, 0, 0xD424, 0x6540, 0x3C7A, 0x305D, 0x653B, 0x6543,
- 0x6547, 0x394B, 0x4C56, 0xD425, 0x4456, 0x653D, 0xD426, 0xD427,
- 0x6545, 0xD428, 0x653A, 0x433E, 0, 0x653F, 0x303D, 0x4C4A,
-};
-static const unsigned short utf8_to_euc_E7B6_x0213[] = {
- 0, 0xD372, 0xD373, 0x7A26, 0, 0xD375, 0xF43E, 0,
- 0xF43F, 0x6535, 0, 0x7A27, 0xF440, 0xD37A, 0, 0x6537,
- 0, 0xD37B, 0, 0x6534, 0, 0, 0xD37C, 0xF441,
- 0, 0x3751, 0x4233, 0x6539, 0x416E, 0xF443, 0xD421, 0x6546,
- 0x7A28, 0, 0x6542, 0x653C, 0, 0, 0x7A29, 0xF444,
- 0, 0, 0xF445, 0x6540, 0x3C7A, 0x305D, 0x653B, 0x6543,
- 0x6547, 0x394B, 0x4C56, 0xD425, 0x4456, 0x653D, 0xF446, 0xF447,
- 0x6545, 0xD428, 0x653A, 0x433E, 0, 0x653F, 0x303D, 0x4C4A,
-};
-static const unsigned short utf8_to_euc_E7B7[] = {
- 0, 0, 0xD429, 0xD42A, 0xD42B, 0xD42C, 0xD42D, 0x653E,
- 0, 0, 0x365B, 0x486C, 0xD42E, 0xD42F, 0xD430, 0x416D,
- 0, 0x4E50, 0x3D6F, 0, 0, 0x656E, 0xF45D, 0xD431,
- 0x6548, 0xD432, 0x407E, 0, 0x6544, 0x6549, 0x654B, 0,
- 0x4479, 0x654E, 0xD434, 0, 0x654A, 0xD435, 0xD436, 0,
- 0x4A54, 0x344B, 0xD437, 0xD438, 0x4C4B, 0xD439, 0, 0x305E,
- 0, 0xD43A, 0x654D, 0, 0x4E7D, 0xD43B, 0xD43C, 0,
- 0, 0xD43D, 0xD43E, 0x654C, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E7B7_x0213[] = {
- 0xF448, 0, 0x7A2A, 0xD42A, 0xD42B, 0xD42C, 0xD42D, 0x653E,
- 0, 0, 0x365B, 0x486C, 0x7A2B, 0xD42F, 0xD430, 0x416D,
- 0, 0x4E50, 0x3D6F, 0, 0, 0x656E, 0x7A2C, 0xF449,
- 0x6548, 0xF44A, 0x407E, 0, 0x6544, 0x6549, 0x654B, 0,
- 0x4479, 0x654E, 0xD434, 0x7A2D, 0x654A, 0xD435, 0xF44B, 0,
- 0x4A54, 0x344B, 0xD437, 0xD438, 0x4C4B, 0xD439, 0, 0x305E,
- 0, 0xF44C, 0x654D, 0, 0x4E7D, 0xD43B, 0xD43C, 0,
- 0, 0xF44D, 0xD43E, 0x654C, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E7B8[] = {
- 0xD433, 0x316F, 0, 0, 0x466C, 0x654F, 0, 0,
- 0xD43F, 0x6556, 0x6550, 0x6557, 0, 0, 0, 0,
- 0xD440, 0xD441, 0x6553, 0, 0, 0xD442, 0, 0xD443,
- 0, 0, 0, 0x477B, 0xD444, 0xD445, 0x3C4A, 0x6555,
- 0xD446, 0x6552, 0x6558, 0x6551, 0, 0, 0x3D44, 0xD447,
- 0xD448, 0, 0, 0x4B25, 0xD449, 0xD44A, 0x3D4C, 0xD44B,
- 0, 0x6554, 0x6560, 0xD44C, 0, 0x655C, 0xD44D, 0x655F,
- 0, 0x655D, 0x6561, 0x655B, 0, 0x6541, 0x4053, 0xD44E,
-};
-static const unsigned short utf8_to_euc_E7B8_x0213[] = {
- 0xD433, 0x316F, 0, 0, 0x466C, 0x654F, 0, 0,
- 0x7A30, 0x6556, 0x6550, 0x6557, 0, 0, 0, 0,
- 0xF451, 0x7A31, 0x6553, 0, 0, 0x7A32, 0, 0xF452,
- 0, 0, 0, 0x477B, 0xD444, 0xF453, 0x3C4A, 0x6555,
- 0xF454, 0x6552, 0x6558, 0x6551, 0, 0, 0x3D44, 0xF455,
- 0x7A2F, 0, 0, 0x4B25, 0xF456, 0xD44A, 0x3D4C, 0xD44B,
- 0, 0x6554, 0x6560, 0xD44C, 0, 0x655C, 0xD44D, 0x655F,
- 0, 0x655D, 0x6561, 0x655B, 0, 0x6541, 0x4053, 0xD44E,
-};
-static const unsigned short utf8_to_euc_E7B9[] = {
- 0, 0x484B, 0, 0x655E, 0xD44F, 0xD450, 0x6559, 0xD451,
- 0, 0, 0x4121, 0x3752, 0, 0x3D2B, 0xD452, 0,
- 0xD453, 0, 0xD454, 0, 0x3F25, 0x4136, 0x6564, 0,
- 0xD455, 0x6566, 0x6567, 0, 0, 0x6563, 0x6565, 0xD456,
- 0, 0xD457, 0xD458, 0, 0, 0xD459, 0x655A, 0x6562,
- 0, 0x656A, 0x6569, 0xD45A, 0, 0x4B7A, 0xD45B, 0xD45C,
- 0x372B, 0, 0, 0xD45D, 0, 0, 0, 0,
- 0xD45E, 0x6568, 0, 0x656C, 0x656B, 0x656F, 0xD45F, 0x6571,
-};
-static const unsigned short utf8_to_euc_E7B9_x0213[] = {
- 0, 0x484B, 0, 0x655E, 0xD44F, 0xF457, 0x6559, 0x7A34,
- 0, 0, 0x4121, 0x3752, 0, 0x3D2B, 0xD452, 0,
- 0xD453, 0, 0x7A35, 0, 0x3F25, 0x4136, 0x6564, 0,
- 0xD455, 0x6566, 0x6567, 0, 0, 0x6563, 0x6565, 0xD456,
- 0, 0x7A36, 0xD458, 0, 0, 0xD459, 0x655A, 0x6562,
- 0, 0x656A, 0x6569, 0x7E7E, 0, 0x4B7A, 0xD45B, 0xD45C,
- 0x372B, 0, 0, 0xF458, 0, 0xF459, 0, 0,
- 0xD45E, 0x6568, 0, 0x656C, 0x656B, 0x656F, 0xF45A, 0x6571,
-};
-static const unsigned short utf8_to_euc_E7BA[] = {
- 0, 0xD460, 0x3B3C, 0x656D, 0, 0, 0xD461, 0xD462,
- 0x6572, 0x6573, 0xD463, 0, 0x6574, 0xD464, 0x657A, 0x453B,
- 0x6576, 0xD465, 0x6575, 0x6577, 0x6578, 0xD466, 0x6579, 0,
- 0xD467, 0, 0xD468, 0x657B, 0x657C, 0xD469, 0xD46A, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E7BA_x0213[] = {
- 0, 0xD460, 0x3B3C, 0x656D, 0, 0, 0xF45B, 0xF45C,
- 0x6572, 0x6573, 0x7A37, 0, 0x6574, 0x7A38, 0x657A, 0x453B,
- 0x6576, 0xF45E, 0x6575, 0x6577, 0x6578, 0xD466, 0x6579, 0,
- 0xF45F, 0, 0xF460, 0x657B, 0x657C, 0xD469, 0xD46A, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E7BC[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x344C, 0,
- 0x657D, 0, 0x657E, 0xD46C, 0xD46B, 0xD46D, 0xD46E, 0xD46F,
-};
-static const unsigned short utf8_to_euc_E7BC_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x344C, 0,
- 0x657D, 0, 0x657E, 0xF463, 0xF462, 0xD46D, 0xF464, 0xD46F,
-};
-static const unsigned short utf8_to_euc_E7BD[] = {
- 0, 0, 0, 0xD470, 0xD471, 0x6621, 0, 0xD472,
- 0, 0, 0, 0, 0x6622, 0x6623, 0x6624, 0xD473,
- 0x6625, 0x6626, 0xD474, 0xD475, 0x6628, 0x6627, 0, 0,
- 0x6629, 0, 0, 0xD476, 0xD477, 0xD478, 0, 0x662A,
- 0x662B, 0xD479, 0, 0xD47A, 0xD47B, 0xD47C, 0xD47D, 0x662E,
- 0x662C, 0x662D, 0x3A61, 0x3753, 0, 0xD47E, 0x4356, 0,
- 0x4833, 0xD521, 0x3D70, 0, 0, 0x474D, 0, 0x486D,
- 0x662F, 0x586D, 0, 0, 0, 0xD522, 0xD523, 0xD524,
-};
-static const unsigned short utf8_to_euc_E7BD_x0213[] = {
- 0, 0, 0, 0xF465, 0xF466, 0x6621, 0, 0x7A39,
- 0, 0, 0, 0, 0x6622, 0x6623, 0x6624, 0xF467,
- 0x6625, 0x6626, 0xF46A, 0xD475, 0x6628, 0x6627, 0, 0,
- 0x6629, 0, 0, 0xD476, 0xD477, 0xD478, 0, 0x662A,
- 0x662B, 0xF46C, 0, 0xF46D, 0xF46E, 0xD47C, 0xD47D, 0x662E,
- 0x662C, 0x662D, 0x3A61, 0x3753, 0, 0xF46F, 0x4356, 0,
- 0x4833, 0xD521, 0x3D70, 0, 0, 0x474D, 0, 0x486D,
- 0x662F, 0x586D, 0, 0, 0, 0xF470, 0xF471, 0xD524,
-};
-static const unsigned short utf8_to_euc_E7BE[] = {
- 0xD525, 0, 0x6630, 0x6632, 0, 0x4D65, 0x6631, 0x6634,
- 0x6633, 0, 0x4D53, 0xD526, 0x6635, 0xD527, 0x487E, 0xD528,
- 0xD529, 0xD52A, 0, 0, 0x6636, 0, 0xD52B, 0xD52C,
- 0, 0, 0x6639, 0, 0xD52D, 0x6638, 0x6637, 0,
- 0, 0xD52E, 0xD52F, 0x663A, 0x3732, 0, 0xD530, 0,
- 0x4122, 0x3541, 0xD531, 0, 0, 0xD532, 0x663E, 0x663B,
- 0, 0, 0x663C, 0, 0xD533, 0, 0x663F, 0,
- 0x6640, 0x663D, 0, 0, 0xD534, 0x3129, 0, 0xD535,
-};
-static const unsigned short utf8_to_euc_E7BE_x0213[] = {
- 0xD525, 0, 0x6630, 0x6632, 0, 0x4D65, 0x6631, 0x6634,
- 0x6633, 0, 0x4D53, 0xD526, 0x6635, 0xD527, 0x487E, 0xD528,
- 0xF473, 0x7A3B, 0, 0, 0x6636, 0, 0xF476, 0x7A3C,
- 0, 0, 0x6639, 0, 0xF477, 0x6638, 0x6637, 0,
- 0, 0, 0xD52F, 0x663A, 0x3732, 0, 0xD530, 0,
- 0x4122, 0x3541, 0xD531, 0, 0, 0xF478, 0x663E, 0x663B,
- 0, 0, 0x663C, 0, 0xD533, 0, 0x663F, 0,
- 0x6640, 0x663D, 0, 0, 0xD534, 0x3129, 0, 0x7A3D,
-};
-static const unsigned short utf8_to_euc_E7BF[] = {
- 0xD536, 0x3227, 0, 0xD537, 0, 0x6642, 0x6643, 0,
- 0xD538, 0, 0x6644, 0, 0x4D62, 0, 0xD539, 0xD53A,
- 0, 0, 0x3D2C, 0, 0x6646, 0x6645, 0, 0,
- 0, 0, 0, 0xD53B, 0, 0, 0, 0xD53C,
- 0x3F69, 0x6647, 0, 0xD53D, 0, 0xD53E, 0x6648, 0,
- 0xD53F, 0x6649, 0, 0x3465, 0xD540, 0, 0xD541, 0xD542,
- 0x344D, 0, 0xD543, 0x664A, 0, 0, 0, 0,
- 0, 0x664B, 0xD544, 0x4B5D, 0x4D63, 0xD545, 0xD546, 0xD547,
-};
-static const unsigned short utf8_to_euc_E7BF_x0213[] = {
- 0xD536, 0x3227, 0, 0xF47A, 0, 0x6642, 0x6643, 0,
- 0xD538, 0, 0x6644, 0, 0x4D62, 0, 0x7A3E, 0xF47B,
- 0, 0, 0x3D2C, 0, 0x6646, 0x6645, 0, 0,
- 0, 0, 0, 0x7A3F, 0, 0, 0, 0x7A40,
- 0x3F69, 0x6647, 0, 0xF47C, 0, 0xF47D, 0x6648, 0,
- 0xD53F, 0x6649, 0, 0x3465, 0x7A41, 0, 0x7A42, 0xF47E,
- 0x344D, 0, 0xF521, 0x664A, 0, 0, 0, 0,
- 0, 0x664B, 0x7A43, 0x4B5D, 0x4D63, 0xD545, 0xD546, 0xD547,
-};
-static const unsigned short utf8_to_euc_E880[] = {
- 0x4D54, 0x4F37, 0, 0x394D, 0x664E, 0x3C54, 0x664D, 0xD548,
- 0xD549, 0, 0xD54A, 0x664F, 0x3C29, 0xD54B, 0xD54C, 0xD54D,
- 0x4251, 0xD54E, 0x6650, 0xD54F, 0xD550, 0x394C, 0xD551, 0x4C57,
- 0x6651, 0x6652, 0, 0, 0x6653, 0xD552, 0xD553, 0xD554,
- 0xD555, 0x6654, 0, 0, 0xD556, 0, 0xD557, 0,
- 0x6655, 0, 0, 0, 0xD558, 0, 0xD559, 0,
- 0xD55A, 0, 0, 0x3C2A, 0xD55B, 0xD55C, 0x4C6D, 0xD55D,
- 0, 0xD55E, 0xD55F, 0x6657, 0xD560, 0x433F, 0xD561, 0x6656,
-};
-static const unsigned short utf8_to_euc_E880_x0213[] = {
- 0x4D54, 0x4F37, 0xF522, 0x394D, 0x664E, 0x3C54, 0x664D, 0xD548,
- 0xF524, 0, 0xF523, 0x664F, 0x3C29, 0xD54B, 0xF525, 0xD54D,
- 0x4251, 0xF526, 0x6650, 0xD54F, 0x7A45, 0x394C, 0xF527, 0x4C57,
- 0x6651, 0x6652, 0, 0, 0x6653, 0xD552, 0xD553, 0xD554,
- 0xD555, 0x6654, 0, 0, 0xF528, 0, 0x7A46, 0,
- 0x6655, 0, 0, 0, 0xF529, 0, 0xD559, 0,
- 0xF52A, 0, 0, 0x3C2A, 0xD55B, 0x7A47, 0x4C6D, 0x7A48,
- 0, 0xD55E, 0xD55F, 0x6657, 0x7A49, 0x433F, 0xD561, 0x6656,
-};
-static const unsigned short utf8_to_euc_E881[] = {
- 0xD562, 0, 0, 0, 0xD563, 0, 0x6659, 0,
- 0, 0, 0x6658, 0, 0, 0, 0, 0,
- 0, 0, 0x665A, 0, 0, 0, 0x403B, 0,
- 0x665B, 0, 0x665C, 0, 0, 0, 0x4A39, 0x665D,
- 0xD564, 0x416F, 0x665E, 0, 0xD565, 0, 0xD566, 0,
- 0x665F, 0, 0, 0, 0, 0xD567, 0, 0x4E7E,
- 0x6662, 0xD568, 0x6661, 0x6660, 0x4430, 0xD569, 0x6663, 0x3F26,
- 0, 0x6664, 0, 0, 0, 0x6665, 0x4F38, 0x6666,
-};
-static const unsigned short utf8_to_euc_E881_x0213[] = {
- 0xD562, 0, 0, 0xF52B, 0xD563, 0, 0x6659, 0,
- 0, 0, 0x6658, 0, 0, 0, 0, 0,
- 0, 0, 0x665A, 0, 0, 0, 0x403B, 0,
- 0x665B, 0, 0x665C, 0, 0, 0, 0x4A39, 0x665D,
- 0xD564, 0x416F, 0x665E, 0, 0xD565, 0, 0xF52C, 0,
- 0x665F, 0, 0, 0, 0, 0xD567, 0, 0x4E7E,
- 0x6662, 0xF52D, 0x6661, 0x6660, 0x4430, 0xF52E, 0x6663, 0x3F26,
- 0, 0x6664, 0, 0xF52F, 0, 0x6665, 0x4F38, 0x6666,
-};
-static const unsigned short utf8_to_euc_E882[] = {
- 0, 0xD56A, 0, 0, 0x6667, 0x6669, 0x6668, 0x4825,
- 0xD56B, 0x4679, 0, 0x4F3E, 0x4829, 0, 0xD56C, 0,
- 0, 0, 0, 0x666B, 0, 0, 0x3E53, 0,
- 0x492A, 0, 0x666C, 0x666A, 0xD56D, 0x344E, 0xD56E, 0,
- 0, 0x3854, 0x3B68, 0, 0, 0x486E, 0xD56F, 0xD570,
- 0, 0x382A, 0x4B43, 0xD571, 0x666F, 0x666D, 0, 0x394E,
- 0, 0x394F, 0x3069, 0, 0x3A68, 0, 0, 0,
- 0xD572, 0xD573, 0x4759, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E882_x0213[] = {
- 0, 0xD56A, 0, 0, 0x6667, 0x6669, 0x6668, 0x4825,
- 0xD56B, 0x4679, 0, 0x4F3E, 0x4829, 0, 0xD56C, 0,
- 0, 0, 0, 0x666B, 0, 0, 0x3E53, 0,
- 0x492A, 0xF530, 0x666C, 0x666A, 0xF531, 0x344E, 0xD56E, 0,
- 0, 0x3854, 0x3B68, 0, 0xF532, 0x486E, 0xD56F, 0xF533,
- 0, 0x382A, 0x4B43, 0xD571, 0x666F, 0x666D, 0, 0x394E,
- 0, 0x394F, 0x3069, 0, 0x3A68, 0, 0, 0,
- 0xF534, 0xD573, 0x4759, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E883[] = {
- 0, 0, 0, 0x305F, 0x6674, 0, 0x4340, 0,
- 0xD574, 0, 0, 0, 0x4758, 0xD575, 0x425B, 0xD576,
- 0, 0, 0xD577, 0, 0xD578, 0xD579, 0x6676, 0xD57A,
- 0xD57B, 0x6672, 0x6675, 0x6670, 0, 0x6673, 0x4B26, 0,
- 0xD57C, 0x3855, 0, 0, 0x307D, 0x6671, 0, 0,
- 0, 0, 0, 0, 0, 0xD57D, 0xD57E, 0x6678,
- 0xD621, 0x6679, 0xD622, 0xD623, 0x4639, 0, 0xD624, 0,
- 0x363B, 0xD625, 0xD626, 0, 0x6726, 0x473D, 0xD627, 0,
-};
-static const unsigned short utf8_to_euc_E883_x0213[] = {
- 0, 0, 0, 0x305F, 0x6674, 0xF536, 0x4340, 0,
- 0xD574, 0, 0x7A4A, 0, 0x4758, 0xD575, 0x425B, 0xD576,
- 0, 0, 0xD577, 0, 0xD578, 0xF537, 0x6676, 0x7A4B,
- 0xF538, 0x6672, 0x6675, 0x6670, 0, 0x6673, 0x4B26, 0,
- 0x7A4C, 0x3855, 0, 0, 0x307D, 0x6671, 0xF539, 0,
- 0, 0, 0, 0, 0, 0xD57D, 0xD57E, 0x6678,
- 0xD621, 0x6679, 0xD622, 0x7A4D, 0x4639, 0xF53C, 0xD624, 0,
- 0x363B, 0xD625, 0xD626, 0xF53D, 0x6726, 0x473D, 0xD627, 0,
-};
-static const unsigned short utf8_to_euc_E884[] = {
- 0, 0, 0x3B69, 0xD628, 0, 0x363C, 0x4048, 0x4F46,
- 0x4C2E, 0x6677, 0x4054, 0xD629, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xD62A, 0xD62B,
- 0xD62C, 0, 0x3553, 0x667A, 0xD62D, 0, 0xD62E, 0,
- 0xD62F, 0, 0, 0x667C, 0xD630, 0, 0, 0xD631,
- 0, 0x667B, 0, 0, 0xD632, 0, 0, 0x667D,
- 0xD633, 0x4326, 0, 0x473E, 0, 0xD634, 0, 0,
- 0, 0x4431, 0xD635, 0, 0xD636, 0, 0x6723, 0,
-};
-static const unsigned short utf8_to_euc_E884_x0213[] = {
- 0, 0, 0x3B69, 0xD628, 0, 0x363C, 0x4048, 0x4F46,
- 0x4C2E, 0x6677, 0x4054, 0xD629, 0, 0xF53B, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xF540, 0xD62B,
- 0x7A4E, 0, 0x3553, 0x667A, 0xD62D, 0, 0xF541, 0,
- 0xD62F, 0, 0, 0x667C, 0xF543, 0, 0, 0xF544,
- 0, 0x667B, 0, 0, 0xF545, 0, 0, 0x667D,
- 0xD633, 0x4326, 0, 0x473E, 0, 0xF53F, 0, 0,
- 0, 0x4431, 0xD635, 0, 0xD636, 0xF547, 0x6723, 0,
-};
-static const unsigned short utf8_to_euc_E885[] = {
- 0, 0, 0, 0, 0, 0xD637, 0x6722, 0xD638,
- 0, 0, 0xD639, 0x667E, 0xD63A, 0, 0x3F55, 0,
- 0x4965, 0x6725, 0xD63B, 0x6724, 0x3950, 0x4F53, 0, 0xD63C,
- 0, 0, 0, 0, 0, 0, 0, 0x6735,
- 0xD63D, 0xD63E, 0, 0, 0, 0x6729, 0x672A, 0xD63F,
- 0xD640, 0xD641, 0, 0x3C70, 0, 0xD642, 0x6728, 0xD643,
- 0x3978, 0x6727, 0, 0, 0x672B, 0, 0, 0xD644,
- 0x4432, 0x4A22, 0x4123, 0, 0, 0, 0, 0x425C,
-};
-static const unsigned short utf8_to_euc_E885_x0213[] = {
- 0, 0, 0, 0, 0, 0xD637, 0x6722, 0xD638,
- 0, 0, 0x7A4F, 0x667E, 0xD63A, 0, 0x3F55, 0,
- 0x4965, 0x6725, 0xD63B, 0x6724, 0x3950, 0x4F53, 0, 0xD63C,
- 0, 0, 0, 0, 0, 0, 0, 0x6735,
- 0x7A50, 0xD63E, 0, 0, 0, 0x6729, 0x672A, 0x7A51,
- 0x7A52, 0xF549, 0, 0x3C70, 0, 0x7A53, 0x6728, 0xD643,
- 0x3978, 0x6727, 0, 0, 0x672B, 0, 0, 0xD644,
- 0x4432, 0x4A22, 0x4123, 0, 0, 0, 0, 0x425C,
-};
-static const unsigned short utf8_to_euc_E886[] = {
- 0x672F, 0xD645, 0x6730, 0x672C, 0xD647, 0xD648, 0xD649, 0,
- 0x672D, 0, 0x672E, 0xD64A, 0, 0, 0xD64B, 0x3951,
- 0xD646, 0, 0, 0x6736, 0, 0x6732, 0xD64C, 0,
- 0xD64D, 0, 0x4966, 0xD64E, 0x4B6C, 0x4928, 0xD64F, 0,
- 0x6731, 0, 0xD650, 0x6734, 0x6733, 0, 0, 0,
- 0x4B44, 0x6737, 0, 0, 0, 0, 0xD651, 0,
- 0x6738, 0, 0xD652, 0x4137, 0xD653, 0x6739, 0, 0,
- 0x673B, 0, 0x673F, 0xD654, 0, 0x673C, 0x673A, 0x473F,
-};
-static const unsigned short utf8_to_euc_E886_x0213[] = {
- 0x672F, 0xF54B, 0x6730, 0x672C, 0xF54D, 0xF54E, 0xD649, 0,
- 0x672D, 0, 0x672E, 0xD64A, 0, 0, 0xD64B, 0x3951,
- 0xD646, 0, 0, 0x6736, 0, 0x6732, 0xD64C, 0,
- 0xF550, 0, 0x4966, 0xD64E, 0x4B6C, 0x4928, 0xD64F, 0,
- 0x6731, 0, 0xD650, 0x6734, 0x6733, 0, 0, 0,
- 0x4B44, 0x6737, 0, 0, 0, 0, 0xD651, 0,
- 0x6738, 0, 0xF551, 0x4137, 0xD653, 0x6739, 0, 0,
- 0x673B, 0, 0x673F, 0x7A54, 0, 0x673C, 0x673A, 0x473F,
-};
-static const unsigned short utf8_to_euc_E887[] = {
- 0x673D, 0, 0x673E, 0xD656, 0, 0xD657, 0x3232, 0,
- 0x6745, 0x6740, 0xD658, 0xD655, 0, 0x6741, 0xD659, 0xD65A,
- 0, 0x6742, 0, 0x4221, 0, 0xD65B, 0, 0xD65C,
- 0x6744, 0x6743, 0x6746, 0xD65D, 0, 0xD65E, 0xD65F, 0x6747,
- 0x6748, 0xD660, 0, 0x3F43, 0xD661, 0x3269, 0, 0x6749,
- 0x4E57, 0, 0x3C2B, 0xD662, 0xD663, 0x3D2D, 0, 0,
- 0xD664, 0xD665, 0xD666, 0x3B6A, 0x4357, 0xD667, 0xD668, 0,
- 0xD669, 0xD66A, 0x674A, 0x674B, 0x3131, 0xD66B, 0x674C, 0xD66C,
-};
-static const unsigned short utf8_to_euc_E887_x0213[] = {
- 0x673D, 0xF552, 0x673E, 0xF553, 0, 0xD657, 0x3232, 0,
- 0x6745, 0x6740, 0x7A55, 0xD655, 0, 0x6741, 0xD659, 0x7A56,
- 0, 0x6742, 0, 0x4221, 0, 0xD65B, 0xF554, 0x7A57,
- 0x6744, 0x6743, 0x6746, 0xF555, 0, 0xD65E, 0xD65F, 0x6747,
- 0x6748, 0xD660, 0, 0x3F43, 0xF557, 0x3269, 0, 0x6749,
- 0x4E57, 0, 0x3C2B, 0xD662, 0xF559, 0x3D2D, 0, 0,
- 0xD664, 0xD665, 0xD666, 0x3B6A, 0x4357, 0xD667, 0xD668, 0,
- 0xD669, 0xD66A, 0x674A, 0x674B, 0x3131, 0xF55B, 0x674C, 0xF55C,
-};
-static const unsigned short utf8_to_euc_E888[] = {
- 0xD66D, 0x674D, 0x674E, 0xD66E, 0, 0x674F, 0, 0x6750,
- 0x363D, 0x5A2A, 0x6751, 0, 0x4065, 0x6752, 0x3C4B, 0xD66F,
- 0x6753, 0, 0x5030, 0xD670, 0xD671, 0, 0x6754, 0x4A5E,
- 0x345C, 0xD672, 0xD673, 0x4124, 0x3D58, 0xD674, 0x4971, 0x3D2E,
- 0, 0xD675, 0xD676, 0, 0, 0, 0, 0,
- 0xD677, 0x6755, 0x3952, 0x6756, 0x484C, 0, 0x6764, 0,
- 0, 0, 0xD678, 0x6758, 0xD679, 0x4249, 0x4775, 0x383F,
- 0x6757, 0x4125, 0xD67A, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E888_x0213[] = {
- 0xD66D, 0x674D, 0x674E, 0xD66E, 0xF55E, 0x674F, 0, 0x6750,
- 0x363D, 0x5A2A, 0x6751, 0, 0x4065, 0x6752, 0x3C4B, 0xD66F,
- 0x6753, 0, 0x5030, 0xD670, 0xD671, 0, 0x6754, 0x4A5E,
- 0x345C, 0xF560, 0xD673, 0x4124, 0x3D58, 0xD674, 0x4971, 0x3D2E,
- 0, 0xF561, 0xF562, 0, 0, 0, 0, 0,
- 0xD677, 0x6755, 0x3952, 0x6756, 0x484C, 0, 0x6764, 0,
- 0, 0, 0xF564, 0x6758, 0xF565, 0x4249, 0x4775, 0x383F,
- 0x6757, 0x4125, 0xD67A, 0, 0xF566, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E889[] = {
- 0x6759, 0, 0, 0xD67B, 0xD67C, 0xD67D, 0xD67E, 0x447A,
- 0, 0, 0, 0xD721, 0, 0, 0xD722, 0xD723,
- 0, 0xD724, 0, 0, 0, 0, 0xD725, 0,
- 0x675B, 0x675A, 0x675D, 0, 0xD726, 0x675C, 0, 0x675E,
- 0xD727, 0, 0x6760, 0xD728, 0x675F, 0, 0x344F, 0xD729,
- 0x6761, 0, 0x6762, 0x6763, 0, 0xD72A, 0x3A31, 0x4E49,
- 0, 0x6765, 0x3F27, 0, 0xD72B, 0, 0x3170, 0x6766,
- 0x6767, 0, 0, 0xD72C, 0, 0xD72D, 0x6768, 0xD72E,
-};
-static const unsigned short utf8_to_euc_E889_x0213[] = {
- 0x6759, 0, 0, 0xD67B, 0xD67C, 0xF569, 0xF567, 0x447A,
- 0, 0xF568, 0, 0xF56B, 0, 0, 0xD722, 0xF56D,
- 0, 0xD724, 0, 0, 0, 0, 0xD725, 0xF56F,
- 0x675B, 0x675A, 0x675D, 0, 0xF571, 0x675C, 0, 0x675E,
- 0x7A5B, 0, 0x6760, 0xF572, 0x675F, 0, 0x344F, 0xD729,
- 0x6761, 0, 0x6762, 0x6763, 0, 0xD72A, 0x3A31, 0x4E49,
- 0, 0x6765, 0x3F27, 0, 0x7A5C, 0, 0x3170, 0x6766,
- 0x6767, 0xF576, 0, 0xD72C, 0, 0xF578, 0x6768, 0xF579,
-};
-static const unsigned short utf8_to_euc_E88A[] = {
- 0xD72F, 0xD730, 0, 0xD731, 0xD732, 0, 0, 0xD733,
- 0, 0xD734, 0xD735, 0x3072, 0, 0x6769, 0xD736, 0,
- 0, 0xD737, 0x676A, 0, 0xD738, 0, 0xD739, 0,
- 0xD73A, 0x4967, 0xD73B, 0xD73C, 0, 0x3C47, 0, 0x676C,
- 0xD73D, 0xD73E, 0, 0xD73F, 0xD740, 0x3329, 0x3032, 0xD741,
- 0xD742, 0xD743, 0xD744, 0x676B, 0x676E, 0x474E, 0xD745, 0x3F44,
- 0xD746, 0x3256, 0xD747, 0x4B27, 0xD748, 0, 0, 0xD749,
- 0x375D, 0x365C, 0xD74A, 0x676D, 0xD74B, 0x326A, 0xD74C, 0xD74D,
-};
-static const unsigned short utf8_to_euc_E88A_x0213[] = {
- 0xD72F, 0xD730, 0, 0xF57A, 0xD732, 0, 0, 0xD733,
- 0, 0xD734, 0xF57B, 0x3072, 0, 0x6769, 0x7A5E, 0,
- 0, 0xD737, 0x676A, 0xF57C, 0xD738, 0, 0xD739, 0,
- 0xD73A, 0x4967, 0xD73B, 0xD73C, 0, 0x3C47, 0, 0x676C,
- 0xD73D, 0x7A5F, 0, 0x7A60, 0x7A61, 0x3329, 0x3032, 0xF57D,
- 0xF57E, 0x7A62, 0xD744, 0x676B, 0x676E, 0x474E, 0x7A63, 0x3F44,
- 0xD746, 0x3256, 0xF621, 0x4B27, 0xF622, 0, 0, 0x7A64,
- 0x375D, 0x365C, 0xF623, 0x676D, 0xF624, 0x326A, 0x7A65, 0x7A66,
-};
-static const unsigned short utf8_to_euc_E88B[] = {
- 0, 0, 0, 0, 0, 0x3423, 0xD74E, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xD74F, 0x3171, 0x6772, 0x4E6A, 0x425D, 0xD750, 0, 0x4944,
- 0, 0x677E, 0xD751, 0x3257, 0x677C, 0, 0x677A, 0x6771,
- 0xD752, 0x676F, 0xD753, 0x6770, 0xD754, 0x3C63, 0x366C, 0x4377,
- 0xD755, 0, 0xD756, 0x4651, 0, 0xD757, 0, 0xD758,
- 0, 0x3151, 0, 0x6774, 0x6773, 0, 0xD759, 0xD75A,
- 0, 0x6779, 0x6775, 0x6778, 0, 0xD75B, 0xD75C, 0,
-};
-static const unsigned short utf8_to_euc_E88B_x0213[] = {
- 0, 0, 0, 0, 0, 0x3423, 0x7A67, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xD74F, 0x3171, 0x6772, 0x4E6A, 0x425D, 0x7A68, 0, 0x4944,
- 0, 0x677E, 0xD751, 0x3257, 0x677C, 0, 0x677A, 0x6771,
- 0xD752, 0x676F, 0xF625, 0x6770, 0xD754, 0x3C63, 0x366C, 0x4377,
- 0xF626, 0, 0xD756, 0x4651, 0, 0xD757, 0, 0xD758,
- 0, 0x3151, 0, 0x6774, 0x6773, 0, 0xD759, 0xF627,
- 0, 0x6779, 0x6775, 0x6778, 0, 0x7A69, 0x7A6A, 0,
-};
-static const unsigned short utf8_to_euc_E88C[] = {
- 0xD75D, 0xD75E, 0x4C50, 0x6777, 0x3258, 0x337D, 0x677B, 0xD75F,
- 0xD760, 0x677D, 0xD761, 0xD762, 0, 0, 0x3754, 0,
- 0, 0, 0, 0, 0, 0, 0x6823, 0x682C,
- 0x682D, 0, 0, 0xD764, 0x302B, 0xD765, 0xD766, 0xD767,
- 0, 0xD768, 0xD769, 0x6834, 0, 0, 0, 0,
- 0x3071, 0, 0, 0x682B, 0xD76A, 0xD76B, 0xD76C, 0x682A,
- 0xD76D, 0x6825, 0x6824, 0xD76E, 0x6822, 0x6821, 0x4363, 0xD76F,
- 0x427B, 0x6827, 0xD770, 0, 0xD771, 0xD772, 0, 0,
-};
-static const unsigned short utf8_to_euc_E88C_x0213[] = {
- 0x7A6B, 0x7A6C, 0x4C50, 0x6777, 0x3258, 0x337D, 0x677B, 0xF628,
- 0xF629, 0x677D, 0xD761, 0xD762, 0xF62A, 0, 0x3754, 0,
- 0, 0, 0, 0, 0, 0, 0x6823, 0x682C,
- 0x682D, 0, 0, 0xF62C, 0x302B, 0xF62D, 0xD766, 0xD767,
- 0, 0xD768, 0x7A6E, 0x6834, 0, 0, 0, 0,
- 0x3071, 0, 0, 0x682B, 0xD76A, 0x7A6F, 0xD76C, 0x682A,
- 0xF62E, 0x6825, 0x6824, 0xD76E, 0x6822, 0x6821, 0x4363, 0xD76F,
- 0x427B, 0x6827, 0x7A70, 0, 0xF62F, 0xD772, 0, 0,
-};
-static const unsigned short utf8_to_euc_E88D[] = {
- 0x6826, 0, 0xD773, 0xD774, 0xD775, 0x6829, 0, 0xD776,
- 0, 0x4170, 0x3755, 0, 0, 0xD777, 0xD778, 0x3141,
- 0x6828, 0xD779, 0x3953, 0xD83E, 0xD763, 0xD77A, 0xD77B, 0xD77C,
- 0x4171, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xF45F, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xD77D, 0, 0, 0x683A, 0, 0x683B, 0, 0x3259,
- 0xD77E, 0, 0, 0x322E, 0x6838, 0xD821, 0, 0xD822,
-};
-static const unsigned short utf8_to_euc_E88D_x0213[] = {
- 0x6826, 0, 0xD773, 0x7A71, 0xF630, 0x6829, 0, 0x7A72,
- 0, 0x4170, 0x3755, 0, 0, 0xD777, 0xD778, 0x3141,
- 0x6828, 0x7A73, 0x3953, 0xD83E, 0xF62B, 0x7A74, 0xD77B, 0xF631,
- 0x4171, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x7A6D, 0xAE4A, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xD77D, 0, 0, 0x683A, 0, 0x683B, 0, 0x3259,
- 0xD77E, 0, 0, 0x322E, 0x6838, 0x7A75, 0, 0xF633,
-};
-static const unsigned short utf8_to_euc_E88E[] = {
- 0xD823, 0, 0xD824, 0, 0xD825, 0x682E, 0xD826, 0x6836,
- 0, 0x683D, 0x6837, 0, 0, 0xD827, 0x6835, 0,
- 0, 0, 0xD828, 0x6776, 0xD829, 0xD82A, 0x6833, 0,
- 0xD82B, 0xD82C, 0x682F, 0xD82D, 0xD82E, 0xD82F, 0x3450, 0x6831,
- 0x683C, 0, 0x6832, 0, 0, 0, 0xD830, 0xD831,
- 0x683E, 0xD832, 0x6830, 0x477C, 0xD833, 0xD84C, 0, 0,
- 0, 0x4D69, 0, 0, 0, 0x6839, 0, 0,
- 0, 0, 0, 0, 0, 0x684F, 0xD834, 0xD835,
-};
-static const unsigned short utf8_to_euc_E88E_x0213[] = {
- 0xD823, 0, 0xD824, 0, 0xD825, 0x682E, 0x7A76, 0x6836,
- 0, 0x683D, 0x6837, 0, 0, 0xF636, 0x6835, 0,
- 0, 0, 0x7A77, 0x6776, 0xF637, 0xF638, 0x6833, 0,
- 0x7A78, 0xD82C, 0x682F, 0xF639, 0xD82E, 0xF63A, 0x3450, 0x6831,
- 0x683C, 0, 0x6832, 0, 0, 0, 0xD830, 0x7A79,
- 0x683E, 0x7A7A, 0x6830, 0x477C, 0xD833, 0xD84C, 0, 0,
- 0, 0x4D69, 0, 0, 0, 0x6839, 0, 0,
- 0, 0, 0, 0, 0, 0x684F, 0xD834, 0x7A7B,
-};
-static const unsigned short utf8_to_euc_E88F[] = {
- 0xD836, 0x6847, 0, 0, 0, 0x3F7B, 0, 0xD837,
- 0, 0xD838, 0x3546, 0, 0x365D, 0, 0x6842, 0xD839,
- 0xD83A, 0xD83B, 0, 0x325B, 0xD83C, 0, 0x3E54, 0,
- 0x6845, 0, 0, 0, 0x3A5A, 0xD83D, 0, 0x4551,
- 0x684A, 0, 0, 0, 0, 0, 0, 0,
- 0xD83F, 0x4A6E, 0xD840, 0x6841, 0, 0, 0, 0x325A,
- 0x3856, 0x4929, 0x684B, 0, 0x683F, 0, 0xD841, 0x6848,
- 0xD842, 0xD843, 0, 0x6852, 0xD844, 0x6843, 0, 0,
-};
-static const unsigned short utf8_to_euc_E88F_x0213[] = {
- 0x7A7C, 0x6847, 0, 0, 0, 0x3F7B, 0, 0x7A7D,
- 0, 0xF63B, 0x3546, 0, 0x365D, 0, 0x6842, 0x7A7E,
- 0xF63C, 0x7B21, 0, 0x325B, 0xF63D, 0, 0x3E54, 0,
- 0x6845, 0, 0, 0, 0x3A5A, 0xF63E, 0, 0x4551,
- 0x684A, 0x7B22, 0, 0, 0, 0xF63F, 0, 0,
- 0xD83F, 0x4A6E, 0x7B23, 0x6841, 0, 0, 0, 0x325A,
- 0x3856, 0x4929, 0x684B, 0, 0x683F, 0, 0, 0x6848,
- 0xD842, 0xF640, 0, 0x6852, 0xD844, 0x6843, 0, 0,
-};
-static const unsigned short utf8_to_euc_E890[] = {
- 0, 0xD845, 0, 0x6844, 0x463A, 0, 0xD846, 0x6849,
- 0, 0, 0xD847, 0x6846, 0x4B28, 0x684C, 0x3060, 0xD848,
- 0, 0xD849, 0, 0x6840, 0, 0xD84A, 0, 0,
- 0, 0xD84B, 0, 0, 0, 0, 0, 0,
- 0x684E, 0, 0x684D, 0, 0, 0, 0, 0,
- 0, 0x476B, 0x6854, 0, 0x685F, 0, 0, 0xD84D,
- 0, 0x337E, 0, 0, 0, 0x6862, 0, 0,
- 0x6850, 0xD84E, 0, 0, 0x6855, 0x4D6E, 0, 0,
-};
-static const unsigned short utf8_to_euc_E890_x0213[] = {
- 0, 0x7B24, 0, 0x6844, 0x463A, 0, 0x7B25, 0x6849,
- 0, 0, 0x7B26, 0x6846, 0x4B28, 0x684C, 0x3060, 0xF641,
- 0, 0xF642, 0, 0x6840, 0, 0xF643, 0, 0xF645,
- 0, 0xD84B, 0, 0, 0, 0, 0, 0,
- 0x684E, 0, 0x684D, 0, 0, 0, 0, 0,
- 0, 0x476B, 0x6854, 0, 0x685F, 0, 0, 0xD84D,
- 0, 0x337E, 0, 0, 0, 0x6862, 0, 0,
- 0x6850, 0xF646, 0, 0, 0x6855, 0x4D6E, 0, 0,
-};
-static const unsigned short utf8_to_euc_E891[] = {
- 0, 0, 0, 0, 0, 0xD84F, 0x685E, 0xD850,
- 0xD851, 0x4D55, 0xD852, 0, 0, 0xD853, 0x4E2A, 0xD854,
- 0, 0xD855, 0xD856, 0, 0, 0, 0xD857, 0x4378,
- 0xD858, 0xD859, 0xD85A, 0x336B, 0xD85B, 0, 0, 0,
- 0xD85C, 0x4972, 0x6864, 0x4621, 0xD85D, 0xD85E, 0x3031, 0xD85F,
- 0, 0x685D, 0xD860, 0x6859, 0x4172, 0x6853, 0x685B, 0x6860,
- 0xD861, 0x472C, 0, 0xD862, 0xD863, 0x302A, 0xD864, 0x6858,
- 0xD865, 0x6861, 0x4978, 0, 0xD866, 0xD867, 0, 0,
-};
-static const unsigned short utf8_to_euc_E891_x0213[] = {
- 0, 0, 0, 0, 0, 0xD84F, 0x685E, 0xD850,
- 0x7B28, 0x4D55, 0xF647, 0, 0, 0xD853, 0x4E2A, 0xF648,
- 0, 0xF649, 0xF64A, 0, 0, 0, 0xD857, 0x4378,
- 0xD858, 0xF64B, 0xF64C, 0x336B, 0xF64D, 0, 0, 0x7B29,
- 0xD85C, 0x4972, 0x6864, 0x4621, 0xD85D, 0xF64F, 0x3031, 0xD85F,
- 0, 0x685D, 0xD860, 0x6859, 0x4172, 0x6853, 0x685B, 0x6860,
- 0x7B2A, 0x472C, 0, 0x7B2B, 0xD863, 0x302A, 0xF650, 0x6858,
- 0xF651, 0x6861, 0x4978, 0, 0xF652, 0xD867, 0, 0,
-};
-static const unsigned short utf8_to_euc_E892[] = {
- 0, 0xD868, 0x685C, 0, 0x6857, 0xD869, 0, 0,
- 0, 0, 0, 0x3E55, 0, 0, 0, 0,
- 0x3D2F, 0, 0xD86A, 0xD86B, 0x3C2C, 0xD86C, 0, 0,
- 0, 0x4C58, 0, 0, 0x4947, 0, 0xD86D, 0x6867,
- 0, 0x6870, 0, 0, 0, 0, 0xD86E, 0,
- 0xD86F, 0xD870, 0xD871, 0, 0, 0x685A, 0, 0xD872,
- 0, 0xD873, 0x3377, 0, 0xD874, 0, 0, 0,
- 0x3E78, 0x6865, 0xD875, 0x686A, 0x4173, 0xD876, 0xD877, 0x6866,
-};
-static const unsigned short utf8_to_euc_E892_x0213[] = {
- 0, 0xF653, 0x685C, 0, 0x6857, 0x7B2C, 0, 0,
- 0, 0, 0, 0x3E55, 0, 0, 0, 0,
- 0x3D2F, 0, 0xD86A, 0xD86B, 0x3C2C, 0xD86C, 0, 0xF656,
- 0, 0x4C58, 0, 0, 0x4947, 0, 0x7B2D, 0x6867,
- 0, 0x6870, 0, 0, 0, 0, 0xF657, 0,
- 0xD86F, 0xD870, 0xD871, 0, 0, 0x685A, 0, 0x7B2E,
- 0, 0xD873, 0x3377, 0, 0x7B2F, 0, 0, 0,
- 0x3E78, 0x6865, 0x7B30, 0x686A, 0x4173, 0xD876, 0xF658, 0x6866,
-};
-static const unsigned short utf8_to_euc_E893[] = {
- 0xD878, 0x686D, 0xD879, 0, 0x435F, 0, 0x686E, 0xD87A,
- 0xD87B, 0x4D56, 0x6863, 0x3338, 0xD87C, 0x6869, 0, 0xD87D,
- 0x686C, 0x4C2C, 0, 0xD87E, 0, 0, 0x686F, 0,
- 0, 0x6868, 0x686B, 0, 0xD921, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xD922,
- 0, 0, 0xD923, 0, 0x4B29, 0, 0x4F21, 0xD924,
- 0xD925, 0xD926, 0xD927, 0, 0x6873, 0, 0, 0xD928,
- 0, 0, 0xD92A, 0xD92B, 0x687A, 0xD92C, 0, 0x6872,
-};
-static const unsigned short utf8_to_euc_E893_x0213[] = {
- 0x7B31, 0x686D, 0x7B32, 0, 0x435F, 0, 0x686E, 0xD87A,
- 0xD87B, 0x4D56, 0x6863, 0x3338, 0xD87C, 0x6869, 0xF65A, 0xF65B,
- 0x686C, 0x4C2C, 0, 0xF65C, 0, 0, 0x686F, 0,
- 0, 0x6868, 0x686B, 0, 0xF655, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xF65E,
- 0, 0, 0xF65F, 0, 0x4B29, 0, 0x4F21, 0xF660,
- 0xF661, 0xF662, 0xD927, 0, 0x6873, 0, 0, 0xD928,
- 0, 0, 0xF663, 0xD92B, 0x687A, 0xF664, 0, 0x6872,
-};
-static const unsigned short utf8_to_euc_E894[] = {
- 0x3C43, 0, 0xD92D, 0xD92E, 0, 0, 0x6851, 0xD92F,
- 0, 0, 0, 0, 0xD930, 0, 0xD931, 0,
- 0xD932, 0x4A4E, 0, 0x4C22, 0x6879, 0x6878, 0, 0x6874,
- 0x6875, 0, 0x3136, 0, 0xD933, 0, 0xD934, 0x6877,
- 0, 0x6871, 0xD935, 0xD936, 0xD937, 0xD938, 0x4455, 0xD939,
- 0, 0, 0xD93A, 0xD93B, 0x6876, 0x307E, 0, 0xD93C,
- 0, 0, 0xD929, 0xD93D, 0xD93E, 0x4222, 0xD93F, 0,
- 0, 0, 0, 0, 0, 0x4A43, 0, 0xD940,
-};
-static const unsigned short utf8_to_euc_E894_x0213[] = {
- 0x3C43, 0, 0xD92D, 0xD92E, 0, 0, 0x6851, 0xD92F,
- 0, 0, 0, 0, 0xF665, 0, 0xD931, 0,
- 0xD932, 0x4A4E, 0, 0x4C22, 0x6879, 0x6878, 0, 0x6874,
- 0x6875, 0, 0x3136, 0xF666, 0xD933, 0, 0x7B35, 0x6877,
- 0, 0x6871, 0xD935, 0x7B36, 0xF667, 0xF668, 0x4455, 0xD939,
- 0, 0, 0xD93A, 0xF669, 0x6876, 0x307E, 0, 0x7B37,
- 0, 0, 0x7B34, 0xD93D, 0xF66A, 0x4222, 0xD93F, 0,
- 0, 0, 0, 0, 0, 0x4A43, 0xF66F, 0xD940,
-};
-static const unsigned short utf8_to_euc_E895[] = {
- 0x687B, 0x6921, 0, 0x4859, 0, 0, 0xD941, 0,
- 0x687E, 0x3E56, 0x3C49, 0x6923, 0, 0, 0x363E, 0xD942,
- 0xD943, 0xD944, 0xD945, 0xD946, 0, 0x6924, 0xD947, 0x4979,
- 0x687D, 0xD948, 0x6856, 0, 0xD949, 0xD94A, 0xD94B, 0xD94C,
- 0xD94D, 0xD94E, 0xD94F, 0x687C, 0xD950, 0, 0, 0,
- 0x4F4F, 0x4622, 0x4973, 0xD951, 0, 0x692B, 0, 0xD952,
- 0, 0, 0, 0, 0, 0, 0, 0x6931,
- 0, 0xD953, 0xD954, 0xD955, 0, 0xD956, 0x6932, 0xD957,
-};
-static const unsigned short utf8_to_euc_E895_x0213[] = {
- 0x687B, 0x6921, 0, 0x4859, 0, 0, 0xD941, 0,
- 0x687E, 0x3E56, 0x3C49, 0x6923, 0, 0, 0x363E, 0xF66B,
- 0xD943, 0xF670, 0xD945, 0xF671, 0, 0x6924, 0xD947, 0x4979,
- 0x687D, 0x7B38, 0x6856, 0, 0xD949, 0xD94A, 0xF672, 0xD94C,
- 0xD94D, 0xF673, 0xF674, 0x687C, 0x7B39, 0, 0, 0,
- 0x4F4F, 0x4622, 0x4973, 0, 0, 0x692B, 0, 0xF66C,
- 0, 0, 0, 0, 0, 0, 0, 0x6931,
- 0, 0xD953, 0x7B3C, 0xF676, 0, 0xF677, 0x6932, 0xF678,
-};
-static const unsigned short utf8_to_euc_E896[] = {
- 0x6925, 0xD958, 0, 0, 0x4776, 0xD959, 0xD95A, 0x692F,
- 0x6927, 0xD95B, 0x6929, 0xD95C, 0xD95D, 0, 0, 0xD95E,
- 0x6933, 0x6928, 0, 0xD95F, 0x692C, 0, 0, 0x3172,
- 0xD960, 0x4665, 0, 0x692D, 0x6930, 0xD961, 0, 0xD962,
- 0xD963, 0, 0xD964, 0, 0x6926, 0xD965, 0x4126, 0xD966,
- 0x692A, 0x3B27, 0x3F45, 0x3730, 0x4C74, 0xD974, 0x4C79, 0x3D72,
- 0xF461, 0, 0, 0, 0xD967, 0, 0xD968, 0xD969,
- 0xD96A, 0x6937, 0x6935, 0, 0xD96B, 0xD96C, 0xD96D, 0xD96E,
-};
-static const unsigned short utf8_to_euc_E896_x0213[] = {
- 0x6925, 0xF679, 0, 0, 0x4776, 0xD959, 0xF67A, 0x692F,
- 0x6927, 0xD95B, 0x6929, 0xD95C, 0x7B3D, 0, 0, 0x7B3E,
- 0x6933, 0x6928, 0, 0xF67B, 0x692C, 0, 0, 0x3172,
- 0xD960, 0x4665, 0, 0x692D, 0x6930, 0xF67C, 0, 0xF67D,
- 0xD963, 0, 0x7B3F, 0, 0x6926, 0xD965, 0x4126, 0xD966,
- 0x692A, 0x3B27, 0x3F45, 0x3730, 0x4C74, 0x7B3B, 0x4C79, 0x3D72,
- 0x7B40, 0, 0, 0, 0xD967, 0, 0xD968, 0xF723,
- 0xD96A, 0x6937, 0x6935, 0, 0xF724, 0xD96C, 0xD96D, 0xD96E,
-};
-static const unsigned short utf8_to_euc_E897[] = {
- 0, 0x4F4E, 0xD96F, 0, 0, 0, 0, 0xD970,
- 0, 0x6934, 0xD971, 0xD972, 0, 0x4D75, 0xD973, 0x6936,
- 0x6938, 0, 0, 0, 0, 0x6939, 0, 0,
- 0xD975, 0, 0xD976, 0, 0x693C, 0x693A, 0, 0xD977,
- 0xD978, 0, 0, 0, 0x4623, 0x693B, 0xD979, 0,
- 0xD97A, 0x484D, 0x692E, 0, 0, 0xD97B, 0, 0,
- 0, 0, 0, 0xD97C, 0, 0, 0xD97D, 0x3D73,
- 0, 0x693D, 0x6942, 0x4174, 0xD97E, 0, 0x6941, 0xDA21,
-};
-static const unsigned short utf8_to_euc_E897_x0213[] = {
- 0, 0x4F4E, 0xD96F, 0, 0, 0, 0, 0xF725,
- 0, 0x6934, 0xF726, 0x7B41, 0, 0x4D75, 0x7B42, 0x6936,
- 0x6938, 0, 0, 0, 0, 0x6939, 0, 0,
- 0xF727, 0xF728, 0xD976, 0, 0x693C, 0x693A, 0, 0xF729,
- 0xD978, 0xF72A, 0, 0, 0x4623, 0x693B, 0xF72B, 0,
- 0xD97A, 0x484D, 0x692E, 0, 0, 0x7B43, 0, 0,
- 0, 0, 0, 0xD97C, 0, 0, 0xF72C, 0x3D73,
- 0, 0x693D, 0x6942, 0x4174, 0xD97E, 0, 0x6941, 0x7B45,
-};
-static const unsigned short utf8_to_euc_E898[] = {
- 0xDA22, 0, 0x6922, 0, 0xDA23, 0xDA24, 0x6943, 0x4149,
- 0, 0, 0x693E, 0x6940, 0, 0xDA25, 0xDA26, 0,
- 0xDA27, 0xDA28, 0xDA29, 0x693F, 0, 0, 0x5D31, 0x5D22,
- 0xDA2A, 0xDA2B, 0x6945, 0xDA2C, 0, 0, 0xDA2D, 0,
- 0, 0xDA2E, 0x6944, 0, 0, 0, 0, 0xDA2F,
- 0, 0xDA30, 0, 0, 0, 0x4D76, 0, 0x623C,
- 0x6946, 0, 0, 0, 0, 0, 0xDA31, 0,
- 0xDA32, 0, 0xDA33, 0, 0xDA34, 0xDA35, 0, 0x6947,
-};
-static const unsigned short utf8_to_euc_E898_x0213[] = {
- 0xF72D, 0, 0x6922, 0, 0x7B46, 0x7B47, 0x6943, 0x4149,
- 0, 0, 0x693E, 0x6940, 0, 0xDA25, 0xDA26, 0,
- 0x7B48, 0xF72E, 0x7B44, 0x693F, 0, 0, 0x5D31, 0x5D22,
- 0x7B4A, 0xDA2B, 0x6945, 0xDA2C, 0, 0, 0xF72F, 0,
- 0, 0xF730, 0x6944, 0, 0xF731, 0, 0, 0xF732,
- 0, 0x7B4B, 0, 0, 0, 0x4D76, 0, 0x623C,
- 0x6946, 0, 0, 0, 0, 0, 0xDA31, 0,
- 0x7B4C, 0xF734, 0xDA33, 0, 0xF735, 0xDA35, 0, 0x6947,
-};
-static const unsigned short utf8_to_euc_E899[] = {
- 0xDA36, 0xB866, 0xDA37, 0, 0, 0, 0xDA38, 0,
- 0, 0, 0, 0, 0, 0x6948, 0x3857, 0,
- 0x3554, 0, 0xDA39, 0xDA3A, 0x694A, 0x515D, 0xDA3B, 0xDA3C,
- 0xDA3D, 0xDA3E, 0x3575, 0, 0x4E3A, 0xDA3F, 0x3673, 0x694B,
- 0xDA40, 0xDA41, 0xDA42, 0xDA43, 0xDA44, 0, 0, 0x694C,
- 0, 0xDA45, 0, 0x436E, 0xDA46, 0, 0, 0xDA47,
- 0, 0x694D, 0, 0, 0, 0xDA48, 0xDA49, 0xDA4A,
- 0, 0x467A, 0xDA4B, 0x303A, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E899_x0213[] = {
- 0xF737, 0x2F68, 0xDA37, 0, 0, 0, 0xDA38, 0,
- 0, 0, 0, 0, 0, 0x6948, 0x3857, 0,
- 0x3554, 0, 0xDA39, 0xF739, 0x694A, 0x515D, 0xF73A, 0x7B4D,
- 0xDA3D, 0xDA3E, 0x3575, 0x7B4E, 0x4E3A, 0xDA3F, 0x3673, 0x694B,
- 0xDA40, 0xDA41, 0x7B50, 0xDA43, 0xDA44, 0, 0, 0x694C,
- 0, 0xDA45, 0, 0x436E, 0x7B52, 0, 0, 0xF73B,
- 0, 0x694D, 0, 0, 0, 0x7B53, 0xDA49, 0xF73C,
- 0, 0x467A, 0xF73D, 0x303A, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E89A[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xDA6D, 0, 0x3263, 0x6952, 0x6953, 0xDA4C, 0, 0,
- 0, 0xDA4D, 0, 0x694E, 0, 0x3B3D, 0xDA4E, 0,
- 0xDA4F, 0, 0xDA50, 0, 0xDA51, 0, 0, 0,
- 0, 0xDA52, 0, 0x694F, 0x4742, 0, 0xDA53, 0xDA54,
- 0xDA55, 0x6950, 0x6951, 0x695B, 0, 0xDA56, 0, 0x6955,
- 0x6958, 0xDA57, 0, 0xDA58, 0xDA59, 0xDA5A, 0x6954, 0xDA5B,
- 0xDA5C, 0xDA5D, 0, 0, 0, 0, 0, 0xDA5E,
-};
-static const unsigned short utf8_to_euc_E89A_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0xF73E,
- 0xDA6D, 0xF73F, 0x3263, 0x6952, 0x6953, 0xF740, 0, 0,
- 0, 0xF741, 0, 0x694E, 0, 0x3B3D, 0xDA4E, 0,
- 0x7B54, 0, 0xDA50, 0, 0xF742, 0xF743, 0, 0,
- 0, 0xDA52, 0, 0x694F, 0x4742, 0, 0xDA53, 0xDA54,
- 0xF744, 0x6950, 0x6951, 0x695B, 0, 0xDA56, 0, 0x6955,
- 0x6958, 0xF746, 0, 0xF747, 0xDA59, 0xDA5A, 0x6954, 0xDA5B,
- 0x7B55, 0xDA5D, 0, 0, 0, 0, 0, 0xDA5E,
-};
-static const unsigned short utf8_to_euc_E89B[] = {
- 0xDA5F, 0xDA60, 0, 0xDA61, 0x6956, 0xDA62, 0x6957, 0x3C58,
- 0, 0x6959, 0, 0x4341, 0, 0x3756, 0x3342, 0,
- 0, 0xDA63, 0xDA64, 0, 0x695C, 0xDA65, 0, 0xDA66,
- 0, 0x333F, 0xDA67, 0x6961, 0xDA68, 0, 0x695D, 0x6960,
- 0xDA69, 0, 0, 0xDA6A, 0x483A, 0xDA6B, 0, 0xDA6C,
- 0, 0x695E, 0, 0, 0x695F, 0x4948, 0x485A, 0x6962,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x427D, 0x696C, 0xDA6E, 0x6968, 0xDA6F, 0xDA70, 0x326B, 0,
-};
-static const unsigned short utf8_to_euc_E89B_x0213[] = {
- 0xDA5F, 0xF748, 0, 0xF749, 0x6956, 0xDA62, 0x6957, 0x3C58,
- 0, 0x6959, 0, 0x4341, 0, 0x3756, 0x3342, 0,
- 0, 0xF74A, 0xDA64, 0, 0x695C, 0xF74B, 0, 0xF74C,
- 0, 0x333F, 0xDA67, 0x6961, 0xDA68, 0, 0x695D, 0x6960,
- 0xDA69, 0, 0, 0xF74D, 0x483A, 0xDA6B, 0xF74E, 0xDA6C,
- 0, 0x695E, 0, 0, 0x695F, 0x4948, 0x485A, 0x6962,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x427D, 0x696C, 0x7B56, 0x6968, 0x7B57, 0x7B58, 0x326B, 0,
-};
-static const unsigned short utf8_to_euc_E89C[] = {
- 0x6966, 0, 0x4B2A, 0x6967, 0xDA71, 0xDA72, 0x6964, 0xDA73,
- 0x6965, 0x696A, 0x696D, 0xDA74, 0, 0x696B, 0xDA75, 0xDA76,
- 0xDA77, 0x6969, 0x6963, 0xDA78, 0xDA79, 0, 0, 0,
- 0x4358, 0xDA7A, 0x6974, 0, 0x4C2A, 0, 0xDA7B, 0xDA7C,
- 0, 0xDA7D, 0, 0xDA7E, 0, 0x6972, 0, 0,
- 0xDB21, 0x6973, 0, 0, 0, 0, 0xDB22, 0xDB23,
- 0, 0xDB24, 0xDB25, 0, 0x696E, 0, 0, 0x6970,
- 0, 0xDB26, 0xDB27, 0x6971, 0xDB28, 0xDB29, 0xDB2A, 0x696F,
-};
-static const unsigned short utf8_to_euc_E89C_x0213[] = {
- 0x6966, 0, 0x4B2A, 0x6967, 0xDA71, 0xF750, 0x6964, 0xF751,
- 0x6965, 0x696A, 0x696D, 0x7B59, 0, 0x696B, 0xF752, 0xDA76,
- 0xF753, 0x6969, 0x6963, 0xF754, 0xDA79, 0, 0, 0,
- 0x4358, 0xF755, 0x6974, 0, 0x4C2A, 0, 0xDA7B, 0xF756,
- 0, 0xF757, 0, 0xF758, 0, 0x6972, 0, 0,
- 0xDB21, 0x6973, 0, 0, 0, 0, 0xDB22, 0xDB23,
- 0, 0xF759, 0xDB25, 0, 0x696E, 0, 0, 0x6970,
- 0, 0xDB26, 0xF75A, 0x6971, 0xDB28, 0xDB29, 0xF75B, 0x696F,
-};
-static const unsigned short utf8_to_euc_E89D[] = {
- 0xDB2B, 0, 0, 0xDB2C, 0, 0xDB2D, 0, 0,
- 0, 0x4066, 0, 0x4F39, 0x6978, 0xDB2E, 0x6979, 0,
- 0, 0, 0, 0x6A21, 0, 0x3F2A, 0, 0x697B,
- 0xDB2F, 0x697E, 0, 0, 0, 0xDB30, 0, 0x6976,
- 0x6975, 0xDB31, 0, 0x6A22, 0xDB32, 0xDB33, 0x325C, 0,
- 0x697C, 0, 0x6A23, 0, 0, 0, 0x697D, 0xDB34,
- 0, 0xDB35, 0xDB36, 0, 0x697A, 0, 0x4433, 0,
- 0x6977, 0, 0, 0xDB37, 0, 0, 0, 0x4768,
-};
-static const unsigned short utf8_to_euc_E89D_x0213[] = {
- 0xF75C, 0, 0, 0xF75D, 0, 0xDB2D, 0, 0,
- 0, 0x4066, 0, 0x4F39, 0x6978, 0xDB2E, 0x6979, 0,
- 0, 0xF75E, 0, 0x6A21, 0, 0x3F2A, 0, 0x697B,
- 0xF75F, 0x697E, 0, 0, 0, 0xDB30, 0, 0x6976,
- 0x6975, 0xDB31, 0, 0x6A22, 0xF760, 0xF761, 0x325C, 0,
- 0x697C, 0, 0x6A23, 0, 0, 0, 0x697D, 0xDB34,
- 0, 0x7B5A, 0xF762, 0, 0x697A, 0, 0x4433, 0,
- 0x6977, 0, 0, 0xDB37, 0xF763, 0, 0, 0x4768,
-};
-static const unsigned short utf8_to_euc_E89E[] = {
- 0, 0, 0x6A27, 0xDB38, 0xDB39, 0xDB3A, 0xDB3B, 0xDB3C,
- 0xDB3D, 0xDB3E, 0, 0xDB3F, 0xDB40, 0x4D3B, 0, 0,
- 0xDB41, 0, 0, 0xDB42, 0, 0xDB43, 0, 0xDB44,
- 0xDB45, 0xDB46, 0, 0, 0, 0, 0xDB47, 0x6A26,
- 0xDB48, 0, 0x6A25, 0xDB49, 0, 0, 0, 0xDB4A,
- 0, 0, 0, 0x6A2E, 0xDB4B, 0xDB4C, 0xDB4D, 0x6A28,
- 0, 0xDB4E, 0, 0x6A30, 0, 0xDB4F, 0, 0,
- 0, 0, 0x4D66, 0x6A33, 0, 0x6A2A, 0xDB50, 0xDB51,
-};
-static const unsigned short utf8_to_euc_E89E_x0213[] = {
- 0, 0, 0x6A27, 0xDB38, 0xDB39, 0xDB3A, 0xDB3B, 0x7B5B,
- 0x7B5C, 0xF767, 0, 0xF768, 0xDB40, 0x4D3B, 0, 0,
- 0xDB41, 0, 0, 0xF769, 0, 0xDB43, 0, 0xDB44,
- 0xDB45, 0xDB46, 0, 0, 0, 0, 0xDB47, 0x6A26,
- 0xF76A, 0, 0x6A25, 0xDB49, 0, 0, 0, 0xF766,
- 0, 0, 0, 0x6A2E, 0x7B5D, 0x7B5E, 0xDB4D, 0x6A28,
- 0, 0xDB4E, 0, 0x6A30, 0, 0x7B5F, 0, 0,
- 0, 0, 0x4D66, 0x6A33, 0, 0x6A2A, 0xF76D, 0xDB51,
-};
-static const unsigned short utf8_to_euc_E89F[] = {
- 0x6A2B, 0xDB52, 0, 0, 0x6A2F, 0, 0x6A32, 0x6A31,
- 0xDB53, 0xDB54, 0xDB55, 0x6A29, 0, 0, 0xDB56, 0,
- 0x6A2C, 0, 0x6A3D, 0, 0, 0xDB57, 0xDB58, 0,
- 0, 0xDB59, 0xDB5A, 0, 0xDB5B, 0, 0, 0xDB5C,
- 0x6A36, 0, 0xDB5D, 0xDB5E, 0xDB5F, 0, 0, 0,
- 0, 0, 0xDB60, 0xDB61, 0, 0xDB62, 0, 0x6A34,
- 0, 0xDB63, 0x6A35, 0xDB64, 0, 0, 0x6A3A, 0x6A3B,
- 0xDB65, 0x332A, 0xDB66, 0x3542, 0, 0, 0x6A39, 0xDB67,
-};
-static const unsigned short utf8_to_euc_E89F_x0213[] = {
- 0x6A2B, 0xF76F, 0, 0, 0x6A2F, 0, 0x6A32, 0x6A31,
- 0xDB53, 0xDB54, 0xDB55, 0x6A29, 0, 0, 0xF770, 0,
- 0x6A2C, 0, 0x6A3D, 0, 0, 0xDB57, 0x7B61, 0,
- 0, 0xDB59, 0xDB5A, 0, 0xDB5B, 0, 0, 0xF772,
- 0x6A36, 0, 0xDB5D, 0xF774, 0xDB5F, 0xF775, 0xF776, 0,
- 0, 0, 0xF777, 0xF778, 0x7B62, 0xF779, 0, 0x6A34,
- 0, 0xDB63, 0x6A35, 0xDB64, 0, 0xF771, 0x6A3A, 0x6A3B,
- 0xDB65, 0x332A, 0xDB66, 0x3542, 0, 0, 0x6A39, 0xDB67,
-};
-static const unsigned short utf8_to_euc_E8A0[] = {
- 0, 0xDB68, 0, 0xDB69, 0, 0x6A24, 0xDB6A, 0xF464,
- 0, 0xDB6B, 0xDB6C, 0xDB6D, 0, 0x6A38, 0x6A3C, 0x6A37,
- 0xDB6E, 0x6A3E, 0xDB70, 0xDB71, 0xDB72, 0x6A40, 0x6A3F, 0,
- 0xDB73, 0xDB6F, 0xDB74, 0xDB75, 0xDB76, 0, 0xDB77, 0xDB78,
- 0, 0x6A42, 0x6A41, 0x695A, 0, 0, 0, 0x6A46,
- 0xDB79, 0, 0, 0, 0, 0xDB7A, 0xDB7B, 0,
- 0xDB7C, 0x6A43, 0xDB7D, 0, 0, 0xDB7E, 0x6A44, 0,
- 0, 0x6A45, 0xDC21, 0x6A47, 0xDC22, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E8A0_x0213[] = {
- 0, 0xF77A, 0, 0xF77B, 0, 0x6A24, 0x7B63, 0,
- 0, 0xDB6B, 0x7B64, 0xF77C, 0, 0x6A38, 0x6A3C, 0x6A37,
- 0x7B65, 0x6A3E, 0xDB70, 0xF77D, 0x7B66, 0x6A40, 0x6A3F, 0,
- 0xDB73, 0xDB6F, 0xDB74, 0xDB75, 0xDB76, 0, 0xDB77, 0x7B67,
- 0, 0x6A42, 0x6A41, 0x695A, 0, 0, 0, 0x6A46,
- 0xF77E, 0, 0, 0, 0, 0xDB7A, 0xF821, 0,
- 0xDB7C, 0x6A43, 0xF822, 0, 0, 0xDB7E, 0x6A44, 0,
- 0, 0x6A45, 0xDC21, 0x6A47, 0xF823, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E8A1[] = {
- 0x376C, 0xDC23, 0x6A49, 0xDC24, 0x6A48, 0xDC25, 0x3D30, 0,
- 0xDC26, 0xDC27, 0xDC28, 0xDC29, 0x3954, 0x5E27, 0xDC2A, 0,
- 0, 0xDC2B, 0x6A4A, 0x3D51, 0, 0xDC2C, 0xDC2D, 0x3339,
- 0xDC2E, 0x6A4B, 0xDC2F, 0x3152, 0xDC30, 0x3E57, 0x6A4C, 0xDC31,
- 0xDC32, 0x3955, 0x6A4D, 0x3061, 0xDC33, 0, 0, 0,
- 0x493D, 0xDC34, 0, 0x6A4E, 0, 0, 0, 0,
- 0x3F6A, 0xDC35, 0x6A55, 0, 0, 0x6A52, 0, 0x436F,
- 0, 0xDC36, 0, 0xDC37, 0, 0x6A53, 0x6A50, 0x365E,
-};
-static const unsigned short utf8_to_euc_E8A1_x0213[] = {
- 0x376C, 0xDC23, 0x6A49, 0xDC24, 0x6A48, 0xDC25, 0x3D30, 0,
- 0xDC26, 0xDC27, 0xF825, 0xDC29, 0x3954, 0x5E27, 0xDC2A, 0,
- 0, 0xDC2B, 0x6A4A, 0x3D51, 0, 0xDC2C, 0xDC2D, 0x3339,
- 0xF826, 0x6A4B, 0xDC2F, 0x3152, 0xDC30, 0x3E57, 0x6A4C, 0xF827,
- 0xDC32, 0x3955, 0x6A4D, 0x3061, 0xF828, 0, 0, 0,
- 0x493D, 0xF82B, 0, 0x6A4E, 0, 0, 0, 0xF82D,
- 0x3F6A, 0xDC35, 0x6A55, 0, 0, 0x6A52, 0, 0x436F,
- 0, 0xDC36, 0, 0xDC37, 0, 0x6A53, 0x6A50, 0x365E,
-};
-static const unsigned short utf8_to_euc_E8A2[] = {
- 0xDC38, 0x6A4F, 0x6A56, 0, 0, 0, 0, 0,
- 0x3736, 0, 0, 0x425E, 0, 0x6A5C, 0, 0,
- 0, 0, 0x6A58, 0, 0, 0, 0x4235, 0x6A57,
- 0xDC39, 0x6A5A, 0xDC3A, 0xDC3B, 0xDC3C, 0, 0x6A51, 0xDC3D,
- 0xDC3E, 0, 0x6A5B, 0, 0x6A5D, 0, 0, 0,
- 0xDC3F, 0, 0xDC40, 0x486F, 0, 0, 0x6A59, 0,
- 0x6A5E, 0x6A60, 0, 0, 0x3853, 0x6A54, 0, 0x3041,
- 0, 0, 0xDC41, 0, 0, 0xDC42, 0xDC43, 0x6A5F,
-};
-static const unsigned short utf8_to_euc_E8A2_x0213[] = {
- 0xDC38, 0x6A4F, 0x6A56, 0, 0, 0, 0, 0,
- 0x3736, 0, 0, 0x425E, 0, 0x6A5C, 0, 0,
- 0, 0, 0x6A58, 0, 0, 0, 0x4235, 0x6A57,
- 0x7B68, 0x6A5A, 0xDC3A, 0xDC3B, 0xDC3C, 0, 0x6A51, 0xDC3D,
- 0xF82E, 0, 0x6A5B, 0, 0x6A5D, 0, 0, 0,
- 0xDC3F, 0, 0x7B69, 0x486F, 0, 0, 0x6A59, 0,
- 0x6A5E, 0x6A60, 0, 0, 0x3853, 0x6A54, 0, 0x3041,
- 0, 0, 0xDC41, 0, 0xF82F, 0xF830, 0xF831, 0x6A5F,
-};
-static const unsigned short utf8_to_euc_E8A3[] = {
- 0xDC44, 0x3A5B, 0x4E76, 0x6A61, 0x6A62, 0x4175, 0, 0,
- 0, 0, 0xDC45, 0xDC46, 0xDC47, 0xDC48, 0xDC49, 0x4E22,
- 0, 0xDC4A, 0xDC4B, 0xDC4C, 0x6A63, 0x4D35, 0, 0,
- 0x6A64, 0x6A65, 0, 0xDC4D, 0x4A64, 0x6A66, 0xDC4E, 0x3A40,
- 0, 0x4E23, 0, 0, 0, 0, 0, 0xDC4F,
- 0x6A6B, 0, 0, 0, 0, 0, 0, 0xDC50,
- 0xDC51, 0xDC52, 0x6A6C, 0x3E58, 0x6A6A, 0xDC53, 0, 0xDC54,
- 0x4D67, 0x6A67, 0, 0, 0x6A69, 0x403D, 0x3F7E, 0,
-};
-static const unsigned short utf8_to_euc_E8A3_x0213[] = {
- 0xF832, 0x3A5B, 0x4E76, 0x6A61, 0x6A62, 0x4175, 0, 0,
- 0, 0, 0x7B6A, 0xDC46, 0xDC47, 0xDC48, 0x7B6B, 0x4E22,
- 0, 0xF835, 0xF833, 0xF836, 0x6A63, 0x4D35, 0, 0,
- 0x6A64, 0x6A65, 0, 0xF837, 0x4A64, 0x6A66, 0xDC4E, 0x3A40,
- 0, 0x4E23, 0, 0, 0, 0, 0, 0xDC4F,
- 0x6A6B, 0, 0, 0, 0, 0, 0, 0xDC50,
- 0xF838, 0xF839, 0x6A6C, 0x3E58, 0x6A6A, 0x7B6D, 0, 0xDC54,
- 0x4D67, 0x6A67, 0, 0, 0x6A69, 0x403D, 0x3F7E, 0,
-};
-static const unsigned short utf8_to_euc_E8A4[] = {
- 0, 0xDC55, 0x6A68, 0, 0x6A6D, 0, 0xDC56, 0x4A23,
- 0, 0, 0x6A6F, 0, 0x6A6E, 0xDC57, 0xDC58, 0xDC59,
- 0x336C, 0, 0x4B2B, 0x6A70, 0, 0xDC5A, 0xDC5B, 0,
- 0xDC5C, 0xDC5D, 0xDC5E, 0, 0xDC5F, 0x6A7C, 0x6A72, 0,
- 0xDC60, 0, 0, 0, 0, 0x6A73, 0xDC61, 0xDC62,
- 0xDC63, 0, 0x6A74, 0x6A75, 0, 0, 0, 0,
- 0xDC64, 0xDC65, 0xDC66, 0, 0, 0xDC67, 0x6A79, 0,
- 0x6A7A, 0xDC68, 0xDC69, 0x6A78, 0, 0, 0xDC6A, 0,
-};
-static const unsigned short utf8_to_euc_E8A4_x0213[] = {
- 0, 0xF83B, 0x6A68, 0, 0x6A6D, 0, 0xDC56, 0x4A23,
- 0, 0, 0x6A6F, 0, 0x6A6E, 0xDC57, 0xDC58, 0xDC59,
- 0x336C, 0, 0x4B2B, 0x6A70, 0, 0xDC5A, 0xDC5B, 0,
- 0x7B70, 0x7B71, 0x7B72, 0, 0x7B6E, 0x6A7C, 0x6A72, 0,
- 0xDC60, 0, 0, 0, 0, 0x6A73, 0xDC61, 0x7B73,
- 0xDC63, 0, 0x6A74, 0x6A75, 0, 0, 0, 0,
- 0x7B74, 0xDC65, 0x7B75, 0, 0, 0xDC67, 0x6A79, 0xF83D,
- 0x6A7A, 0x7B76, 0xDC69, 0x6A78, 0, 0, 0xDC6A, 0,
-};
-static const unsigned short utf8_to_euc_E8A5[] = {
- 0xDC6B, 0x6A76, 0xDC6C, 0x6A71, 0x6A77, 0xDC6D, 0xDC6E, 0,
- 0, 0xDC6F, 0, 0, 0x6A7B, 0x7037, 0, 0xDC70,
- 0, 0, 0xDC71, 0, 0, 0, 0x3228, 0xDC72,
- 0, 0, 0xDC73, 0xDC74, 0xDC75, 0, 0x6A7E, 0x365F,
- 0x6A7D, 0xDC76, 0xDC77, 0xDC78, 0x6B22, 0, 0x6B21, 0,
- 0, 0, 0x6B24, 0xDC79, 0, 0x6B23, 0xDC7A, 0x6B25,
- 0xDC7B, 0, 0x3D31, 0xDC7C, 0x6B26, 0xDC7D, 0, 0x6B27,
- 0, 0, 0xDC7E, 0xDD21, 0xDD22, 0xDD23, 0x6B28, 0x403E,
-};
-static const unsigned short utf8_to_euc_E8A5_x0213[] = {
- 0x7B77, 0x6A76, 0xF83F, 0x6A71, 0x6A77, 0xF840, 0xDC6E, 0,
- 0, 0xF841, 0, 0, 0x6A7B, 0x7037, 0, 0xDC70,
- 0, 0, 0xDC71, 0, 0, 0, 0x3228, 0xDC72,
- 0, 0, 0xDC73, 0xDC74, 0xDC75, 0, 0x6A7E, 0x365F,
- 0x6A7D, 0xDC76, 0xF844, 0xDC78, 0x6B22, 0, 0x6B21, 0,
- 0, 0, 0x6B24, 0xDC79, 0, 0x6B23, 0xDC7A, 0x6B25,
- 0xDC7B, 0, 0x3D31, 0xDC7C, 0x6B26, 0xDC7D, 0, 0x6B27,
- 0, 0, 0xDC7E, 0xDD21, 0xDD22, 0xDD23, 0x6B28, 0x403E,
-};
-static const unsigned short utf8_to_euc_E8A6[] = {
- 0, 0x4D57, 0, 0x6B29, 0, 0, 0x4A24, 0x4746,
- 0x6B2A, 0xDD24, 0x6B2B, 0x382B, 0, 0xDD25, 0, 0x352C,
- 0xDD26, 0, 0, 0x6B2C, 0xDD27, 0xDD28, 0x3B6B, 0x4741,
- 0x6B2D, 0, 0x3350, 0xDD29, 0xDD2A, 0, 0, 0xDD2B,
- 0xDD2C, 0x6B2E, 0, 0, 0, 0xDD2D, 0x6B30, 0x4D77,
- 0, 0x6B2F, 0x3F46, 0, 0x6B31, 0, 0, 0x6B32,
- 0xDD2E, 0, 0x6B33, 0x3451, 0xDD2F, 0xDD30, 0xDD31, 0xDD32,
- 0, 0, 0x6B34, 0, 0xDD33, 0x6B35, 0, 0x6B36,
-};
-static const unsigned short utf8_to_euc_E8A6_x0213[] = {
- 0xF845, 0x4D57, 0, 0x6B29, 0, 0, 0x4A24, 0x4746,
- 0x6B2A, 0xF846, 0x6B2B, 0x382B, 0, 0xDD25, 0, 0x352C,
- 0xF847, 0, 0, 0x6B2C, 0x7B78, 0xDD28, 0x3B6B, 0x4741,
- 0x6B2D, 0, 0x3350, 0xDD29, 0xDD2A, 0, 0, 0xF848,
- 0xDD2C, 0x6B2E, 0, 0, 0, 0xDD2D, 0x6B30, 0x4D77,
- 0, 0x6B2F, 0x3F46, 0, 0x6B31, 0, 0, 0x6B32,
- 0xF849, 0, 0x6B33, 0x3451, 0xDD2F, 0xDD30, 0xDD31, 0xF84A,
- 0, 0, 0x6B34, 0, 0xDD33, 0x6B35, 0, 0x6B36,
-};
-static const unsigned short utf8_to_euc_E8A7[] = {
- 0x6B37, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x3351, 0, 0xDD34, 0xDD35, 0xDD36, 0xDD37,
- 0xDD38, 0, 0x6B38, 0, 0x6B39, 0x6B3A, 0, 0,
- 0, 0, 0, 0x3272, 0, 0xDD39, 0x3F28, 0x6B3B,
- 0, 0xDD3A, 0, 0xDD3B, 0, 0xDD3C, 0, 0,
- 0, 0xDD3D, 0, 0xDD3E, 0x6B3C, 0, 0xDD3F, 0,
- 0x6B3D, 0xDD40, 0, 0, 0, 0xDD41, 0, 0xDD42,
-};
-static const unsigned short utf8_to_euc_E8A7_x0213[] = {
- 0x6B37, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0x3351, 0, 0x7B7A, 0xDD35, 0xF84B, 0xDD37,
- 0xF84C, 0, 0x6B38, 0, 0x6B39, 0x6B3A, 0, 0,
- 0, 0, 0, 0x3272, 0, 0x7B7B, 0x3F28, 0x6B3B,
- 0, 0xDD3A, 0, 0xF84D, 0, 0xDD3C, 0, 0,
- 0, 0xF84F, 0, 0xF850, 0x6B3C, 0, 0x7B7C, 0,
- 0x6B3D, 0xDD40, 0, 0, 0, 0xF851, 0, 0xF852,
-};
-static const unsigned short utf8_to_euc_E8A8[] = {
- 0x3840, 0, 0x447B, 0x6B3E, 0xDD43, 0xDD44, 0, 0xDD45,
- 0x3757, 0, 0x3F56, 0, 0x6B41, 0, 0x4624, 0xDD46,
- 0x6B40, 0xDD47, 0xDD48, 0x3731, 0xDD49, 0xDD4A, 0x6B3F, 0x4277,
- 0x352D, 0, 0, 0x6B42, 0, 0x6B43, 0xDD4B, 0x3E59,
- 0xDD4C, 0, 0xDD4D, 0x376D, 0xDD4E, 0x6B44, 0xDD4F, 0,
- 0, 0, 0x4B2C, 0xDD50, 0xDD51, 0x405F, 0, 0xDD52,
- 0, 0x3576, 0, 0x4C75, 0x414A, 0xDD53, 0x6B45, 0xDD54,
- 0, 0, 0x3F47, 0x4370, 0x3E5A, 0xDD55, 0xDD56, 0,
-};
-static const unsigned short utf8_to_euc_E8A8_x0213[] = {
- 0x3840, 0, 0x447B, 0x6B3E, 0xDD43, 0xDD44, 0, 0xDD45,
- 0x3757, 0, 0x3F56, 0, 0x6B41, 0, 0x4624, 0xDD46,
- 0x6B40, 0xF854, 0x7B7D, 0x3731, 0xF855, 0x7B7E, 0x6B3F, 0x4277,
- 0x352D, 0, 0, 0x6B42, 0, 0x6B43, 0xDD4B, 0x3E59,
- 0xDD4C, 0xF857, 0x7C21, 0x376D, 0xDD4E, 0x6B44, 0xDD4F, 0,
- 0, 0, 0x4B2C, 0xDD50, 0xDD51, 0x405F, 0, 0xDD52,
- 0, 0x3576, 0, 0x4C75, 0x414A, 0xF858, 0x6B45, 0x7C22,
- 0, 0, 0x3F47, 0x4370, 0x3E5A, 0xDD55, 0xF859, 0,
-};
-static const unsigned short utf8_to_euc_E8A9[] = {
- 0xDD57, 0x6B46, 0, 0xDD58, 0, 0xDD59, 0x6B49, 0xDD5A,
- 0x6B4A, 0xDD5B, 0, 0, 0, 0xDD5C, 0xDD5D, 0,
- 0x3A3E, 0x4242, 0x6B48, 0xDD5E, 0x3E5B, 0x493E, 0xDD5F, 0xDD60,
- 0xDD61, 0, 0, 0x6B47, 0xDD62, 0xDD63, 0x3B6C, 0,
- 0x3153, 0xDD64, 0x6B4E, 0x3758, 0, 0xDD65, 0x3B6E, 0xDD66,
- 0, 0x3B6D, 0, 0x4F4D, 0x6B4D, 0x6B4C, 0x4127, 0,
- 0x354D, 0x4F43, 0x333A, 0x3E5C, 0, 0xDD67, 0xDD68, 0xDD69,
- 0, 0xDD6A, 0xDD6B, 0xDD6C, 0x6B4B, 0, 0xDD6D, 0xDD6E,
-};
-static const unsigned short utf8_to_euc_E8A9_x0213[] = {
- 0xDD57, 0x6B46, 0, 0xDD58, 0, 0xF85A, 0x6B49, 0x7C23,
- 0x6B4A, 0xDD5B, 0, 0, 0, 0xF85B, 0x7C24, 0,
- 0x3A3E, 0x4242, 0x6B48, 0xDD5E, 0x3E5B, 0x493E, 0xDD5F, 0xDD60,
- 0xF85C, 0, 0, 0x6B47, 0xDD62, 0x7C25, 0x3B6C, 0,
- 0x3153, 0x7C26, 0x6B4E, 0x3758, 0, 0xDD65, 0x3B6E, 0xDD66,
- 0, 0x3B6D, 0, 0x4F4D, 0x6B4D, 0x6B4C, 0x4127, 0,
- 0x354D, 0x4F43, 0x333A, 0x3E5C, 0, 0x7C27, 0xDD68, 0xDD69,
- 0, 0x7C28, 0xDD6B, 0xDD6C, 0x6B4B, 0, 0xDD6D, 0xDD6E,
-};
-static const unsigned short utf8_to_euc_E8AA[] = {
- 0xDD6F, 0, 0x6B50, 0xDD70, 0x6B51, 0x6B4F, 0xDD71, 0x3858,
- 0, 0x4D40, 0, 0xDD72, 0x3B6F, 0x4727, 0, 0xDD73,
- 0xDD74, 0x6B54, 0xDD75, 0x4040, 0, 0x4342, 0xDD76, 0xDD77,
- 0x4D36, 0xDD78, 0x6B57, 0, 0, 0, 0x386C, 0xDD79,
- 0x403F, 0x6B53, 0, 0x6B58, 0x386D, 0x6B55, 0x6B56, 0xDD7A,
- 0x6B52, 0xDD7B, 0, 0, 0x4062, 0x4649, 0xDD7C, 0xDD7D,
- 0x432F, 0, 0x325D, 0xDD7E, 0, 0, 0xDE21, 0xDE22,
- 0, 0x4870, 0, 0xDE23, 0x3543, 0, 0xDE24, 0x4434,
-};
-static const unsigned short utf8_to_euc_E8AA_x0213[] = {
- 0xDD6F, 0, 0x6B50, 0xDD70, 0x6B51, 0x6B4F, 0xDD71, 0x3858,
- 0, 0x4D40, 0, 0xDD72, 0x3B6F, 0x4727, 0, 0xDD73,
- 0xF85E, 0x6B54, 0xDD75, 0x4040, 0, 0x4342, 0xDD76, 0xDD77,
- 0x4D36, 0xDD78, 0x6B57, 0, 0, 0, 0x386C, 0xDD79,
- 0x403F, 0x6B53, 0, 0x6B58, 0x386D, 0x6B55, 0x6B56, 0x7C29,
- 0x6B52, 0xDD7B, 0, 0, 0x4062, 0x4649, 0xF85D, 0xDD7D,
- 0x432F, 0, 0x325D, 0xDD7E, 0, 0, 0xDE21, 0xF85F,
- 0, 0x4870, 0, 0xDE23, 0x3543, 0, 0xF860, 0x4434,
-};
-static const unsigned short utf8_to_euc_E8AB[] = {
- 0, 0, 0x6B5B, 0xDE25, 0x6B59, 0, 0xDE26, 0x434C,
- 0xDE27, 0xDE28, 0xDE29, 0x4041, 0x3452, 0x6B5A, 0, 0x3F5B,
- 0, 0xDE2A, 0x4E4A, 0xDE2B, 0xDE2C, 0xDE2D, 0x4F40, 0xDE2E,
- 0, 0, 0x6B5C, 0x6B67, 0x4435, 0xDE2F, 0x6B66, 0xDE30,
- 0x6B63, 0x6B6B, 0x6B64, 0, 0x6B60, 0, 0x447C, 0x6B5F,
- 0, 0, 0, 0x6B5D, 0xDE31, 0x4D21, 0x3B70, 0,
- 0xDE32, 0x6B61, 0, 0x6B5E, 0xDE33, 0xDE34, 0xDE35, 0x6B65,
- 0x3D74, 0, 0x3841, 0, 0xDE36, 0, 0x427A, 0xDE37,
-};
-static const unsigned short utf8_to_euc_E8AB_x0213[] = {
- 0, 0, 0x6B5B, 0xDE25, 0x6B59, 0, 0xDE26, 0x434C,
- 0xDE27, 0xDE28, 0xDE29, 0x4041, 0x3452, 0x6B5A, 0, 0x3F5B,
- 0x7C2A, 0xDE2A, 0x4E4A, 0xDE2B, 0xDE2C, 0xDE2D, 0x4F40, 0xF861,
- 0, 0, 0x6B5C, 0x6B67, 0x4435, 0xDE2F, 0x6B66, 0x7C2B,
- 0x6B63, 0x6B6B, 0x6B64, 0, 0x6B60, 0, 0x447C, 0x6B5F,
- 0, 0, 0, 0x6B5D, 0xDE31, 0x4D21, 0x3B70, 0,
- 0xDE32, 0x6B61, 0, 0x6B5E, 0x7C2C, 0xDE34, 0x7C2D, 0x6B65,
- 0x3D74, 0, 0x3841, 0, 0xF862, 0, 0x427A, 0xDE37,
-};
-static const unsigned short utf8_to_euc_E8AC[] = {
- 0x4B45, 0x315A, 0x3062, 0, 0x4625, 0xDE38, 0xDE39, 0x6B69,
- 0, 0, 0xDE3F, 0xDE3A, 0x6B68, 0, 0x4666, 0,
- 0x6B6D, 0xDE3B, 0, 0, 0x6B62, 0, 0x6B6C, 0x6B6E,
- 0, 0x382C, 0x6B6A, 0x3956, 0xDE3C, 0x3C55, 0xDE3D, 0xDE3E,
- 0x6B6F, 0x4D58, 0, 0, 0, 0, 0x6B72, 0,
- 0x6B75, 0, 0, 0x6B73, 0x4935, 0xDE40, 0, 0,
- 0xDE41, 0, 0, 0x6B70, 0, 0, 0, 0xDE42,
- 0, 0x3660, 0, 0, 0xDE43, 0, 0x6B74, 0,
-};
-static const unsigned short utf8_to_euc_E8AC_x0213[] = {
- 0x4B45, 0x315A, 0x3062, 0, 0x4625, 0xF865, 0xDE39, 0x6B69,
- 0, 0, 0xF864, 0xDE3A, 0x6B68, 0xF866, 0x4666, 0,
- 0x6B6D, 0xDE3B, 0, 0, 0x6B62, 0, 0x6B6C, 0x6B6E,
- 0, 0x382C, 0x6B6A, 0x3956, 0xF867, 0x3C55, 0xDE3D, 0xF868,
- 0x6B6F, 0x4D58, 0, 0, 0, 0, 0x6B72, 0,
- 0x6B75, 0, 0, 0x6B73, 0x4935, 0xF869, 0, 0,
- 0xDE41, 0, 0, 0x6B70, 0, 0, 0, 0xDE42,
- 0, 0x3660, 0, 0, 0xDE43, 0, 0x6B74, 0,
-};
-static const unsigned short utf8_to_euc_E8AD[] = {
- 0, 0x6B76, 0xDE44, 0xDE45, 0xDE46, 0xDE47, 0xDE48, 0,
- 0xDE49, 0x6B7A, 0, 0, 0x6B77, 0xDE4E, 0x6B79, 0x6B78,
- 0, 0, 0xDE4A, 0xDE4B, 0xDE4C, 0, 0x6B7B, 0,
- 0x3C31, 0xDE4D, 0x6B7D, 0x6B7C, 0x4968, 0, 0xDE4F, 0x6C21,
- 0, 0, 0, 0xDE50, 0, 0, 0x3759, 0,
- 0, 0, 0, 0x6B7E, 0x6C22, 0xDE51, 0, 0x6C23,
- 0x3544, 0x6641, 0x3E79, 0, 0x6C24, 0, 0xDE52, 0x386E,
- 0xDE53, 0xDE54, 0, 0, 0xDE55, 0x6C25, 0xDE56, 0xF466,
-};
-static const unsigned short utf8_to_euc_E8AD_x0213[] = {
- 0, 0x6B76, 0xDE44, 0xF86A, 0xDE46, 0xDE47, 0x7C31, 0,
- 0xDE49, 0x6B7A, 0, 0, 0x6B77, 0xDE4E, 0x6B79, 0x6B78,
- 0, 0xF86C, 0xDE4A, 0, 0x7C32, 0, 0x6B7B, 0,
- 0x3C31, 0x7C33, 0x6B7D, 0x6B7C, 0x4968, 0, 0xF86D, 0x6C21,
- 0, 0, 0, 0xDE50, 0, 0, 0x3759, 0,
- 0, 0x7C34, 0, 0x6B7E, 0x6C22, 0xDE51, 0, 0x6C23,
- 0x3544, 0x6641, 0x3E79, 0, 0x6C24, 0, 0xF86E, 0x386E,
- 0xDE53, 0xDE54, 0, 0, 0xDE55, 0x6C25, 0xDE56, 0xF86F,
-};
-static const unsigned short utf8_to_euc_E8AE[] = {
- 0x6C26, 0xDE57, 0, 0x3B3E, 0xDE58, 0xDE59, 0, 0,
- 0, 0, 0x5A4E, 0xDE5A, 0x6C27, 0xDE5B, 0x6C28, 0xDE5C,
- 0x3D32, 0, 0x6C29, 0x6C2A, 0xDE5D, 0xDE5E, 0x6C2B, 0,
- 0, 0x6C2C, 0x6C2D, 0, 0xDE5F, 0, 0xDE60, 0xDE61,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E8AE_x0213[] = {
- 0x6C26, 0xF870, 0, 0x3B3E, 0xDE58, 0xDE59, 0, 0,
- 0, 0, 0x5A4E, 0xF871, 0x6C27, 0xDE5B, 0x6C28, 0xDE5C,
- 0x3D32, 0, 0x6C29, 0x6C2A, 0xF872, 0xF873, 0x6C2B, 0,
- 0, 0x6C2C, 0x6C2D, 0, 0xF874, 0x7C35, 0xF875, 0xDE61,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E8B0[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x432B,
- 0xDE62, 0xDE63, 0x6C2E, 0, 0, 0xDE64, 0xDE65, 0x6C30,
-};
-static const unsigned short utf8_to_euc_E8B0_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x432B,
- 0xDE62, 0xF876, 0x6C2E, 0, 0, 0xF878, 0xDE65, 0x6C30,
-};
-static const unsigned short utf8_to_euc_E8B1[] = {
- 0, 0x6C2F, 0, 0, 0, 0xDE66, 0x4626, 0xDE67,
- 0x6C31, 0xDE68, 0x4B2D, 0xDE69, 0x6C32, 0, 0x6C33, 0xDE6A,
- 0x6C34, 0xDE6B, 0, 0xDE6C, 0xDE6D, 0x6C35, 0, 0xDE6E,
- 0xDE6F, 0xDE72, 0x465A, 0xDE70, 0, 0xDE71, 0, 0,
- 0, 0x3E5D, 0x6C36, 0xDE73, 0xDE74, 0, 0xDE75, 0,
- 0xDE76, 0xDE77, 0x396B, 0x502E, 0x6C37, 0xDE78, 0, 0,
- 0, 0, 0, 0xDE79, 0, 0xDE7A, 0xDE7B, 0,
- 0x6C38, 0x493F, 0x6C39, 0xDE7C, 0x6C41, 0, 0xDE7D, 0,
-};
-static const unsigned short utf8_to_euc_E8B1_x0213[] = {
- 0, 0x6C2F, 0, 0, 0, 0xF87B, 0x4626, 0xF87C,
- 0x6C31, 0x7C36, 0x4B2D, 0xDE69, 0x6C32, 0, 0x6C33, 0xF87D,
- 0x6C34, 0xDE6B, 0, 0xDE6C, 0xF87E, 0x6C35, 0, 0xF921,
- 0xDE6F, 0xDE72, 0x465A, 0xDE70, 0, 0xDE71, 0, 0,
- 0, 0x3E5D, 0x6C36, 0xDE73, 0xDE74, 0, 0xDE75, 0,
- 0x7C37, 0xF922, 0x396B, 0x502E, 0x6C37, 0xF923, 0, 0,
- 0, 0, 0, 0xF924, 0, 0xDE7A, 0xDE7B, 0,
- 0x6C38, 0x493F, 0x6C39, 0xDE7C, 0x6C41, 0, 0xDE7D, 0,
-};
-static const unsigned short utf8_to_euc_E8B2[] = {
- 0, 0, 0x6C3A, 0, 0, 0x6C3C, 0xDE7E, 0xDF21,
- 0, 0x6C3B, 0x6C3D, 0xDF22, 0x4B46, 0x6C3E, 0x6C3F, 0,
- 0xDF23, 0, 0xDF24, 0xDF25, 0x6C40, 0, 0, 0,
- 0x6C42, 0xDF26, 0, 0xDF27, 0xDF28, 0x332D, 0x4467, 0,
- 0x4969, 0x3A62, 0x3957, 0, 0xDF29, 0, 0, 0x494F,
- 0x325F, 0x484E, 0x6C45, 0x3453, 0x4055, 0x6C44, 0x6C49, 0x4379,
- 0x4C63, 0, 0x6C47, 0x6C48, 0x352E, 0, 0x6C4A, 0x4763,
- 0x425F, 0xDF2A, 0xDF2B, 0x4871, 0x453D, 0x6C46, 0, 0x4B47,
-};
-static const unsigned short utf8_to_euc_E8B2_x0213[] = {
- 0, 0, 0x6C3A, 0, 0, 0x6C3C, 0xDE7E, 0xDF21,
- 0, 0x6C3B, 0x6C3D, 0xDF22, 0x4B46, 0x6C3E, 0x6C3F, 0,
- 0xDF23, 0, 0xF927, 0xF926, 0x6C40, 0, 0, 0,
- 0x6C42, 0xF928, 0, 0xF92A, 0xDF28, 0x332D, 0x4467, 0,
- 0x4969, 0x3A62, 0x3957, 0, 0xF92B, 0, 0, 0x494F,
- 0x325F, 0x484E, 0x6C45, 0x3453, 0x4055, 0x6C44, 0x6C49, 0x4379,
- 0x4C63, 0, 0x6C47, 0x6C48, 0x352E, 0, 0x6C4A, 0x4763,
- 0x425F, 0xDF2A, 0xDF2B, 0x4871, 0x453D, 0x6C46, 0, 0x4B47,
-};
-static const unsigned short utf8_to_euc_E8B3[] = {
- 0x326C, 0x6C4C, 0x4F28, 0x4442, 0x4F45, 0xDF2C, 0xDF2D, 0x3B71,
- 0x6C4B, 0xDF2E, 0x4231, 0xDF2F, 0, 0x6C5C, 0x4128, 0xDF30,
- 0, 0x4678, 0, 0x4950, 0, 0xDF32, 0xDF31, 0,
- 0, 0xDF33, 0x6C4F, 0x3B3F, 0x3B72, 0xDF34, 0x3E5E, 0,
- 0x4765, 0xDF35, 0x382D, 0x6C4E, 0x6C4D, 0, 0x496A, 0,
- 0xDF36, 0, 0x3C41, 0, 0xDF37, 0x4552, 0, 0xDF38,
- 0xDF39, 0, 0xDF3A, 0, 0xF467, 0xDF3B, 0, 0xDF3C,
- 0xDF3D, 0, 0x6C51, 0x6C52, 0x3958, 0x6C50, 0xDF3E, 0xDF3F,
-};
-static const unsigned short utf8_to_euc_E8B3_x0213[] = {
- 0x326C, 0x6C4C, 0x4F28, 0x4442, 0x4F45, 0xDF2C, 0xDF2D, 0x3B71,
- 0x6C4B, 0xDF2E, 0x4231, 0xDF2F, 0, 0x6C5C, 0x4128, 0xDF30,
- 0, 0x4678, 0, 0x4950, 0, 0xF92D, 0xF92C, 0,
- 0, 0xF92E, 0x6C4F, 0x3B3F, 0x3B72, 0xDF34, 0x3E5E, 0,
- 0x4765, 0x7C39, 0x382D, 0x6C4E, 0x6C4D, 0, 0x496A, 0,
- 0xDF36, 0, 0x3C41, 0, 0xDF37, 0x4552, 0, 0xDF38,
- 0xF930, 0xF931, 0xDF3A, 0, 0x7C3A, 0xDF3B, 0, 0xDF3C,
- 0x7C3B, 0, 0x6C51, 0x6C52, 0x3958, 0x6C50, 0x7C3C, 0xDF3F,
-};
-static const unsigned short utf8_to_euc_E8B4[] = {
- 0, 0xDF40, 0, 0xDF41, 0x6C53, 0x6C54, 0, 0x6C56,
- 0x4223, 0xDF42, 0x6C55, 0x3466, 0, 0x6C58, 0, 0x6C57,
- 0x6C59, 0, 0xDF43, 0x6C5B, 0x6C5D, 0, 0x6C5E, 0xDF44,
- 0, 0, 0, 0xDF45, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E8B4_x0213[] = {
- 0, 0xDF40, 0, 0xDF41, 0x6C53, 0x6C54, 0, 0x6C56,
- 0x4223, 0xF933, 0x6C55, 0x3466, 0, 0x6C58, 0xF934, 0x6C57,
- 0x6C59, 0, 0x7C3E, 0x6C5B, 0x6C5D, 0, 0x6C5E, 0xDF44,
- 0, 0, 0, 0x7C3F, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E8B5[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x4056, 0xDF46, 0x3C4F, 0x6C5F,
- 0, 0xDF47, 0, 0x3352, 0xDF48, 0x6C60, 0xDF49, 0,
- 0x4176, 0x6C61, 0, 0x6C62, 0x496B, 0, 0xF468, 0x352F,
- 0, 0, 0, 0, 0, 0, 0, 0xDF4A,
-};
-static const unsigned short utf8_to_euc_E8B5_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x4056, 0xDF46, 0x3C4F, 0x6C5F,
- 0, 0xDF47, 0, 0x3352, 0xF935, 0x6C60, 0xDF49, 0,
- 0x4176, 0x6C61, 0, 0x6C62, 0x496B, 0, 0, 0x352F,
- 0, 0, 0, 0, 0, 0, 0, 0xDF4A,
-};
-static const unsigned short utf8_to_euc_E8B6[] = {
- 0, 0x6C63, 0xDF4B, 0, 0xDF4C, 0x4436, 0, 0,
- 0xDF4D, 0, 0x315B, 0, 0, 0xDF4E, 0, 0,
- 0xDF4F, 0xDF50, 0, 0, 0, 0xDF51, 0, 0,
- 0, 0x6C64, 0, 0, 0, 0, 0xDF52, 0xDF53,
- 0xDF54, 0, 0, 0x3C71, 0, 0, 0xDF55, 0,
- 0x3F76, 0, 0, 0xDF56, 0xDF57, 0, 0, 0xDF58,
- 0, 0, 0xDF59, 0x422D, 0, 0xDF5A, 0, 0xDF5B,
- 0, 0xDF5C, 0x6C67, 0xDF5D, 0xDF6F, 0, 0x6C66, 0,
-};
-static const unsigned short utf8_to_euc_E8B6_x0213[] = {
- 0, 0x6C63, 0xDF4B, 0, 0xF936, 0x4436, 0, 0,
- 0xDF4D, 0, 0x315B, 0, 0, 0xDF4E, 0, 0,
- 0xDF4F, 0xDF50, 0, 0, 0, 0xF937, 0, 0,
- 0, 0x6C64, 0, 0, 0, 0, 0xDF52, 0xDF53,
- 0xDF54, 0, 0, 0x3C71, 0, 0, 0xF938, 0,
- 0x3F76, 0, 0, 0xDF56, 0xDF57, 0, 0, 0x7C40,
- 0, 0, 0xDF59, 0x422D, 0, 0xDF5A, 0, 0xDF5B,
- 0, 0xDF5C, 0x6C67, 0xDF5D, 0xDF6F, 0, 0x6C66, 0,
-};
-static const unsigned short utf8_to_euc_E8B7[] = {
- 0xDF5E, 0, 0x6C65, 0, 0, 0xDF5F, 0xDF60, 0xDF61,
- 0xDF62, 0, 0xDF63, 0x6C6D, 0x6C6B, 0, 0xDF64, 0x6C68,
- 0, 0xDF65, 0, 0, 0xDF66, 0xDF67, 0x6C6A, 0xDF68,
- 0, 0xDF69, 0x6C69, 0x6C6C, 0, 0x3577, 0, 0x6C70,
- 0, 0x4057, 0, 0x6C71, 0xDF6A, 0xDF6B, 0, 0xDF6C,
- 0x3859, 0, 0x6C6E, 0x6C6F, 0xDF6D, 0, 0, 0x4F29,
- 0xDF6E, 0xDF70, 0xDF71, 0x4437, 0xDF72, 0x4129, 0, 0,
- 0, 0, 0, 0, 0x6C72, 0xDF73, 0, 0x6C75,
-};
-static const unsigned short utf8_to_euc_E8B7_x0213[] = {
- 0xDF5E, 0, 0x6C65, 0, 0, 0xDF5F, 0xF93A, 0xDF61,
- 0xF93B, 0, 0xDF63, 0x6C6D, 0x6C6B, 0, 0x7C41, 0x6C68,
- 0, 0x7C42, 0, 0, 0xDF66, 0xDF67, 0x6C6A, 0x7C43,
- 0, 0xF93C, 0x6C69, 0x6C6C, 0, 0x3577, 0, 0x6C70,
- 0, 0x4057, 0, 0x6C71, 0xDF6A, 0xDF6B, 0, 0xDF6C,
- 0x3859, 0, 0x6C6E, 0x6C6F, 0xF93D, 0, 0, 0x4F29,
- 0xDF6E, 0xDF70, 0xDF71, 0x4437, 0xDF72, 0x4129, 0, 0,
- 0, 0, 0, 0, 0x6C72, 0xF940, 0, 0x6C75,
-};
-static const unsigned short utf8_to_euc_E8B8[] = {
- 0, 0xDF74, 0, 0, 0xDF75, 0xDF76, 0xDF77, 0,
- 0x6C73, 0x6C74, 0x4D59, 0xDF78, 0, 0, 0, 0x4627,
- 0x6C78, 0xDF79, 0, 0, 0xDF7A, 0, 0xDF7B, 0,
- 0, 0, 0, 0, 0, 0x6C76, 0x6C77, 0x6C79,
- 0xDF7C, 0xDF7D, 0xDF7E, 0xE021, 0, 0, 0xE022, 0xE023,
- 0, 0, 0x6D29, 0, 0, 0, 0, 0,
- 0x6C7C, 0xE024, 0, 0xE025, 0x6C7D, 0x6C7B, 0xE026, 0xE027,
- 0xE028, 0xE029, 0, 0, 0, 0xE02A, 0, 0,
-};
-static const unsigned short utf8_to_euc_E8B8_x0213[] = {
- 0, 0xDF74, 0, 0, 0xDF75, 0xDF76, 0xF941, 0,
- 0x6C73, 0x6C74, 0x4D59, 0xDF78, 0xF93E, 0, 0, 0x4627,
- 0x6C78, 0xDF79, 0, 0, 0xF943, 0, 0xF944, 0,
- 0, 0, 0, 0, 0, 0x6C76, 0x6C77, 0x6C79,
- 0x7C44, 0xF945, 0xF946, 0x7C45, 0, 0, 0xE022, 0xF947,
- 0, 0, 0x6D29, 0, 0, 0, 0, 0,
- 0x6C7C, 0xE024, 0, 0xE025, 0x6C7D, 0x6C7B, 0xF94A, 0xE027,
- 0xE028, 0xF94B, 0, 0, 0, 0x7C46, 0, 0,
-};
-static const unsigned short utf8_to_euc_E8B9[] = {
- 0xE02B, 0xE02C, 0x6C7A, 0, 0x447D, 0, 0, 0x6D21,
- 0x6D25, 0x6D22, 0x6C7E, 0xE02D, 0x6D23, 0xE02E, 0xE02F, 0xE030,
- 0x6D24, 0, 0, 0, 0xE031, 0x6D2B, 0, 0,
- 0, 0x6D26, 0, 0xE032, 0xE033, 0xE034, 0xE035, 0x4058,
- 0x6D28, 0xE036, 0xE037, 0x6D2A, 0x6D27, 0, 0, 0,
- 0, 0xE038, 0, 0, 0xE039, 0xE03A, 0, 0xE03B,
- 0xE03C, 0xE03D, 0x6D2D, 0, 0x3D33, 0, 0x6D2C, 0,
- 0, 0xE03E, 0xE03F, 0xE040, 0x6D2E, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E8B9_x0213[] = {
- 0xE02B, 0xE02C, 0x6C7A, 0, 0x447D, 0, 0, 0x6D21,
- 0x6D25, 0x6D22, 0x6C7E, 0xF94C, 0x6D23, 0xE02E, 0xE02F, 0xE030,
- 0x6D24, 0, 0, 0, 0xF94D, 0x6D2B, 0, 0,
- 0, 0x6D26, 0, 0xE032, 0xE033, 0xE034, 0xE035, 0x4058,
- 0x6D28, 0xE036, 0xF94E, 0x6D2A, 0x6D27, 0, 0, 0,
- 0, 0xE038, 0, 0, 0xF94F, 0xF950, 0, 0xF951,
- 0x7C47, 0xE03D, 0x6D2D, 0, 0x3D33, 0, 0x6D2C, 0,
- 0, 0xE03E, 0xE03F, 0x7C48, 0x6D2E, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E8BA[] = {
- 0, 0x6D2F, 0xE041, 0xE042, 0x6D32, 0x6D31, 0, 0x6D30,
- 0, 0xE043, 0x6D34, 0x6D33, 0, 0x4C76, 0, 0,
- 0xE044, 0x6D36, 0xE045, 0x6D35, 0x6D37, 0xE046, 0, 0,
- 0, 0x6D38, 0xE047, 0xE048, 0, 0xE049, 0xE04A, 0,
- 0, 0x6D3A, 0xE04B, 0, 0, 0, 0, 0xE04C,
- 0, 0xE04D, 0x6D39, 0x3F48, 0x6D3B, 0xE04E, 0xE04F, 0x366D,
- 0x6D3C, 0x6D3E, 0, 0xE050, 0, 0xE051, 0, 0,
- 0, 0, 0xE052, 0xE053, 0, 0, 0x6D3F, 0,
-};
-static const unsigned short utf8_to_euc_E8BA_x0213[] = {
- 0, 0x6D2F, 0xE041, 0xE042, 0x6D32, 0x6D31, 0, 0x6D30,
- 0, 0xE043, 0x6D34, 0x6D33, 0, 0x4C76, 0, 0,
- 0xE044, 0x6D36, 0xE045, 0x6D35, 0x6D37, 0xE046, 0, 0,
- 0xF952, 0x6D38, 0xE047, 0xE048, 0, 0xE049, 0xF953, 0,
- 0, 0x6D3A, 0xE04B, 0, 0, 0, 0, 0xE04C,
- 0, 0xE04D, 0x6D39, 0x3F48, 0x6D3B, 0xE04E, 0xF954, 0x366D,
- 0x6D3C, 0x6D3E, 0, 0xF955, 0, 0xF956, 0xF957, 0,
- 0, 0, 0xE052, 0xF958, 0, 0, 0x6D3F, 0,
-};
-static const unsigned short utf8_to_euc_E8BB[] = {
- 0xE054, 0xE055, 0, 0xE056, 0xE057, 0x6D40, 0x6D3D, 0xE058,
- 0x6D41, 0, 0x3C56, 0x6D42, 0x3530, 0x3733, 0, 0xE059,
- 0, 0xE05A, 0x382E, 0, 0xE05B, 0, 0, 0,
- 0, 0, 0, 0x6D43, 0xE05C, 0, 0, 0x4670,
- 0, 0, 0x453E, 0x6D44, 0, 0, 0, 0,
- 0xE05D, 0, 0, 0x6D47, 0, 0xE064, 0xE05E, 0,
- 0xE05F, 0xE060, 0, 0, 0, 0, 0, 0xE061,
- 0x3C34, 0xE062, 0xE063, 0x6D46, 0x6D45, 0x375A, 0x6D48, 0,
-};
-static const unsigned short utf8_to_euc_E8BB_x0213[] = {
- 0x7C4A, 0xE055, 0, 0xE056, 0xE057, 0x6D40, 0x6D3D, 0xE058,
- 0x6D41, 0, 0x3C56, 0x6D42, 0x3530, 0x3733, 0, 0,
- 0, 0xF95A, 0x382E, 0, 0xF95B, 0, 0, 0,
- 0, 0, 0, 0x6D43, 0xE05C, 0, 0, 0x4670,
- 0, 0, 0x453E, 0x6D44, 0, 0, 0, 0,
- 0xE05D, 0, 0, 0x6D47, 0, 0xE064, 0xE05E, 0,
- 0xE05F, 0xE060, 0, 0, 0, 0, 0, 0xE061,
- 0x3C34, 0xF95D, 0x7C4C, 0x6D46, 0x6D45, 0x375A, 0x6D48, 0,
-};
-static const unsigned short utf8_to_euc_E8BC[] = {
- 0xE065, 0, 0xE066, 0x3353, 0, 0x6D4A, 0, 0xE067,
- 0xE068, 0x3A5C, 0x6D49, 0, 0x6D52, 0, 0, 0xE069,
- 0xE06A, 0, 0x6D4C, 0x6D4E, 0x4A65, 0x6D4B, 0xE06B, 0xE06C,
- 0xE06D, 0x6D4D, 0, 0x6D51, 0x6D4F, 0x3531, 0xE06E, 0x6D50,
- 0xE06F, 0xE070, 0, 0xE071, 0, 0xE072, 0x6D53, 0xE073,
- 0xE074, 0x475A, 0x4E58, 0, 0xE075, 0xE076, 0xE077, 0x3D34,
- 0, 0, 0, 0x6D54, 0xE078, 0xE079, 0xE07A, 0xE07B,
- 0x4D22, 0x6D56, 0xE07C, 0x6D55, 0, 0, 0x6D59, 0x4D41,
-};
-static const unsigned short utf8_to_euc_E8BC_x0213[] = {
- 0xF95F, 0, 0xE066, 0x3353, 0, 0x6D4A, 0, 0xE067,
- 0xF960, 0x3A5C, 0x6D49, 0, 0x6D52, 0, 0, 0xE069,
- 0xE06A, 0, 0x6D4C, 0x6D4E, 0x4A65, 0x6D4B, 0xE06B, 0xF961,
- 0xE06D, 0x6D4D, 0, 0x6D51, 0x6D4F, 0x3531, 0x7C4D, 0x6D50,
- 0xE06F, 0xE070, 0, 0xE071, 0, 0xE072, 0x6D53, 0xE073,
- 0xE074, 0x475A, 0x4E58, 0xF962, 0xE075, 0x7C4E, 0xE077, 0x3D34,
- 0, 0, 0, 0x6D54, 0xE078, 0xE079, 0x7C4F, 0xE07B,
- 0x4D22, 0x6D56, 0xE07C, 0x6D55, 0, 0, 0x6D59, 0x4D41,
-};
-static const unsigned short utf8_to_euc_E8BD[] = {
- 0xE07D, 0xE07E, 0x6D58, 0xE121, 0x336D, 0x6D57, 0x6D5C, 0xE122,
- 0, 0x6D5B, 0, 0, 0x6D5A, 0x4532, 0x6D5D, 0xE123,
- 0, 0xE124, 0xE125, 0xE126, 0xE127, 0xE128, 0, 0x6D5E,
- 0xE129, 0, 0, 0, 0x6D5F, 0xE12A, 0xE12B, 0x396C,
- 0, 0x3725, 0x6D60, 0x6D61, 0x6D62, 0xE12C, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E8BD_x0213[] = {
- 0xF963, 0xE07E, 0x6D58, 0xE121, 0x336D, 0x6D57, 0x6D5C, 0xE122,
- 0, 0x6D5B, 0xF964, 0, 0x6D5A, 0x4532, 0x6D5D, 0xE123,
- 0, 0xE124, 0xE125, 0xE126, 0x7C50, 0xE128, 0, 0x6D5E,
- 0xF965, 0, 0, 0, 0x6D5F, 0xE12A, 0xE12B, 0x396C,
- 0, 0x3725, 0x6D60, 0x6D61, 0x6D62, 0xE12C, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E8BE[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x3F49, 0x6D63, 0xE12D, 0x3C2D, 0x6D64,
- 0xE12E, 0xE12F, 0, 0x6D65, 0xE130, 0xE131, 0xE132, 0x5221,
- 0x517E, 0, 0, 0, 0, 0x6D66, 0x6570, 0x6D67,
- 0x4324, 0x3F2B, 0x4740, 0, 0, 0xE133, 0xE134, 0x6D68,
- 0xE135, 0, 0x4A55, 0x4454, 0x397E, 0, 0xE136, 0x4329,
-};
-static const unsigned short utf8_to_euc_E8BE_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x3F49, 0x6D63, 0xE12D, 0x3C2D, 0x6D64,
- 0xE12E, 0xE12F, 0, 0x6D65, 0xF967, 0xE131, 0x7C52, 0x5221,
- 0x517E, 0, 0, 0, 0, 0x6D66, 0x6570, 0x6D67,
- 0x4324, 0x3F2B, 0x4740, 0, 0xF968, 0x7C53, 0xF96A, 0x6D68,
- 0xE135, 0, 0x4A55, 0x4454, 0x397E, 0, 0xE136, 0x4329,
-};
-static const unsigned short utf8_to_euc_E8BF[] = {
- 0xE137, 0xE138, 0x312A, 0, 0x4B78, 0x3F57, 0xE139, 0,
- 0, 0, 0xE13A, 0xE13B, 0, 0xE13C, 0x375E, 0,
- 0xE13D, 0x3661, 0xE13E, 0xE13F, 0x4A56, 0xE140, 0, 0,
- 0, 0, 0x6D69, 0, 0, 0, 0, 0,
- 0xE141, 0, 0x6D6B, 0xE142, 0xE143, 0x6D6A, 0x3260, 0,
- 0xE144, 0x4676, 0x6D6C, 0x4777, 0, 0x4533, 0xE145, 0x6D6D,
- 0x3D52, 0xE146, 0, 0, 0x6D6F, 0xE147, 0xE148, 0x4C42,
- 0x6D7E, 0x6D71, 0x6D72, 0xE149, 0, 0x4449, 0xE14A, 0,
-};
-static const unsigned short utf8_to_euc_E8BF_x0213[] = {
- 0xE137, 0xF96C, 0x312A, 0, 0x4B78, 0x3F57, 0xF96D, 0,
- 0, 0, 0xF96F, 0xE13B, 0, 0xF970, 0x375E, 0,
- 0xE13D, 0x3661, 0xE13E, 0xF971, 0x4A56, 0xF972, 0, 0,
- 0, 0, 0x6D69, 0, 0, 0, 0, 0,
- 0xF973, 0, 0x6D6B, 0xE142, 0x7C54, 0x6D6A, 0x3260, 0,
- 0x7C55, 0x4676, 0x6D6C, 0x4777, 0, 0x4533, 0x7C56, 0x6D6D,
- 0x3D52, 0xF974, 0, 0, 0x6D6F, 0xF975, 0xE148, 0x4C42,
- 0x6D7E, 0x6D71, 0x6D72, 0xF976, 0, 0x4449, 0xE14A, 0,
-};
-static const unsigned short utf8_to_euc_E980[] = {
- 0x4260, 0x4177, 0xE14B, 0x4628, 0xE14C, 0x6D70, 0x3555, 0,
- 0xE14D, 0, 0, 0x6D79, 0xE14E, 0x6D76, 0x6E25, 0x4629,
- 0x4360, 0x6D73, 0, 0x447E, 0x4553, 0x6D74, 0x6D78, 0x3F60,
- 0xE14F, 0x4767, 0x444C, 0xE150, 0, 0x4042, 0x6D77, 0x422E,
- 0x4224, 0x6D75, 0x3029, 0x4F22, 0, 0, 0, 0x6D7A,
- 0xE151, 0xE152, 0xE154, 0, 0xE155, 0xE156, 0x4261, 0xE153,
- 0, 0x3D35, 0x3F4A, 0xE157, 0xE158, 0x6D7C, 0x6D7B, 0xE159,
- 0x306F, 0x6D7D, 0, 0, 0x492F, 0, 0x6E27, 0xE15A,
-};
-static const unsigned short utf8_to_euc_E980_x0213[] = {
- 0x4260, 0x4177, 0xF977, 0x4628, 0xE14C, 0x6D70, 0x3555, 0,
- 0x7C57, 0, 0, 0x6D79, 0xF978, 0x6D76, 0x6E25, 0x4629,
- 0x4360, 0x6D73, 0, 0x447E, 0x4553, 0x6D74, 0x6D78, 0x3F60,
- 0xE14F, 0x4767, 0x444C, 0xE150, 0, 0x4042, 0x6D77, 0x422E,
- 0x4224, 0x6D75, 0x3029, 0x4F22, 0, 0, 0, 0x6D7A,
- 0xE151, 0xE152, 0xE154, 0, 0xE155, 0x7C58, 0x4261, 0xE153,
- 0, 0x3D35, 0x3F4A, 0xE157, 0xE158, 0x6D7C, 0x6D7B, 0xF979,
- 0x306F, 0x6D7D, 0, 0, 0x492F, 0, 0x6E27, 0xE15A,
-};
-static const unsigned short utf8_to_euc_E981[] = {
- 0, 0x465B, 0x3F6B, 0xE15B, 0xE15C, 0x4359, 0, 0x3678,
- 0, 0x6E26, 0x4D37, 0x313F, 0xE15D, 0x4A57, 0x3261, 0x6E21,
- 0x6E22, 0x6E23, 0x6E24, 0x463B, 0x4323, 0x3063, 0x6E28, 0,
- 0x6E29, 0x7423, 0, 0xE15E, 0x423D, 0xE15F, 0x6E2A, 0,
- 0x3173, 0x414C, 0xE160, 0x382F, 0, 0x4D5A, 0xE161, 0xE162,
- 0x6E2B, 0x452C, 0, 0, 0xE163, 0x4178, 0x3C57, 0x6E2C,
- 0xE164, 0, 0x6E2F, 0, 0xE165, 0x3D65, 0x6E2D, 0x412B,
- 0x412A, 0xE166, 0x3064, 0, 0x4E4B, 0x6E31, 0, 0x4872,
-};
-static const unsigned short utf8_to_euc_E981_x0213[] = {
- 0, 0x465B, 0x3F6B, 0xF97B, 0xF97C, 0x4359, 0, 0x3678,
- 0, 0x6E26, 0x4D37, 0x313F, 0xE15D, 0x4A57, 0x3261, 0x6E21,
- 0x6E22, 0x6E23, 0x6E24, 0x463B, 0x4323, 0x3063, 0x6E28, 0,
- 0x6E29, 0x7423, 0, 0xE15E, 0x423D, 0xF97D, 0x6E2A, 0,
- 0x3173, 0x414C, 0xE160, 0x382F, 0, 0x4D5A, 0xE161, 0,
- 0x6E2B, 0x452C, 0, 0, 0xE163, 0x4178, 0x3C57, 0x6E2C,
- 0xE164, 0, 0x6E2F, 0, 0xE165, 0x3D65, 0x6E2D, 0x412B,
- 0x412A, 0xE166, 0x3064, 0, 0x4E4B, 0x6E31, 0, 0x4872,
-};
-static const unsigned short utf8_to_euc_E982[] = {
- 0x6E33, 0x6E32, 0x6E30, 0x6364, 0x3454, 0xE167, 0, 0x6D6E,
- 0xE168, 0x6E35, 0x6E34, 0xE169, 0xE16A, 0, 0xE16B, 0x6E36,
- 0xE16C, 0x4D38, 0, 0, 0, 0xE16D, 0, 0xE16E,
- 0xE16F, 0xE170, 0, 0xE171, 0, 0, 0, 0,
- 0xE172, 0xE173, 0xE174, 0x4661, 0, 0xE175, 0x4B2E, 0,
- 0x6E37, 0, 0x3C59, 0, 0, 0, 0, 0x6E38,
- 0xE176, 0x6E39, 0xE177, 0xE178, 0xE179, 0x6E3A, 0xE17A, 0,
- 0x4521, 0, 0, 0, 0, 0xE17B, 0xE17D, 0,
-};
-static const unsigned short utf8_to_euc_E982_x0213[] = {
- 0x6E33, 0x6E32, 0x6E30, 0x6364, 0x3454, 0xFA22, 0, 0x6D6E,
- 0x7C5A, 0x6E35, 0x6E34, 0xE169, 0xFA23, 0, 0xE16B, 0x6E36,
- 0xFA24, 0x4D38, 0, 0, 0, 0x7C5B, 0, 0x7C5C,
- 0xE16F, 0x7C5D, 0, 0x7C5E, 0, 0, 0, 0,
- 0xE172, 0xFA26, 0x7C5F, 0x4661, 0, 0xE175, 0x4B2E, 0,
- 0x6E37, 0, 0x3C59, 0, 0, 0, 0, 0x6E38,
- 0xFA28, 0x6E39, 0xE177, 0x7C60, 0xE179, 0x6E3A, 0xFA29, 0,
- 0x4521, 0, 0, 0, 0, 0xE17B, 0x7C61, 0,
-};
-static const unsigned short utf8_to_euc_E983[] = {
- 0, 0x306A, 0, 0xE17E, 0xE221, 0xE222, 0, 0xE223,
- 0xE224, 0, 0x3959, 0, 0xE17C, 0, 0x4F3A, 0,
- 0, 0, 0xE22D, 0, 0, 0xE225, 0, 0xE226,
- 0xE227, 0xE228, 0, 0x6E3E, 0xE229, 0xE22A, 0xF46C, 0xE22B,
- 0, 0x3734, 0x6E3B, 0, 0x6E3C, 0xE22C, 0, 0,
- 0x4974, 0, 0, 0xE22F, 0, 0x3354, 0, 0xE230,
- 0xE231, 0, 0, 0, 0xE232, 0x4D39, 0xE22E, 0x363F,
- 0, 0, 0, 0, 0, 0x4554, 0xE233, 0xE234,
-};
-static const unsigned short utf8_to_euc_E983_x0213[] = {
- 0, 0x306A, 0, 0xFA2A, 0x7C62, 0x7C63, 0, 0x7C64,
- 0xFA2B, 0, 0x3959, 0, 0xE17C, 0, 0x4F3A, 0,
- 0, 0, 0xE22D, 0, 0, 0xE225, 0, 0x7C65,
- 0xE227, 0xE228, 0, 0x6E3E, 0xFA2D, 0x7C66, 0x7C67, 0xFA2E,
- 0, 0x3734, 0x6E3B, 0, 0x6E3C, 0xE22C, 0, 0,
- 0x4974, 0, 0, 0xFA33, 0, 0x3354, 0, 0x7C68,
- 0xE231, 0, 0xFA31, 0, 0x7C69, 0x4D39, 0xFA30, 0x363F,
- 0, 0, 0, 0, 0, 0x4554, 0xFA34, 0xFA35,
-};
-static const unsigned short utf8_to_euc_E984[] = {
- 0xE235, 0, 0x6E3F, 0, 0xE236, 0xE237, 0xE238, 0,
- 0xE239, 0, 0, 0, 0, 0xE23A, 0, 0,
- 0xE23B, 0, 0x6E40, 0, 0xE23C, 0xF46E, 0xE23D, 0xE23E,
- 0xE23F, 0x6E41, 0xE240, 0, 0xE241, 0, 0xE242, 0,
- 0xE243, 0, 0xE245, 0xE246, 0, 0xE244, 0, 0xE247,
- 0, 0xE248, 0, 0, 0, 0x4522, 0xE249, 0xE24A,
- 0x6E43, 0xE24B, 0x6E42, 0, 0xE24C, 0, 0xE24D, 0xE24E,
- 0, 0xE24F, 0xE250, 0, 0xE251, 0xE252, 0, 0,
-};
-static const unsigned short utf8_to_euc_E984_x0213[] = {
- 0xFA32, 0, 0x6E3F, 0, 0xFA36, 0xE237, 0xFA37, 0,
- 0xE239, 0, 0, 0, 0, 0xE23A, 0, 0,
- 0xE23B, 0, 0x6E40, 0, 0x7C6B, 0x7C6C, 0x7C6D, 0xE23E,
- 0xFA38, 0x6E41, 0xE240, 0, 0xFA39, 0, 0xFA3A, 0,
- 0xE243, 0, 0x7C6E, 0x7C6F, 0, 0xE244, 0, 0x7C70,
- 0, 0xE248, 0, 0, 0, 0x4522, 0xE249, 0x7C71,
- 0x6E43, 0x7C72, 0x6E42, 0, 0x7C73, 0, 0xE24D, 0xFA3B,
- 0, 0xFA3C, 0xFA3D, 0, 0xE251, 0x7C74, 0, 0,
-};
-static const unsigned short utf8_to_euc_E985[] = {
- 0, 0, 0, 0xE253, 0, 0, 0, 0xE254,
- 0xE255, 0x4653, 0x6E44, 0x3D36, 0x3C60, 0x475B, 0x4371, 0xE256,
- 0, 0, 0x3C72, 0xE257, 0x3F6C, 0, 0x6E45, 0xE258,
- 0x6E46, 0xE259, 0xE25A, 0xE25B, 0, 0, 0, 0,
- 0, 0xE25C, 0x3F5D, 0x6E47, 0xE25D, 0x6E48, 0, 0xE25E,
- 0, 0x6E49, 0x4D6F, 0, 0x3D37, 0xE25F, 0, 0,
- 0, 0, 0x6E4B, 0x6E4A, 0xE260, 0x395A, 0, 0x3973,
- 0x3B40, 0xE261, 0xE262, 0xE263, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E985_x0213[] = {
- 0, 0, 0, 0xE253, 0, 0, 0xFA3E, 0xFA3F,
- 0x7C75, 0x4653, 0x6E44, 0x3D36, 0x3C60, 0x475B, 0x4371, 0xE256,
- 0, 0, 0x3C72, 0xE257, 0x3F6C, 0, 0x6E45, 0xFA40,
- 0x6E46, 0xFA41, 0xE25A, 0x7C76, 0, 0, 0, 0,
- 0, 0xFA42, 0x3F5D, 0x6E47, 0xFA43, 0x6E48, 0, 0xE25E,
- 0, 0x6E49, 0x4D6F, 0, 0x3D37, 0xE25F, 0, 0,
- 0, 0, 0x6E4B, 0x6E4A, 0xFA44, 0x395A, 0, 0x3973,
- 0x3B40, 0xFA45, 0xE262, 0xE263, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E986[] = {
- 0, 0xE264, 0x6E4E, 0xE265, 0, 0xE266, 0xE267, 0x3D66,
- 0, 0x6E4D, 0xE268, 0x6E4C, 0, 0x4269, 0xE269, 0,
- 0x386F, 0xE26A, 0x4043, 0xE26B, 0xE26C, 0xE26D, 0, 0x4830,
- 0xE26E, 0, 0, 0, 0x3D39, 0, 0xE26F, 0,
- 0, 0xE270, 0x6E4F, 0, 0x3E5F, 0, 0xE271, 0,
- 0xE272, 0, 0x6E52, 0x6E50, 0xE273, 0xE274, 0xE275, 0x6E51,
- 0xE276, 0xE277, 0xE278, 0xE279, 0x6E54, 0x6E53, 0xE27A, 0,
- 0x3E7A, 0, 0x6E55, 0xE27B, 0xE27C, 0xE27D, 0, 0xE27E,
-};
-static const unsigned short utf8_to_euc_E986_x0213[] = {
- 0, 0xE264, 0x6E4E, 0x7C77, 0, 0xFA46, 0xE267, 0x3D66,
- 0, 0x6E4D, 0xE268, 0x6E4C, 0, 0x4269, 0xFA47, 0,
- 0x386F, 0xE26A, 0x4043, 0xE26B, 0xE26C, 0xE26D, 0, 0x4830,
- 0xE26E, 0, 0, 0, 0x3D39, 0, 0x7C78, 0,
- 0, 0xE270, 0x6E4F, 0, 0x3E5F, 0, 0xE271, 0,
- 0xFA48, 0, 0x6E52, 0x6E50, 0x7C79, 0xE274, 0xFA49, 0x6E51,
- 0xE276, 0x7C7A, 0xE278, 0xFA4A, 0x6E54, 0x6E53, 0xFA4B, 0,
- 0x3E7A, 0, 0x6E55, 0xE27B, 0x7C7B, 0xE27D, 0, 0xE27E,
-};
-static const unsigned short utf8_to_euc_E987[] = {
- 0x6E56, 0x6E57, 0xE321, 0xE322, 0, 0xE323, 0x4850, 0x3A53,
- 0x3C61, 0x6E58, 0, 0x6E59, 0x4E24, 0x3D45, 0x4C6E, 0x4E4C,
- 0x6E5A, 0x3662, 0, 0xE324, 0xE325, 0, 0x6E5B, 0xE326,
- 0x4523, 0xE327, 0xE328, 0x6E5E, 0x3378, 0x3F4B, 0xE329, 0x6E5C,
- 0, 0x6E5D, 0, 0x4460, 0xE32A, 0xE32B, 0x4B55, 0x367C,
- 0, 0xE32C, 0xE32D, 0, 0xE32E, 0xE32F, 0xE330, 0xE331,
- 0xE332, 0xE333, 0, 0, 0, 0x6E60, 0x6E61, 0xE334,
- 0, 0xE335, 0, 0xE336, 0x6E5F, 0xE337, 0, 0x6E63,
-};
-static const unsigned short utf8_to_euc_E987_x0213[] = {
- 0x6E56, 0x6E57, 0xE321, 0xFA4C, 0xFA4D, 0xE323, 0x4850, 0x3A53,
- 0x3C61, 0x6E58, 0, 0x6E59, 0x4E24, 0x3D45, 0x4C6E, 0x4E4C,
- 0x6E5A, 0x3662, 0, 0xE324, 0xE325, 0, 0x6E5B, 0x7C7C,
- 0x4523, 0xE327, 0xFA4E, 0x6E5E, 0x3378, 0x3F4B, 0, 0x6E5C,
- 0, 0x6E5D, 0, 0x4460, 0x7C7E, 0x7D21, 0x4B55, 0x367C,
- 0, 0xE32C, 0xE32D, 0, 0xFA51, 0x7D22, 0xFA52, 0xE331,
- 0xE332, 0x7D23, 0, 0, 0, 0x6E60, 0x6E61, 0xE334,
- 0, 0xE335, 0, 0x7C7D, 0x6E5F, 0xE337, 0, 0x6E63,
-};
-static const unsigned short utf8_to_euc_E988[] = {
- 0xE338, 0xE339, 0, 0, 0xE33A, 0xE33B, 0xE33C, 0xE33D,
- 0, 0xE33E, 0xE33F, 0, 0xE340, 0x465F, 0x3343, 0,
- 0xE341, 0x6E67, 0xE342, 0xE343, 0x6E64, 0x6E66, 0xE344, 0,
- 0xE345, 0, 0, 0, 0xE346, 0xE347, 0x6E62, 0,
- 0, 0, 0, 0xE348, 0xE349, 0xE34A, 0xE34B, 0,
- 0xE34C, 0x6F4F, 0, 0, 0x6E65, 0, 0xE34D, 0xE34E,
- 0xE34F, 0, 0, 0xE350, 0x4E6B, 0xE351, 0xE352, 0x385A,
- 0xE353, 0xE354, 0xE355, 0, 0xE356, 0, 0xE357, 0x6E6F,
-};
-static const unsigned short utf8_to_euc_E988_x0213[] = {
- 0xE338, 0xFA53, 0, 0, 0xE33A, 0xE33B, 0, 0x7D24,
- 0, 0xE33E, 0xFA54, 0, 0xE340, 0x465F, 0x3343, 0,
- 0x7D25, 0x6E67, 0xE342, 0xE343, 0x6E64, 0x6E66, 0xFA55, 0xFA56,
- 0xE345, 0, 0, 0, 0xE346, 0xE347, 0x6E62, 0,
- 0, 0, 0, 0xE348, 0xE349, 0xE34A, 0xE34B, 0,
- 0xE34C, 0x6F4F, 0, 0, 0x6E65, 0, 0xE34D, 0xE34E,
- 0xE34F, 0, 0, 0xFA58, 0x4E6B, 0xE351, 0xE352, 0x385A,
- 0x7D26, 0x7D27, 0x7D28, 0, 0x7D29, 0, 0xE357, 0x6E6F,
-};
-static const unsigned short utf8_to_euc_E989[] = {
- 0xE358, 0, 0xE359, 0xE35A, 0x4534, 0x6E6A, 0xE35B, 0xE35C,
- 0x6E6D, 0x6E6B, 0xE35D, 0x6E70, 0, 0xE35E, 0xE35F, 0xE360,
- 0x6E71, 0xE361, 0, 0, 0, 0, 0, 0x6E69,
- 0xE362, 0xE363, 0x6E76, 0x3174, 0xE364, 0xE365, 0x6E68, 0,
- 0xE366, 0xE367, 0x482D, 0, 0x6E6C, 0xE368, 0x3E60, 0xE369,
- 0xE36A, 0xE36B, 0, 0, 0, 0, 0xE36C, 0xE36D,
- 0xE36E, 0x395B, 0, 0, 0, 0xE36F, 0xE370, 0xE371,
- 0xE372, 0xE373, 0, 0xE374, 0xE375, 0xE376, 0x4B48, 0xE377,
-};
-static const unsigned short utf8_to_euc_E989_x0213[] = {
- 0x7D2A, 0, 0xFA59, 0x7D2B, 0x4534, 0x6E6A, 0xE35B, 0xFA5A,
- 0x6E6D, 0x6E6B, 0xFA5B, 0x6E70, 0, 0xE35E, 0xFA5C, 0x7D2C,
- 0x6E71, 0xFA5D, 0, 0, 0, 0, 0xFA5E, 0x6E69,
- 0xE362, 0xFA5F, 0x6E76, 0x3174, 0xE364, 0xE365, 0x6E68, 0,
- 0xFA60, 0xFA61, 0x482D, 0, 0x6E6C, 0xFA62, 0x3E60, 0xFA63,
- 0xFA64, 0xE36B, 0, 0, 0, 0, 0xE36C, 0xE36D,
- 0xE36E, 0x395B, 0, 0, 0, 0xE36F, 0xE370, 0,
- 0x7D2D, 0xE373, 0, 0xE374, 0xFA67, 0xFA68, 0x4B48, 0xFA69,
-};
-static const unsigned short utf8_to_euc_E98A[] = {
- 0x3664, 0, 0, 0x3D46, 0, 0x463C, 0, 0,
- 0xE378, 0xE379, 0xE37A, 0, 0, 0xE37B, 0xE37C, 0,
- 0, 0x412D, 0xE37D, 0x6E74, 0, 0x6E6E, 0x6E73, 0xE37E,
- 0x4C43, 0xE421, 0x4438, 0x6E75, 0x6E72, 0, 0, 0xE422,
- 0xE423, 0, 0, 0, 0xE424, 0xE425, 0, 0xE426,
- 0xE427, 0, 0, 0xE428, 0, 0x412C, 0, 0xE429,
- 0, 0, 0xE42A, 0, 0, 0, 0xE42B, 0x6E79,
- 0xE42C, 0x6E78, 0xE42D, 0xE42E, 0xE42F, 0xE430, 0, 0xE431,
-};
-static const unsigned short utf8_to_euc_E98A_x0213[] = {
- 0x3664, 0, 0, 0x3D46, 0, 0x463C, 0, 0,
- 0x7D2E, 0xFA6A, 0xE37A, 0, 0, 0xFA6B, 0xE37C, 0,
- 0, 0x412D, 0xE37D, 0x6E74, 0, 0x6E6E, 0x6E73, 0xFA6C,
- 0x4C43, 0xFA6D, 0x4438, 0x6E75, 0x6E72, 0, 0, 0xFA6E,
- 0xE423, 0, 0, 0, 0xE424, 0xE425, 0, 0xFA6F,
- 0xE427, 0, 0, 0xFA70, 0, 0x412C, 0, 0xE429,
- 0, 0, 0xFA73, 0, 0, 0, 0xE42B, 0x6E79,
- 0xE42C, 0x6E78, 0xE42D, 0xE42E, 0xE42F, 0xE430, 0, 0xFA74,
-};
-static const unsigned short utf8_to_euc_E98B[] = {
- 0xE432, 0xE433, 0xE434, 0xE435, 0, 0xE436, 0xE437, 0xE438,
- 0xE439, 0, 0, 0xE43A, 0xE43B, 0xE43C, 0xE43D, 0x6E77,
- 0xE43E, 0, 0x4B2F, 0xE43F, 0, 0xE440, 0, 0xE441,
- 0xE442, 0xE443, 0, 0, 0xE444, 0xE445, 0, 0xE446,
- 0xE447, 0xE448, 0, 0xE449, 0x3D7B, 0xE44A, 0, 0xE44B,
- 0xE44C, 0x6E7A, 0x4A5F, 0, 0xE44D, 0x3154, 0xE44E, 0,
- 0xE44F, 0, 0x4946, 0x4372, 0, 0, 0, 0,
- 0x3578, 0xE450, 0x6E7C, 0xE451, 0x395D, 0, 0, 0xE452,
-};
-static const unsigned short utf8_to_euc_E98B_x0213[] = {
- 0xFA75, 0xE433, 0x7D2F, 0xE435, 0, 0xE436, 0xFA76, 0xE438,
- 0xE439, 0, 0, 0x7D30, 0x7D31, 0xE43C, 0xFA77, 0x6E77,
- 0xFA78, 0, 0x4B2F, 0x7D32, 0, 0, 0, 0xFA79,
- 0xE442, 0xFA7A, 0, 0, 0xE444, 0xE445, 0, 0xE446,
- 0x7D33, 0xE448, 0, 0xE449, 0x3D7B, 0xFA7B, 0, 0xFA7C,
- 0xE44C, 0x6E7A, 0x4A5F, 0, 0xE44D, 0x3154, 0xE44E, 0,
- 0xE44F, 0, 0x4946, 0x4372, 0, 0, 0, 0xFB22,
- 0x3578, 0xFB23, 0x6E7C, 0xFB24, 0x395D, 0, 0, 0x7D34,
-};
-static const unsigned short utf8_to_euc_E98C[] = {
- 0xE453, 0, 0xE454, 0, 0, 0, 0x3B2C, 0,
- 0xE455, 0, 0, 0, 0, 0xE456, 0, 0x6E7B,
- 0x3F6D, 0xE457, 0, 0, 0xE458, 0xE459, 0, 0,
- 0x3F6E, 0x6F21, 0x6F23, 0, 0xE45A, 0xE45B, 0xE45C, 0xE45D,
- 0x3E7B, 0xE45E, 0x6F22, 0x6F24, 0xE45F, 0xE460, 0x3653, 0xE461,
- 0x4945, 0xE462, 0xE463, 0x3C62, 0x4F23, 0, 0x6E7E, 0x3A78,
- 0, 0, 0x4F3F, 0xE464, 0xE465, 0x6F26, 0xE466, 0xE467,
- 0, 0, 0x6F25, 0x6F27, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E98C_x0213[] = {
- 0xE453, 0, 0xFB25, 0, 0x7D35, 0, 0x3B2C, 0,
- 0xE455, 0, 0, 0, 0, 0xFB26, 0, 0x6E7B,
- 0x3F6D, 0xFA7D, 0, 0, 0xE458, 0xFB27, 0, 0,
- 0x3F6E, 0x6F21, 0x6F23, 0, 0xE45A, 0xFB28, 0xFB29, 0x7D36,
- 0x3E7B, 0x7D37, 0x6F22, 0x6F24, 0xE45F, 0x7D38, 0x3653, 0xFB2A,
- 0x4945, 0xFB2B, 0xE463, 0x3C62, 0x4F23, 0, 0x6E7E, 0x3A78,
- 0, 0, 0x4F3F, 0xE464, 0xE465, 0x6F26, 0xE466, 0xE467,
- 0, 0, 0x6F25, 0x6F27, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E98D[] = {
- 0, 0, 0, 0, 0x6E7D, 0, 0, 0xE468,
- 0xE469, 0xE46A, 0, 0x4669, 0, 0x4555, 0, 0,
- 0xE46B, 0xE46C, 0xE46D, 0, 0x4457, 0xE46E, 0x6F2C, 0xE46F,
- 0xE470, 0, 0xE471, 0x4343, 0x6F28, 0, 0xE472, 0,
- 0x6F29, 0, 0, 0, 0xE473, 0xE474, 0, 0xE475,
- 0, 0xE476, 0xE477, 0, 0x372D, 0xE478, 0x6F2B, 0xE479,
- 0xE47A, 0xE47B, 0, 0xE47C, 0xE47D, 0x3830, 0xE47E, 0,
- 0, 0, 0xE521, 0, 0x6F2A, 0xE522, 0x3E61, 0xE523,
-};
-static const unsigned short utf8_to_euc_E98D_x0213[] = {
- 0, 0, 0, 0, 0x6E7D, 0, 0, 0xFB2E,
- 0x7D39, 0x7D3A, 0x7D3B, 0x4669, 0, 0x4555, 0, 0,
- 0xE46B, 0xFB2F, 0xE46D, 0, 0x4457, 0xE46E, 0x6F2C, 0xFB30,
- 0xE470, 0, 0xFB31, 0x4343, 0x6F28, 0, 0xE472, 0,
- 0x6F29, 0, 0, 0, 0x7D3C, 0x7D3D, 0, 0xE475,
- 0, 0xE476, 0x7D3E, 0xFB32, 0x372D, 0xE478, 0x6F2B, 0xE479,
- 0x7D3F, 0xFB33, 0, 0xFB34, 0xE47D, 0x3830, 0xE47E, 0,
- 0, 0, 0xE521, 0, 0x6F2A, 0xE522, 0x3E61, 0xE523,
-};
-static const unsigned short utf8_to_euc_E98E[] = {
- 0xE524, 0xE525, 0xE526, 0, 0, 0, 0, 0,
- 0xE527, 0, 0xE528, 0xE529, 0x3379, 0xE52A, 0, 0xE52B,
- 0, 0, 0xE52C, 0, 0x6F30, 0xE52D, 0x3A3F, 0x4179,
- 0xE52E, 0, 0x444A, 0xE52F, 0, 0, 0xE530, 0,
- 0, 0xE531, 0, 0xE532, 0xE533, 0, 0xE534, 0x333B,
- 0xE535, 0xE53B, 0, 0xE536, 0x6F2E, 0x6F2F, 0x4443, 0,
- 0x6F2D, 0, 0, 0, 0xE537, 0xE538, 0xE539, 0,
- 0, 0x6F31, 0xE53A, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E98E_x0213[] = {
- 0xE524, 0xE525, 0xE526, 0, 0, 0, 0, 0,
- 0xFB38, 0, 0xE528, 0xFB39, 0x3379, 0xE52A, 0, 0xFB3A,
- 0, 0, 0xE52C, 0, 0x6F30, 0xE52D, 0x3A3F, 0x4179,
- 0xE52E, 0, 0x444A, 0x7D40, 0, 0, 0xFB3B, 0,
- 0, 0xFB35, 0, 0x7D41, 0, 0, 0xE534, 0x333B,
- 0xE535, 0xE53B, 0, 0xE536, 0x6F2E, 0x6F2F, 0x4443, 0,
- 0x6F2D, 0, 0, 0, 0xE537, 0xE538, 0xE539, 0,
- 0, 0x6F31, 0x7D42, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E98F[] = {
- 0, 0xE53C, 0, 0x6F37, 0xE53D, 0xE53E, 0xE53F, 0xE540,
- 0x6F3A, 0xE541, 0xE542, 0xE543, 0xE544, 0xE545, 0, 0,
- 0x6F39, 0x452D, 0, 0xE546, 0, 0, 0x6F32, 0x6F33,
- 0x6F36, 0xE547, 0, 0, 0xE548, 0x6F38, 0xE549, 0xE54A,
- 0, 0x3640, 0xE54B, 0, 0x6F3B, 0x6F35, 0xE54C, 0xE54D,
- 0x6F34, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xE54F,
- 0xE550, 0xE54E, 0xE551, 0xE552, 0, 0xE553, 0, 0,
-};
-static const unsigned short utf8_to_euc_E98F_x0213[] = {
- 0, 0xFB40, 0, 0x6F37, 0xE53D, 0xE53E, 0x7D43, 0xFB41,
- 0x6F3A, 0xE541, 0xE542, 0xE543, 0xE544, 0xE545, 0, 0,
- 0x6F39, 0x452D, 0, 0xE546, 0, 0, 0x6F32, 0x6F33,
- 0x6F36, 0xE547, 0, 0, 0xFB42, 0x6F38, 0x7D44, 0x7D45,
- 0, 0x3640, 0xFB43, 0, 0x6F3B, 0x6F35, 0xE54C, 0xFB44,
- 0x6F34, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFB3F, 0, 0, 0, 0xFB3C, 0, 0xE54F,
- 0, 0xE54E, 0xE551, 0xFB49, 0, 0x7D47, 0, 0,
-};
-static const unsigned short utf8_to_euc_E990[] = {
- 0, 0xE554, 0xE555, 0x6F3F, 0xE556, 0, 0, 0x6F40,
- 0xE557, 0xE558, 0, 0, 0, 0xE559, 0xE55A, 0xE55B,
- 0x6F41, 0, 0, 0x6F3E, 0x6F3D, 0xE55C, 0xE55D, 0xE55E,
- 0x3E62, 0x462A, 0x6F3C, 0, 0, 0, 0, 0xE55F,
- 0, 0x6F45, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x6F43, 0, 0, 0xE560, 0xE561,
- 0, 0xE562, 0xE563, 0xE564, 0xE565, 0x6F44, 0x6F42, 0,
- 0x4278, 0, 0x6F46, 0xE566, 0, 0xE568, 0, 0xE567,
-};
-static const unsigned short utf8_to_euc_E990_x0213[] = {
- 0, 0xE554, 0xE555, 0x6F3F, 0x7D46, 0, 0, 0x6F40,
- 0xE557, 0xFB45, 0, 0, 0, 0xE559, 0xE55A, 0xFB46,
- 0x6F41, 0, 0, 0x6F3E, 0x6F3D, 0xE55C, 0xFB47, 0xFB48,
- 0x3E62, 0x462A, 0x6F3C, 0, 0, 0, 0, 0xE55F,
- 0, 0x6F45, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x6F43, 0, 0, 0xE560, 0xE561,
- 0, 0, 0xFB4A, 0x7D48, 0xFB4B, 0x6F44, 0x6F42, 0,
- 0x4278, 0, 0x6F46, 0xFB4C, 0, 0xE568, 0, 0xE567,
-};
-static const unsigned short utf8_to_euc_E991[] = {
- 0, 0x6F47, 0, 0xE569, 0x6F49, 0xE56A, 0, 0,
- 0xE56B, 0, 0xE56C, 0, 0xE56D, 0, 0, 0,
- 0, 0x3455, 0x6F48, 0x4C7A, 0, 0xE56E, 0, 0,
- 0, 0xE56F, 0x6F54, 0x6F4A, 0xE570, 0, 0x6F4D, 0xE571,
- 0x6F4B, 0xE572, 0x6F4C, 0xE573, 0, 0, 0, 0,
- 0xE574, 0, 0x6F4E, 0xE575, 0, 0xE576, 0xE577, 0xE578,
- 0x6F50, 0xE579, 0xE57A, 0, 0, 0x6F51, 0, 0x6F52,
- 0, 0, 0, 0, 0x6F55, 0x6F53, 0x6F56, 0x6F58,
-};
-static const unsigned short utf8_to_euc_E991_x0213[] = {
- 0, 0x6F47, 0, 0xE569, 0x6F49, 0xFB4D, 0, 0,
- 0, 0, 0x7D49, 0, 0xE56D, 0, 0, 0,
- 0, 0x3455, 0x6F48, 0x4C7A, 0, 0xE56E, 0, 0,
- 0, 0xE56F, 0x6F54, 0x6F4A, 0xE570, 0, 0x6F4D, 0xE571,
- 0x6F4B, 0xE572, 0x6F4C, 0x7D4A, 0, 0, 0, 0,
- 0xE574, 0, 0x6F4E, 0x7D4B, 0, 0xFB50, 0xE577, 0xFB51,
- 0x6F50, 0x7D4C, 0x7D4D, 0, 0, 0x6F51, 0, 0x6F52,
- 0, 0, 0, 0, 0x6F55, 0x6F53, 0x6F56, 0x6F58,
-};
-static const unsigned short utf8_to_euc_E992[] = {
- 0, 0x6F57, 0, 0xE57C, 0xE57B, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E995[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x4439,
- 0xE57D, 0xE57E, 0, 0, 0, 0, 0xE621, 0,
-};
-static const unsigned short utf8_to_euc_E995_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x4439,
- 0xFB52, 0xFB53, 0, 0, 0, 0, 0xE621, 0,
-};
-static const unsigned short utf8_to_euc_E996[] = {
- 0x4C67, 0, 0x6F59, 0x412E, 0xE622, 0, 0, 0x6F5A,
- 0xE623, 0x4A44, 0x6F5B, 0x332B, 0xE624, 0xE625, 0xE626, 0x313C,
- 0, 0x3457, 0xF471, 0x3456, 0x6F5C, 0, 0x6F5D, 0,
- 0x6F5E, 0x6F5F, 0, 0, 0, 0xE627, 0xE628, 0xE629,
- 0x6F60, 0xE62A, 0x3458, 0x3355, 0x395E, 0x4836, 0xE62B, 0x6F62,
- 0x6F61, 0xE62C, 0, 0xE62D, 0xE62E, 0x6F63, 0, 0,
- 0, 0, 0x315C, 0, 0xE62F, 0, 0xE630, 0,
- 0, 0x6F66, 0xE631, 0x6F65, 0x6F64, 0xE632, 0x6F67, 0xE633,
-};
-static const unsigned short utf8_to_euc_E996_x0213[] = {
- 0x4C67, 0, 0x6F59, 0x412E, 0xE622, 0, 0xFB54, 0x6F5A,
- 0xE623, 0x4A44, 0x6F5B, 0x332B, 0xFB55, 0xFB56, 0x7D4E, 0x313C,
- 0, 0x3457, 0, 0x3456, 0x6F5C, 0, 0x6F5D, 0,
- 0x6F5E, 0x6F5F, 0, 0, 0, 0xE627, 0xE628, 0x7D4F,
- 0x6F60, 0xE62A, 0x3458, 0x3355, 0x395E, 0x4836, 0x7D50, 0x6F62,
- 0x6F61, 0x7D51, 0, 0xFB58, 0x7D52, 0x6F63, 0, 0,
- 0, 0, 0x315C, 0, 0xFB59, 0, 0x7D53, 0,
- 0, 0x6F66, 0xE631, 0x6F65, 0x6F64, 0x7D54, 0x6F67, 0xE633,
-};
-static const unsigned short utf8_to_euc_E997[] = {
- 0, 0, 0, 0x6F6A, 0, 0, 0xE634, 0x3047,
- 0xE635, 0xE636, 0x6F68, 0xE637, 0x6F6C, 0x6F6B, 0, 0,
- 0xE638, 0xE639, 0xE63A, 0xE63B, 0x6F6E, 0x6F6D, 0x6F6F, 0,
- 0x462E, 0xE63C, 0xE63D, 0, 0x6F70, 0xE63E, 0xE63F, 0xE640,
- 0xE641, 0x6F71, 0x6F73, 0, 0xE642, 0x6F72, 0xE643, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E997_x0213[] = {
- 0, 0, 0, 0x6F6A, 0, 0, 0xE634, 0x3047,
- 0xFB5B, 0xE636, 0x6F68, 0x7D55, 0x6F6C, 0x6F6B, 0, 0,
- 0x7D56, 0xE639, 0xE63A, 0x7D57, 0x6F6E, 0x6F6D, 0x6F6F, 0,
- 0x462E, 0xE63C, 0x7D59, 0, 0x6F70, 0xE63E, 0x7D5A, 0xE640,
- 0xE641, 0x6F71, 0x6F73, 0, 0xE642, 0x6F72, 0xE643, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E998[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x496C, 0xE644, 0xE645, 0,
- 0, 0x6F74, 0xE646, 0, 0xE647, 0xE648, 0xE649, 0,
- 0x6F75, 0, 0x3A65, 0, 0xE64A, 0, 0x6F76, 0x6F77,
- 0, 0xE64B, 0x4B49, 0xE64C, 0, 0, 0, 0xE64D,
- 0xE64E, 0xE64F, 0xE650, 0x414B, 0xE651, 0xE652, 0, 0x3024,
-};
-static const unsigned short utf8_to_euc_E998_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x496C, 0xFA25, 0xE645, 0,
- 0, 0x6F74, 0xE646, 0, 0xE647, 0xE648, 0xE649, 0,
- 0x6F75, 0, 0x3A65, 0, 0xFB5E, 0, 0x6F76, 0x6F77,
- 0, 0xE64B, 0x4B49, 0xFB5F, 0xFB60, 0, 0, 0xE64D,
- 0xE64E, 0xE64F, 0xE650, 0x414B, 0xFB62, 0xE652, 0, 0x3024,
-};
-static const unsigned short utf8_to_euc_E999[] = {
- 0x424B, 0xE653, 0x6F78, 0, 0x496D, 0, 0, 0,
- 0, 0, 0, 0x6F7B, 0x6F79, 0x395F, 0, 0x6F7A,
- 0x3842, 0, 0xE654, 0, 0xE655, 0, 0xE656, 0xE657,
- 0xE658, 0, 0, 0x4A45, 0x6F7D, 0x7021, 0x6F7E, 0x7022,
- 0, 0xE659, 0x3121, 0x3F58, 0x3D7C, 0x3459, 0x7023, 0,
- 0, 0, 0x4766, 0, 0x7025, 0, 0xE65A, 0,
- 0x3122, 0, 0x7024, 0x4444, 0xE65B, 0x4E4D, 0x462B, 0x6F7C,
- 0x4E26, 0, 0x3831, 0xE65C, 0xE65D, 0x4D5B, 0xE65E, 0xE65F,
-};
-static const unsigned short utf8_to_euc_E999_x0213[] = {
- 0x424B, 0xFB63, 0x6F78, 0, 0x496D, 0, 0, 0,
- 0, 0, 0, 0x6F7B, 0x6F79, 0x395F, 0, 0x6F7A,
- 0x3842, 0, 0xE654, 0, 0xE655, 0, 0xE656, 0xE657,
- 0x7D5B, 0, 0, 0x4A45, 0x6F7D, 0x7021, 0x6F7E, 0x7022,
- 0, 0xFB64, 0x3121, 0x3F58, 0x3D7C, 0x3459, 0x7023, 0,
- 0, 0, 0x4766, 0, 0x7025, 0, 0xE65A, 0,
- 0x3122, 0, 0x7024, 0x4444, 0xE65B, 0x4E4D, 0x462B, 0x6F7C,
- 0x4E26, 0, 0x3831, 0xE65C, 0xE65D, 0x4D5B, 0xE65E, 0xE65F,
-};
-static const unsigned short utf8_to_euc_E99A[] = {
- 0, 0xE660, 0xE661, 0xE662, 0xE663, 0x3679, 0x4E34, 0,
- 0x3728, 0xE664, 0x4262, 0x6721, 0, 0x7026, 0x332C, 0x3F6F,
- 0, 0xE665, 0, 0, 0x3356, 0x7028, 0xE666, 0x7029,
- 0x7027, 0x3764, 0xE667, 0x3A5D, 0x3E63, 0xE668, 0, 0xE669,
- 0x3123, 0, 0, 0x4E59, 0xE66A, 0xE66B, 0xE66C, 0x702B,
- 0x6E2E, 0xE66D, 0x702A, 0, 0, 0, 0xE66E, 0xE66F,
- 0x702E, 0x702C, 0x702D, 0xE670, 0x702F, 0, 0x7030, 0x4E6C,
- 0x7031, 0x7032, 0xE671, 0x4049, 0x483B, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E99A_x0213[] = {
- 0, 0xE660, 0xFB66, 0xE662, 0x7D5C, 0x3679, 0x4E34, 0,
- 0x3728, 0xE664, 0x4262, 0x6721, 0, 0x7026, 0x332C, 0x3F6F,
- 0, 0xE665, 0, 0, 0x3356, 0x7028, 0xE666, 0x7029,
- 0x7027, 0x3764, 0xFB68, 0x3A5D, 0x3E63, 0x7D5E, 0, 0xE669,
- 0x3123, 0, 0, 0x4E59, 0x7D5F, 0x7D60, 0xE66C, 0x702B,
- 0x6E2E, 0xFB6B, 0x702A, 0, 0, 0, 0xE66E, 0xFB6C,
- 0x702E, 0x702C, 0x702D, 0xFB6D, 0x702F, 0, 0x7030, 0x4E6C,
- 0x7031, 0x7032, 0xFB6E, 0x4049, 0x483B, 0xFB6F, 0, 0,
-};
-static const unsigned short utf8_to_euc_E99B[] = {
- 0x3F7D, 0x3467, 0, 0, 0x4D3A, 0x326D, 0x3D38, 0x385B,
- 0, 0x7035, 0xE672, 0x7034, 0x3B73, 0x7036, 0x7033, 0,
- 0, 0x3B28, 0xE673, 0, 0, 0x703A, 0x6A2D, 0,
- 0xE675, 0x5256, 0xE676, 0x3F77, 0x7038, 0xE677, 0xE678, 0xE679,
- 0, 0, 0x4E25, 0x4671, 0, 0, 0, 0,
- 0x312B, 0xE67A, 0x4063, 0x3C36, 0, 0, 0, 0xE67B,
- 0x4A37, 0xE67C, 0x3140, 0, 0, 0, 0x4E6D, 0x4D6B,
- 0, 0x703B, 0xE67D, 0x4545, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E99B_x0213[] = {
- 0x3F7D, 0x3467, 0, 0, 0x4D3A, 0x326D, 0x3D38, 0x385B,
- 0, 0x7035, 0xE672, 0x7034, 0x3B73, 0x7036, 0x7033, 0,
- 0, 0x3B28, 0x7D61, 0, 0, 0x703A, 0x6A2D, 0,
- 0xFB72, 0x5256, 0xFB73, 0x3F77, 0x7038, 0xFB74, 0x7D62, 0xE679,
- 0, 0, 0x4E25, 0x4671, 0, 0, 0, 0,
- 0x312B, 0x7D64, 0x4063, 0x3C36, 0, 0, 0, 0x7D65,
- 0x4A37, 0xE67C, 0x3140, 0, 0, 0, 0x4E6D, 0x4D6B,
- 0, 0x703B, 0xE67D, 0x4545, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E99C[] = {
- 0x3C7B, 0, 0xE67E, 0xE721, 0x703C, 0xE722, 0x703D, 0x3F4C,
- 0x703E, 0xE723, 0x4E6E, 0, 0, 0x7039, 0x7040, 0x7042,
- 0, 0x7041, 0, 0x703F, 0, 0, 0x7043, 0,
- 0, 0x7044, 0xE724, 0xE725, 0x417A, 0xE726, 0x3262, 0,
- 0, 0xE727, 0xE728, 0xE729, 0x7045, 0, 0, 0x4C38,
- 0xE72A, 0, 0x7046, 0, 0, 0, 0, 0,
- 0x7047, 0xE72B, 0x4F2A, 0xE72C, 0, 0, 0, 0,
- 0x5B31, 0x7048, 0, 0xF474, 0, 0x7049, 0x704A, 0,
-};
-static const unsigned short utf8_to_euc_E99C_x0213[] = {
- 0x3C7B, 0, 0xE67E, 0xE721, 0x703C, 0xE722, 0x703D, 0x3F4C,
- 0x703E, 0xE723, 0x4E6E, 0, 0, 0x7039, 0x7040, 0x7042,
- 0, 0x7041, 0, 0x703F, 0xFB76, 0, 0x7043, 0,
- 0, 0x7044, 0xE724, 0xE725, 0x417A, 0xE726, 0x3262, 0,
- 0, 0xE727, 0xE728, 0xFB77, 0x7045, 0, 0, 0x4C38,
- 0xE72A, 0, 0x7046, 0, 0, 0, 0, 0,
- 0x7047, 0xE72B, 0x4F2A, 0x7D66, 0, 0, 0xFB79, 0,
- 0x5B31, 0x7048, 0, 0x7D67, 0, 0x7049, 0x704A, 0,
-};
-static const unsigned short utf8_to_euc_E99D[] = {
- 0, 0xE72D, 0x704E, 0xE72E, 0x704B, 0, 0x704C, 0,
- 0x704D, 0x704F, 0xE72F, 0, 0, 0xF475, 0xE730, 0xE731,
- 0, 0xF476, 0x4044, 0, 0, 0xE732, 0x4C77, 0xE733,
- 0xE734, 0x4045, 0xE735, 0xE736, 0x7050, 0, 0x4873, 0,
- 0x7051, 0x7353, 0x4C4C, 0xE737, 0x7052, 0, 0x7053, 0xE738,
- 0x7054, 0x3357, 0xE739, 0x7056, 0, 0x3F59, 0xE73A, 0,
- 0, 0x7057, 0, 0xE73B, 0x3724, 0, 0xE73C, 0xE73D,
- 0xE73E, 0x7058, 0x705C, 0xE73F, 0x705A, 0xE740, 0, 0xE741,
-};
-static const unsigned short utf8_to_euc_E99D_x0213[] = {
- 0, 0xFB7A, 0x704E, 0, 0x704B, 0, 0x704C, 0xFB7B,
- 0x704D, 0x704F, 0xE72F, 0, 0, 0x7D68, 0x7D69, 0x7D6A,
- 0, 0, 0x4044, 0, 0, 0xFB7C, 0x4C77, 0xFB7D,
- 0xE734, 0x4045, 0x7D6B, 0xFB7E, 0x7050, 0, 0x4873, 0,
- 0x7051, 0x7353, 0x4C4C, 0xE737, 0x7052, 0, 0x7053, 0xE738,
- 0x7054, 0x3357, 0xFC21, 0x7056, 0, 0x3F59, 0x7D6C, 0,
- 0, 0x7057, 0, 0x7D6D, 0x3724, 0, 0xE73C, 0xE73D,
- 0xE73E, 0x7058, 0x705C, 0xE73F, 0x705A, 0xE740, 0, 0xE741,
-};
-static const unsigned short utf8_to_euc_E99E[] = {
- 0xE742, 0x705B, 0, 0, 0x3373, 0x7059, 0x705D, 0,
- 0, 0xE743, 0, 0x705E, 0, 0x3048, 0, 0x705F,
- 0x7060, 0, 0, 0, 0, 0xE744, 0xE745, 0xE746,
- 0x3E64, 0xE747, 0xE748, 0, 0x7061, 0, 0xE749, 0xE74A,
- 0x3547, 0, 0xE74B, 0x7064, 0, 0, 0x7063, 0,
- 0x7062, 0, 0, 0x6B71, 0xE74C, 0x4A5C, 0xE74D, 0,
- 0, 0xE74E, 0xE74F, 0x7065, 0x7066, 0xE750, 0xE751, 0,
- 0xE752, 0xE753, 0xE754, 0, 0xE755, 0, 0xE756, 0xE757,
-};
-static const unsigned short utf8_to_euc_E99E_x0213[] = {
- 0xE742, 0x705B, 0, 0, 0x3373, 0x7059, 0x705D, 0,
- 0, 0xE743, 0, 0x705E, 0, 0x3048, 0, 0x705F,
- 0x7060, 0, 0, 0, 0, 0x7D6E, 0xFC24, 0xE746,
- 0x3E64, 0xE747, 0xFC25, 0, 0x7061, 0, 0xFC26, 0xE74A,
- 0x3547, 0, 0xFC27, 0x7064, 0, 0, 0x7063, 0,
- 0x7062, 0, 0, 0x6B71, 0xE74C, 0x4A5C, 0x7D6F, 0,
- 0, 0xFC28, 0xFC29, 0x7065, 0x7066, 0xE750, 0xE751, 0,
- 0xE752, 0xE753, 0x7D70, 0, 0xE755, 0, 0xFC2A, 0xE757,
-};
-static const unsigned short utf8_to_euc_E99F[] = {
- 0, 0xE758, 0, 0x7067, 0xE759, 0xE75A, 0x7068, 0xE75B,
- 0x7069, 0xE75C, 0xE75D, 0x706A, 0xE75E, 0xE75F, 0xE760, 0,
- 0xE761, 0xE762, 0, 0x345A, 0xE763, 0, 0, 0xE764,
- 0xE765, 0xE766, 0, 0xE76A, 0x706B, 0xE767, 0xE768, 0,
- 0xE769, 0xE76B, 0, 0, 0xE76C, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x706C, 0x4723, 0xE76D,
- 0, 0xE76E, 0x706E, 0x323B, 0xE76F, 0x7071, 0x7070, 0xE770,
- 0xE771, 0, 0xE772, 0x3124, 0, 0, 0, 0x3641,
-};
-static const unsigned short utf8_to_euc_E99F_x0213[] = {
- 0, 0x7D71, 0, 0x7067, 0xE759, 0xE75A, 0x7068, 0xE75B,
- 0x7069, 0x7D72, 0xE75D, 0x706A, 0xFC2B, 0xE75F, 0xE760, 0,
- 0xE761, 0xFC2C, 0, 0x345A, 0xFC2D, 0, 0, 0xE764,
- 0xFC2E, 0xFC2F, 0, 0x7D74, 0x706B, 0xE767, 0x7D73, 0,
- 0xE769, 0xFC30, 0, 0, 0xE76C, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x706C, 0x4723, 0xE76D,
- 0, 0xFC31, 0x706E, 0x323B, 0x7D75, 0x7071, 0x7070, 0xE770,
- 0xE771, 0, 0xE772, 0x3124, 0, 0, 0, 0x3641,
-};
-static const unsigned short utf8_to_euc_E9A0[] = {
- 0, 0x4A47, 0x443A, 0x3A22, 0, 0x3960, 0x3D67, 0xE773,
- 0x3F5C, 0, 0xE774, 0, 0x7073, 0xE776, 0xE777, 0x7072,
- 0x4D42, 0x3468, 0x4852, 0x465C, 0xE778, 0, 0xE779, 0x3F7C,
- 0x4E4E, 0xE775, 0x375B, 0, 0xE77A, 0, 0xE77B, 0,
- 0xE77C, 0x7076, 0, 0xE77D, 0x7075, 0xE828, 0xE77E, 0,
- 0, 0, 0, 0xE821, 0x4B4B, 0x462C, 0xE822, 0xE823,
- 0xE824, 0, 0xE825, 0xE826, 0x3150, 0xE827, 0, 0x7077,
- 0x7074, 0, 0, 0x4951, 0x4D6A, 0x7078, 0xE829, 0,
-};
-static const unsigned short utf8_to_euc_E9A0_x0213[] = {
- 0, 0x4A47, 0x443A, 0x3A22, 0xFC32, 0x3960, 0x3D67, 0xE773,
- 0x3F5C, 0, 0x7D77, 0, 0x7073, 0xFC33, 0xFC34, 0x7072,
- 0x4D42, 0x3468, 0x4852, 0x465C, 0xFC35, 0, 0xFC36, 0x3F7C,
- 0x4E4E, 0xE775, 0x375B, 0, 0xE77A, 0, 0x7D78, 0,
- 0xE77C, 0x7076, 0, 0xFC39, 0x7075, 0xFC3C, 0xE77E, 0,
- 0, 0, 0, 0x7D79, 0x4B4B, 0x462C, 0xE822, 0xE823,
- 0x7D7A, 0, 0xFC3A, 0xFC3B, 0x3150, 0xE827, 0, 0x7077,
- 0x7074, 0, 0, 0x4951, 0x4D6A, 0x7078, 0xE829, 0,
-};
-static const unsigned short utf8_to_euc_E9A1[] = {
- 0, 0, 0, 0, 0xE82A, 0, 0x7079, 0xE82B,
- 0, 0, 0xE82C, 0x707B, 0x426A, 0x335B, 0x335C, 0x707A,
- 0, 0xE82D, 0xE82E, 0xE82F, 0x3469, 0x3832, 0xE830, 0xE831,
- 0x346A, 0xE832, 0xE833, 0x453F, 0, 0, 0x4E60, 0,
- 0, 0, 0xE834, 0xE835, 0, 0xE836, 0xE837, 0x385C,
- 0, 0, 0xE838, 0x707C, 0xE839, 0, 0, 0x707D,
- 0x707E, 0x7121, 0, 0x7123, 0x7122, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E9A1_x0213[] = {
- 0, 0, 0, 0, 0xE82A, 0, 0x7079, 0xFC3D,
- 0, 0, 0xE82C, 0x707B, 0x426A, 0x335B, 0x335C, 0x707A,
- 0, 0xE82D, 0x7D7C, 0x7D7D, 0x3469, 0x3832, 0x7D7E, 0x7E21,
- 0x346A, 0x7E22, 0x7E23, 0x453F, 0, 0, 0x4E60, 0,
- 0, 0, 0xE834, 0xE835, 0, 0x7E25, 0xFC3E, 0x385C,
- 0, 0, 0xE838, 0x707C, 0x7E26, 0, 0, 0x707D,
- 0x707E, 0x7121, 0, 0x7123, 0x7122, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E9A2[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x4977, 0, 0x7124, 0xE83A, 0, 0xE83B, 0xE83C, 0x7125,
- 0xE83D, 0x7126, 0, 0, 0xE83E, 0, 0x7127, 0xE83F,
- 0xE840, 0, 0xE841, 0xE842, 0, 0, 0, 0xE843,
-};
-static const unsigned short utf8_to_euc_E9A2_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x4977, 0, 0x7124, 0xFC3F, 0, 0xFC40, 0xE83C, 0x7125,
- 0xFC41, 0x7126, 0, 0, 0xE83E, 0, 0x7127, 0xFC43,
- 0xFC44, 0, 0x7E27, 0xFC45, 0xFC46, 0, 0, 0xFC47,
-};
-static const unsigned short utf8_to_euc_E9A3[] = {
- 0, 0, 0xE844, 0x7129, 0x7128, 0xE845, 0x712A, 0,
- 0xE846, 0, 0, 0, 0xE847, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x4874, 0x664C, 0, 0, 0x3F29,
- 0, 0xE848, 0x3532, 0xE849, 0, 0xE84A, 0xE84B, 0xE84C,
- 0, 0x712B, 0xE84D, 0x712C, 0, 0x522C, 0x5D3B, 0x4853,
- 0, 0, 0x307B, 0xE84E, 0x303B, 0, 0xE84F, 0,
- 0, 0, 0, 0, 0x3B74, 0x4B30, 0x3E7E, 0,
-};
-static const unsigned short utf8_to_euc_E9A3_x0213[] = {
- 0, 0, 0xFC48, 0x7129, 0x7128, 0xE845, 0x712A, 0xFC49,
- 0x7E28, 0, 0, 0xFC4A, 0xE847, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x4874, 0x664C, 0, 0, 0x3F29,
- 0xFC4B, 0xFC4D, 0x3532, 0xFC4E, 0, 0xFC4F, 0xE84B, 0x7E29,
- 0, 0x712B, 0xFC50, 0x712C, 0, 0x522C, 0x5D3B, 0x4853,
- 0xFC51, 0xFC52, 0x307B, 0xFC53, 0x303B, 0, 0xE84F, 0,
- 0, 0, 0, 0, 0x3B74, 0x4B30, 0x3E7E, 0,
-};
-static const unsigned short utf8_to_euc_E9A4[] = {
- 0, 0, 0xE850, 0x712D, 0, 0x4C5F, 0, 0xE851,
- 0xE852, 0x712E, 0x4D5C, 0, 0x3142, 0, 0, 0,
- 0x3B41, 0xE853, 0x712F, 0x326E, 0x7130, 0xE854, 0xE855, 0xE856,
- 0x7131, 0, 0xE857, 0xE858, 0xE859, 0x7133, 0x7134, 0xE85A,
- 0x7136, 0x7132, 0xE85B, 0, 0x7135, 0, 0xE85C, 0xE85D,
- 0x345B, 0, 0, 0xE85E, 0x7137, 0, 0x7138, 0,
- 0, 0xE85F, 0xE860, 0xE861, 0xE862, 0xE863, 0, 0,
- 0, 0xE864, 0xE865, 0xE866, 0xE867, 0x7139, 0x713A, 0,
-};
-static const unsigned short utf8_to_euc_E9A4_x0213[] = {
- 0, 0, 0xE850, 0x712D, 0, 0x4C5F, 0, 0xE851,
- 0xFC54, 0x712E, 0x4D5C, 0, 0x3142, 0, 0, 0,
- 0x3B41, 0xE853, 0x712F, 0x326E, 0x7130, 0xE854, 0xFC57, 0xFC58,
- 0x7131, 0, 0xFC5A, 0xFC5B, 0xFC5C, 0x7133, 0x7134, 0xE85A,
- 0x7136, 0x7132, 0xE85B, 0, 0x7135, 0, 0xE85C, 0,
- 0x345B, 0, 0, 0xE85E, 0x7137, 0, 0x7138, 0,
- 0, 0xFC5E, 0xFC5F, 0xFC60, 0xE862, 0xE863, 0, 0,
- 0, 0xE864, 0xFC61, 0xFC62, 0xFC63, 0x7139, 0x713A, 0,
-};
-static const unsigned short utf8_to_euc_E9A5[] = {
- 0xE868, 0xE869, 0x713B, 0, 0, 0x713D, 0xE86A, 0xE86B,
- 0xE86C, 0x713C, 0, 0x713F, 0x7142, 0xE86D, 0xE86E, 0,
- 0x713E, 0x7140, 0x7141, 0, 0xE86F, 0x7143, 0, 0x3642,
- 0xE870, 0xE871, 0, 0xE872, 0xE873, 0, 0xE874, 0xE875,
- 0xE876, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E9A5_x0213[] = {
- 0xFC64, 0xFC65, 0x713B, 0, 0, 0x713D, 0xFC66, 0xE86B,
- 0xE86C, 0x713C, 0, 0x713F, 0x7142, 0xFC67, 0xFC68, 0,
- 0x713E, 0x7140, 0x7141, 0, 0xE86F, 0x7143, 0, 0x3642,
- 0x7E2A, 0xE871, 0, 0xE872, 0xFC69, 0, 0xE874, 0xFC6A,
- 0xFC6B, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E9A6[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x3C73, 0x7144,
- 0x7145, 0x3961, 0, 0xE877, 0, 0xE878, 0xF47A, 0xE879,
- 0, 0, 0, 0, 0, 0x7146, 0xE87A, 0,
- 0x333E, 0, 0, 0, 0x474F, 0x7147, 0x7148, 0,
- 0xE87B, 0xE87C, 0xE87D, 0x435A, 0x466B, 0xE87E, 0, 0,
- 0, 0xE921, 0xE922, 0, 0x7149, 0xE923, 0, 0xE924,
-};
-static const unsigned short utf8_to_euc_E9A6_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x3C73, 0x7144,
- 0x7145, 0x3961, 0, 0xE877, 0, 0xE878, 0x7E2B, 0xE879,
- 0, 0, 0, 0xFC6C, 0, 0x7146, 0xFC6D, 0,
- 0x333E, 0, 0, 0, 0x474F, 0x7147, 0x7148, 0,
- 0xE87B, 0xE87C, 0xE87D, 0x435A, 0x466B, 0xE87E, 0, 0,
- 0, 0xFC6E, 0xE922, 0, 0x7149, 0xFC6F, 0, 0xFC70,
-};
-static const unsigned short utf8_to_euc_E9A7[] = {
- 0, 0x477D, 0, 0xE925, 0x424C, 0x3158, 0x366E, 0,
- 0x366F, 0xE926, 0, 0, 0, 0, 0, 0,
- 0x4373, 0x714E, 0x3670, 0xE927, 0xE928, 0x326F, 0, 0,
- 0x714D, 0xE929, 0xE92A, 0x714B, 0xE92B, 0x714C, 0xE92C, 0x714A,
- 0, 0, 0x7158, 0, 0, 0, 0, 0xE92D,
- 0, 0, 0xE92E, 0xE92F, 0xE930, 0x714F, 0x7150, 0,
- 0xE931, 0x7151, 0x7152, 0, 0xE932, 0xE933, 0, 0,
- 0x7154, 0xE934, 0, 0x7153, 0, 0xE935, 0xE936, 0x3D59,
-};
-static const unsigned short utf8_to_euc_E9A7_x0213[] = {
- 0, 0x477D, 0, 0xFC71, 0x424C, 0x3158, 0x366E, 0,
- 0x366F, 0xFC72, 0, 0, 0, 0, 0, 0,
- 0x4373, 0x714E, 0x3670, 0xE927, 0xFC73, 0x326F, 0, 0,
- 0x714D, 0xFC74, 0xE92A, 0x714B, 0xE92B, 0x714C, 0xFC75, 0x714A,
- 0, 0, 0x7158, 0, 0, 0, 0, 0xE92D,
- 0, 0, 0xE92E, 0xE92F, 0xE930, 0x714F, 0x7150, 0,
- 0xFC77, 0x7151, 0x7152, 0, 0xE932, 0xE933, 0, 0,
- 0x7154, 0xFC78, 0, 0x7153, 0xFC79, 0xE935, 0xE936, 0x3D59,
-};
-static const unsigned short utf8_to_euc_E9A8[] = {
- 0, 0x7155, 0xE937, 0xE938, 0xE939, 0x7157, 0, 0,
- 0, 0, 0, 0xE93A, 0xE93B, 0, 0x3533, 0x7156,
- 0xE93C, 0xE93D, 0x417B, 0x3833, 0, 0, 0xE93E, 0,
- 0, 0x7159, 0, 0, 0, 0, 0xE93F, 0,
- 0xE940, 0, 0xE941, 0xE942, 0xE943, 0, 0, 0xE944,
- 0x424D, 0, 0, 0x715A, 0, 0xE945, 0xE946, 0,
- 0x462D, 0, 0, 0xE947, 0, 0xE948, 0xE949, 0x715B,
- 0xE94A, 0, 0, 0, 0, 0, 0x7160, 0,
-};
-static const unsigned short utf8_to_euc_E9A8_x0213[] = {
- 0, 0x7155, 0x7E2C, 0x7E2D, 0xE939, 0x7157, 0, 0,
- 0, 0, 0xFC7A, 0xE93A, 0xE93B, 0, 0x3533, 0x7156,
- 0xE93C, 0xFC7B, 0x417B, 0x3833, 0, 0, 0xFC7C, 0,
- 0, 0x7159, 0xFC7D, 0, 0, 0, 0xE93F, 0,
- 0xFC7E, 0, 0xE941, 0xE942, 0x7E2E, 0, 0, 0xE944,
- 0x424D, 0, 0, 0x715A, 0, 0x7E2F, 0x7E30, 0,
- 0x462D, 0xFD21, 0, 0xE947, 0, 0xE948, 0xFD22, 0x715B,
- 0x7E31, 0, 0, 0, 0, 0, 0x7160, 0,
-};
-static const unsigned short utf8_to_euc_E9A9[] = {
- 0x715E, 0xE94C, 0x715D, 0x715F, 0xE94D, 0x715C, 0, 0xE94B,
- 0, 0, 0xE94E, 0xE94F, 0xE950, 0x7162, 0xE951, 0,
- 0, 0xE952, 0, 0, 0xE953, 0x7161, 0xE954, 0x7164,
- 0, 0, 0x3643, 0x7163, 0, 0xE955, 0, 0x7165,
- 0, 0, 0x7166, 0, 0x7168, 0x7167, 0, 0,
- 0, 0x7169, 0x716B, 0x716A, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E9A9_x0213[] = {
- 0x715E, 0xE94C, 0x715D, 0x715F, 0xFD23, 0x715C, 0, 0xE94B,
- 0, 0, 0x7E32, 0xE94F, 0xFD24, 0x7162, 0x7E33, 0,
- 0, 0xE952, 0x7E34, 0, 0xE953, 0x7161, 0xE954, 0x7164,
- 0xFD25, 0, 0x3643, 0x7163, 0, 0xE955, 0, 0x7165,
- 0, 0, 0x7166, 0, 0x7168, 0x7167, 0, 0,
- 0, 0x7169, 0x716B, 0x716A, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E9AA[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x397C, 0, 0xE956, 0, 0xE957, 0x716C, 0xE958, 0xE959,
- 0x716D, 0, 0xE95A, 0, 0xE95B, 0xE95C, 0xE95D, 0,
- 0x333C, 0xE95E, 0, 0xE95F, 0x716E, 0, 0xE960, 0xE961,
-};
-static const unsigned short utf8_to_euc_E9AA_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x397C, 0, 0xE956, 0, 0xE957, 0x716C, 0xE958, 0xFD27,
- 0x716D, 0, 0xE95A, 0, 0xE95B, 0xE95C, 0x7E35, 0xFD29,
- 0x333C, 0xFD2B, 0, 0xE95F, 0x716E, 0, 0xE960, 0xE961,
-};
-static const unsigned short utf8_to_euc_E9AB[] = {
- 0x716F, 0xE962, 0, 0xE963, 0x3F71, 0, 0xE964, 0,
- 0xE965, 0, 0, 0, 0, 0, 0xE966, 0x7170,
- 0xE967, 0x7171, 0xE968, 0x7172, 0x7173, 0xE969, 0xE96A, 0xE96B,
- 0x3962, 0xF47B, 0, 0xE96C, 0xE96D, 0, 0x7174, 0x7175,
- 0xE96E, 0, 0x7176, 0x7177, 0xE96F, 0xE970, 0x7178, 0xE971,
- 0, 0xE972, 0x4831, 0x717A, 0xE973, 0x4926, 0x717B, 0x7179,
- 0, 0x717D, 0xE974, 0xE975, 0x717C, 0xE976, 0, 0x717E,
- 0, 0xE977, 0xE978, 0x7221, 0, 0xE979, 0, 0xE97A,
-};
-static const unsigned short utf8_to_euc_E9AB_x0213[] = {
- 0x716F, 0x7E36, 0, 0x7E37, 0x3F71, 0, 0xFD2D, 0,
- 0xE965, 0, 0, 0, 0, 0, 0x7E38, 0x7170,
- 0xFD2E, 0x7171, 0xFD2F, 0x7172, 0x7173, 0xFD30, 0x7E39, 0xE96B,
- 0x3962, 0, 0, 0xE96C, 0xFD32, 0, 0x7174, 0x7175,
- 0xFD33, 0, 0x7176, 0x7177, 0xE96F, 0xFD34, 0x7178, 0xE971,
- 0, 0xFD35, 0x4831, 0x717A, 0xE973, 0x4926, 0x717B, 0x7179,
- 0, 0x717D, 0xE974, 0xE975, 0x717C, 0xE976, 0, 0x717E,
- 0, 0x7E3A, 0xE978, 0x7221, 0, 0xE979, 0, 0xE97A,
-};
-static const unsigned short utf8_to_euc_E9AC[] = {
- 0xE97B, 0xE97C, 0xE97D, 0xE97E, 0xEA21, 0xEA22, 0x7222, 0,
- 0xEA23, 0xEA24, 0, 0xEA25, 0xEA26, 0xEA27, 0xEA28, 0,
- 0xEA29, 0, 0xEA2A, 0, 0, 0, 0xEA2B, 0,
- 0x7223, 0xEA2C, 0x7224, 0xEA2D, 0xEA2E, 0, 0, 0x7225,
- 0xEA2F, 0, 0x7226, 0x7227, 0, 0x7228, 0xEA30, 0x7229,
- 0x722A, 0x722B, 0x722C, 0xEA31, 0, 0xEA32, 0x722D, 0x722E,
- 0, 0x5D35, 0x722F, 0xEA33, 0xEA34, 0xEA35, 0, 0xEA36,
- 0, 0xEA37, 0xEA38, 0x6478, 0x3534, 0xEA39, 0, 0,
-};
-static const unsigned short utf8_to_euc_E9AC_x0213[] = {
- 0xE97B, 0xE97C, 0x7E3B, 0xFD36, 0xEA21, 0xEA22, 0x7222, 0,
- 0x7E3C, 0xEA24, 0, 0xEA25, 0xFD37, 0xEA27, 0xEA28, 0,
- 0xFD38, 0, 0xFD39, 0, 0, 0, 0xFD3A, 0,
- 0x7223, 0xEA2C, 0x7224, 0xEA2D, 0xFD3B, 0, 0, 0x7225,
- 0x7E3D, 0, 0x7226, 0x7227, 0, 0x7228, 0xEA30, 0x7229,
- 0x722A, 0x722B, 0x722C, 0xFD3C, 0, 0x7E3F, 0x722D, 0x722E,
- 0, 0x5D35, 0x722F, 0xFD3D, 0xEA34, 0xEA35, 0, 0xEA36,
- 0, 0xEA37, 0xEA38, 0x6478, 0x3534, 0xFD3E, 0, 0,
-};
-static const unsigned short utf8_to_euc_E9AD[] = {
- 0, 0x3321, 0x3A32, 0x7231, 0x7230, 0x4C25, 0, 0,
- 0xEA3A, 0, 0, 0xEA3B, 0xEA3C, 0x7233, 0x7234, 0x7232,
- 0, 0x7235, 0, 0, 0x4B62, 0xEA3D, 0xEA3E, 0xEA3F,
- 0x7236, 0, 0x357B, 0xEA40, 0, 0, 0xEA41, 0,
- 0, 0xEA42, 0, 0xEA43, 0, 0xEA44, 0xEA45, 0,
- 0xEA46, 0, 0xEA47, 0xEA48, 0xEA49, 0xEA4A, 0xEA4B, 0x4F25,
- 0, 0, 0xF47C, 0xEA4C, 0x7237, 0xEA4D, 0, 0xEA4E,
- 0xEA4F, 0xEA50, 0, 0, 0, 0, 0, 0xEA51,
-};
-static const unsigned short utf8_to_euc_E9AD_x0213[] = {
- 0, 0x3321, 0x3A32, 0x7231, 0x7230, 0x4C25, 0, 0,
- 0xEA3A, 0, 0, 0xFD40, 0xEA3C, 0x7233, 0x7234, 0x7232,
- 0, 0x7235, 0, 0, 0x4B62, 0xEA3D, 0xEA3E, 0xEA3F,
- 0x7236, 0, 0x357B, 0xEA40, 0, 0, 0x7E40, 0,
- 0, 0xEA42, 0, 0xFD41, 0, 0xFD42, 0x7E42, 0,
- 0xEA46, 0, 0xEA47, 0xFD43, 0xFD44, 0xEA4A, 0xEA4B, 0x4F25,
- 0, 0, 0x7E43, 0xFD45, 0x7237, 0x7E44, 0xFD46, 0xFD47,
- 0xEA4F, 0x7E41, 0, 0, 0, 0, 0, 0xEA51,
-};
-static const unsigned short utf8_to_euc_E9AE[] = {
- 0xEA52, 0, 0, 0x7239, 0xEA53, 0xEA54, 0xEA55, 0xEA56,
- 0, 0xEA57, 0xEA58, 0xEA59, 0, 0xEA5A, 0x303E, 0xEA5B,
- 0xEA5C, 0x723A, 0x4A2B, 0x7238, 0xEA5D, 0, 0x723B, 0x723C,
- 0, 0, 0xEA5E, 0, 0, 0xEA5F, 0xEA60, 0x723D,
- 0x723E, 0, 0, 0, 0, 0, 0xEA61, 0xEA62,
- 0x723F, 0xEA63, 0x4B6E, 0x3B2D, 0xEA64, 0x3A7A, 0x412F, 0,
- 0xEA65, 0xEA66, 0xEA67, 0, 0x7240, 0, 0, 0xEA68,
- 0xEA69, 0x7243, 0, 0xEA6A, 0xEA6B, 0, 0xEA6C, 0xEA6D,
-};
-static const unsigned short utf8_to_euc_E9AE_x0213[] = {
- 0xEA52, 0, 0, 0x7239, 0x7E45, 0xEA54, 0xEA55, 0xEA56,
- 0, 0xEA57, 0x7E46, 0xEA59, 0, 0xEA5A, 0x303E, 0x7E47,
- 0xEA5C, 0x723A, 0x4A2B, 0x7238, 0xEA5D, 0, 0x723B, 0x723C,
- 0, 0, 0xEA5E, 0, 0, 0xEA5F, 0x7E48, 0x723D,
- 0x723E, 0, 0, 0, 0, 0, 0xFD48, 0x7E49,
- 0x723F, 0xEA63, 0x4B6E, 0x3B2D, 0xFD49, 0x3A7A, 0x412F, 0,
- 0xEA65, 0xFD4A, 0xFD4D, 0, 0x7240, 0, 0, 0xEA68,
- 0xFD4E, 0x7243, 0, 0, 0xEA6B, 0, 0xFD4F, 0xEA6D,
-};
-static const unsigned short utf8_to_euc_E9AF[] = {
- 0x7241, 0xEA6E, 0, 0, 0, 0, 0x7244, 0xEA6F,
- 0xEA70, 0x3871, 0x7242, 0, 0, 0, 0xEA71, 0x7245,
- 0xEA72, 0x7246, 0x7247, 0, 0x724B, 0, 0x3B2A, 0xEA73,
- 0xEA74, 0, 0, 0x4264, 0, 0xEA75, 0, 0xEA76,
- 0, 0x724C, 0x7249, 0x7248, 0x724A, 0xEA77, 0, 0xEA78,
- 0x375F, 0, 0xEA79, 0xEA7A, 0, 0, 0, 0xEA7B,
- 0x7250, 0x724F, 0x724E, 0xEA7C, 0, 0x3033, 0, 0xEA7D,
- 0xEA7E, 0xEB21, 0xEB22, 0, 0, 0xEB23, 0, 0xEB24,
-};
-static const unsigned short utf8_to_euc_E9AF_x0213[] = {
- 0x7241, 0x7E4A, 0, 0, 0, 0, 0x7244, 0xFD50,
- 0xEA70, 0x3871, 0x7242, 0, 0, 0, 0x7E4B, 0x7245,
- 0xEA72, 0x7246, 0x7247, 0, 0x724B, 0, 0x3B2A, 0xEA73,
- 0xFD52, 0, 0, 0x4264, 0, 0xFD53, 0, 0xEA76,
- 0, 0x724C, 0x7249, 0x7248, 0x724A, 0x7E4C, 0, 0xFD54,
- 0x375F, 0, 0xFD55, 0xFD56, 0, 0, 0xFD58, 0xFD57,
- 0x7250, 0x724F, 0x724E, 0xFD51, 0, 0x3033, 0, 0xFD5C,
- 0x7E4D, 0xEB21, 0xFD5A, 0, 0, 0x7E4E, 0, 0xEB24,
-};
-static const unsigned short utf8_to_euc_E9B0[] = {
- 0xEB25, 0, 0xEB26, 0, 0x725A, 0, 0x7256, 0,
- 0x7257, 0x7253, 0x7259, 0xEB27, 0x7255, 0x3362, 0, 0xEB28,
- 0x4F4C, 0xEB29, 0x7258, 0x7254, 0x7252, 0x7251, 0xEB2A, 0,
- 0xEB2B, 0xEB2C, 0xEB2D, 0x725C, 0xEB2E, 0, 0xEB2F, 0,
- 0, 0x725F, 0xEB30, 0xEB31, 0x725E, 0x725D, 0xEB32, 0xEB33,
- 0xEB34, 0xEB35, 0xEB36, 0, 0, 0x4949, 0x725B, 0x3073,
- 0x7260, 0xEB37, 0x7262, 0, 0, 0xEB38, 0xEB39, 0xEB3A,
- 0, 0x336F, 0x724D, 0x3137, 0, 0xEB3B, 0x7264, 0,
-};
-static const unsigned short utf8_to_euc_E9B0_x0213[] = {
- 0x7E4F, 0, 0xEB26, 0, 0x725A, 0, 0x7256, 0,
- 0x7257, 0x7253, 0x7259, 0xEB27, 0x7255, 0x3362, 0, 0xEB28,
- 0x4F4C, 0xEB29, 0x7258, 0x7254, 0x7252, 0x7251, 0xFD5E, 0,
- 0xFD5F, 0xFD60, 0xFD61, 0x725C, 0xEB2E, 0xFD62, 0xEB2F, 0,
- 0, 0x725F, 0xFD63, 0x7E50, 0x725E, 0x725D, 0xEB32, 0xFD64,
- 0xEB34, 0xFD65, 0xFD66, 0, 0, 0x4949, 0x725B, 0x3073,
- 0x7260, 0xFD68, 0x7262, 0, 0, 0xEB38, 0xFD69, 0xFD6A,
- 0, 0x336F, 0x724D, 0x3137, 0, 0xEB3B, 0x7264, 0,
-};
-static const unsigned short utf8_to_euc_E9B1[] = {
- 0, 0xEB3C, 0, 0xEB3D, 0xEB3E, 0xEB3F, 0x7263, 0x7261,
- 0x432D, 0xEB40, 0xEB41, 0, 0, 0, 0xEB42, 0xEB43,
- 0xEB44, 0, 0x4B70, 0xEB45, 0xEB46, 0, 0xEB47, 0x4E5A,
- 0xEB48, 0, 0x7265, 0xEB49, 0xEB50, 0xEB4A, 0xEB4B, 0xEB4C,
- 0x7266, 0, 0, 0xEB4D, 0, 0, 0, 0x7267,
- 0xEB52, 0xEB4E, 0xEB4F, 0xEB51, 0, 0, 0xEB53, 0,
- 0xEB54, 0, 0xEB55, 0, 0, 0xEB56, 0x7268, 0xEB57,
- 0x7269, 0, 0, 0xEB58, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E9B1_x0213[] = {
- 0, 0x7E51, 0, 0xEB3D, 0xEB3E, 0xFD6B, 0x7263, 0x7261,
- 0x432D, 0xFD6E, 0xFD6F, 0, 0, 0, 0xEB42, 0x7E52,
- 0x7E53, 0, 0x4B70, 0x7E54, 0xFD71, 0, 0xEB47, 0x4E5A,
- 0xFD72, 0, 0x7265, 0xFD73, 0xFD6C, 0xFD74, 0xEB4B, 0xFD75,
- 0x7266, 0, 0, 0x7E55, 0, 0x7E56, 0, 0x7267,
- 0xEB52, 0xFD76, 0xFD77, 0xFD78, 0, 0xFD79, 0xFD7A, 0,
- 0xFD7B, 0, 0xFD7C, 0, 0, 0xFD7D, 0x7268, 0x7E57,
- 0x7269, 0, 0xFD7E, 0xEB58, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E9B3[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x443B, 0xEB59, 0x726A,
- 0, 0x4837, 0, 0x726F, 0x726B, 0, 0, 0,
- 0x726C, 0, 0xEB5A, 0x4B31, 0x4C44, 0, 0x4650, 0xEB5B,
- 0, 0xEB5C, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E9B3_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x443B, 0xFE21, 0x726A,
- 0, 0x4837, 0, 0x726F, 0x726B, 0, 0, 0,
- 0x726C, 0, 0xFE22, 0x4B31, 0x4C44, 0, 0x4650, 0xEB5B,
- 0, 0xEB5C, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E9B4[] = {
- 0, 0, 0xEB5E, 0x7270, 0, 0, 0x7271, 0x463E,
- 0x726E, 0x726D, 0, 0xEB5D, 0, 0, 0x322A, 0,
- 0, 0xEB5F, 0x7279, 0, 0, 0x7278, 0, 0xEB60,
- 0xEB61, 0, 0, 0x3175, 0xEB62, 0xEB63, 0xEB64, 0x7276,
- 0, 0, 0, 0x7275, 0, 0, 0x7273, 0,
- 0x337B, 0, 0x7272, 0x3C32, 0x3229, 0, 0, 0xEB65,
- 0xEB66, 0, 0xEB67, 0xEB68, 0xEB69, 0, 0, 0,
- 0, 0, 0xEB6A, 0x3963, 0xEB6B, 0xEB6D, 0x727C, 0x727B,
-};
-static const unsigned short utf8_to_euc_E9B4_x0213[] = {
- 0, 0, 0xFE24, 0x7270, 0, 0, 0x7271, 0x463E,
- 0x726E, 0x726D, 0, 0xFE23, 0, 0, 0x322A, 0,
- 0, 0xFE26, 0x7279, 0, 0, 0x7278, 0, 0xFE27,
- 0xFE28, 0, 0, 0x3175, 0xEB62, 0x7E58, 0x7E59, 0x7276,
- 0, 0, 0, 0x7275, 0, 0, 0x7273, 0,
- 0x337B, 0, 0x7272, 0x3C32, 0x3229, 0, 0, 0xEB65,
- 0xEB66, 0, 0xFE2C, 0xEB68, 0xEB69, 0, 0, 0,
- 0, 0, 0xEB6A, 0x3963, 0xEB6B, 0xEB6D, 0x727C, 0x727B,
-};
-static const unsigned short utf8_to_euc_E9B5[] = {
- 0, 0x727A, 0xEB6E, 0xEB6F, 0x7277, 0xEB6C, 0x727D, 0xEB70,
- 0x727E, 0, 0xEB71, 0, 0, 0, 0, 0,
- 0x7325, 0x7324, 0, 0xEB72, 0xEB73, 0, 0, 0,
- 0, 0x7326, 0, 0, 0x312D, 0x7321, 0x7322, 0xEB74,
- 0x3974, 0x4C39, 0xEB76, 0xEB75, 0x7323, 0xEB77, 0, 0,
- 0, 0xEB78, 0xEB79, 0xEB7A, 0x4B32, 0, 0, 0x732B,
- 0xEB7B, 0, 0x7327, 0, 0, 0, 0xEB7C, 0xEB7D,
- 0, 0, 0x732C, 0xEB7E, 0xEC21, 0, 0xEC22, 0,
-};
-static const unsigned short utf8_to_euc_E9B5_x0213[] = {
- 0, 0x727A, 0xFE2E, 0x7E5A, 0x7277, 0xEB6C, 0x727D, 0x7E5B,
- 0x727E, 0, 0xFE2F, 0, 0, 0, 0, 0,
- 0x7325, 0x7324, 0x7E5C, 0xEB72, 0xEB73, 0, 0, 0,
- 0, 0x7326, 0, 0, 0x312D, 0x7321, 0x7322, 0xFE30,
- 0x3974, 0x4C39, 0xFE31, 0x7E5D, 0x7323, 0xEB77, 0, 0,
- 0, 0xFE33, 0xEB79, 0xFE34, 0x4B32, 0, 0, 0x732B,
- 0x7E5E, 0, 0x7327, 0xFE36, 0, 0, 0xFE37, 0xFE38,
- 0, 0, 0x732C, 0xEB7E, 0x7E5F, 0, 0xFE39, 0,
-};
-static const unsigned short utf8_to_euc_E9B6[] = {
- 0, 0, 0, 0xEC23, 0xEC24, 0, 0xEC25, 0x7329,
- 0, 0x7328, 0xEC26, 0, 0, 0xEC27, 0xEC28, 0x375C,
- 0, 0, 0xEC29, 0xEC2A, 0, 0xEC2B, 0xEC2C, 0xEC2D,
- 0xEC2E, 0, 0x732D, 0, 0, 0, 0, 0,
- 0, 0xEC2F, 0, 0, 0x732E, 0, 0, 0,
- 0, 0x732F, 0xEC30, 0x732A, 0xEC31, 0, 0xEC32, 0x7274,
- 0, 0xEC33, 0x7330, 0, 0x4461, 0xEC34, 0, 0,
- 0x7334, 0xEC35, 0x7335, 0x7333, 0xEC36, 0, 0, 0xEC37,
-};
-static const unsigned short utf8_to_euc_E9B6_x0213[] = {
- 0, 0, 0, 0xEC23, 0xFE3A, 0, 0xEC25, 0x7329,
- 0, 0x7328, 0x7E60, 0, 0, 0xFE3B, 0xEC28, 0x375C,
- 0, 0, 0xEC29, 0xEC2A, 0, 0xEC2B, 0x7E61, 0xEC2D,
- 0xEC2E, 0xFE3C, 0x732D, 0, 0, 0, 0, 0,
- 0, 0xFE3D, 0, 0, 0x732E, 0, 0, 0,
- 0, 0x732F, 0xEC30, 0x732A, 0x7E63, 0, 0xEC32, 0x7274,
- 0, 0xEC33, 0x7330, 0, 0x4461, 0xFE3F, 0, 0,
- 0x7334, 0xFE40, 0x7335, 0x7333, 0x7E64, 0xFE41, 0, 0xFE3E,
-};
-static const unsigned short utf8_to_euc_E9B7[] = {
- 0, 0x7332, 0x7338, 0xEC38, 0x7331, 0, 0x7336, 0xEC39,
- 0, 0xEC3A, 0xEC3B, 0, 0, 0, 0, 0x7337,
- 0, 0, 0, 0x733A, 0xEC3C, 0xEC3D, 0xEC3E, 0xEC3F,
- 0, 0x7339, 0xEC40, 0, 0, 0, 0xEC41, 0xEC42,
- 0xEC43, 0, 0, 0, 0, 0xEC44, 0x733C, 0xEC45,
- 0, 0xEC46, 0, 0xEC47, 0, 0x733D, 0xEC48, 0x733E,
- 0xEC49, 0, 0x4F49, 0xEC4A, 0xEC4B, 0, 0, 0,
- 0x733B, 0x426B, 0x3A6D, 0, 0, 0x733F, 0xEC4C, 0,
-};
-static const unsigned short utf8_to_euc_E9B7_x0213[] = {
- 0x7E62, 0x7332, 0x7338, 0xFE42, 0x7331, 0, 0x7336, 0xFE43,
- 0, 0xFE44, 0xEC3B, 0, 0, 0, 0, 0x7337,
- 0, 0, 0, 0x733A, 0xEC3C, 0xEC3D, 0xFE45, 0x7E65,
- 0, 0x7339, 0xFE46, 0, 0, 0, 0xEC41, 0xFE47,
- 0xFE48, 0, 0, 0xFE49, 0, 0xEC44, 0x733C, 0x7E67,
- 0, 0xEC46, 0, 0xEC47, 0, 0x733D, 0xEC48, 0x733E,
- 0xEC49, 0, 0x4F49, 0xEC4A, 0xFE4A, 0, 0, 0,
- 0x733B, 0x426B, 0x3A6D, 0, 0, 0x733F, 0xEC4C, 0,
-};
-static const unsigned short utf8_to_euc_E9B8[] = {
- 0, 0, 0xEC4E, 0, 0, 0, 0, 0xEC4F,
- 0, 0, 0xEC4D, 0, 0, 0, 0xEC50, 0,
- 0xEC51, 0xEC52, 0xEC53, 0, 0, 0xEC54, 0xEC55, 0,
- 0, 0xEC56, 0x7340, 0x7341, 0xEC57, 0xEC58, 0x7342, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E9B8_x0213[] = {
- 0, 0, 0xFE4D, 0, 0, 0, 0, 0x7E68,
- 0, 0, 0xFE4C, 0, 0, 0xFE4E, 0xEC50, 0,
- 0xEC51, 0xEC52, 0xEC53, 0, 0, 0x7E69, 0xEC55, 0,
- 0, 0xFE4F, 0x7340, 0x7341, 0xFE50, 0xFE51, 0x7342, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E9B9[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x7343, 0, 0,
- 0x3834, 0x7344, 0xEC59, 0xEC5A, 0xEC5B, 0x7345, 0, 0x3C2F,
-};
-static const unsigned short utf8_to_euc_E9B9_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x7343, 0, 0,
- 0x3834, 0x7344, 0xEC59, 0xFE52, 0x7E6A, 0x7345, 0, 0x3C2F,
-};
-static const unsigned short utf8_to_euc_E9BA[] = {
- 0xEC5C, 0x7346, 0xEC5D, 0xEC5E, 0xEC5F, 0xEC60, 0, 0xEC61,
- 0x7347, 0, 0, 0x7348, 0x7349, 0, 0xEC62, 0xEC63,
- 0, 0x734C, 0x734A, 0x4F3C, 0, 0x734B, 0xEC64, 0x4E6F,
- 0xEC65, 0, 0, 0xEC66, 0, 0x734D, 0xEC67, 0x4E5B,
- 0, 0, 0, 0, 0xEC68, 0x734E, 0x477E, 0,
- 0xEC69, 0x734F, 0x7351, 0, 0xEC6A, 0x7352, 0xEC6B, 0xEC6C,
- 0xEC6D, 0, 0, 0xEC6E, 0xEC6F, 0xEC70, 0, 0,
- 0x7350, 0x396D, 0x4C4D, 0x4B63, 0x5677, 0, 0x5D60, 0x4B7B,
-};
-static const unsigned short utf8_to_euc_E9BA_x0213[] = {
- 0xFE54, 0x7346, 0xEC5D, 0xEC5E, 0xEC5F, 0xFE55, 0, 0xEC61,
- 0x7347, 0, 0, 0x7348, 0x7349, 0, 0xEC62, 0xEC63,
- 0, 0x734C, 0x734A, 0x4F3C, 0, 0x734B, 0xEC64, 0x4E6F,
- 0xEC65, 0, 0, 0xFE56, 0, 0x734D, 0x7E6B, 0x4E5B,
- 0, 0, 0, 0, 0x7E6C, 0x734E, 0x477E, 0,
- 0xFE57, 0x734F, 0x7351, 0, 0x7E6D, 0x7352, 0xEC6B, 0x7E6E,
- 0xEC6D, 0, 0, 0xEC6E, 0x7E6F, 0x7E70, 0, 0,
- 0x7350, 0x396D, 0x4C4D, 0x4B63, 0x5677, 0xFE59, 0x5D60, 0x4B7B,
-};
-static const unsigned short utf8_to_euc_E9BB[] = {
- 0, 0, 0, 0, 0x322B, 0, 0xEC71, 0,
- 0xEC72, 0, 0, 0xEC73, 0x7354, 0x3550, 0x7355, 0x7356,
- 0x7357, 0xF47E, 0x3975, 0, 0x7358, 0xEC74, 0, 0,
- 0x6054, 0x4C5B, 0, 0x4263, 0x7359, 0x735B, 0x735A, 0xEC75,
- 0x735C, 0, 0, 0, 0xEC76, 0x735D, 0, 0xEC77,
- 0x735E, 0, 0, 0, 0xEC78, 0xEC79, 0xEC7A, 0x735F,
- 0xEC7B, 0xEC7C, 0xEC7D, 0, 0x7360, 0xEC7E, 0x7361, 0x7362,
- 0xED21, 0x7363, 0, 0x7364, 0x7365, 0x7366, 0, 0xED22,
-};
-static const unsigned short utf8_to_euc_E9BB_x0213[] = {
- 0, 0, 0, 0x7E71, 0x322B, 0, 0xEC71, 0,
- 0xEC72, 0, 0, 0xEC73, 0x7354, 0x3550, 0x7355, 0x7356,
- 0x7357, 0x7E72, 0x3975, 0, 0x7358, 0xEC74, 0, 0,
- 0x6054, 0x4C5B, 0, 0x4263, 0x7359, 0x735B, 0x735A, 0xFE5B,
- 0x735C, 0, 0, 0, 0xEC76, 0x735D, 0, 0xFE5C,
- 0x735E, 0, 0, 0, 0xEC78, 0xEC79, 0xFE5D, 0x735F,
- 0xEC7B, 0xEC7C, 0xEC7D, 0, 0x7360, 0xEC7E, 0x7361, 0x7362,
- 0xED21, 0x7363, 0, 0x7364, 0x7365, 0x7366, 0, 0xFE5E,
-};
-static const unsigned short utf8_to_euc_E9BC[] = {
- 0, 0, 0xED23, 0xED24, 0, 0, 0, 0x7367,
- 0x7368, 0xED25, 0, 0, 0, 0, 0x4524, 0xED26,
- 0xED27, 0xED28, 0xED29, 0x385D, 0xED2A, 0x736A, 0xED2B, 0xED2C,
- 0, 0xED2D, 0xED2E, 0xED2F, 0, 0, 0, 0xED30,
- 0x414D, 0x736B, 0xED31, 0, 0, 0, 0xED32, 0,
- 0, 0, 0xED33, 0xED34, 0x736C, 0, 0, 0xED35,
- 0, 0xED36, 0xED37, 0, 0xED38, 0, 0, 0xED39,
- 0, 0xED3A, 0xED3B, 0x4921, 0xED3C, 0xED3D, 0x736D, 0xED3E,
-};
-static const unsigned short utf8_to_euc_E9BC_x0213[] = {
- 0, 0, 0xFE5F, 0xFE61, 0, 0, 0, 0x7367,
- 0x7368, 0xED25, 0, 0, 0, 0, 0x4524, 0xED26,
- 0x7E73, 0xED28, 0xED29, 0x385D, 0xED2A, 0x736A, 0xED2B, 0xFE62,
- 0, 0xFE63, 0xED2E, 0xED2F, 0, 0, 0, 0xED30,
- 0x414D, 0x736B, 0xED31, 0, 0, 0, 0xED32, 0,
- 0, 0, 0xED33, 0xED34, 0x736C, 0, 0, 0xFE64,
- 0, 0xED36, 0xED37, 0, 0xED38, 0, 0, 0xFE65,
- 0, 0x7E74, 0xFE66, 0x4921, 0xED3C, 0xFE67, 0x736D, 0xED3E,
-};
-static const unsigned short utf8_to_euc_E9BD[] = {
- 0, 0xED3F, 0, 0xED40, 0xED41, 0xED42, 0xED43, 0xED44,
- 0, 0, 0x736E, 0x6337, 0, 0, 0x6C5A, 0x706D,
- 0, 0, 0x736F, 0xED45, 0x7370, 0xED46, 0xED47, 0xED48,
- 0xED49, 0, 0xED4A, 0, 0, 0xED4B, 0xED4C, 0x7372,
- 0x7373, 0x7374, 0x4E70, 0x7371, 0, 0, 0x7375, 0x7376,
- 0xED4D, 0xED4E, 0x7378, 0, 0x7377, 0xED4F, 0xED50, 0xED51,
- 0xED52, 0xED53, 0x737A, 0xED54, 0, 0xED55, 0x737B, 0x7379,
- 0, 0, 0xED56, 0, 0, 0xED57, 0, 0,
-};
-static const unsigned short utf8_to_euc_E9BD_x0213[] = {
- 0, 0xFE68, 0, 0xED40, 0xED41, 0xFE69, 0xFE6A, 0xED44,
- 0, 0, 0x736E, 0x6337, 0, 0, 0x6C5A, 0x706D,
- 0, 0, 0x736F, 0xFE6B, 0x7370, 0xFE6C, 0xED47, 0x7E75,
- 0xFE6D, 0, 0xED4A, 0, 0, 0xFE6F, 0xED4C, 0x7372,
- 0x7373, 0x7374, 0x4E70, 0x7371, 0, 0, 0x7375, 0x7376,
- 0xED4D, 0xFE71, 0x7378, 0, 0x7377, 0xFE73, 0xED50, 0xED51,
- 0xFE74, 0xED53, 0x737A, 0xED54, 0, 0xFE75, 0x737B, 0x7379,
- 0, 0, 0xED56, 0, 0, 0xED57, 0, 0,
-};
-static const unsigned short utf8_to_euc_E9BE[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x4E36, 0, 0xED58,
- 0xED59, 0xED5A, 0xED5B, 0, 0xED5C, 0x737C, 0xED5D, 0xED5E,
- 0, 0, 0, 0, 0x737D, 0x6354, 0xED5F, 0,
- 0x737E, 0xED60, 0xED61, 0xED62, 0, 0xED63, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_E9BE_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x4E36, 0, 0xED58,
- 0x7E76, 0xED5A, 0xED5B, 0, 0x7E77, 0x737C, 0xED5D, 0x7E78,
- 0, 0, 0, 0, 0x737D, 0x6354, 0xED5F, 0,
- 0x737E, 0xED60, 0x7E79, 0xED62, 0, 0xED63, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_EFA4[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xF445, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_EFA4_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0x763B, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x742E, 0x754E, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0x7B4F, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_EFA5_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x7649, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_EFA7[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xF472, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_EFA7_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x7E24, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0x7D5D, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_EFA8[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xF434, 0xF437,
- 0xF438, 0xF43D, 0xF444, 0xF447, 0xF448, 0xF44E, 0xF44F, 0xF453,
- 0xF455, 0xF456, 0xF457, 0xF458, 0xF45A, 0xF45B, 0xF45E, 0xF460,
- 0xF462, 0xF463, 0xF465, 0xF469, 0xF46A, 0xF46B, 0xF46D, 0xF46F,
- 0xF470, 0xF473, 0xF477, 0xF478, 0xF479, 0xF47D, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_EFA8_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x2F4B,
- 0x2F57, 0x4F72, 0, 0xAE79, 0x757A, 0x775A, 0x776F, 0,
- 0, 0x793C, 0x793D, 0x7941, 0, 0, 0, 0x7B3A,
- 0xF738, 0xF745, 0x7C2E, 0, 0xF96E, 0, 0x7C6A, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2E38, 0x2E49, 0x2E50, 0x2E63, 0x2E68, 0x2E6E, 0x2F2C, 0x2F2F,
- 0x2F36, 0x2F5A, 0x2F5E, 0x4F61, 0x4F62, 0x7450, 0x745C, 0x745E,
-};
-static const unsigned short utf8_to_euc_EFA9_x0213[] = {
- 0x7461, 0x7528, 0x752B, 0x7543, 0x7565, 0x7669, 0x7677, 0x7725,
- 0x7755, 0xF029, 0x7825, 0x7927, 0x7933, 0x7934, 0x7937, 0x7938,
- 0x7939, 0x793B, 0x793F, 0x7940, 0x794D, 0x7951, 0x7964, 0x7A2E,
- 0xF450, 0x7A33, 0x7A3A, 0x7A44, 0x7A58, 0xF574, 0xF575, 0x7B27,
- 0x7B6F, 0x7B79, 0x7C2F, 0x7C30, 0x7C38, 0x7C3D, 0xF969, 0x7C59,
- 0x7D63, 0x7D76, 0x7D7B, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_EFB9_x0213[] = {
- 0, 0, 0, 0, 0, 0x233E, 0x233D, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_EFBC[] = {
- 0, 0x212A, 0xF42A, 0x2174, 0x2170, 0x2173, 0x2175, 0xF429,
- 0x214A, 0x214B, 0x2176, 0x215C, 0x2124, 0x215D, 0x2125, 0x213F,
- 0x2330, 0x2331, 0x2332, 0x2333, 0x2334, 0x2335, 0x2336, 0x2337,
- 0x2338, 0x2339, 0x2127, 0x2128, 0x2163, 0x2161, 0x2164, 0x2129,
- 0x2177, 0x2341, 0x2342, 0x2343, 0x2344, 0x2345, 0x2346, 0x2347,
- 0x2348, 0x2349, 0x234A, 0x234B, 0x234C, 0x234D, 0x234E, 0x234F,
- 0x2350, 0x2351, 0x2352, 0x2353, 0x2354, 0x2355, 0x2356, 0x2357,
- 0x2358, 0x2359, 0x235A, 0x214E, 0x2140, 0x214F, 0x2130, 0x2132,
-};
-static const unsigned short utf8_to_euc_EFBC_x0213[] = {
- 0, 0x212A, 0x2230, 0x2174, 0x2170, 0x2173, 0x2175, 0x222F,
- 0x214A, 0x214B, 0x2176, 0x215C, 0x2124, 0x2231, 0x2125, 0x213F,
- 0x2330, 0x2331, 0x2332, 0x2333, 0x2334, 0x2335, 0x2336, 0x2337,
- 0x2338, 0x2339, 0x2127, 0x2128, 0x2163, 0x2161, 0x2164, 0x2129,
- 0x2177, 0x2341, 0x2342, 0x2343, 0x2344, 0x2345, 0x2346, 0x2347,
- 0x2348, 0x2349, 0x234A, 0x234B, 0x234C, 0x234D, 0x234E, 0x234F,
- 0x2350, 0x2351, 0x2352, 0x2353, 0x2354, 0x2355, 0x2356, 0x2357,
- 0x2358, 0x2359, 0x235A, 0x214E, 0x2140, 0x214F, 0x2130, 0x2132,
-};
-static const unsigned short utf8_to_euc_EFBD[] = {
- 0x212E, 0x2361, 0x2362, 0x2363, 0x2364, 0x2365, 0x2366, 0x2367,
- 0x2368, 0x2369, 0x236A, 0x236B, 0x236C, 0x236D, 0x236E, 0x236F,
- 0x2370, 0x2371, 0x2372, 0x2373, 0x2374, 0x2375, 0x2376, 0x2377,
- 0x2378, 0x2379, 0x237A, 0x2150, 0x2143, 0x2151, 0xA237, 0,
- 0, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27,
- 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F,
- 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37,
- 0x0E38, 0x0E39, 0x0E3A, 0x0E3B, 0x0E3C, 0x0E3D, 0x0E3E, 0x0E3F,
-};
-static const unsigned short utf8_to_euc_EFBD_ms[] = {
- 0x212E, 0x2361, 0x2362, 0x2363, 0x2364, 0x2365, 0x2366, 0x2367,
- 0x2368, 0x2369, 0x236A, 0x236B, 0x236C, 0x236D, 0x236E, 0x236F,
- 0x2370, 0x2371, 0x2372, 0x2373, 0x2374, 0x2375, 0x2376, 0x2377,
- 0x2378, 0x2379, 0x237A, 0x2150, 0x2143, 0x2151, 0x2141, 0,
- 0, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27,
- 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F,
- 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37,
- 0x0E38, 0x0E39, 0x0E3A, 0x0E3B, 0x0E3C, 0x0E3D, 0x0E3E, 0x0E3F,
-};
-static const unsigned short utf8_to_euc_EFBD_x0213[] = {
- 0x212E, 0x2361, 0x2362, 0x2363, 0x2364, 0x2365, 0x2366, 0x2367,
- 0x2368, 0x2369, 0x236A, 0x236B, 0x236C, 0x236D, 0x236E, 0x236F,
- 0x2370, 0x2371, 0x2372, 0x2373, 0x2374, 0x2375, 0x2376, 0x2377,
- 0x2378, 0x2379, 0x237A, 0x2150, 0x2143, 0x2151, 0x2232, 0x2256,
- 0x2257, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27,
- 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F,
- 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37,
- 0x0E38, 0x0E39, 0x0E3A, 0x0E3B, 0x0E3C, 0x0E3D, 0x0E3E, 0x0E3F,
-};
-static const unsigned short utf8_to_euc_EFBE[] = {
- 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47,
- 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F,
- 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57,
- 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0x0E5C, 0x0E5D, 0x0E5E, 0x0E5F,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_EFBF[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0x2171, 0x2172, 0x224C, 0x2131, 0xA243, 0x216F, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short utf8_to_euc_EFBF_x0213[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x2131, 0, 0x216F, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short *const utf8_to_euc_E1_x0213[] = {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- utf8_to_euc_E1B8_x0213, 0, 0, 0,
- 0, utf8_to_euc_E1BD_x0213, 0, 0,
-};
-static const unsigned short *const utf8_to_euc_E2[] = {
- utf8_to_euc_E280, 0, 0, 0,
- utf8_to_euc_E284, utf8_to_euc_E285, utf8_to_euc_E286, utf8_to_euc_E287,
- utf8_to_euc_E288, utf8_to_euc_E289, utf8_to_euc_E28A, 0,
- utf8_to_euc_E28C, 0, 0, 0,
- 0, utf8_to_euc_E291, 0, 0,
- utf8_to_euc_E294, utf8_to_euc_E295, utf8_to_euc_E296, utf8_to_euc_E297,
- utf8_to_euc_E298, utf8_to_euc_E299, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
-};
-static const unsigned short *const utf8_to_euc_E2_ms[] = {
- utf8_to_euc_E280_ms, 0, 0, 0,
- utf8_to_euc_E284, utf8_to_euc_E285, utf8_to_euc_E286, utf8_to_euc_E287,
- utf8_to_euc_E288, utf8_to_euc_E289, utf8_to_euc_E28A, 0,
- utf8_to_euc_E28C, 0, 0, 0,
- 0, utf8_to_euc_E291, 0, 0,
- utf8_to_euc_E294, utf8_to_euc_E295, utf8_to_euc_E296, utf8_to_euc_E297,
- utf8_to_euc_E298, utf8_to_euc_E299, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
-};
-static const unsigned short *const utf8_to_euc_E2_932[] = {
- utf8_to_euc_E280_932, 0, 0, 0,
- utf8_to_euc_E284, utf8_to_euc_E285, utf8_to_euc_E286, utf8_to_euc_E287,
- utf8_to_euc_E288_932, utf8_to_euc_E289, utf8_to_euc_E28A, 0,
- utf8_to_euc_E28C, 0, 0, 0,
- 0, utf8_to_euc_E291, 0, 0,
- utf8_to_euc_E294, utf8_to_euc_E295, utf8_to_euc_E296, utf8_to_euc_E297,
- utf8_to_euc_E298, utf8_to_euc_E299, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
-};
-static const unsigned short *const utf8_to_euc_E2_mac[] = {
- utf8_to_euc_E280_932, 0, 0, 0,
- utf8_to_euc_E284_mac, utf8_to_euc_E285_mac, utf8_to_euc_E286, utf8_to_euc_E287,
- utf8_to_euc_E288_mac, utf8_to_euc_E289, utf8_to_euc_E28A_mac, 0,
- utf8_to_euc_E28C, 0, 0, 0,
- 0, utf8_to_euc_E291_mac, 0, 0,
- utf8_to_euc_E294, utf8_to_euc_E295, utf8_to_euc_E296, utf8_to_euc_E297,
- utf8_to_euc_E298, utf8_to_euc_E299, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
-};
-static const unsigned short *const utf8_to_euc_E2_x0213[] = {
- utf8_to_euc_E280_x0213, utf8_to_euc_E281_x0213, utf8_to_euc_E282_x0213, 0,
- utf8_to_euc_E284_x0213, utf8_to_euc_E285_x0213, utf8_to_euc_E286_x0213, utf8_to_euc_E287_x0213,
- utf8_to_euc_E288_x0213, utf8_to_euc_E289_x0213, utf8_to_euc_E28A_x0213, utf8_to_euc_E28B_x0213,
- utf8_to_euc_E28C_x0213, 0, utf8_to_euc_E28E_x0213, utf8_to_euc_E28F_x0213,
- utf8_to_euc_E290_x0213, utf8_to_euc_E291, 0, utf8_to_euc_E293_x0213,
- utf8_to_euc_E294, utf8_to_euc_E295, utf8_to_euc_E296_x0213, utf8_to_euc_E297_x0213,
- utf8_to_euc_E298_x0213, utf8_to_euc_E299_x0213, 0, 0,
- utf8_to_euc_E29C_x0213, utf8_to_euc_E29D_x0213, 0, 0,
- 0, 0, 0, 0,
- utf8_to_euc_E2A4_x0213, 0, utf8_to_euc_E2A6_x0213, utf8_to_euc_E2A7_x0213,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
-};
-static const unsigned short *const utf8_to_euc_E3[] = {
- utf8_to_euc_E380, utf8_to_euc_E381, utf8_to_euc_E382, utf8_to_euc_E383,
- 0, 0, 0, 0,
- utf8_to_euc_E388, 0, utf8_to_euc_E38A, 0,
- utf8_to_euc_E38C, utf8_to_euc_E38D, utf8_to_euc_E38E, utf8_to_euc_E38F,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
-};
-static const unsigned short *const utf8_to_euc_E3_932[] = {
- utf8_to_euc_E380_932, utf8_to_euc_E381, utf8_to_euc_E382_932, utf8_to_euc_E383,
- 0, 0, 0, 0,
- utf8_to_euc_E388, 0, utf8_to_euc_E38A, 0,
- utf8_to_euc_E38C, utf8_to_euc_E38D, utf8_to_euc_E38E, utf8_to_euc_E38F,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
-};
-static const unsigned short *const utf8_to_euc_E3_mac[] = {
- utf8_to_euc_E380_932, utf8_to_euc_E381, utf8_to_euc_E382_932, utf8_to_euc_E383,
- 0, 0, 0, 0,
- utf8_to_euc_E388_mac, 0, utf8_to_euc_E38A_mac, 0,
- utf8_to_euc_E38C_mac, utf8_to_euc_E38D_mac, utf8_to_euc_E38E_mac, utf8_to_euc_E38F_mac,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
-};
-static const unsigned short *const utf8_to_euc_E3_x0213[] = {
- utf8_to_euc_E380_x0213, utf8_to_euc_E381, utf8_to_euc_E382_x0213, utf8_to_euc_E383_x0213,
- 0, 0, 0, utf8_to_euc_E387_x0213,
- utf8_to_euc_E388, utf8_to_euc_E389_x0213, utf8_to_euc_E38A_x0213, utf8_to_euc_E38B_x0213,
- utf8_to_euc_E38C, utf8_to_euc_E38D, utf8_to_euc_E38E, utf8_to_euc_E38F_x0213,
- utf8_to_euc_E390_x0213, utf8_to_euc_E391_x0213, utf8_to_euc_E392_x0213, utf8_to_euc_E393_x0213,
- utf8_to_euc_E394_x0213, utf8_to_euc_E395_x0213, utf8_to_euc_E396_x0213, utf8_to_euc_E397_x0213,
- utf8_to_euc_E398_x0213, utf8_to_euc_E399_x0213, utf8_to_euc_E39A_x0213, utf8_to_euc_E39B_x0213,
- 0, utf8_to_euc_E39D_x0213, utf8_to_euc_E39E_x0213, utf8_to_euc_E39F_x0213,
- utf8_to_euc_E3A0_x0213, utf8_to_euc_E3A1_x0213, 0, utf8_to_euc_E3A3_x0213,
- utf8_to_euc_E3A4_x0213, utf8_to_euc_E3A5_x0213, 0, 0,
- 0, utf8_to_euc_E3A9_x0213, 0, utf8_to_euc_E3AB_x0213,
- utf8_to_euc_E3AC_x0213, utf8_to_euc_E3AD_x0213, utf8_to_euc_E3AE_x0213, utf8_to_euc_E3AF_x0213,
- utf8_to_euc_E3B0_x0213, 0, 0, utf8_to_euc_E3B3_x0213,
- utf8_to_euc_E3B4_x0213, utf8_to_euc_E3B5_x0213, utf8_to_euc_E3B6_x0213, utf8_to_euc_E3B7_x0213,
- utf8_to_euc_E3B8_x0213, utf8_to_euc_E3B9_x0213, utf8_to_euc_E3BA_x0213, 0,
- 0, utf8_to_euc_E3BD_x0213, utf8_to_euc_E3BE_x0213, utf8_to_euc_E3BF_x0213,
-};
-static const unsigned short *const utf8_to_euc_E4[] = {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- utf8_to_euc_E4B8, utf8_to_euc_E4B9, utf8_to_euc_E4BA, utf8_to_euc_E4BB,
- utf8_to_euc_E4BC, utf8_to_euc_E4BD, utf8_to_euc_E4BE, utf8_to_euc_E4BF,
-};
-static const unsigned short *const utf8_to_euc_E4_x0213[] = {
- utf8_to_euc_E480_x0213, utf8_to_euc_E481_x0213, utf8_to_euc_E482_x0213, 0,
- utf8_to_euc_E484_x0213, utf8_to_euc_E485_x0213, utf8_to_euc_E486_x0213, utf8_to_euc_E487_x0213,
- utf8_to_euc_E488_x0213, utf8_to_euc_E489_x0213, 0, utf8_to_euc_E48B_x0213,
- utf8_to_euc_E48C_x0213, utf8_to_euc_E48D_x0213, 0, utf8_to_euc_E48F_x0213,
- utf8_to_euc_E490_x0213, utf8_to_euc_E491_x0213, utf8_to_euc_E492_x0213, utf8_to_euc_E493_x0213,
- utf8_to_euc_E494_x0213, utf8_to_euc_E495_x0213, utf8_to_euc_E496_x0213, utf8_to_euc_E497_x0213,
- utf8_to_euc_E498_x0213, utf8_to_euc_E499_x0213, utf8_to_euc_E49A_x0213, 0,
- utf8_to_euc_E49C_x0213, utf8_to_euc_E49D_x0213, 0, utf8_to_euc_E49F_x0213,
- utf8_to_euc_E4A0_x0213, utf8_to_euc_E4A1_x0213, utf8_to_euc_E4A2_x0213, 0,
- 0, 0, utf8_to_euc_E4A6_x0213, utf8_to_euc_E4A7_x0213,
- utf8_to_euc_E4A8_x0213, 0, utf8_to_euc_E4AA_x0213, 0,
- utf8_to_euc_E4AC_x0213, 0, 0, utf8_to_euc_E4AF_x0213,
- utf8_to_euc_E4B0_x0213, 0, 0, utf8_to_euc_E4B3_x0213,
- utf8_to_euc_E4B4_x0213, utf8_to_euc_E4B5_x0213, 0, 0,
- utf8_to_euc_E4B8_x0213, utf8_to_euc_E4B9_x0213, utf8_to_euc_E4BA_x0213, utf8_to_euc_E4BB_x0213,
- utf8_to_euc_E4BC_x0213, utf8_to_euc_E4BD_x0213, utf8_to_euc_E4BE_x0213, utf8_to_euc_E4BF_x0213,
-};
-static const unsigned short *const utf8_to_euc_E5[] = {
- utf8_to_euc_E580, utf8_to_euc_E581, utf8_to_euc_E582, utf8_to_euc_E583,
- utf8_to_euc_E584, utf8_to_euc_E585, utf8_to_euc_E586, utf8_to_euc_E587,
- utf8_to_euc_E588, utf8_to_euc_E589, utf8_to_euc_E58A, utf8_to_euc_E58B,
- utf8_to_euc_E58C, utf8_to_euc_E58D, utf8_to_euc_E58E, utf8_to_euc_E58F,
- utf8_to_euc_E590, utf8_to_euc_E591, utf8_to_euc_E592, utf8_to_euc_E593,
- utf8_to_euc_E594, utf8_to_euc_E595, utf8_to_euc_E596, utf8_to_euc_E597,
- utf8_to_euc_E598, utf8_to_euc_E599, utf8_to_euc_E59A, utf8_to_euc_E59B,
- utf8_to_euc_E59C, utf8_to_euc_E59D, utf8_to_euc_E59E, utf8_to_euc_E59F,
- utf8_to_euc_E5A0, utf8_to_euc_E5A1, utf8_to_euc_E5A2, utf8_to_euc_E5A3,
- utf8_to_euc_E5A4, utf8_to_euc_E5A5, utf8_to_euc_E5A6, utf8_to_euc_E5A7,
- utf8_to_euc_E5A8, utf8_to_euc_E5A9, utf8_to_euc_E5AA, utf8_to_euc_E5AB,
- utf8_to_euc_E5AC, utf8_to_euc_E5AD, utf8_to_euc_E5AE, utf8_to_euc_E5AF,
- utf8_to_euc_E5B0, utf8_to_euc_E5B1, utf8_to_euc_E5B2, utf8_to_euc_E5B3,
- utf8_to_euc_E5B4, utf8_to_euc_E5B5, utf8_to_euc_E5B6, utf8_to_euc_E5B7,
- utf8_to_euc_E5B8, utf8_to_euc_E5B9, utf8_to_euc_E5BA, utf8_to_euc_E5BB,
- utf8_to_euc_E5BC, utf8_to_euc_E5BD, utf8_to_euc_E5BE, utf8_to_euc_E5BF,
-};
-static const unsigned short *const utf8_to_euc_E5_x0213[] = {
- utf8_to_euc_E580_x0213, utf8_to_euc_E581_x0213, utf8_to_euc_E582_x0213, utf8_to_euc_E583_x0213,
- utf8_to_euc_E584_x0213, utf8_to_euc_E585_x0213, utf8_to_euc_E586_x0213, utf8_to_euc_E587_x0213,
- utf8_to_euc_E588_x0213, utf8_to_euc_E589_x0213, utf8_to_euc_E58A_x0213, utf8_to_euc_E58B_x0213,
- utf8_to_euc_E58C_x0213, utf8_to_euc_E58D_x0213, utf8_to_euc_E58E_x0213, utf8_to_euc_E58F_x0213,
- utf8_to_euc_E590_x0213, utf8_to_euc_E591_x0213, utf8_to_euc_E592_x0213, utf8_to_euc_E593_x0213,
- utf8_to_euc_E594_x0213, utf8_to_euc_E595_x0213, utf8_to_euc_E596_x0213, utf8_to_euc_E597_x0213,
- utf8_to_euc_E598_x0213, utf8_to_euc_E599_x0213, utf8_to_euc_E59A_x0213, utf8_to_euc_E59B_x0213,
- utf8_to_euc_E59C_x0213, utf8_to_euc_E59D_x0213, utf8_to_euc_E59E_x0213, utf8_to_euc_E59F_x0213,
- utf8_to_euc_E5A0_x0213, utf8_to_euc_E5A1_x0213, utf8_to_euc_E5A2_x0213, utf8_to_euc_E5A3_x0213,
- utf8_to_euc_E5A4_x0213, utf8_to_euc_E5A5_x0213, utf8_to_euc_E5A6_x0213, utf8_to_euc_E5A7_x0213,
- utf8_to_euc_E5A8_x0213, utf8_to_euc_E5A9_x0213, utf8_to_euc_E5AA_x0213, utf8_to_euc_E5AB_x0213,
- utf8_to_euc_E5AC_x0213, utf8_to_euc_E5AD_x0213, utf8_to_euc_E5AE_x0213, utf8_to_euc_E5AF_x0213,
- utf8_to_euc_E5B0_x0213, utf8_to_euc_E5B1_x0213, utf8_to_euc_E5B2_x0213, utf8_to_euc_E5B3_x0213,
- utf8_to_euc_E5B4_x0213, utf8_to_euc_E5B5_x0213, utf8_to_euc_E5B6_x0213, utf8_to_euc_E5B7_x0213,
- utf8_to_euc_E5B8_x0213, utf8_to_euc_E5B9_x0213, utf8_to_euc_E5BA_x0213, utf8_to_euc_E5BB_x0213,
- utf8_to_euc_E5BC_x0213, utf8_to_euc_E5BD_x0213, utf8_to_euc_E5BE_x0213, utf8_to_euc_E5BF_x0213,
-};
-static const unsigned short *const utf8_to_euc_E6[] = {
- utf8_to_euc_E680, utf8_to_euc_E681, utf8_to_euc_E682, utf8_to_euc_E683,
- utf8_to_euc_E684, utf8_to_euc_E685, utf8_to_euc_E686, utf8_to_euc_E687,
- utf8_to_euc_E688, utf8_to_euc_E689, utf8_to_euc_E68A, utf8_to_euc_E68B,
- utf8_to_euc_E68C, utf8_to_euc_E68D, utf8_to_euc_E68E, utf8_to_euc_E68F,
- utf8_to_euc_E690, utf8_to_euc_E691, utf8_to_euc_E692, utf8_to_euc_E693,
- utf8_to_euc_E694, utf8_to_euc_E695, utf8_to_euc_E696, utf8_to_euc_E697,
- utf8_to_euc_E698, utf8_to_euc_E699, utf8_to_euc_E69A, utf8_to_euc_E69B,
- utf8_to_euc_E69C, utf8_to_euc_E69D, utf8_to_euc_E69E, utf8_to_euc_E69F,
- utf8_to_euc_E6A0, utf8_to_euc_E6A1, utf8_to_euc_E6A2, utf8_to_euc_E6A3,
- utf8_to_euc_E6A4, utf8_to_euc_E6A5, utf8_to_euc_E6A6, utf8_to_euc_E6A7,
- utf8_to_euc_E6A8, utf8_to_euc_E6A9, utf8_to_euc_E6AA, utf8_to_euc_E6AB,
- utf8_to_euc_E6AC, utf8_to_euc_E6AD, utf8_to_euc_E6AE, utf8_to_euc_E6AF,
- utf8_to_euc_E6B0, utf8_to_euc_E6B1, utf8_to_euc_E6B2, utf8_to_euc_E6B3,
- utf8_to_euc_E6B4, utf8_to_euc_E6B5, utf8_to_euc_E6B6, utf8_to_euc_E6B7,
- utf8_to_euc_E6B8, utf8_to_euc_E6B9, utf8_to_euc_E6BA, utf8_to_euc_E6BB,
- utf8_to_euc_E6BC, utf8_to_euc_E6BD, utf8_to_euc_E6BE, utf8_to_euc_E6BF,
-};
-static const unsigned short *const utf8_to_euc_E6_x0213[] = {
- utf8_to_euc_E680_x0213, utf8_to_euc_E681_x0213, utf8_to_euc_E682_x0213, utf8_to_euc_E683_x0213,
- utf8_to_euc_E684_x0213, utf8_to_euc_E685_x0213, utf8_to_euc_E686_x0213, utf8_to_euc_E687_x0213,
- utf8_to_euc_E688_x0213, utf8_to_euc_E689_x0213, utf8_to_euc_E68A_x0213, utf8_to_euc_E68B_x0213,
- utf8_to_euc_E68C_x0213, utf8_to_euc_E68D_x0213, utf8_to_euc_E68E_x0213, utf8_to_euc_E68F_x0213,
- utf8_to_euc_E690_x0213, utf8_to_euc_E691_x0213, utf8_to_euc_E692_x0213, utf8_to_euc_E693_x0213,
- utf8_to_euc_E694_x0213, utf8_to_euc_E695_x0213, utf8_to_euc_E696_x0213, utf8_to_euc_E697_x0213,
- utf8_to_euc_E698_x0213, utf8_to_euc_E699_x0213, utf8_to_euc_E69A_x0213, utf8_to_euc_E69B_x0213,
- utf8_to_euc_E69C_x0213, utf8_to_euc_E69D_x0213, utf8_to_euc_E69E_x0213, utf8_to_euc_E69F_x0213,
- utf8_to_euc_E6A0_x0213, utf8_to_euc_E6A1_x0213, utf8_to_euc_E6A2_x0213, utf8_to_euc_E6A3_x0213,
- utf8_to_euc_E6A4_x0213, utf8_to_euc_E6A5_x0213, utf8_to_euc_E6A6_x0213, utf8_to_euc_E6A7_x0213,
- utf8_to_euc_E6A8_x0213, utf8_to_euc_E6A9_x0213, utf8_to_euc_E6AA_x0213, utf8_to_euc_E6AB_x0213,
- utf8_to_euc_E6AC_x0213, utf8_to_euc_E6AD_x0213, utf8_to_euc_E6AE_x0213, utf8_to_euc_E6AF_x0213,
- utf8_to_euc_E6B0_x0213, utf8_to_euc_E6B1_x0213, utf8_to_euc_E6B2_x0213, utf8_to_euc_E6B3_x0213,
- utf8_to_euc_E6B4_x0213, utf8_to_euc_E6B5_x0213, utf8_to_euc_E6B6_x0213, utf8_to_euc_E6B7_x0213,
- utf8_to_euc_E6B8_x0213, utf8_to_euc_E6B9_x0213, utf8_to_euc_E6BA_x0213, utf8_to_euc_E6BB_x0213,
- utf8_to_euc_E6BC_x0213, utf8_to_euc_E6BD_x0213, utf8_to_euc_E6BE_x0213, utf8_to_euc_E6BF_x0213,
-};
-static const unsigned short *const utf8_to_euc_E7[] = {
- utf8_to_euc_E780, utf8_to_euc_E781, utf8_to_euc_E782, utf8_to_euc_E783,
- utf8_to_euc_E784, utf8_to_euc_E785, utf8_to_euc_E786, utf8_to_euc_E787,
- utf8_to_euc_E788, utf8_to_euc_E789, utf8_to_euc_E78A, utf8_to_euc_E78B,
- utf8_to_euc_E78C, utf8_to_euc_E78D, utf8_to_euc_E78E, utf8_to_euc_E78F,
- utf8_to_euc_E790, utf8_to_euc_E791, utf8_to_euc_E792, utf8_to_euc_E793,
- utf8_to_euc_E794, utf8_to_euc_E795, utf8_to_euc_E796, utf8_to_euc_E797,
- utf8_to_euc_E798, utf8_to_euc_E799, utf8_to_euc_E79A, utf8_to_euc_E79B,
- utf8_to_euc_E79C, utf8_to_euc_E79D, utf8_to_euc_E79E, utf8_to_euc_E79F,
- utf8_to_euc_E7A0, utf8_to_euc_E7A1, utf8_to_euc_E7A2, utf8_to_euc_E7A3,
- utf8_to_euc_E7A4, utf8_to_euc_E7A5, utf8_to_euc_E7A6, utf8_to_euc_E7A7,
- utf8_to_euc_E7A8, utf8_to_euc_E7A9, utf8_to_euc_E7AA, utf8_to_euc_E7AB,
- utf8_to_euc_E7AC, utf8_to_euc_E7AD, utf8_to_euc_E7AE, utf8_to_euc_E7AF,
- utf8_to_euc_E7B0, utf8_to_euc_E7B1, utf8_to_euc_E7B2, utf8_to_euc_E7B3,
- utf8_to_euc_E7B4, utf8_to_euc_E7B5, utf8_to_euc_E7B6, utf8_to_euc_E7B7,
- utf8_to_euc_E7B8, utf8_to_euc_E7B9, utf8_to_euc_E7BA, 0,
- utf8_to_euc_E7BC, utf8_to_euc_E7BD, utf8_to_euc_E7BE, utf8_to_euc_E7BF,
-};
-static const unsigned short *const utf8_to_euc_E7_x0213[] = {
- utf8_to_euc_E780_x0213, utf8_to_euc_E781_x0213, utf8_to_euc_E782_x0213, utf8_to_euc_E783_x0213,
- utf8_to_euc_E784_x0213, utf8_to_euc_E785_x0213, utf8_to_euc_E786_x0213, utf8_to_euc_E787_x0213,
- utf8_to_euc_E788_x0213, utf8_to_euc_E789_x0213, utf8_to_euc_E78A_x0213, utf8_to_euc_E78B_x0213,
- utf8_to_euc_E78C_x0213, utf8_to_euc_E78D_x0213, utf8_to_euc_E78E_x0213, utf8_to_euc_E78F_x0213,
- utf8_to_euc_E790_x0213, utf8_to_euc_E791_x0213, utf8_to_euc_E792_x0213, utf8_to_euc_E793_x0213,
- utf8_to_euc_E794_x0213, utf8_to_euc_E795_x0213, utf8_to_euc_E796_x0213, utf8_to_euc_E797_x0213,
- utf8_to_euc_E798_x0213, utf8_to_euc_E799_x0213, utf8_to_euc_E79A_x0213, utf8_to_euc_E79B_x0213,
- utf8_to_euc_E79C_x0213, utf8_to_euc_E79D_x0213, utf8_to_euc_E79E_x0213, utf8_to_euc_E79F_x0213,
- utf8_to_euc_E7A0_x0213, utf8_to_euc_E7A1_x0213, utf8_to_euc_E7A2_x0213, utf8_to_euc_E7A3_x0213,
- utf8_to_euc_E7A4_x0213, utf8_to_euc_E7A5_x0213, utf8_to_euc_E7A6_x0213, utf8_to_euc_E7A7_x0213,
- utf8_to_euc_E7A8_x0213, utf8_to_euc_E7A9_x0213, utf8_to_euc_E7AA_x0213, utf8_to_euc_E7AB_x0213,
- utf8_to_euc_E7AC_x0213, utf8_to_euc_E7AD_x0213, utf8_to_euc_E7AE_x0213, utf8_to_euc_E7AF_x0213,
- utf8_to_euc_E7B0_x0213, utf8_to_euc_E7B1_x0213, utf8_to_euc_E7B2_x0213, utf8_to_euc_E7B3_x0213,
- utf8_to_euc_E7B4_x0213, utf8_to_euc_E7B5_x0213, utf8_to_euc_E7B6_x0213, utf8_to_euc_E7B7_x0213,
- utf8_to_euc_E7B8_x0213, utf8_to_euc_E7B9_x0213, utf8_to_euc_E7BA_x0213, 0,
- utf8_to_euc_E7BC_x0213, utf8_to_euc_E7BD_x0213, utf8_to_euc_E7BE_x0213, utf8_to_euc_E7BF_x0213,
-};
-static const unsigned short *const utf8_to_euc_E8[] = {
- utf8_to_euc_E880, utf8_to_euc_E881, utf8_to_euc_E882, utf8_to_euc_E883,
- utf8_to_euc_E884, utf8_to_euc_E885, utf8_to_euc_E886, utf8_to_euc_E887,
- utf8_to_euc_E888, utf8_to_euc_E889, utf8_to_euc_E88A, utf8_to_euc_E88B,
- utf8_to_euc_E88C, utf8_to_euc_E88D, utf8_to_euc_E88E, utf8_to_euc_E88F,
- utf8_to_euc_E890, utf8_to_euc_E891, utf8_to_euc_E892, utf8_to_euc_E893,
- utf8_to_euc_E894, utf8_to_euc_E895, utf8_to_euc_E896, utf8_to_euc_E897,
- utf8_to_euc_E898, utf8_to_euc_E899, utf8_to_euc_E89A, utf8_to_euc_E89B,
- utf8_to_euc_E89C, utf8_to_euc_E89D, utf8_to_euc_E89E, utf8_to_euc_E89F,
- utf8_to_euc_E8A0, utf8_to_euc_E8A1, utf8_to_euc_E8A2, utf8_to_euc_E8A3,
- utf8_to_euc_E8A4, utf8_to_euc_E8A5, utf8_to_euc_E8A6, utf8_to_euc_E8A7,
- utf8_to_euc_E8A8, utf8_to_euc_E8A9, utf8_to_euc_E8AA, utf8_to_euc_E8AB,
- utf8_to_euc_E8AC, utf8_to_euc_E8AD, utf8_to_euc_E8AE, 0,
- utf8_to_euc_E8B0, utf8_to_euc_E8B1, utf8_to_euc_E8B2, utf8_to_euc_E8B3,
- utf8_to_euc_E8B4, utf8_to_euc_E8B5, utf8_to_euc_E8B6, utf8_to_euc_E8B7,
- utf8_to_euc_E8B8, utf8_to_euc_E8B9, utf8_to_euc_E8BA, utf8_to_euc_E8BB,
- utf8_to_euc_E8BC, utf8_to_euc_E8BD, utf8_to_euc_E8BE, utf8_to_euc_E8BF,
-};
-static const unsigned short *const utf8_to_euc_E8_x0213[] = {
- utf8_to_euc_E880_x0213, utf8_to_euc_E881_x0213, utf8_to_euc_E882_x0213, utf8_to_euc_E883_x0213,
- utf8_to_euc_E884_x0213, utf8_to_euc_E885_x0213, utf8_to_euc_E886_x0213, utf8_to_euc_E887_x0213,
- utf8_to_euc_E888_x0213, utf8_to_euc_E889_x0213, utf8_to_euc_E88A_x0213, utf8_to_euc_E88B_x0213,
- utf8_to_euc_E88C_x0213, utf8_to_euc_E88D_x0213, utf8_to_euc_E88E_x0213, utf8_to_euc_E88F_x0213,
- utf8_to_euc_E890_x0213, utf8_to_euc_E891_x0213, utf8_to_euc_E892_x0213, utf8_to_euc_E893_x0213,
- utf8_to_euc_E894_x0213, utf8_to_euc_E895_x0213, utf8_to_euc_E896_x0213, utf8_to_euc_E897_x0213,
- utf8_to_euc_E898_x0213, utf8_to_euc_E899_x0213, utf8_to_euc_E89A_x0213, utf8_to_euc_E89B_x0213,
- utf8_to_euc_E89C_x0213, utf8_to_euc_E89D_x0213, utf8_to_euc_E89E_x0213, utf8_to_euc_E89F_x0213,
- utf8_to_euc_E8A0_x0213, utf8_to_euc_E8A1_x0213, utf8_to_euc_E8A2_x0213, utf8_to_euc_E8A3_x0213,
- utf8_to_euc_E8A4_x0213, utf8_to_euc_E8A5_x0213, utf8_to_euc_E8A6_x0213, utf8_to_euc_E8A7_x0213,
- utf8_to_euc_E8A8_x0213, utf8_to_euc_E8A9_x0213, utf8_to_euc_E8AA_x0213, utf8_to_euc_E8AB_x0213,
- utf8_to_euc_E8AC_x0213, utf8_to_euc_E8AD_x0213, utf8_to_euc_E8AE_x0213, 0,
- utf8_to_euc_E8B0_x0213, utf8_to_euc_E8B1_x0213, utf8_to_euc_E8B2_x0213, utf8_to_euc_E8B3_x0213,
- utf8_to_euc_E8B4_x0213, utf8_to_euc_E8B5_x0213, utf8_to_euc_E8B6_x0213, utf8_to_euc_E8B7_x0213,
- utf8_to_euc_E8B8_x0213, utf8_to_euc_E8B9_x0213, utf8_to_euc_E8BA_x0213, utf8_to_euc_E8BB_x0213,
- utf8_to_euc_E8BC_x0213, utf8_to_euc_E8BD_x0213, utf8_to_euc_E8BE_x0213, utf8_to_euc_E8BF_x0213,
-};
-static const unsigned short *const utf8_to_euc_E9[] = {
- utf8_to_euc_E980, utf8_to_euc_E981, utf8_to_euc_E982, utf8_to_euc_E983,
- utf8_to_euc_E984, utf8_to_euc_E985, utf8_to_euc_E986, utf8_to_euc_E987,
- utf8_to_euc_E988, utf8_to_euc_E989, utf8_to_euc_E98A, utf8_to_euc_E98B,
- utf8_to_euc_E98C, utf8_to_euc_E98D, utf8_to_euc_E98E, utf8_to_euc_E98F,
- utf8_to_euc_E990, utf8_to_euc_E991, utf8_to_euc_E992, 0,
- 0, utf8_to_euc_E995, utf8_to_euc_E996, utf8_to_euc_E997,
- utf8_to_euc_E998, utf8_to_euc_E999, utf8_to_euc_E99A, utf8_to_euc_E99B,
- utf8_to_euc_E99C, utf8_to_euc_E99D, utf8_to_euc_E99E, utf8_to_euc_E99F,
- utf8_to_euc_E9A0, utf8_to_euc_E9A1, utf8_to_euc_E9A2, utf8_to_euc_E9A3,
- utf8_to_euc_E9A4, utf8_to_euc_E9A5, utf8_to_euc_E9A6, utf8_to_euc_E9A7,
- utf8_to_euc_E9A8, utf8_to_euc_E9A9, utf8_to_euc_E9AA, utf8_to_euc_E9AB,
- utf8_to_euc_E9AC, utf8_to_euc_E9AD, utf8_to_euc_E9AE, utf8_to_euc_E9AF,
- utf8_to_euc_E9B0, utf8_to_euc_E9B1, 0, utf8_to_euc_E9B3,
- utf8_to_euc_E9B4, utf8_to_euc_E9B5, utf8_to_euc_E9B6, utf8_to_euc_E9B7,
- utf8_to_euc_E9B8, utf8_to_euc_E9B9, utf8_to_euc_E9BA, utf8_to_euc_E9BB,
- utf8_to_euc_E9BC, utf8_to_euc_E9BD, utf8_to_euc_E9BE, 0,
-};
-static const unsigned short *const utf8_to_euc_E9_x0213[] = {
- utf8_to_euc_E980_x0213, utf8_to_euc_E981_x0213, utf8_to_euc_E982_x0213, utf8_to_euc_E983_x0213,
- utf8_to_euc_E984_x0213, utf8_to_euc_E985_x0213, utf8_to_euc_E986_x0213, utf8_to_euc_E987_x0213,
- utf8_to_euc_E988_x0213, utf8_to_euc_E989_x0213, utf8_to_euc_E98A_x0213, utf8_to_euc_E98B_x0213,
- utf8_to_euc_E98C_x0213, utf8_to_euc_E98D_x0213, utf8_to_euc_E98E_x0213, utf8_to_euc_E98F_x0213,
- utf8_to_euc_E990_x0213, utf8_to_euc_E991_x0213, utf8_to_euc_E992, 0,
- 0, utf8_to_euc_E995_x0213, utf8_to_euc_E996_x0213, utf8_to_euc_E997_x0213,
- utf8_to_euc_E998_x0213, utf8_to_euc_E999_x0213, utf8_to_euc_E99A_x0213, utf8_to_euc_E99B_x0213,
- utf8_to_euc_E99C_x0213, utf8_to_euc_E99D_x0213, utf8_to_euc_E99E_x0213, utf8_to_euc_E99F_x0213,
- utf8_to_euc_E9A0_x0213, utf8_to_euc_E9A1_x0213, utf8_to_euc_E9A2_x0213, utf8_to_euc_E9A3_x0213,
- utf8_to_euc_E9A4_x0213, utf8_to_euc_E9A5_x0213, utf8_to_euc_E9A6_x0213, utf8_to_euc_E9A7_x0213,
- utf8_to_euc_E9A8_x0213, utf8_to_euc_E9A9_x0213, utf8_to_euc_E9AA_x0213, utf8_to_euc_E9AB_x0213,
- utf8_to_euc_E9AC_x0213, utf8_to_euc_E9AD_x0213, utf8_to_euc_E9AE_x0213, utf8_to_euc_E9AF_x0213,
- utf8_to_euc_E9B0_x0213, utf8_to_euc_E9B1_x0213, 0, utf8_to_euc_E9B3_x0213,
- utf8_to_euc_E9B4_x0213, utf8_to_euc_E9B5_x0213, utf8_to_euc_E9B6_x0213, utf8_to_euc_E9B7_x0213,
- utf8_to_euc_E9B8_x0213, utf8_to_euc_E9B9_x0213, utf8_to_euc_E9BA_x0213, utf8_to_euc_E9BB_x0213,
- utf8_to_euc_E9BC_x0213, utf8_to_euc_E9BD_x0213, utf8_to_euc_E9BE_x0213, 0,
-};
-static const unsigned short *const utf8_to_euc_EF[] = {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- utf8_to_euc_EFA4, 0, 0, utf8_to_euc_EFA7,
- utf8_to_euc_EFA8, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- utf8_to_euc_EFBC, utf8_to_euc_EFBD, utf8_to_euc_EFBE, utf8_to_euc_EFBF,
-};
-static const unsigned short *const utf8_to_euc_EF_ms[] = {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- utf8_to_euc_EFA4, 0, 0, utf8_to_euc_EFA7,
- utf8_to_euc_EFA8, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- utf8_to_euc_EFBC, utf8_to_euc_EFBD_ms, utf8_to_euc_EFBE, utf8_to_euc_EFBF,
-};
-static const unsigned short *const utf8_to_euc_EF_x0213[] = {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- utf8_to_euc_EFA4_x0213, utf8_to_euc_EFA5_x0213, 0, utf8_to_euc_EFA7_x0213,
- utf8_to_euc_EFA8_x0213, utf8_to_euc_EFA9_x0213, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, utf8_to_euc_EFB9_x0213, 0, 0,
- utf8_to_euc_EFBC_x0213, utf8_to_euc_EFBD_x0213, utf8_to_euc_EFBE, utf8_to_euc_EFBF_x0213,
-};
-const unsigned short *const utf8_to_euc_2bytes[] = {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, utf8_to_euc_C2, utf8_to_euc_C3,
- utf8_to_euc_C4, utf8_to_euc_C5, 0, utf8_to_euc_C7,
- 0, 0, 0, utf8_to_euc_CB,
- 0, 0, utf8_to_euc_CE, utf8_to_euc_CF,
- utf8_to_euc_D0, utf8_to_euc_D1, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
-};
-const unsigned short *const utf8_to_euc_2bytes_ms[] = {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, utf8_to_euc_C2_ms, utf8_to_euc_C3,
- utf8_to_euc_C4, utf8_to_euc_C5, 0, utf8_to_euc_C7,
- 0, 0, 0, utf8_to_euc_CB,
- 0, 0, utf8_to_euc_CE, utf8_to_euc_CF,
- utf8_to_euc_D0, utf8_to_euc_D1, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
-};
-const unsigned short *const utf8_to_euc_2bytes_932[] = {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, utf8_to_euc_C2_932, utf8_to_euc_C3_932,
- utf8_to_euc_C4, utf8_to_euc_C5, 0, utf8_to_euc_C7,
- 0, 0, 0, utf8_to_euc_CB,
- 0, 0, utf8_to_euc_CE, utf8_to_euc_CF,
- utf8_to_euc_D0, utf8_to_euc_D1, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
-};
-const unsigned short *const utf8_to_euc_2bytes_mac[] = {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, utf8_to_euc_C2_mac, utf8_to_euc_C3,
- utf8_to_euc_C4, utf8_to_euc_C5, 0, utf8_to_euc_C7,
- 0, 0, 0, utf8_to_euc_CB,
- 0, 0, utf8_to_euc_CE, utf8_to_euc_CF,
- utf8_to_euc_D0, utf8_to_euc_D1, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
-};
-const unsigned short *const utf8_to_euc_2bytes_x0213[] = {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, utf8_to_euc_C2_x0213, utf8_to_euc_C3_x0213,
- utf8_to_euc_C4_x0213, utf8_to_euc_C5_x0213, utf8_to_euc_C6_x0213, utf8_to_euc_C7_x0213,
- 0, utf8_to_euc_C9_x0213, utf8_to_euc_CA_x0213, utf8_to_euc_CB_x0213,
- utf8_to_euc_CC_x0213, utf8_to_euc_CD_x0213, utf8_to_euc_CE, utf8_to_euc_CF_x0213,
- utf8_to_euc_D0, utf8_to_euc_D1, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
-};
-const unsigned short *const *const utf8_to_euc_3bytes[] = {
- 0, 0, utf8_to_euc_E2, utf8_to_euc_E3,
- utf8_to_euc_E4, utf8_to_euc_E5, utf8_to_euc_E6, utf8_to_euc_E7,
- utf8_to_euc_E8, utf8_to_euc_E9, 0, 0,
- 0, 0, 0, utf8_to_euc_EF,
-};
-const unsigned short *const *const utf8_to_euc_3bytes_ms[] = {
- 0, 0, utf8_to_euc_E2_ms, utf8_to_euc_E3,
- utf8_to_euc_E4, utf8_to_euc_E5, utf8_to_euc_E6, utf8_to_euc_E7,
- utf8_to_euc_E8, utf8_to_euc_E9, 0, 0,
- 0, 0, 0, utf8_to_euc_EF_ms,
-};
-const unsigned short *const *const utf8_to_euc_3bytes_932[] = {
- 0, 0, utf8_to_euc_E2_932, utf8_to_euc_E3_932,
- utf8_to_euc_E4, utf8_to_euc_E5, utf8_to_euc_E6, utf8_to_euc_E7,
- utf8_to_euc_E8, utf8_to_euc_E9, 0, 0,
- 0, 0, 0, utf8_to_euc_EF_ms,
-};
-const unsigned short *const *const utf8_to_euc_3bytes_mac[] = {
- 0, 0, utf8_to_euc_E2_mac, utf8_to_euc_E3_mac,
- utf8_to_euc_E4, utf8_to_euc_E5, utf8_to_euc_E6, utf8_to_euc_E7,
- utf8_to_euc_E8, utf8_to_euc_E9, 0, 0,
- 0, 0, 0, utf8_to_euc_EF_ms,
-};
-const unsigned short *const *const utf8_to_euc_3bytes_x0213[] = {
- 0, utf8_to_euc_E1_x0213, utf8_to_euc_E2_x0213, utf8_to_euc_E3_x0213,
- utf8_to_euc_E4_x0213, utf8_to_euc_E5_x0213, utf8_to_euc_E6_x0213, utf8_to_euc_E7_x0213,
- utf8_to_euc_E8_x0213, utf8_to_euc_E9_x0213, 0, 0,
- 0, 0, 0, utf8_to_euc_EF_x0213,
-};
-
-#ifdef UNICODE_NORMALIZATION
-
-/* Normalization Table by Apple */
-/* http://developer.apple.com/technotes/tn/tn1150table.html */
-
-const struct normalization_pair normalization_table[] = {
- {{0xcd,0xbe}, {0x3b}},
- {{0xc3,0x80}, {0x41,0xcc,0x80,0x00}},
- {{0xc3,0x81}, {0x41,0xcc,0x81}},
- {{0xc3,0x82}, {0x41,0xcc,0x82}},
- {{0xe1,0xba,0xa6}, {0x41,0xcc,0x82,0xcc,0x80}},
- {{0xe1,0xba,0xa4}, {0x41,0xcc,0x82,0xcc,0x81}},
- {{0xe1,0xba,0xaa}, {0x41,0xcc,0x82,0xcc,0x83}},
- {{0xe1,0xba,0xa8}, {0x41,0xcc,0x82,0xcc,0x89}},
- {{0xc3,0x83}, {0x41,0xcc,0x83}},
- {{0xc4,0x80}, {0x41,0xcc,0x84}},
- {{0xc4,0x82}, {0x41,0xcc,0x86}},
- {{0xe1,0xba,0xb0}, {0x41,0xcc,0x86,0xcc,0x80}},
- {{0xe1,0xba,0xae}, {0x41,0xcc,0x86,0xcc,0x81}},
- {{0xe1,0xba,0xb4}, {0x41,0xcc,0x86,0xcc,0x83}},
- {{0xe1,0xba,0xb2}, {0x41,0xcc,0x86,0xcc,0x89}},
- {{0xc7,0xa0}, {0x41,0xcc,0x87,0xcc,0x84}},
- {{0xc3,0x84}, {0x41,0xcc,0x88}},
- {{0xc7,0x9e}, {0x41,0xcc,0x88,0xcc,0x84}},
- {{0xe1,0xba,0xa2}, {0x41,0xcc,0x89}},
- {{0xc3,0x85}, {0x41,0xcc,0x8a}},
- {{0xc7,0xba}, {0x41,0xcc,0x8a,0xcc,0x81}},
- {{0xc7,0x8d}, {0x41,0xcc,0x8c}},
- {{0xc8,0x80}, {0x41,0xcc,0x8f}},
- {{0xc8,0x82}, {0x41,0xcc,0x91}},
- {{0xe1,0xba,0xa0}, {0x41,0xcc,0xa3}},
- {{0xe1,0xba,0xac}, {0x41,0xcc,0xa3,0xcc,0x82}},
- {{0xe1,0xba,0xb6}, {0x41,0xcc,0xa3,0xcc,0x86}},
- {{0xe1,0xb8,0x80}, {0x41,0xcc,0xa5}},
- {{0xc4,0x84}, {0x41,0xcc,0xa8}},
- {{0xe1,0xb8,0x82}, {0x42,0xcc,0x87}},
- {{0xe1,0xb8,0x84}, {0x42,0xcc,0xa3}},
- {{0xe1,0xb8,0x86}, {0x42,0xcc,0xb1}},
- {{0xc4,0x86}, {0x43,0xcc,0x81}},
- {{0xc4,0x88}, {0x43,0xcc,0x82}},
- {{0xc4,0x8a}, {0x43,0xcc,0x87}},
- {{0xc4,0x8c}, {0x43,0xcc,0x8c}},
- {{0xc3,0x87}, {0x43,0xcc,0xa7}},
- {{0xe1,0xb8,0x88}, {0x43,0xcc,0xa7,0xcc,0x81}},
- {{0xe1,0xb8,0x8a}, {0x44,0xcc,0x87}},
- {{0xc4,0x8e}, {0x44,0xcc,0x8c}},
- {{0xe1,0xb8,0x8c}, {0x44,0xcc,0xa3}},
- {{0xe1,0xb8,0x90}, {0x44,0xcc,0xa7}},
- {{0xe1,0xb8,0x92}, {0x44,0xcc,0xad}},
- {{0xe1,0xb8,0x8e}, {0x44,0xcc,0xb1}},
- {{0xc3,0x88}, {0x45,0xcc,0x80}},
- {{0xc3,0x89}, {0x45,0xcc,0x81}},
- {{0xc3,0x8a}, {0x45,0xcc,0x82}},
- {{0xe1,0xbb,0x80}, {0x45,0xcc,0x82,0xcc,0x80}},
- {{0xe1,0xba,0xbe}, {0x45,0xcc,0x82,0xcc,0x81}},
- {{0xe1,0xbb,0x84}, {0x45,0xcc,0x82,0xcc,0x83}},
- {{0xe1,0xbb,0x82}, {0x45,0xcc,0x82,0xcc,0x89}},
- {{0xe1,0xba,0xbc}, {0x45,0xcc,0x83}},
- {{0xc4,0x92}, {0x45,0xcc,0x84}},
- {{0xe1,0xb8,0x94}, {0x45,0xcc,0x84,0xcc,0x80}},
- {{0xe1,0xb8,0x96}, {0x45,0xcc,0x84,0xcc,0x81}},
- {{0xc4,0x94}, {0x45,0xcc,0x86}},
- {{0xc4,0x96}, {0x45,0xcc,0x87}},
- {{0xc3,0x8b}, {0x45,0xcc,0x88}},
- {{0xe1,0xba,0xba}, {0x45,0xcc,0x89}},
- {{0xc4,0x9a}, {0x45,0xcc,0x8c}},
- {{0xc8,0x84}, {0x45,0xcc,0x8f}},
- {{0xc8,0x86}, {0x45,0xcc,0x91}},
- {{0xe1,0xba,0xb8}, {0x45,0xcc,0xa3}},
- {{0xe1,0xbb,0x86}, {0x45,0xcc,0xa3,0xcc,0x82}},
- {{0xe1,0xb8,0x9c}, {0x45,0xcc,0xa7,0xcc,0x86}},
- {{0xc4,0x98}, {0x45,0xcc,0xa8}},
- {{0xe1,0xb8,0x98}, {0x45,0xcc,0xad}},
- {{0xe1,0xb8,0x9a}, {0x45,0xcc,0xb0}},
- {{0xe1,0xb8,0x9e}, {0x46,0xcc,0x87}},
- {{0xc7,0xb4}, {0x47,0xcc,0x81}},
- {{0xc4,0x9c}, {0x47,0xcc,0x82}},
- {{0xe1,0xb8,0xa0}, {0x47,0xcc,0x84}},
- {{0xc4,0x9e}, {0x47,0xcc,0x86}},
- {{0xc4,0xa0}, {0x47,0xcc,0x87}},
- {{0xc7,0xa6}, {0x47,0xcc,0x8c}},
- {{0xc4,0xa2}, {0x47,0xcc,0xa7}},
- {{0xc4,0xa4}, {0x48,0xcc,0x82}},
- {{0xe1,0xb8,0xa2}, {0x48,0xcc,0x87}},
- {{0xe1,0xb8,0xa6}, {0x48,0xcc,0x88}},
- {{0xe1,0xb8,0xa4}, {0x48,0xcc,0xa3}},
- {{0xe1,0xb8,0xa8}, {0x48,0xcc,0xa7}},
- {{0xe1,0xb8,0xaa}, {0x48,0xcc,0xae}},
- {{0xc3,0x8c}, {0x49,0xcc,0x80}},
- {{0xc3,0x8d}, {0x49,0xcc,0x81}},
- {{0xc3,0x8e}, {0x49,0xcc,0x82}},
- {{0xc4,0xa8}, {0x49,0xcc,0x83}},
- {{0xc4,0xaa}, {0x49,0xcc,0x84}},
- {{0xc4,0xac}, {0x49,0xcc,0x86}},
- {{0xc4,0xb0}, {0x49,0xcc,0x87}},
- {{0xc3,0x8f}, {0x49,0xcc,0x88}},
- {{0xe1,0xb8,0xae}, {0x49,0xcc,0x88,0xcc,0x81}},
- {{0xe1,0xbb,0x88}, {0x49,0xcc,0x89}},
- {{0xc7,0x8f}, {0x49,0xcc,0x8c}},
- {{0xc8,0x88}, {0x49,0xcc,0x8f}},
- {{0xc8,0x8a}, {0x49,0xcc,0x91}},
- {{0xe1,0xbb,0x8a}, {0x49,0xcc,0xa3}},
- {{0xc4,0xae}, {0x49,0xcc,0xa8}},
- {{0xe1,0xb8,0xac}, {0x49,0xcc,0xb0}},
- {{0xc4,0xb4}, {0x4a,0xcc,0x82}},
- {{0xe1,0xb8,0xb0}, {0x4b,0xcc,0x81}},
- {{0xc7,0xa8}, {0x4b,0xcc,0x8c}},
- {{0xe1,0xb8,0xb2}, {0x4b,0xcc,0xa3}},
- {{0xc4,0xb6}, {0x4b,0xcc,0xa7}},
- {{0xe1,0xb8,0xb4}, {0x4b,0xcc,0xb1}},
- {{0xc4,0xb9}, {0x4c,0xcc,0x81}},
- {{0xc4,0xbd}, {0x4c,0xcc,0x8c}},
- {{0xe1,0xb8,0xb6}, {0x4c,0xcc,0xa3}},
- {{0xe1,0xb8,0xb8}, {0x4c,0xcc,0xa3,0xcc,0x84}},
- {{0xc4,0xbb}, {0x4c,0xcc,0xa7}},
- {{0xe1,0xb8,0xbc}, {0x4c,0xcc,0xad}},
- {{0xe1,0xb8,0xba}, {0x4c,0xcc,0xb1}},
- {{0xe1,0xb8,0xbe}, {0x4d,0xcc,0x81}},
- {{0xe1,0xb9,0x80}, {0x4d,0xcc,0x87}},
- {{0xe1,0xb9,0x82}, {0x4d,0xcc,0xa3}},
- {{0xc5,0x83}, {0x4e,0xcc,0x81}},
- {{0xc3,0x91}, {0x4e,0xcc,0x83}},
- {{0xe1,0xb9,0x84}, {0x4e,0xcc,0x87}},
- {{0xc5,0x87}, {0x4e,0xcc,0x8c}},
- {{0xe1,0xb9,0x86}, {0x4e,0xcc,0xa3}},
- {{0xc5,0x85}, {0x4e,0xcc,0xa7}},
- {{0xe1,0xb9,0x8a}, {0x4e,0xcc,0xad}},
- {{0xe1,0xb9,0x88}, {0x4e,0xcc,0xb1}},
- {{0xc3,0x92}, {0x4f,0xcc,0x80}},
- {{0xc3,0x93}, {0x4f,0xcc,0x81}},
- {{0xc3,0x94}, {0x4f,0xcc,0x82}},
- {{0xe1,0xbb,0x92}, {0x4f,0xcc,0x82,0xcc,0x80}},
- {{0xe1,0xbb,0x90}, {0x4f,0xcc,0x82,0xcc,0x81}},
- {{0xe1,0xbb,0x96}, {0x4f,0xcc,0x82,0xcc,0x83}},
- {{0xe1,0xbb,0x94}, {0x4f,0xcc,0x82,0xcc,0x89}},
- {{0xc3,0x95}, {0x4f,0xcc,0x83}},
- {{0xe1,0xb9,0x8c}, {0x4f,0xcc,0x83,0xcc,0x81}},
- {{0xe1,0xb9,0x8e}, {0x4f,0xcc,0x83,0xcc,0x88}},
- {{0xc5,0x8c}, {0x4f,0xcc,0x84}},
- {{0xe1,0xb9,0x90}, {0x4f,0xcc,0x84,0xcc,0x80}},
- {{0xe1,0xb9,0x92}, {0x4f,0xcc,0x84,0xcc,0x81}},
- {{0xc5,0x8e}, {0x4f,0xcc,0x86}},
- {{0xc3,0x96}, {0x4f,0xcc,0x88}},
- {{0xe1,0xbb,0x8e}, {0x4f,0xcc,0x89}},
- {{0xc5,0x90}, {0x4f,0xcc,0x8b}},
- {{0xc7,0x91}, {0x4f,0xcc,0x8c}},
- {{0xc8,0x8c}, {0x4f,0xcc,0x8f}},
- {{0xc8,0x8e}, {0x4f,0xcc,0x91}},
- {{0xc6,0xa0}, {0x4f,0xcc,0x9b}},
- {{0xe1,0xbb,0x9c}, {0x4f,0xcc,0x9b,0xcc,0x80}},
- {{0xe1,0xbb,0x9a}, {0x4f,0xcc,0x9b,0xcc,0x81}},
- {{0xe1,0xbb,0xa0}, {0x4f,0xcc,0x9b,0xcc,0x83}},
- {{0xe1,0xbb,0x9e}, {0x4f,0xcc,0x9b,0xcc,0x89}},
- {{0xe1,0xbb,0xa2}, {0x4f,0xcc,0x9b,0xcc,0xa3}},
- {{0xe1,0xbb,0x8c}, {0x4f,0xcc,0xa3}},
- {{0xe1,0xbb,0x98}, {0x4f,0xcc,0xa3,0xcc,0x82}},
- {{0xc7,0xaa}, {0x4f,0xcc,0xa8}},
- {{0xc7,0xac}, {0x4f,0xcc,0xa8,0xcc,0x84}},
- {{0xe1,0xb9,0x94}, {0x50,0xcc,0x81}},
- {{0xe1,0xb9,0x96}, {0x50,0xcc,0x87}},
- {{0xc5,0x94}, {0x52,0xcc,0x81}},
- {{0xe1,0xb9,0x98}, {0x52,0xcc,0x87}},
- {{0xc5,0x98}, {0x52,0xcc,0x8c}},
- {{0xc8,0x90}, {0x52,0xcc,0x8f}},
- {{0xc8,0x92}, {0x52,0xcc,0x91}},
- {{0xe1,0xb9,0x9a}, {0x52,0xcc,0xa3}},
- {{0xe1,0xb9,0x9c}, {0x52,0xcc,0xa3,0xcc,0x84}},
- {{0xc5,0x96}, {0x52,0xcc,0xa7}},
- {{0xe1,0xb9,0x9e}, {0x52,0xcc,0xb1}},
- {{0xc5,0x9a}, {0x53,0xcc,0x81}},
- {{0xe1,0xb9,0xa4}, {0x53,0xcc,0x81,0xcc,0x87}},
- {{0xc5,0x9c}, {0x53,0xcc,0x82}},
- {{0xe1,0xb9,0xa0}, {0x53,0xcc,0x87}},
- {{0xc5,0xa0}, {0x53,0xcc,0x8c}},
- {{0xe1,0xb9,0xa6}, {0x53,0xcc,0x8c,0xcc,0x87}},
- {{0xe1,0xb9,0xa2}, {0x53,0xcc,0xa3}},
- {{0xe1,0xb9,0xa8}, {0x53,0xcc,0xa3,0xcc,0x87}},
- {{0xc5,0x9e}, {0x53,0xcc,0xa7}},
- {{0xe1,0xb9,0xaa}, {0x54,0xcc,0x87}},
- {{0xc5,0xa4}, {0x54,0xcc,0x8c}},
- {{0xe1,0xb9,0xac}, {0x54,0xcc,0xa3}},
- {{0xc5,0xa2}, {0x54,0xcc,0xa7}},
- {{0xe1,0xb9,0xb0}, {0x54,0xcc,0xad}},
- {{0xe1,0xb9,0xae}, {0x54,0xcc,0xb1}},
- {{0xc3,0x99}, {0x55,0xcc,0x80}},
- {{0xc3,0x9a}, {0x55,0xcc,0x81}},
- {{0xc3,0x9b}, {0x55,0xcc,0x82}},
- {{0xc5,0xa8}, {0x55,0xcc,0x83}},
- {{0xe1,0xb9,0xb8}, {0x55,0xcc,0x83,0xcc,0x81}},
- {{0xc5,0xaa}, {0x55,0xcc,0x84}},
- {{0xe1,0xb9,0xba}, {0x55,0xcc,0x84,0xcc,0x88}},
- {{0xc5,0xac}, {0x55,0xcc,0x86}},
- {{0xc3,0x9c}, {0x55,0xcc,0x88}},
- {{0xc7,0x9b}, {0x55,0xcc,0x88,0xcc,0x80}},
- {{0xc7,0x97}, {0x55,0xcc,0x88,0xcc,0x81}},
- {{0xc7,0x95}, {0x55,0xcc,0x88,0xcc,0x84}},
- {{0xc7,0x99}, {0x55,0xcc,0x88,0xcc,0x8c}},
- {{0xe1,0xbb,0xa6}, {0x55,0xcc,0x89}},
- {{0xc5,0xae}, {0x55,0xcc,0x8a}},
- {{0xc5,0xb0}, {0x55,0xcc,0x8b}},
- {{0xc7,0x93}, {0x55,0xcc,0x8c}},
- {{0xc8,0x94}, {0x55,0xcc,0x8f}},
- {{0xc8,0x96}, {0x55,0xcc,0x91}},
- {{0xc6,0xaf}, {0x55,0xcc,0x9b}},
- {{0xe1,0xbb,0xaa}, {0x55,0xcc,0x9b,0xcc,0x80}},
- {{0xe1,0xbb,0xa8}, {0x55,0xcc,0x9b,0xcc,0x81}},
- {{0xe1,0xbb,0xae}, {0x55,0xcc,0x9b,0xcc,0x83}},
- {{0xe1,0xbb,0xac}, {0x55,0xcc,0x9b,0xcc,0x89}},
- {{0xe1,0xbb,0xb0}, {0x55,0xcc,0x9b,0xcc,0xa3}},
- {{0xe1,0xbb,0xa4}, {0x55,0xcc,0xa3}},
- {{0xe1,0xb9,0xb2}, {0x55,0xcc,0xa4}},
- {{0xc5,0xb2}, {0x55,0xcc,0xa8}},
- {{0xe1,0xb9,0xb6}, {0x55,0xcc,0xad}},
- {{0xe1,0xb9,0xb4}, {0x55,0xcc,0xb0}},
- {{0xe1,0xb9,0xbc}, {0x56,0xcc,0x83}},
- {{0xe1,0xb9,0xbe}, {0x56,0xcc,0xa3}},
- {{0xe1,0xba,0x80}, {0x57,0xcc,0x80}},
- {{0xe1,0xba,0x82}, {0x57,0xcc,0x81}},
- {{0xc5,0xb4}, {0x57,0xcc,0x82}},
- {{0xe1,0xba,0x86}, {0x57,0xcc,0x87}},
- {{0xe1,0xba,0x84}, {0x57,0xcc,0x88}},
- {{0xe1,0xba,0x88}, {0x57,0xcc,0xa3}},
- {{0xe1,0xba,0x8a}, {0x58,0xcc,0x87}},
- {{0xe1,0xba,0x8c}, {0x58,0xcc,0x88}},
- {{0xe1,0xbb,0xb2}, {0x59,0xcc,0x80}},
- {{0xc3,0x9d}, {0x59,0xcc,0x81}},
- {{0xc5,0xb6}, {0x59,0xcc,0x82}},
- {{0xe1,0xbb,0xb8}, {0x59,0xcc,0x83}},
- {{0xe1,0xba,0x8e}, {0x59,0xcc,0x87}},
- {{0xc5,0xb8}, {0x59,0xcc,0x88}},
- {{0xe1,0xbb,0xb6}, {0x59,0xcc,0x89}},
- {{0xe1,0xbb,0xb4}, {0x59,0xcc,0xa3}},
- {{0xc5,0xb9}, {0x5a,0xcc,0x81}},
- {{0xe1,0xba,0x90}, {0x5a,0xcc,0x82}},
- {{0xc5,0xbb}, {0x5a,0xcc,0x87}},
- {{0xc5,0xbd}, {0x5a,0xcc,0x8c}},
- {{0xe1,0xba,0x92}, {0x5a,0xcc,0xa3}},
- {{0xe1,0xba,0x94}, {0x5a,0xcc,0xb1}},
- {{0xe1,0xbf,0xaf}, {0x60}},
- {{0xc3,0xa0}, {0x61,0xcc,0x80}},
- {{0xc3,0xa1}, {0x61,0xcc,0x81}},
- {{0xc3,0xa2}, {0x61,0xcc,0x82}},
- {{0xe1,0xba,0xa7}, {0x61,0xcc,0x82,0xcc,0x80}},
- {{0xe1,0xba,0xa5}, {0x61,0xcc,0x82,0xcc,0x81}},
- {{0xe1,0xba,0xab}, {0x61,0xcc,0x82,0xcc,0x83}},
- {{0xe1,0xba,0xa9}, {0x61,0xcc,0x82,0xcc,0x89}},
- {{0xc3,0xa3}, {0x61,0xcc,0x83}},
- {{0xc4,0x81}, {0x61,0xcc,0x84}},
- {{0xc4,0x83}, {0x61,0xcc,0x86}},
- {{0xe1,0xba,0xb1}, {0x61,0xcc,0x86,0xcc,0x80}},
- {{0xe1,0xba,0xaf}, {0x61,0xcc,0x86,0xcc,0x81}},
- {{0xe1,0xba,0xb5}, {0x61,0xcc,0x86,0xcc,0x83}},
- {{0xe1,0xba,0xb3}, {0x61,0xcc,0x86,0xcc,0x89}},
- {{0xc7,0xa1}, {0x61,0xcc,0x87,0xcc,0x84}},
- {{0xc3,0xa4}, {0x61,0xcc,0x88}},
- {{0xc7,0x9f}, {0x61,0xcc,0x88,0xcc,0x84}},
- {{0xe1,0xba,0xa3}, {0x61,0xcc,0x89}},
- {{0xc3,0xa5}, {0x61,0xcc,0x8a}},
- {{0xc7,0xbb}, {0x61,0xcc,0x8a,0xcc,0x81}},
- {{0xc7,0x8e}, {0x61,0xcc,0x8c}},
- {{0xc8,0x81}, {0x61,0xcc,0x8f}},
- {{0xc8,0x83}, {0x61,0xcc,0x91}},
- {{0xe1,0xba,0xa1}, {0x61,0xcc,0xa3}},
- {{0xe1,0xba,0xad}, {0x61,0xcc,0xa3,0xcc,0x82}},
- {{0xe1,0xba,0xb7}, {0x61,0xcc,0xa3,0xcc,0x86}},
- {{0xe1,0xb8,0x81}, {0x61,0xcc,0xa5}},
- {{0xc4,0x85}, {0x61,0xcc,0xa8}},
- {{0xe1,0xb8,0x83}, {0x62,0xcc,0x87}},
- {{0xe1,0xb8,0x85}, {0x62,0xcc,0xa3}},
- {{0xe1,0xb8,0x87}, {0x62,0xcc,0xb1}},
- {{0xc4,0x87}, {0x63,0xcc,0x81}},
- {{0xc4,0x89}, {0x63,0xcc,0x82}},
- {{0xc4,0x8b}, {0x63,0xcc,0x87}},
- {{0xc4,0x8d}, {0x63,0xcc,0x8c}},
- {{0xc3,0xa7}, {0x63,0xcc,0xa7}},
- {{0xe1,0xb8,0x89}, {0x63,0xcc,0xa7,0xcc,0x81}},
- {{0xe1,0xb8,0x8b}, {0x64,0xcc,0x87}},
- {{0xc4,0x8f}, {0x64,0xcc,0x8c}},
- {{0xe1,0xb8,0x8d}, {0x64,0xcc,0xa3}},
- {{0xe1,0xb8,0x91}, {0x64,0xcc,0xa7}},
- {{0xe1,0xb8,0x93}, {0x64,0xcc,0xad}},
- {{0xe1,0xb8,0x8f}, {0x64,0xcc,0xb1}},
- {{0xc3,0xa8}, {0x65,0xcc,0x80}},
- {{0xc3,0xa9}, {0x65,0xcc,0x81}},
- {{0xc3,0xaa}, {0x65,0xcc,0x82}},
- {{0xe1,0xbb,0x81}, {0x65,0xcc,0x82,0xcc,0x80}},
- {{0xe1,0xba,0xbf}, {0x65,0xcc,0x82,0xcc,0x81}},
- {{0xe1,0xbb,0x85}, {0x65,0xcc,0x82,0xcc,0x83}},
- {{0xe1,0xbb,0x83}, {0x65,0xcc,0x82,0xcc,0x89}},
- {{0xe1,0xba,0xbd}, {0x65,0xcc,0x83}},
- {{0xc4,0x93}, {0x65,0xcc,0x84}},
- {{0xe1,0xb8,0x95}, {0x65,0xcc,0x84,0xcc,0x80}},
- {{0xe1,0xb8,0x97}, {0x65,0xcc,0x84,0xcc,0x81}},
- {{0xc4,0x95}, {0x65,0xcc,0x86}},
- {{0xc4,0x97}, {0x65,0xcc,0x87}},
- {{0xc3,0xab}, {0x65,0xcc,0x88}},
- {{0xe1,0xba,0xbb}, {0x65,0xcc,0x89}},
- {{0xc4,0x9b}, {0x65,0xcc,0x8c}},
- {{0xc8,0x85}, {0x65,0xcc,0x8f}},
- {{0xc8,0x87}, {0x65,0xcc,0x91}},
- {{0xe1,0xba,0xb9}, {0x65,0xcc,0xa3}},
- {{0xe1,0xbb,0x87}, {0x65,0xcc,0xa3,0xcc,0x82}},
- {{0xe1,0xb8,0x9d}, {0x65,0xcc,0xa7,0xcc,0x86}},
- {{0xc4,0x99}, {0x65,0xcc,0xa8}},
- {{0xe1,0xb8,0x99}, {0x65,0xcc,0xad}},
- {{0xe1,0xb8,0x9b}, {0x65,0xcc,0xb0}},
- {{0xe1,0xb8,0x9f}, {0x66,0xcc,0x87}},
- {{0xc7,0xb5}, {0x67,0xcc,0x81}},
- {{0xc4,0x9d}, {0x67,0xcc,0x82}},
- {{0xe1,0xb8,0xa1}, {0x67,0xcc,0x84}},
- {{0xc4,0x9f}, {0x67,0xcc,0x86}},
- {{0xc4,0xa1}, {0x67,0xcc,0x87}},
- {{0xc7,0xa7}, {0x67,0xcc,0x8c}},
- {{0xc4,0xa3}, {0x67,0xcc,0xa7}},
- {{0xc4,0xa5}, {0x68,0xcc,0x82}},
- {{0xe1,0xb8,0xa3}, {0x68,0xcc,0x87}},
- {{0xe1,0xb8,0xa7}, {0x68,0xcc,0x88}},
- {{0xe1,0xb8,0xa5}, {0x68,0xcc,0xa3}},
- {{0xe1,0xb8,0xa9}, {0x68,0xcc,0xa7}},
- {{0xe1,0xb8,0xab}, {0x68,0xcc,0xae}},
- {{0xe1,0xba,0x96}, {0x68,0xcc,0xb1}},
- {{0xc3,0xac}, {0x69,0xcc,0x80}},
- {{0xc3,0xad}, {0x69,0xcc,0x81}},
- {{0xc3,0xae}, {0x69,0xcc,0x82}},
- {{0xc4,0xa9}, {0x69,0xcc,0x83}},
- {{0xc4,0xab}, {0x69,0xcc,0x84}},
- {{0xc4,0xad}, {0x69,0xcc,0x86}},
- {{0xc3,0xaf}, {0x69,0xcc,0x88}},
- {{0xe1,0xb8,0xaf}, {0x69,0xcc,0x88,0xcc,0x81}},
- {{0xe1,0xbb,0x89}, {0x69,0xcc,0x89}},
- {{0xc7,0x90}, {0x69,0xcc,0x8c}},
- {{0xc8,0x89}, {0x69,0xcc,0x8f}},
- {{0xc8,0x8b}, {0x69,0xcc,0x91}},
- {{0xe1,0xbb,0x8b}, {0x69,0xcc,0xa3}},
- {{0xc4,0xaf}, {0x69,0xcc,0xa8}},
- {{0xe1,0xb8,0xad}, {0x69,0xcc,0xb0}},
- {{0xc4,0xb5}, {0x6a,0xcc,0x82}},
- {{0xc7,0xb0}, {0x6a,0xcc,0x8c}},
- {{0xe1,0xb8,0xb1}, {0x6b,0xcc,0x81}},
- {{0xc7,0xa9}, {0x6b,0xcc,0x8c}},
- {{0xe1,0xb8,0xb3}, {0x6b,0xcc,0xa3}},
- {{0xc4,0xb7}, {0x6b,0xcc,0xa7}},
- {{0xe1,0xb8,0xb5}, {0x6b,0xcc,0xb1}},
- {{0xc4,0xba}, {0x6c,0xcc,0x81}},
- {{0xc4,0xbe}, {0x6c,0xcc,0x8c}},
- {{0xe1,0xb8,0xb7}, {0x6c,0xcc,0xa3}},
- {{0xe1,0xb8,0xb9}, {0x6c,0xcc,0xa3,0xcc,0x84}},
- {{0xc4,0xbc}, {0x6c,0xcc,0xa7}},
- {{0xe1,0xb8,0xbd}, {0x6c,0xcc,0xad}},
- {{0xe1,0xb8,0xbb}, {0x6c,0xcc,0xb1}},
- {{0xe1,0xb8,0xbf}, {0x6d,0xcc,0x81}},
- {{0xe1,0xb9,0x81}, {0x6d,0xcc,0x87}},
- {{0xe1,0xb9,0x83}, {0x6d,0xcc,0xa3}},
- {{0xc5,0x84}, {0x6e,0xcc,0x81}},
- {{0xc3,0xb1}, {0x6e,0xcc,0x83}},
- {{0xe1,0xb9,0x85}, {0x6e,0xcc,0x87}},
- {{0xc5,0x88}, {0x6e,0xcc,0x8c}},
- {{0xe1,0xb9,0x87}, {0x6e,0xcc,0xa3}},
- {{0xc5,0x86}, {0x6e,0xcc,0xa7}},
- {{0xe1,0xb9,0x8b}, {0x6e,0xcc,0xad}},
- {{0xe1,0xb9,0x89}, {0x6e,0xcc,0xb1}},
- {{0xc3,0xb2}, {0x6f,0xcc,0x80}},
- {{0xc3,0xb3}, {0x6f,0xcc,0x81}},
- {{0xc3,0xb4}, {0x6f,0xcc,0x82}},
- {{0xe1,0xbb,0x93}, {0x6f,0xcc,0x82,0xcc,0x80}},
- {{0xe1,0xbb,0x91}, {0x6f,0xcc,0x82,0xcc,0x81}},
- {{0xe1,0xbb,0x97}, {0x6f,0xcc,0x82,0xcc,0x83}},
- {{0xe1,0xbb,0x95}, {0x6f,0xcc,0x82,0xcc,0x89}},
- {{0xc3,0xb5}, {0x6f,0xcc,0x83}},
- {{0xe1,0xb9,0x8d}, {0x6f,0xcc,0x83,0xcc,0x81}},
- {{0xe1,0xb9,0x8f}, {0x6f,0xcc,0x83,0xcc,0x88}},
- {{0xc5,0x8d}, {0x6f,0xcc,0x84}},
- {{0xe1,0xb9,0x91}, {0x6f,0xcc,0x84,0xcc,0x80}},
- {{0xe1,0xb9,0x93}, {0x6f,0xcc,0x84,0xcc,0x81}},
- {{0xc5,0x8f}, {0x6f,0xcc,0x86}},
- {{0xc3,0xb6}, {0x6f,0xcc,0x88}},
- {{0xe1,0xbb,0x8f}, {0x6f,0xcc,0x89}},
- {{0xc5,0x91}, {0x6f,0xcc,0x8b}},
- {{0xc7,0x92}, {0x6f,0xcc,0x8c}},
- {{0xc8,0x8d}, {0x6f,0xcc,0x8f}},
- {{0xc8,0x8f}, {0x6f,0xcc,0x91}},
- {{0xc6,0xa1}, {0x6f,0xcc,0x9b}},
- {{0xe1,0xbb,0x9d}, {0x6f,0xcc,0x9b,0xcc,0x80}},
- {{0xe1,0xbb,0x9b}, {0x6f,0xcc,0x9b,0xcc,0x81}},
- {{0xe1,0xbb,0xa1}, {0x6f,0xcc,0x9b,0xcc,0x83}},
- {{0xe1,0xbb,0x9f}, {0x6f,0xcc,0x9b,0xcc,0x89}},
- {{0xe1,0xbb,0xa3}, {0x6f,0xcc,0x9b,0xcc,0xa3}},
- {{0xe1,0xbb,0x8d}, {0x6f,0xcc,0xa3}},
- {{0xe1,0xbb,0x99}, {0x6f,0xcc,0xa3,0xcc,0x82}},
- {{0xc7,0xab}, {0x6f,0xcc,0xa8}},
- {{0xc7,0xad}, {0x6f,0xcc,0xa8,0xcc,0x84}},
- {{0xe1,0xb9,0x95}, {0x70,0xcc,0x81}},
- {{0xe1,0xb9,0x97}, {0x70,0xcc,0x87}},
- {{0xc5,0x95}, {0x72,0xcc,0x81}},
- {{0xe1,0xb9,0x99}, {0x72,0xcc,0x87}},
- {{0xc5,0x99}, {0x72,0xcc,0x8c}},
- {{0xc8,0x91}, {0x72,0xcc,0x8f}},
- {{0xc8,0x93}, {0x72,0xcc,0x91}},
- {{0xe1,0xb9,0x9b}, {0x72,0xcc,0xa3}},
- {{0xe1,0xb9,0x9d}, {0x72,0xcc,0xa3,0xcc,0x84}},
- {{0xc5,0x97}, {0x72,0xcc,0xa7}},
- {{0xe1,0xb9,0x9f}, {0x72,0xcc,0xb1}},
- {{0xc5,0x9b}, {0x73,0xcc,0x81}},
- {{0xe1,0xb9,0xa5}, {0x73,0xcc,0x81,0xcc,0x87}},
- {{0xc5,0x9d}, {0x73,0xcc,0x82}},
- {{0xe1,0xb9,0xa1}, {0x73,0xcc,0x87}},
- {{0xc5,0xa1}, {0x73,0xcc,0x8c}},
- {{0xe1,0xb9,0xa7}, {0x73,0xcc,0x8c,0xcc,0x87}},
- {{0xe1,0xb9,0xa3}, {0x73,0xcc,0xa3}},
- {{0xe1,0xb9,0xa9}, {0x73,0xcc,0xa3,0xcc,0x87}},
- {{0xc5,0x9f}, {0x73,0xcc,0xa7}},
- {{0xe1,0xb9,0xab}, {0x74,0xcc,0x87}},
- {{0xe1,0xba,0x97}, {0x74,0xcc,0x88}},
- {{0xc5,0xa5}, {0x74,0xcc,0x8c}},
- {{0xe1,0xb9,0xad}, {0x74,0xcc,0xa3}},
- {{0xc5,0xa3}, {0x74,0xcc,0xa7}},
- {{0xe1,0xb9,0xb1}, {0x74,0xcc,0xad}},
- {{0xe1,0xb9,0xaf}, {0x74,0xcc,0xb1}},
- {{0xc3,0xb9}, {0x75,0xcc,0x80}},
- {{0xc3,0xba}, {0x75,0xcc,0x81}},
- {{0xc3,0xbb}, {0x75,0xcc,0x82}},
- {{0xc5,0xa9}, {0x75,0xcc,0x83}},
- {{0xe1,0xb9,0xb9}, {0x75,0xcc,0x83,0xcc,0x81}},
- {{0xc5,0xab}, {0x75,0xcc,0x84}},
- {{0xe1,0xb9,0xbb}, {0x75,0xcc,0x84,0xcc,0x88}},
- {{0xc5,0xad}, {0x75,0xcc,0x86}},
- {{0xc3,0xbc}, {0x75,0xcc,0x88}},
- {{0xc7,0x9c}, {0x75,0xcc,0x88,0xcc,0x80}},
- {{0xc7,0x98}, {0x75,0xcc,0x88,0xcc,0x81}},
- {{0xc7,0x96}, {0x75,0xcc,0x88,0xcc,0x84}},
- {{0xc7,0x9a}, {0x75,0xcc,0x88,0xcc,0x8c}},
- {{0xe1,0xbb,0xa7}, {0x75,0xcc,0x89}},
- {{0xc5,0xaf}, {0x75,0xcc,0x8a}},
- {{0xc5,0xb1}, {0x75,0xcc,0x8b}},
- {{0xc7,0x94}, {0x75,0xcc,0x8c}},
- {{0xc8,0x95}, {0x75,0xcc,0x8f}},
- {{0xc8,0x97}, {0x75,0xcc,0x91}},
- {{0xc6,0xb0}, {0x75,0xcc,0x9b}},
- {{0xe1,0xbb,0xab}, {0x75,0xcc,0x9b,0xcc,0x80}},
- {{0xe1,0xbb,0xa9}, {0x75,0xcc,0x9b,0xcc,0x81}},
- {{0xe1,0xbb,0xaf}, {0x75,0xcc,0x9b,0xcc,0x83}},
- {{0xe1,0xbb,0xad}, {0x75,0xcc,0x9b,0xcc,0x89}},
- {{0xe1,0xbb,0xb1}, {0x75,0xcc,0x9b,0xcc,0xa3}},
- {{0xe1,0xbb,0xa5}, {0x75,0xcc,0xa3}},
- {{0xe1,0xb9,0xb3}, {0x75,0xcc,0xa4}},
- {{0xc5,0xb3}, {0x75,0xcc,0xa8}},
- {{0xe1,0xb9,0xb7}, {0x75,0xcc,0xad}},
- {{0xe1,0xb9,0xb5}, {0x75,0xcc,0xb0}},
- {{0xe1,0xb9,0xbd}, {0x76,0xcc,0x83}},
- {{0xe1,0xb9,0xbf}, {0x76,0xcc,0xa3}},
- {{0xe1,0xba,0x81}, {0x77,0xcc,0x80}},
- {{0xe1,0xba,0x83}, {0x77,0xcc,0x81}},
- {{0xc5,0xb5}, {0x77,0xcc,0x82}},
- {{0xe1,0xba,0x87}, {0x77,0xcc,0x87}},
- {{0xe1,0xba,0x85}, {0x77,0xcc,0x88}},
- {{0xe1,0xba,0x98}, {0x77,0xcc,0x8a}},
- {{0xe1,0xba,0x89}, {0x77,0xcc,0xa3}},
- {{0xe1,0xba,0x8b}, {0x78,0xcc,0x87}},
- {{0xe1,0xba,0x8d}, {0x78,0xcc,0x88}},
- {{0xe1,0xbb,0xb3}, {0x79,0xcc,0x80}},
- {{0xc3,0xbd}, {0x79,0xcc,0x81}},
- {{0xc5,0xb7}, {0x79,0xcc,0x82}},
- {{0xe1,0xbb,0xb9}, {0x79,0xcc,0x83}},
- {{0xe1,0xba,0x8f}, {0x79,0xcc,0x87}},
- {{0xc3,0xbf}, {0x79,0xcc,0x88}},
- {{0xe1,0xbb,0xb7}, {0x79,0xcc,0x89}},
- {{0xe1,0xba,0x99}, {0x79,0xcc,0x8a}},
- {{0xe1,0xbb,0xb5}, {0x79,0xcc,0xa3}},
- {{0xc5,0xba}, {0x7a,0xcc,0x81}},
- {{0xe1,0xba,0x91}, {0x7a,0xcc,0x82}},
- {{0xc5,0xbc}, {0x7a,0xcc,0x87}},
- {{0xc5,0xbe}, {0x7a,0xcc,0x8c}},
- {{0xe1,0xba,0x93}, {0x7a,0xcc,0xa3}},
- {{0xe1,0xba,0x95}, {0x7a,0xcc,0xb1}},
- {{0xe1,0xbf,0xad}, {0xc2,0xa8,0xcc,0x80}},
- {{0xe1,0xbf,0xae}, {0xc2,0xa8,0xcc,0x81}},
- {{0xce,0x85}, {0xc2,0xa8,0xcc,0x8d}},
- {{0xe1,0xbf,0x81}, {0xc2,0xa8,0xcd,0x82}},
- {{0xe1,0xbf,0xbd}, {0xc2,0xb4}},
- {{0xce,0x87}, {0xc2,0xb7}},
- {{0xd3,0x94}, {0xc3,0x86}},
- {{0xc7,0xbc}, {0xc3,0x86,0xcc,0x81}},
- {{0xc7,0xa2}, {0xc3,0x86,0xcc,0x84}},
- {{0xc7,0xbe}, {0xc3,0x98,0xcc,0x81}},
- {{0xd3,0x95}, {0xc3,0xa6}},
- {{0xc7,0xbd}, {0xc3,0xa6,0xcc,0x81}},
- {{0xc7,0xa3}, {0xc3,0xa6,0xcc,0x84}},
- {{0xc7,0xbf}, {0xc3,0xb8,0xcc,0x81}},
- {{0xe1,0xba,0x9b}, {0xc5,0xbf,0xcc,0x87}},
- {{0xd3,0x98}, {0xc6,0x8f}},
- {{0xd3,0x9a}, {0xc6,0x8f,0xcc,0x88}},
- {{0xd3,0xa8}, {0xc6,0x9f}},
- {{0xd3,0xaa}, {0xc6,0x9f,0xcc,0x88}},
- {{0xd3,0xa0}, {0xc6,0xb7}},
- {{0xc7,0xae}, {0xc6,0xb7,0xcc,0x8c}},
- {{0xd3,0x99}, {0xc9,0x99}},
- {{0xd3,0x9b}, {0xc9,0x99,0xcc,0x88}},
- {{0xd3,0xa9}, {0xc9,0xb5}},
- {{0xd3,0xab}, {0xc9,0xb5,0xcc,0x88}},
- {{0xd3,0xa1}, {0xca,0x92}},
- {{0xc7,0xaf}, {0xca,0x92,0xcc,0x8c}},
- {{0xcd,0xb4}, {0xca,0xb9}},
- {{0xcd,0x80}, {0xcc,0x80}},
- {{0xcd,0x81}, {0xcc,0x81}},
- {{0xcc,0x90}, {0xcc,0x86,0xcc,0x87}},
- {{0xcd,0x84}, {0xcc,0x88,0xcc,0x8d}},
- {{0xcd,0x83}, {0xcc,0x93}},
- {{0xe1,0xbe,0xba}, {0xce,0x91,0xcc,0x80}},
- {{0xe1,0xbe,0xbb}, {0xce,0x91,0xcc,0x81}},
- {{0xe1,0xbe,0xb9}, {0xce,0x91,0xcc,0x84}},
- {{0xe1,0xbe,0xb8}, {0xce,0x91,0xcc,0x86}},
- {{0xce,0x86}, {0xce,0x91,0xcc,0x8d}},
- {{0xe1,0xbc,0x88}, {0xce,0x91,0xcc,0x93}},
- {{0xe1,0xbc,0x8a}, {0xce,0x91,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbc,0x8c}, {0xce,0x91,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbc,0x8e}, {0xce,0x91,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbc,0x89}, {0xce,0x91,0xcc,0x94}},
- {{0xe1,0xbc,0x8b}, {0xce,0x91,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbc,0x8d}, {0xce,0x91,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbc,0x8f}, {0xce,0x91,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbe,0xbc}, {0xce,0x91,0xcd,0x85}},
- {{0xe1,0xbe,0x88}, {0xce,0x91,0xcd,0x85,0xcc,0x93}},
- {{0xe1,0xbe,0x8a}, {0xce,0x91,0xcd,0x85,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbe,0x8c}, {0xce,0x91,0xcd,0x85,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbe,0x8e}, {0xce,0x91,0xcd,0x85,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbe,0x89}, {0xce,0x91,0xcd,0x85,0xcc,0x94}},
- {{0xe1,0xbe,0x8b}, {0xce,0x91,0xcd,0x85,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbe,0x8d}, {0xce,0x91,0xcd,0x85,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbe,0x8f}, {0xce,0x91,0xcd,0x85,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbf,0x88}, {0xce,0x95,0xcc,0x80}},
- {{0xe1,0xbf,0x89}, {0xce,0x95,0xcc,0x81}},
- {{0xce,0x88}, {0xce,0x95,0xcc,0x8d}},
- {{0xe1,0xbc,0x98}, {0xce,0x95,0xcc,0x93}},
- {{0xe1,0xbc,0x9a}, {0xce,0x95,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbc,0x9c}, {0xce,0x95,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbc,0x99}, {0xce,0x95,0xcc,0x94}},
- {{0xe1,0xbc,0x9b}, {0xce,0x95,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbc,0x9d}, {0xce,0x95,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbf,0x8a}, {0xce,0x97,0xcc,0x80}},
- {{0xe1,0xbf,0x8b}, {0xce,0x97,0xcc,0x81}},
- {{0xce,0x89}, {0xce,0x97,0xcc,0x8d}},
- {{0xe1,0xbc,0xa8}, {0xce,0x97,0xcc,0x93}},
- {{0xe1,0xbc,0xaa}, {0xce,0x97,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbc,0xac}, {0xce,0x97,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbc,0xae}, {0xce,0x97,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbc,0xa9}, {0xce,0x97,0xcc,0x94}},
- {{0xe1,0xbc,0xab}, {0xce,0x97,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbc,0xad}, {0xce,0x97,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbc,0xaf}, {0xce,0x97,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbf,0x8c}, {0xce,0x97,0xcd,0x85}},
- {{0xe1,0xbe,0x98}, {0xce,0x97,0xcd,0x85,0xcc,0x93}},
- {{0xe1,0xbe,0x9a}, {0xce,0x97,0xcd,0x85,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbe,0x9c}, {0xce,0x97,0xcd,0x85,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbe,0x9e}, {0xce,0x97,0xcd,0x85,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbe,0x99}, {0xce,0x97,0xcd,0x85,0xcc,0x94}},
- {{0xe1,0xbe,0x9b}, {0xce,0x97,0xcd,0x85,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbe,0x9d}, {0xce,0x97,0xcd,0x85,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbe,0x9f}, {0xce,0x97,0xcd,0x85,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbf,0x9a}, {0xce,0x99,0xcc,0x80}},
- {{0xe1,0xbf,0x9b}, {0xce,0x99,0xcc,0x81}},
- {{0xe1,0xbf,0x99}, {0xce,0x99,0xcc,0x84}},
- {{0xe1,0xbf,0x98}, {0xce,0x99,0xcc,0x86}},
- {{0xce,0xaa}, {0xce,0x99,0xcc,0x88}},
- {{0xce,0x8a}, {0xce,0x99,0xcc,0x8d}},
- {{0xe1,0xbc,0xb8}, {0xce,0x99,0xcc,0x93}},
- {{0xe1,0xbc,0xba}, {0xce,0x99,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbc,0xbc}, {0xce,0x99,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbc,0xbe}, {0xce,0x99,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbc,0xb9}, {0xce,0x99,0xcc,0x94}},
- {{0xe1,0xbc,0xbb}, {0xce,0x99,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbc,0xbd}, {0xce,0x99,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbc,0xbf}, {0xce,0x99,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbf,0xb8}, {0xce,0x9f,0xcc,0x80}},
- {{0xe1,0xbf,0xb9}, {0xce,0x9f,0xcc,0x81}},
- {{0xce,0x8c}, {0xce,0x9f,0xcc,0x8d}},
- {{0xe1,0xbd,0x88}, {0xce,0x9f,0xcc,0x93}},
- {{0xe1,0xbd,0x8a}, {0xce,0x9f,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbd,0x8c}, {0xce,0x9f,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbd,0x89}, {0xce,0x9f,0xcc,0x94}},
- {{0xe1,0xbd,0x8b}, {0xce,0x9f,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbd,0x8d}, {0xce,0x9f,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbf,0xac}, {0xce,0xa1,0xcc,0x94}},
- {{0xe1,0xbf,0xaa}, {0xce,0xa5,0xcc,0x80}},
- {{0xe1,0xbf,0xab}, {0xce,0xa5,0xcc,0x81}},
- {{0xe1,0xbf,0xa9}, {0xce,0xa5,0xcc,0x84}},
- {{0xe1,0xbf,0xa8}, {0xce,0xa5,0xcc,0x86}},
- {{0xce,0xab}, {0xce,0xa5,0xcc,0x88}},
- {{0xce,0x8e}, {0xce,0xa5,0xcc,0x8d}},
- {{0xe1,0xbd,0x99}, {0xce,0xa5,0xcc,0x94}},
- {{0xe1,0xbd,0x9b}, {0xce,0xa5,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbd,0x9d}, {0xce,0xa5,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbd,0x9f}, {0xce,0xa5,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbf,0xba}, {0xce,0xa9,0xcc,0x80}},
- {{0xe1,0xbf,0xbb}, {0xce,0xa9,0xcc,0x81}},
- {{0xce,0x8f}, {0xce,0xa9,0xcc,0x8d}},
- {{0xe1,0xbd,0xa8}, {0xce,0xa9,0xcc,0x93}},
- {{0xe1,0xbd,0xaa}, {0xce,0xa9,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbd,0xac}, {0xce,0xa9,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbd,0xae}, {0xce,0xa9,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbd,0xa9}, {0xce,0xa9,0xcc,0x94}},
- {{0xe1,0xbd,0xab}, {0xce,0xa9,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbd,0xad}, {0xce,0xa9,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbd,0xaf}, {0xce,0xa9,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbf,0xbc}, {0xce,0xa9,0xcd,0x85}},
- {{0xe1,0xbe,0xa8}, {0xce,0xa9,0xcd,0x85,0xcc,0x93}},
- {{0xe1,0xbe,0xaa}, {0xce,0xa9,0xcd,0x85,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbe,0xac}, {0xce,0xa9,0xcd,0x85,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbe,0xae}, {0xce,0xa9,0xcd,0x85,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbe,0xa9}, {0xce,0xa9,0xcd,0x85,0xcc,0x94}},
- {{0xe1,0xbe,0xab}, {0xce,0xa9,0xcd,0x85,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbe,0xad}, {0xce,0xa9,0xcd,0x85,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbe,0xaf}, {0xce,0xa9,0xcd,0x85,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbd,0xb0}, {0xce,0xb1,0xcc,0x80}},
- {{0xe1,0xbd,0xb1}, {0xce,0xb1,0xcc,0x81}},
- {{0xe1,0xbe,0xb1}, {0xce,0xb1,0xcc,0x84}},
- {{0xe1,0xbe,0xb0}, {0xce,0xb1,0xcc,0x86}},
- {{0xce,0xac}, {0xce,0xb1,0xcc,0x8d}},
- {{0xe1,0xbc,0x80}, {0xce,0xb1,0xcc,0x93}},
- {{0xe1,0xbc,0x82}, {0xce,0xb1,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbc,0x84}, {0xce,0xb1,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbc,0x86}, {0xce,0xb1,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbc,0x81}, {0xce,0xb1,0xcc,0x94}},
- {{0xe1,0xbc,0x83}, {0xce,0xb1,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbc,0x85}, {0xce,0xb1,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbc,0x87}, {0xce,0xb1,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbe,0xb6}, {0xce,0xb1,0xcd,0x82}},
- {{0xe1,0xbe,0xb3}, {0xce,0xb1,0xcd,0x85}},
- {{0xe1,0xbe,0xb2}, {0xce,0xb1,0xcd,0x85,0xcc,0x80}},
- {{0xe1,0xbe,0xb4}, {0xce,0xb1,0xcd,0x85,0xcc,0x81}},
- {{0xe1,0xbe,0x80}, {0xce,0xb1,0xcd,0x85,0xcc,0x93}},
- {{0xe1,0xbe,0x82}, {0xce,0xb1,0xcd,0x85,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbe,0x84}, {0xce,0xb1,0xcd,0x85,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbe,0x86}, {0xce,0xb1,0xcd,0x85,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbe,0x81}, {0xce,0xb1,0xcd,0x85,0xcc,0x94}},
- {{0xe1,0xbe,0x83}, {0xce,0xb1,0xcd,0x85,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbe,0x85}, {0xce,0xb1,0xcd,0x85,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbe,0x87}, {0xce,0xb1,0xcd,0x85,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbe,0xb7}, {0xce,0xb1,0xcd,0x85,0xcd,0x82}},
- {{0xe1,0xbd,0xb2}, {0xce,0xb5,0xcc,0x80}},
- {{0xe1,0xbd,0xb3}, {0xce,0xb5,0xcc,0x81}},
- {{0xce,0xad}, {0xce,0xb5,0xcc,0x8d}},
- {{0xe1,0xbc,0x90}, {0xce,0xb5,0xcc,0x93}},
- {{0xe1,0xbc,0x92}, {0xce,0xb5,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbc,0x94}, {0xce,0xb5,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbc,0x91}, {0xce,0xb5,0xcc,0x94}},
- {{0xe1,0xbc,0x93}, {0xce,0xb5,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbc,0x95}, {0xce,0xb5,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbd,0xb4}, {0xce,0xb7,0xcc,0x80}},
- {{0xe1,0xbd,0xb5}, {0xce,0xb7,0xcc,0x81}},
- {{0xce,0xae}, {0xce,0xb7,0xcc,0x8d}},
- {{0xe1,0xbc,0xa0}, {0xce,0xb7,0xcc,0x93}},
- {{0xe1,0xbc,0xa2}, {0xce,0xb7,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbc,0xa4}, {0xce,0xb7,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbc,0xa6}, {0xce,0xb7,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbc,0xa1}, {0xce,0xb7,0xcc,0x94}},
- {{0xe1,0xbc,0xa3}, {0xce,0xb7,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbc,0xa5}, {0xce,0xb7,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbc,0xa7}, {0xce,0xb7,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbf,0x86}, {0xce,0xb7,0xcd,0x82}},
- {{0xe1,0xbf,0x83}, {0xce,0xb7,0xcd,0x85}},
- {{0xe1,0xbf,0x82}, {0xce,0xb7,0xcd,0x85,0xcc,0x80}},
- {{0xe1,0xbf,0x84}, {0xce,0xb7,0xcd,0x85,0xcc,0x81}},
- {{0xe1,0xbe,0x90}, {0xce,0xb7,0xcd,0x85,0xcc,0x93}},
- {{0xe1,0xbe,0x92}, {0xce,0xb7,0xcd,0x85,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbe,0x94}, {0xce,0xb7,0xcd,0x85,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbe,0x96}, {0xce,0xb7,0xcd,0x85,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbe,0x91}, {0xce,0xb7,0xcd,0x85,0xcc,0x94}},
- {{0xe1,0xbe,0x93}, {0xce,0xb7,0xcd,0x85,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbe,0x95}, {0xce,0xb7,0xcd,0x85,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbe,0x97}, {0xce,0xb7,0xcd,0x85,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbf,0x87}, {0xce,0xb7,0xcd,0x85,0xcd,0x82}},
- {{0xe1,0xbe,0xbe}, {0xce,0xb9}},
- {{0xe1,0xbd,0xb6}, {0xce,0xb9,0xcc,0x80}},
- {{0xe1,0xbd,0xb7}, {0xce,0xb9,0xcc,0x81}},
- {{0xe1,0xbf,0x91}, {0xce,0xb9,0xcc,0x84}},
- {{0xe1,0xbf,0x90}, {0xce,0xb9,0xcc,0x86}},
- {{0xcf,0x8a}, {0xce,0xb9,0xcc,0x88}},
- {{0xe1,0xbf,0x92}, {0xce,0xb9,0xcc,0x88,0xcc,0x80}},
- {{0xe1,0xbf,0x93}, {0xce,0xb9,0xcc,0x88,0xcc,0x81}},
- {{0xce,0x90}, {0xce,0xb9,0xcc,0x88,0xcc,0x8d}},
- {{0xe1,0xbf,0x97}, {0xce,0xb9,0xcc,0x88,0xcd,0x82}},
- {{0xce,0xaf}, {0xce,0xb9,0xcc,0x8d}},
- {{0xe1,0xbc,0xb0}, {0xce,0xb9,0xcc,0x93}},
- {{0xe1,0xbc,0xb2}, {0xce,0xb9,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbc,0xb4}, {0xce,0xb9,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbc,0xb6}, {0xce,0xb9,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbc,0xb1}, {0xce,0xb9,0xcc,0x94}},
- {{0xe1,0xbc,0xb3}, {0xce,0xb9,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbc,0xb5}, {0xce,0xb9,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbc,0xb7}, {0xce,0xb9,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbf,0x96}, {0xce,0xb9,0xcd,0x82}},
- {{0xe1,0xbd,0xb8}, {0xce,0xbf,0xcc,0x80}},
- {{0xe1,0xbd,0xb9}, {0xce,0xbf,0xcc,0x81}},
- {{0xcf,0x8c}, {0xce,0xbf,0xcc,0x8d}},
- {{0xe1,0xbd,0x80}, {0xce,0xbf,0xcc,0x93}},
- {{0xe1,0xbd,0x82}, {0xce,0xbf,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbd,0x84}, {0xce,0xbf,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbd,0x81}, {0xce,0xbf,0xcc,0x94}},
- {{0xe1,0xbd,0x83}, {0xce,0xbf,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbd,0x85}, {0xce,0xbf,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbf,0xb4}, {0xce,0xbf,0xcd,0x85,0xcc,0x81}},
- {{0xe1,0xbf,0xa4}, {0xcf,0x81,0xcc,0x93}},
- {{0xe1,0xbf,0xa5}, {0xcf,0x81,0xcc,0x94}},
- {{0xe1,0xbd,0xba}, {0xcf,0x85,0xcc,0x80}},
- {{0xe1,0xbd,0xbb}, {0xcf,0x85,0xcc,0x81}},
- {{0xe1,0xbf,0xa1}, {0xcf,0x85,0xcc,0x84}},
- {{0xe1,0xbf,0xa0}, {0xcf,0x85,0xcc,0x86}},
- {{0xcf,0x8b}, {0xcf,0x85,0xcc,0x88}},
- {{0xe1,0xbf,0xa2}, {0xcf,0x85,0xcc,0x88,0xcc,0x80}},
- {{0xe1,0xbf,0xa3}, {0xcf,0x85,0xcc,0x88,0xcc,0x81}},
- {{0xce,0xb0}, {0xcf,0x85,0xcc,0x88,0xcc,0x8d}},
- {{0xe1,0xbf,0xa7}, {0xcf,0x85,0xcc,0x88,0xcd,0x82}},
- {{0xcf,0x8d}, {0xcf,0x85,0xcc,0x8d}},
- {{0xe1,0xbd,0x90}, {0xcf,0x85,0xcc,0x93}},
- {{0xe1,0xbd,0x92}, {0xcf,0x85,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbd,0x94}, {0xcf,0x85,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbd,0x96}, {0xcf,0x85,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbd,0x91}, {0xcf,0x85,0xcc,0x94}},
- {{0xe1,0xbd,0x93}, {0xcf,0x85,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbd,0x95}, {0xcf,0x85,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbd,0x97}, {0xcf,0x85,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbf,0xa6}, {0xcf,0x85,0xcd,0x82}},
- {{0xe1,0xbd,0xbc}, {0xcf,0x89,0xcc,0x80}},
- {{0xe1,0xbd,0xbd}, {0xcf,0x89,0xcc,0x81}},
- {{0xcf,0x8e}, {0xcf,0x89,0xcc,0x8d}},
- {{0xe1,0xbd,0xa0}, {0xcf,0x89,0xcc,0x93}},
- {{0xe1,0xbd,0xa2}, {0xcf,0x89,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbd,0xa4}, {0xcf,0x89,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbd,0xa6}, {0xcf,0x89,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbd,0xa1}, {0xcf,0x89,0xcc,0x94}},
- {{0xe1,0xbd,0xa3}, {0xcf,0x89,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbd,0xa5}, {0xcf,0x89,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbd,0xa7}, {0xcf,0x89,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbf,0xb6}, {0xcf,0x89,0xcd,0x82}},
- {{0xe1,0xbf,0xb3}, {0xcf,0x89,0xcd,0x85}},
- {{0xe1,0xbf,0xb2}, {0xcf,0x89,0xcd,0x85,0xcc,0x80}},
- {{0xe1,0xbe,0xa0}, {0xcf,0x89,0xcd,0x85,0xcc,0x93}},
- {{0xe1,0xbe,0xa2}, {0xcf,0x89,0xcd,0x85,0xcc,0x93,0xcc,0x80}},
- {{0xe1,0xbe,0xa4}, {0xcf,0x89,0xcd,0x85,0xcc,0x93,0xcc,0x81}},
- {{0xe1,0xbe,0xa6}, {0xcf,0x89,0xcd,0x85,0xcc,0x93,0xcd,0x82}},
- {{0xe1,0xbe,0xa1}, {0xcf,0x89,0xcd,0x85,0xcc,0x94}},
- {{0xe1,0xbe,0xa3}, {0xcf,0x89,0xcd,0x85,0xcc,0x94,0xcc,0x80}},
- {{0xe1,0xbe,0xa5}, {0xcf,0x89,0xcd,0x85,0xcc,0x94,0xcc,0x81}},
- {{0xe1,0xbe,0xa7}, {0xcf,0x89,0xcd,0x85,0xcc,0x94,0xcd,0x82}},
- {{0xe1,0xbf,0xb7}, {0xcf,0x89,0xcd,0x85,0xcd,0x82}},
- {{0xcf,0x94}, {0xcf,0x92,0xcc,0x88}},
- {{0xcf,0x93}, {0xcf,0x92,0xcc,0x8d}},
- {{0xd0,0x87}, {0xd0,0x86,0xcc,0x88}},
- {{0xd3,0x90}, {0xd0,0x90,0xcc,0x86}},
- {{0xd3,0x92}, {0xd0,0x90,0xcc,0x88}},
- {{0xd0,0x83}, {0xd0,0x93,0xcc,0x81}},
- {{0xd3,0x96}, {0xd0,0x95,0xcc,0x86}},
- {{0xd0,0x81}, {0xd0,0x95,0xcc,0x88}},
- {{0xd3,0x81}, {0xd0,0x96,0xcc,0x86}},
- {{0xd3,0x9c}, {0xd0,0x96,0xcc,0x88}},
- {{0xd3,0x9e}, {0xd0,0x97,0xcc,0x88}},
- {{0xd3,0xa2}, {0xd0,0x98,0xcc,0x84}},
- {{0xd0,0x99}, {0xd0,0x98,0xcc,0x86}},
- {{0xd3,0xa4}, {0xd0,0x98,0xcc,0x88}},
- {{0xd0,0x8c}, {0xd0,0x9a,0xcc,0x81}},
- {{0xd3,0xa6}, {0xd0,0x9e,0xcc,0x88}},
- {{0xd3,0xae}, {0xd0,0xa3,0xcc,0x84}},
- {{0xd0,0x8e}, {0xd0,0xa3,0xcc,0x86}},
- {{0xd3,0xb0}, {0xd0,0xa3,0xcc,0x88}},
- {{0xd3,0xb2}, {0xd0,0xa3,0xcc,0x8b}},
- {{0xd3,0xb4}, {0xd0,0xa7,0xcc,0x88}},
- {{0xd3,0xb8}, {0xd0,0xab,0xcc,0x88}},
- {{0xd3,0x91}, {0xd0,0xb0,0xcc,0x86}},
- {{0xd3,0x93}, {0xd0,0xb0,0xcc,0x88}},
- {{0xd1,0x93}, {0xd0,0xb3,0xcc,0x81}},
- {{0xd3,0x97}, {0xd0,0xb5,0xcc,0x86}},
- {{0xd1,0x91}, {0xd0,0xb5,0xcc,0x88}},
- {{0xd3,0x82}, {0xd0,0xb6,0xcc,0x86}},
- {{0xd3,0x9d}, {0xd0,0xb6,0xcc,0x88}},
- {{0xd3,0x9f}, {0xd0,0xb7,0xcc,0x88}},
- {{0xd3,0xa3}, {0xd0,0xb8,0xcc,0x84}},
- {{0xd0,0xb9}, {0xd0,0xb8,0xcc,0x86}},
- {{0xd3,0xa5}, {0xd0,0xb8,0xcc,0x88}},
- {{0xd1,0x9c}, {0xd0,0xba,0xcc,0x81}},
- {{0xd3,0xa7}, {0xd0,0xbe,0xcc,0x88}},
- {{0xd3,0xaf}, {0xd1,0x83,0xcc,0x84}},
- {{0xd1,0x9e}, {0xd1,0x83,0xcc,0x86}},
- {{0xd3,0xb1}, {0xd1,0x83,0xcc,0x88}},
- {{0xd3,0xb3}, {0xd1,0x83,0xcc,0x8b}},
- {{0xd3,0xb5}, {0xd1,0x87,0xcc,0x88}},
- {{0xd3,0xb9}, {0xd1,0x8b,0xcc,0x88}},
- {{0xd1,0x97}, {0xd1,0x96,0xcc,0x88}},
- {{0xd1,0xb6}, {0xd1,0xb4,0xcc,0x8f}},
- {{0xd1,0xb7}, {0xd1,0xb5,0xcc,0x8f}},
- {{0xef,0xac,0xae}, {0xd7,0x90,0xd6,0xb7}},
- {{0xef,0xac,0xaf}, {0xd7,0x90,0xd6,0xb8}},
- {{0xef,0xac,0xb0}, {0xd7,0x90,0xd6,0xbc}},
- {{0xef,0xac,0xb1}, {0xd7,0x91,0xd6,0xbc}},
- {{0xef,0xad,0x8c}, {0xd7,0x91,0xd6,0xbf}},
- {{0xef,0xac,0xb2}, {0xd7,0x92,0xd6,0xbc}},
- {{0xef,0xac,0xb3}, {0xd7,0x93,0xd6,0xbc}},
- {{0xef,0xac,0xb4}, {0xd7,0x94,0xd6,0xbc}},
- {{0xef,0xad,0x8b}, {0xd7,0x95,0xd6,0xb9}},
- {{0xef,0xac,0xb5}, {0xd7,0x95,0xd6,0xbc}},
- {{0xef,0xac,0xb6}, {0xd7,0x96,0xd6,0xbc}},
- {{0xef,0xac,0xb8}, {0xd7,0x98,0xd6,0xbc}},
- {{0xef,0xac,0xb9}, {0xd7,0x99,0xd6,0xbc}},
- {{0xef,0xac,0xba}, {0xd7,0x9a,0xd6,0xbc}},
- {{0xef,0xac,0xbb}, {0xd7,0x9b,0xd6,0xbc}},
- {{0xef,0xad,0x8d}, {0xd7,0x9b,0xd6,0xbf}},
- {{0xef,0xac,0xbc}, {0xd7,0x9c,0xd6,0xbc}},
- {{0xef,0xac,0xbe}, {0xd7,0x9e,0xd6,0xbc}},
- {{0xef,0xad,0x80}, {0xd7,0xa0,0xd6,0xbc}},
- {{0xef,0xad,0x81}, {0xd7,0xa1,0xd6,0xbc}},
- {{0xef,0xad,0x83}, {0xd7,0xa3,0xd6,0xbc}},
- {{0xef,0xad,0x84}, {0xd7,0xa4,0xd6,0xbc}},
- {{0xef,0xad,0x8e}, {0xd7,0xa4,0xd6,0xbf}},
- {{0xef,0xad,0x86}, {0xd7,0xa6,0xd6,0xbc}},
- {{0xef,0xad,0x87}, {0xd7,0xa7,0xd6,0xbc}},
- {{0xef,0xad,0x88}, {0xd7,0xa8,0xd6,0xbc}},
- {{0xef,0xad,0x89}, {0xd7,0xa9,0xd6,0xbc}},
- {{0xef,0xac,0xac}, {0xd7,0xa9,0xd6,0xbc,0xd7,0x81}},
- {{0xef,0xac,0xad}, {0xd7,0xa9,0xd6,0xbc,0xd7,0x82}},
- {{0xef,0xac,0xaa}, {0xd7,0xa9,0xd7,0x81}},
- {{0xef,0xac,0xab}, {0xd7,0xa9,0xd7,0x82}},
- {{0xef,0xad,0x8a}, {0xd7,0xaa,0xd6,0xbc}},
- {{0xef,0xac,0x9f}, {0xd7,0xb2,0xd6,0xb7}},
- {{0xe0,0xa5,0x98}, {0xe0,0xa4,0x95,0xe0,0xa4,0xbc}},
- {{0xe0,0xa5,0x99}, {0xe0,0xa4,0x96,0xe0,0xa4,0xbc}},
- {{0xe0,0xa5,0x9a}, {0xe0,0xa4,0x97,0xe0,0xa4,0xbc}},
- {{0xe0,0xa5,0x9b}, {0xe0,0xa4,0x9c,0xe0,0xa4,0xbc}},
- {{0xe0,0xa5,0x9c}, {0xe0,0xa4,0xa1,0xe0,0xa4,0xbc}},
- {{0xe0,0xa5,0x9d}, {0xe0,0xa4,0xa2,0xe0,0xa4,0xbc}},
- {{0xe0,0xa4,0xa9}, {0xe0,0xa4,0xa8,0xe0,0xa4,0xbc}},
- {{0xe0,0xa5,0x9e}, {0xe0,0xa4,0xab,0xe0,0xa4,0xbc}},
- {{0xe0,0xa5,0x9f}, {0xe0,0xa4,0xaf,0xe0,0xa4,0xbc}},
- {{0xe0,0xa4,0xb1}, {0xe0,0xa4,0xb0,0xe0,0xa4,0xbc}},
- {{0xe0,0xa4,0xb4}, {0xe0,0xa4,0xb3,0xe0,0xa4,0xbc}},
- {{0xe0,0xa7,0x9c}, {0xe0,0xa6,0xa1,0xe0,0xa6,0xbc}},
- {{0xe0,0xa7,0x9d}, {0xe0,0xa6,0xa2,0xe0,0xa6,0xbc}},
- {{0xe0,0xa6,0xb0}, {0xe0,0xa6,0xac,0xe0,0xa6,0xbc}},
- {{0xe0,0xa7,0x9f}, {0xe0,0xa6,0xaf,0xe0,0xa6,0xbc}},
- {{0xe0,0xa7,0x8b}, {0xe0,0xa7,0x87,0xe0,0xa6,0xbe}},
- {{0xe0,0xa7,0x8c}, {0xe0,0xa7,0x87,0xe0,0xa7,0x97}},
- {{0xe0,0xa9,0x99}, {0xe0,0xa8,0x96,0xe0,0xa8,0xbc}},
- {{0xe0,0xa9,0x9a}, {0xe0,0xa8,0x97,0xe0,0xa8,0xbc}},
- {{0xe0,0xa9,0x9b}, {0xe0,0xa8,0x9c,0xe0,0xa8,0xbc}},
- {{0xe0,0xa9,0x9c}, {0xe0,0xa8,0xa1,0xe0,0xa8,0xbc}},
- {{0xe0,0xa9,0x9e}, {0xe0,0xa8,0xab,0xe0,0xa8,0xbc}},
- {{0xe0,0xad,0x9c}, {0xe0,0xac,0xa1,0xe0,0xac,0xbc}},
- {{0xe0,0xad,0x9d}, {0xe0,0xac,0xa2,0xe0,0xac,0xbc}},
- {{0xe0,0xad,0x9f}, {0xe0,0xac,0xaf,0xe0,0xac,0xbc}},
- {{0xe0,0xad,0x8b}, {0xe0,0xad,0x87,0xe0,0xac,0xbe}},
- {{0xe0,0xad,0x88}, {0xe0,0xad,0x87,0xe0,0xad,0x96}},
- {{0xe0,0xad,0x8c}, {0xe0,0xad,0x87,0xe0,0xad,0x97}},
- {{0xe0,0xae,0x94}, {0xe0,0xae,0x92,0xe0,0xaf,0x97}},
- {{0xe0,0xaf,0x8a}, {0xe0,0xaf,0x86,0xe0,0xae,0xbe}},
- {{0xe0,0xaf,0x8c}, {0xe0,0xaf,0x86,0xe0,0xaf,0x97}},
- {{0xe0,0xaf,0x8b}, {0xe0,0xaf,0x87,0xe0,0xae,0xbe}},
- {{0xe0,0xb1,0x88}, {0xe0,0xb1,0x86,0xe0,0xb1,0x96}},
- {{0xe0,0xb3,0x80}, {0xe0,0xb2,0xbf,0xe0,0xb3,0x95}},
- {{0xe0,0xb3,0x8a}, {0xe0,0xb3,0x86,0xe0,0xb3,0x82}},
- {{0xe0,0xb3,0x8b}, {0xe0,0xb3,0x86,0xe0,0xb3,0x82,0xe0,0xb3,0x95}},
- {{0xe0,0xb3,0x87}, {0xe0,0xb3,0x86,0xe0,0xb3,0x95}},
- {{0xe0,0xb3,0x88}, {0xe0,0xb3,0x86,0xe0,0xb3,0x96}},
- {{0xe0,0xb5,0x8a}, {0xe0,0xb5,0x86,0xe0,0xb4,0xbe}},
- {{0xe0,0xb5,0x8c}, {0xe0,0xb5,0x86,0xe0,0xb5,0x97}},
- {{0xe0,0xb5,0x8b}, {0xe0,0xb5,0x87,0xe0,0xb4,0xbe}},
- {{0xe0,0xb8,0xb3}, {0xe0,0xb9,0x8d,0xe0,0xb8,0xb2}},
- {{0xe0,0xba,0xb3}, {0xe0,0xbb,0x8d,0xe0,0xba,0xb2}},
- {{0xe0,0xbd,0xa9}, {0xe0,0xbd,0x80,0xe0,0xbe,0xb5}},
- {{0xe0,0xbd,0x83}, {0xe0,0xbd,0x82,0xe0,0xbe,0xb7}},
- {{0xe0,0xbd,0x8d}, {0xe0,0xbd,0x8c,0xe0,0xbe,0xb7}},
- {{0xe0,0xbd,0x92}, {0xe0,0xbd,0x91,0xe0,0xbe,0xb7}},
- {{0xe0,0xbd,0x97}, {0xe0,0xbd,0x96,0xe0,0xbe,0xb7}},
- {{0xe0,0xbd,0x9c}, {0xe0,0xbd,0x9b,0xe0,0xbe,0xb7}},
- {{0xe0,0xbd,0xb3}, {0xe0,0xbd,0xb2,0xe0,0xbd,0xb1}},
- {{0xe0,0xbd,0xb5}, {0xe0,0xbd,0xb4,0xe0,0xbd,0xb1}},
- {{0xe0,0xbe,0x81}, {0xe0,0xbe,0x80,0xe0,0xbd,0xb1}},
- {{0xe0,0xbe,0xb9}, {0xe0,0xbe,0x90,0xe0,0xbe,0xb5}},
- {{0xe0,0xbe,0x93}, {0xe0,0xbe,0x92,0xe0,0xbe,0xb7}},
- {{0xe0,0xbe,0x9d}, {0xe0,0xbe,0x9c,0xe0,0xbe,0xb7}},
- {{0xe0,0xbe,0xa2}, {0xe0,0xbe,0xa1,0xe0,0xbe,0xb7}},
- {{0xe0,0xbe,0xa7}, {0xe0,0xbe,0xa6,0xe0,0xbe,0xb7}},
- {{0xe0,0xbe,0xac}, {0xe0,0xbe,0xab,0xe0,0xbe,0xb7}},
- {{0xe0,0xbd,0xb6}, {0xe0,0xbe,0xb2,0xe0,0xbe,0x80}},
- {{0xe0,0xbd,0xb7}, {0xe0,0xbe,0xb2,0xe0,0xbe,0x80,0xe0,0xbd,0xb1}},
- {{0xe0,0xbd,0xb8}, {0xe0,0xbe,0xb3,0xe0,0xbe,0x80}},
- {{0xe0,0xbd,0xb9}, {0xe0,0xbe,0xb3,0xe0,0xbe,0x80,0xe0,0xbd,0xb1}},
- {{0xe1,0xbf,0x8d}, {0xe1,0xbe,0xbf,0xcc,0x80}},
- {{0xe1,0xbf,0x8e}, {0xe1,0xbe,0xbf,0xcc,0x81}},
- {{0xe1,0xbf,0x8f}, {0xe1,0xbe,0xbf,0xcd,0x82}},
- {{0xe1,0xbf,0x9d}, {0xe1,0xbf,0xbe,0xcc,0x80}},
- {{0xe1,0xbf,0x9e}, {0xe1,0xbf,0xbe,0xcc,0x81}},
- {{0xe1,0xbf,0x9f}, {0xe1,0xbf,0xbe,0xcd,0x82}},
- {{0xe3,0x82,0x94}, {0xe3,0x81,0x86,0xe3,0x82,0x99}},
- {{0xe3,0x81,0x8c}, {0xe3,0x81,0x8b,0xe3,0x82,0x99}},
- {{0xe3,0x81,0x8e}, {0xe3,0x81,0x8d,0xe3,0x82,0x99}},
- {{0xe3,0x81,0x90}, {0xe3,0x81,0x8f,0xe3,0x82,0x99}},
- {{0xe3,0x81,0x92}, {0xe3,0x81,0x91,0xe3,0x82,0x99}},
- {{0xe3,0x81,0x94}, {0xe3,0x81,0x93,0xe3,0x82,0x99}},
- {{0xe3,0x81,0x96}, {0xe3,0x81,0x95,0xe3,0x82,0x99}},
- {{0xe3,0x81,0x98}, {0xe3,0x81,0x97,0xe3,0x82,0x99}},
- {{0xe3,0x81,0x9a}, {0xe3,0x81,0x99,0xe3,0x82,0x99}},
- {{0xe3,0x81,0x9c}, {0xe3,0x81,0x9b,0xe3,0x82,0x99}},
- {{0xe3,0x81,0x9e}, {0xe3,0x81,0x9d,0xe3,0x82,0x99}},
- {{0xe3,0x81,0xa0}, {0xe3,0x81,0x9f,0xe3,0x82,0x99}},
- {{0xe3,0x81,0xa2}, {0xe3,0x81,0xa1,0xe3,0x82,0x99}},
- {{0xe3,0x81,0xa5}, {0xe3,0x81,0xa4,0xe3,0x82,0x99}},
- {{0xe3,0x81,0xa7}, {0xe3,0x81,0xa6,0xe3,0x82,0x99}},
- {{0xe3,0x81,0xa9}, {0xe3,0x81,0xa8,0xe3,0x82,0x99}},
- {{0xe3,0x81,0xb0}, {0xe3,0x81,0xaf,0xe3,0x82,0x99}},
- {{0xe3,0x81,0xb1}, {0xe3,0x81,0xaf,0xe3,0x82,0x9a}},
- {{0xe3,0x81,0xb3}, {0xe3,0x81,0xb2,0xe3,0x82,0x99}},
- {{0xe3,0x81,0xb4}, {0xe3,0x81,0xb2,0xe3,0x82,0x9a}},
- {{0xe3,0x81,0xb6}, {0xe3,0x81,0xb5,0xe3,0x82,0x99}},
- {{0xe3,0x81,0xb7}, {0xe3,0x81,0xb5,0xe3,0x82,0x9a}},
- {{0xe3,0x81,0xb9}, {0xe3,0x81,0xb8,0xe3,0x82,0x99}},
- {{0xe3,0x81,0xba}, {0xe3,0x81,0xb8,0xe3,0x82,0x9a}},
- {{0xe3,0x81,0xbc}, {0xe3,0x81,0xbb,0xe3,0x82,0x99}},
- {{0xe3,0x81,0xbd}, {0xe3,0x81,0xbb,0xe3,0x82,0x9a}},
- {{0xe3,0x82,0x9e}, {0xe3,0x82,0x9d,0xe3,0x82,0x99}},
- {{0xe3,0x83,0xb4}, {0xe3,0x82,0xa6,0xe3,0x82,0x99}},
- {{0xe3,0x82,0xac}, {0xe3,0x82,0xab,0xe3,0x82,0x99}},
- {{0xe3,0x82,0xae}, {0xe3,0x82,0xad,0xe3,0x82,0x99}},
- {{0xe3,0x82,0xb0}, {0xe3,0x82,0xaf,0xe3,0x82,0x99}},
- {{0xe3,0x82,0xb2}, {0xe3,0x82,0xb1,0xe3,0x82,0x99}},
- {{0xe3,0x82,0xb4}, {0xe3,0x82,0xb3,0xe3,0x82,0x99}},
- {{0xe3,0x82,0xb6}, {0xe3,0x82,0xb5,0xe3,0x82,0x99}},
- {{0xe3,0x82,0xb8}, {0xe3,0x82,0xb7,0xe3,0x82,0x99}},
- {{0xe3,0x82,0xba}, {0xe3,0x82,0xb9,0xe3,0x82,0x99}},
- {{0xe3,0x82,0xbc}, {0xe3,0x82,0xbb,0xe3,0x82,0x99}},
- {{0xe3,0x82,0xbe}, {0xe3,0x82,0xbd,0xe3,0x82,0x99}},
- {{0xe3,0x83,0x80}, {0xe3,0x82,0xbf,0xe3,0x82,0x99}},
- {{0xe3,0x83,0x82}, {0xe3,0x83,0x81,0xe3,0x82,0x99}},
- {{0xe3,0x83,0x85}, {0xe3,0x83,0x84,0xe3,0x82,0x99}},
- {{0xe3,0x83,0x87}, {0xe3,0x83,0x86,0xe3,0x82,0x99}},
- {{0xe3,0x83,0x89}, {0xe3,0x83,0x88,0xe3,0x82,0x99}},
- {{0xe3,0x83,0x90}, {0xe3,0x83,0x8f,0xe3,0x82,0x99}},
- {{0xe3,0x83,0x91}, {0xe3,0x83,0x8f,0xe3,0x82,0x9a}},
- {{0xe3,0x83,0x93}, {0xe3,0x83,0x92,0xe3,0x82,0x99}},
- {{0xe3,0x83,0x94}, {0xe3,0x83,0x92,0xe3,0x82,0x9a}},
- {{0xe3,0x83,0x96}, {0xe3,0x83,0x95,0xe3,0x82,0x99}},
- {{0xe3,0x83,0x97}, {0xe3,0x83,0x95,0xe3,0x82,0x9a}},
- {{0xe3,0x83,0x99}, {0xe3,0x83,0x98,0xe3,0x82,0x99}},
- {{0xe3,0x83,0x9a}, {0xe3,0x83,0x98,0xe3,0x82,0x9a}},
- {{0xe3,0x83,0x9c}, {0xe3,0x83,0x9b,0xe3,0x82,0x99}},
- {{0xe3,0x83,0x9d}, {0xe3,0x83,0x9b,0xe3,0x82,0x9a}},
- {{0xe3,0x83,0xb7}, {0xe3,0x83,0xaf,0xe3,0x82,0x99}},
- {{0xe3,0x83,0xb8}, {0xe3,0x83,0xb0,0xe3,0x82,0x99}},
- {{0xe3,0x83,0xb9}, {0xe3,0x83,0xb1,0xe3,0x82,0x99}},
- {{0xe3,0x83,0xba}, {0xe3,0x83,0xb2,0xe3,0x82,0x99}},
- {{0xe3,0x83,0xbe}, {0xe3,0x83,0xbd,0xe3,0x82,0x99}},
-};
-#endif /* UNICODE_NORMALIZATION */
-#endif /* UTF8_INPUT_ENABLE */
-
-#ifdef SHIFTJIS_CP932
-const unsigned short shiftjis_cp932[3][189] = {
- {
- 0xEEEF, 0xEEF0, 0xEEF1, 0xEEF2, 0xEEF3, 0xEEF4, 0xEEF5, 0xEEF6,
- 0xEEF7, 0xEEF8, 0x8754, 0x8755, 0x8756, 0x8757, 0x8758, 0x8759,
- 0x875A, 0x875B, 0x875C, 0x875D, 0x81CA, 0xEEFA, 0xEEFB, 0xEEFC,
- 0x878A, 0x8782, 0x8784, 0x81E6, 0xED40, 0xED41, 0xED42, 0xED43,
- 0xED44, 0xED45, 0xED46, 0xED47, 0xED48, 0xED49, 0xED4A, 0xED4B,
- 0xED4C, 0xED4D, 0xED4E, 0xED4F, 0xED50, 0xED51, 0xED52, 0xED53,
- 0xED54, 0xED55, 0xED56, 0xED57, 0xED58, 0xED59, 0xED5A, 0xED5B,
- 0xED5C, 0xED5D, 0xED5E, 0xED5F, 0xED60, 0xED61, 0xED62, 0,
- 0xED63, 0xED64, 0xED65, 0xED66, 0xED67, 0xED68, 0xED69, 0xED6A,
- 0xED6B, 0xED6C, 0xED6D, 0xED6E, 0xED6F, 0xED70, 0xED71, 0xED72,
- 0xED73, 0xED74, 0xED75, 0xED76, 0xED77, 0xED78, 0xED79, 0xED7A,
- 0xED7B, 0xED7C, 0xED7D, 0xED7E, 0xED80, 0xED81, 0xED82, 0xED83,
- 0xED84, 0xED85, 0xED86, 0xED87, 0xED88, 0xED89, 0xED8A, 0xED8B,
- 0xED8C, 0xED8D, 0xED8E, 0xED8F, 0xED90, 0xED91, 0xED92, 0xED93,
- 0xED94, 0xED95, 0xED96, 0xED97, 0xED98, 0xED99, 0xED9A, 0xED9B,
- 0xED9C, 0xED9D, 0xED9E, 0xED9F, 0xEDA0, 0xEDA1, 0xEDA2, 0xEDA3,
- 0xEDA4, 0xEDA5, 0xEDA6, 0xEDA7, 0xEDA8, 0xEDA9, 0xEDAA, 0xEDAB,
- 0xEDAC, 0xEDAD, 0xEDAE, 0xEDAF, 0xEDB0, 0xEDB1, 0xEDB2, 0xEDB3,
- 0xEDB4, 0xEDB5, 0xEDB6, 0xEDB7, 0xEDB8, 0xEDB9, 0xEDBA, 0xEDBB,
- 0xEDBC, 0xEDBD, 0xEDBE, 0xEDBF, 0xEDC0, 0xEDC1, 0xEDC2, 0xEDC3,
- 0xEDC4, 0xEDC5, 0xEDC6, 0xEDC7, 0xEDC8, 0xEDC9, 0xEDCA, 0xEDCB,
- 0xEDCC, 0xEDCD, 0xEDCE, 0xEDCF, 0xEDD0, 0xEDD1, 0xEDD2, 0xEDD3,
- 0xEDD4, 0xEDD5, 0xEDD6, 0xEDD7, 0xEDD8, 0xEDD9, 0xEDDA, 0xEDDB,
- 0xEDDC, 0xEDDD, 0xEDDE, 0xEDDF, 0xEDE0,
- },
- {
- 0xEDE1, 0xEDE2, 0xEDE3, 0xEDE4, 0xEDE5, 0xEDE6, 0xEDE7, 0xEDE8,
- 0xEDE9, 0xEDEA, 0xEDEB, 0xEDEC, 0xEDED, 0xEDEE, 0xEDEF, 0xEDF0,
- 0xEDF1, 0xEDF2, 0xEDF3, 0xEDF4, 0xEDF5, 0xEDF6, 0xEDF7, 0xEDF8,
- 0xEDF9, 0xEDFA, 0xEDFB, 0xEDFC, 0xEE40, 0xEE41, 0xEE42, 0xEE43,
- 0xEE44, 0xEE45, 0xEE46, 0xEE47, 0xEE48, 0xEE49, 0xEE4A, 0xEE4B,
- 0xEE4C, 0xEE4D, 0xEE4E, 0xEE4F, 0xEE50, 0xEE51, 0xEE52, 0xEE53,
- 0xEE54, 0xEE55, 0xEE56, 0xEE57, 0xEE58, 0xEE59, 0xEE5A, 0xEE5B,
- 0xEE5C, 0xEE5D, 0xEE5E, 0xEE5F, 0xEE60, 0xEE61, 0xEE62, 0,
- 0xEE63, 0xEE64, 0xEE65, 0xEE66, 0xEE67, 0xEE68, 0xEE69, 0xEE6A,
- 0xEE6B, 0xEE6C, 0xEE6D, 0xEE6E, 0xEE6F, 0xEE70, 0xEE71, 0xEE72,
- 0xEE73, 0xEE74, 0xEE75, 0xEE76, 0xEE77, 0xEE78, 0xEE79, 0xEE7A,
- 0xEE7B, 0xEE7C, 0xEE7D, 0xEE7E, 0xEE80, 0xEE81, 0xEE82, 0xEE83,
- 0xEE84, 0xEE85, 0xEE86, 0xEE87, 0xEE88, 0xEE89, 0xEE8A, 0xEE8B,
- 0xEE8C, 0xEE8D, 0xEE8E, 0xEE8F, 0xEE90, 0xEE91, 0xEE92, 0xEE93,
- 0xEE94, 0xEE95, 0xEE96, 0xEE97, 0xEE98, 0xEE99, 0xEE9A, 0xEE9B,
- 0xEE9C, 0xEE9D, 0xEE9E, 0xEE9F, 0xEEA0, 0xEEA1, 0xEEA2, 0xEEA3,
- 0xEEA4, 0xEEA5, 0xEEA6, 0xEEA7, 0xEEA8, 0xEEA9, 0xEEAA, 0xEEAB,
- 0xEEAC, 0xEEAD, 0xEEAE, 0xEEAF, 0xEEB0, 0xEEB1, 0xEEB2, 0xEEB3,
- 0xEEB4, 0xEEB5, 0xEEB6, 0xEEB7, 0xEEB8, 0xEEB9, 0xEEBA, 0xEEBB,
- 0xEEBC, 0xEEBD, 0xEEBE, 0xEEBF, 0xEEC0, 0xEEC1, 0xEEC2, 0xEEC3,
- 0xEEC4, 0xEEC5, 0xEEC6, 0xEEC7, 0xEEC8, 0xEEC9, 0xEECA, 0xEECB,
- 0xEECC, 0xEECD, 0xEECE, 0xEECF, 0xEED0, 0xEED1, 0xEED2, 0xEED3,
- 0xEED4, 0xEED5, 0xEED6, 0xEED7, 0xEED8, 0xEED9, 0xEEDA, 0xEEDB,
- 0xEEDC, 0xEEDD, 0xEEDE, 0xEEDF, 0xEEE0,
- },
- {
- 0xEEE1, 0xEEE2, 0xEEE3, 0xEEE4, 0xEEE5, 0xEEE6, 0xEEE7, 0xEEE8,
- 0xEEE9, 0xEEEA, 0xEEEB, 0xEEEC, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- },
-};
-const unsigned short cp932inv[2][189] = {
- {
- 0xFA5C, 0xFA5D, 0xFA5E, 0xFA5F, 0xFA60, 0xFA61, 0xFA62, 0xFA63,
- 0xFA64, 0xFA65, 0xFA66, 0xFA67, 0xFA68, 0xFA69, 0xFA6A, 0xFA6B,
- 0xFA6C, 0xFA6D, 0xFA6E, 0xFA6F, 0xFA70, 0xFA71, 0xFA72, 0xFA73,
- 0xFA74, 0xFA75, 0xFA76, 0xFA77, 0xFA78, 0xFA79, 0xFA7A, 0xFA7B,
- 0xFA7C, 0xFA7D, 0xFA7E, 0xFA80, 0xFA81, 0xFA82, 0xFA83, 0xFA84,
- 0xFA85, 0xFA86, 0xFA87, 0xFA88, 0xFA89, 0xFA8A, 0xFA8B, 0xFA8C,
- 0xFA8D, 0xFA8E, 0xFA8F, 0xFA90, 0xFA91, 0xFA92, 0xFA93, 0xFA94,
- 0xFA95, 0xFA96, 0xFA97, 0xFA98, 0xFA99, 0xFA9A, 0xFA9B, 0,
- 0xFA9C, 0xFA9D, 0xFA9E, 0xFA9F, 0xFAA0, 0xFAA1, 0xFAA2, 0xFAA3,
- 0xFAA4, 0xFAA5, 0xFAA6, 0xFAA7, 0xFAA8, 0xFAA9, 0xFAAA, 0xFAAB,
- 0xFAAC, 0xFAAD, 0xFAAE, 0xFAAF, 0xFAB0, 0xFAB1, 0xFAB2, 0xFAB3,
- 0xFAB4, 0xFAB5, 0xFAB6, 0xFAB7, 0xFAB8, 0xFAB9, 0xFABA, 0xFABB,
- 0xFABC, 0xFABD, 0xFABE, 0xFABF, 0xFAC0, 0xFAC1, 0xFAC2, 0xFAC3,
- 0xFAC4, 0xFAC5, 0xFAC6, 0xFAC7, 0xFAC8, 0xFAC9, 0xFACA, 0xFACB,
- 0xFACC, 0xFACD, 0xFACE, 0xFACF, 0xFAD0, 0xFAD1, 0xFAD2, 0xFAD3,
- 0xFAD4, 0xFAD5, 0xFAD6, 0xFAD7, 0xFAD8, 0xFAD9, 0xFADA, 0xFADB,
- 0xFADC, 0xFADD, 0xFADE, 0xFADF, 0xFAE0, 0xFAE1, 0xFAE2, 0xFAE3,
- 0xFAE4, 0xFAE5, 0xFAE6, 0xFAE7, 0xFAE8, 0xFAE9, 0xFAEA, 0xFAEB,
- 0xFAEC, 0xFAED, 0xFAEE, 0xFAEF, 0xFAF0, 0xFAF1, 0xFAF2, 0xFAF3,
- 0xFAF4, 0xFAF5, 0xFAF6, 0xFAF7, 0xFAF8, 0xFAF9, 0xFAFA, 0xFAFB,
- 0xFAFC, 0xFB40, 0xFB41, 0xFB42, 0xFB43, 0xFB44, 0xFB45, 0xFB46,
- 0xFB47, 0xFB48, 0xFB49, 0xFB4A, 0xFB4B, 0xFB4C, 0xFB4D, 0xFB4E,
- 0xFB4F, 0xFB50, 0xFB51, 0xFB52, 0xFB53, 0xFB54, 0xFB55, 0xFB56,
- 0xFB57, 0xFB58, 0xFB59, 0xFB5A, 0xFB5B,
- },
- {
- 0xFB5C, 0xFB5D, 0xFB5E, 0xFB5F, 0xFB60, 0xFB61, 0xFB62, 0xFB63,
- 0xFB64, 0xFB65, 0xFB66, 0xFB67, 0xFB68, 0xFB69, 0xFB6A, 0xFB6B,
- 0xFB6C, 0xFB6D, 0xFB6E, 0xFB6F, 0xFB70, 0xFB71, 0xFB72, 0xFB73,
- 0xFB74, 0xFB75, 0xFB76, 0xFB77, 0xFB78, 0xFB79, 0xFB7A, 0xFB7B,
- 0xFB7C, 0xFB7D, 0xFB7E, 0xFB80, 0xFB81, 0xFB82, 0xFB83, 0xFB84,
- 0xFB85, 0xFB86, 0xFB87, 0xFB88, 0xFB89, 0xFB8A, 0xFB8B, 0xFB8C,
- 0xFB8D, 0xFB8E, 0xFB8F, 0xFB90, 0xFB91, 0xFB92, 0xFB93, 0xFB94,
- 0xFB95, 0xFB96, 0xFB97, 0xFB98, 0xFB99, 0xFB9A, 0xFB9B, 0,
- 0xFB9C, 0xFB9D, 0xFB9E, 0xFB9F, 0xFBA0, 0xFBA1, 0xFBA2, 0xFBA3,
- 0xFBA4, 0xFBA5, 0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9, 0xFBAA, 0xFBAB,
- 0xFBAC, 0xFBAD, 0xFBAE, 0xFBAF, 0xFBB0, 0xFBB1, 0xFBB2, 0xFBB3,
- 0xFBB4, 0xFBB5, 0xFBB6, 0xFBB7, 0xFBB8, 0xFBB9, 0xFBBA, 0xFBBB,
- 0xFBBC, 0xFBBD, 0xFBBE, 0xFBBF, 0xFBC0, 0xFBC1, 0xFBC2, 0xFBC3,
- 0xFBC4, 0xFBC5, 0xFBC6, 0xFBC7, 0xFBC8, 0xFBC9, 0xFBCA, 0xFBCB,
- 0xFBCC, 0xFBCD, 0xFBCE, 0xFBCF, 0xFBD0, 0xFBD1, 0xFBD2, 0xFBD3,
- 0xFBD4, 0xFBD5, 0xFBD6, 0xFBD7, 0xFBD8, 0xFBD9, 0xFBDA, 0xFBDB,
- 0xFBDC, 0xFBDD, 0xFBDE, 0xFBDF, 0xFBE0, 0xFBE1, 0xFBE2, 0xFBE3,
- 0xFBE4, 0xFBE5, 0xFBE6, 0xFBE7, 0xFBE8, 0xFBE9, 0xFBEA, 0xFBEB,
- 0xFBEC, 0xFBED, 0xFBEE, 0xFBEF, 0xFBF0, 0xFBF1, 0xFBF2, 0xFBF3,
- 0xFBF4, 0xFBF5, 0xFBF6, 0xFBF7, 0xFBF8, 0xFBF9, 0xFBFA, 0xFBFB,
- 0xFBFC, 0xFC40, 0xFC41, 0xFC42, 0xFC43, 0xFC44, 0xFC45, 0xFC46,
- 0xFC47, 0xFC48, 0xFC49, 0xFC4A, 0xFC4B, 0, 0, 0xFA40,
- 0xFA41, 0xFA42, 0xFA43, 0xFA44, 0xFA45, 0xFA46, 0xFA47, 0xFA48,
- 0xFA49, 0x81CA, 0xFA55, 0xFA56, 0xFA57,
- },
-};
-#endif /* SHIFTJIS_CP932 */
-
-#ifdef X0212_ENABLE
-const unsigned short shiftjis_x0212[3][189] = {
- {
- 0xF373, 0xF374, 0xF375, 0xF376, 0xF377, 0xF378, 0xF379, 0xF37A,
- 0xF37B, 0xF37C, 0xF37D, 0xF37E, 0xF421, 0xF422, 0xF423, 0xF424,
- 0xF425, 0xF426, 0xF427, 0xF428, 0x224C, 0xA243, 0xF429, 0xF42A,
- 0xF42B, 0xF42C, 0xF42D, 0x2268, 0xD463, 0xDC5F, 0xE469, 0xE378,
- 0xD921, 0xB13B, 0xF42E, 0xC22D, 0xC37C, 0xE450, 0xC23F, 0xBC74,
- 0xB029, 0xB048, 0xF42F, 0xB052, 0xB054, 0xB063, 0xB06E, 0xB127,
- 0xB123, 0xB12C, 0xB129, 0xB13E, 0xB15F, 0xB158, 0xB148, 0xB157,
- 0xB163, 0xB174, 0xB161, 0xB223, 0xF430, 0xB23B, 0xB266, 0,
- 0xB26D, 0xB275, 0xB27C, 0xF431, 0xB335, 0xB358, 0xB35B, 0xB365,
- 0xB36E, 0xB37B, 0xF432, 0xF433, 0xB440, 0xB447, 0xB450, 0xB45E,
- 0xF434, 0xB52A, 0xF435, 0xB52F, 0xB544, 0xB568, 0xF436, 0xB742,
- 0xB764, 0xB768, 0xB767, 0xF437, 0xF438, 0xF439, 0xB84E, 0xB861,
- 0xB875, 0xB877, 0xB878, 0xB87C, 0xB92F, 0xB937, 0xBA3E, 0xBA5B,
- 0xCD2A, 0xBA61, 0xF43A, 0xBA6B, 0xBB33, 0xBB38, 0xF43B, 0xBB4A,
- 0xF43C, 0xF43D, 0xBB50, 0xBB5E, 0xBB74, 0xBB75, 0xBB79, 0xBC64,
- 0xBC6D, 0xBC7E, 0xF43E, 0xBD42, 0xBD67, 0xF43F, 0xBD70, 0xBE30,
- 0xBE2C, 0xF440, 0xBE33, 0xBE3D, 0xBE4D, 0xBE49, 0xBE64, 0xBF28,
- 0xBF49, 0xC044, 0xC064, 0xC074, 0xC126, 0xF441, 0xC175, 0xC17C,
- 0xF442, 0xC178, 0xC22B, 0xC221, 0xC225, 0xF443, 0xC238, 0xC23A,
- 0xF444, 0xC244, 0xC252, 0xC257, 0xC25B, 0xC25E, 0xC26D, 0xC270,
- 0xF445, 0xC321, 0xC335, 0xC349, 0xC339, 0xF446, 0xC358, 0xC37E,
- 0xF447, 0xC44C, 0xF448, 0xC459, 0xC46A, 0xC47D, 0xF449, 0xC527,
- 0xC535, 0xC536, 0xF44A, 0xC555, 0xC638, 0xC657, 0xC660, 0xC66A,
- 0xC663, 0xC721, 0xC72B, 0xC747, 0xC743,
- },
- {
- 0xC74B, 0xC74F, 0xC759, 0xF44B, 0xF44C, 0xC766, 0xC76E, 0xC77C,
- 0xC76B, 0xC770, 0xC831, 0xC865, 0xC878, 0xC926, 0xC92B, 0xC92D,
- 0xF44D, 0xC94A, 0xC953, 0xC969, 0xC963, 0xC97C, 0xC974, 0xC975,
- 0xF44E, 0xCA33, 0xCA3D, 0xCA6F, 0xCA71, 0xCB2E, 0xF44F, 0xCB4A,
- 0xCB66, 0xCB6A, 0xCB70, 0xCB74, 0xCB6E, 0xCC25, 0xCB79, 0xCC2B,
- 0xCC2E, 0xCC2D, 0xCC32, 0xCC42, 0xCC50, 0xCC59, 0xF450, 0xCD3B,
- 0xF451, 0xCE3B, 0xF452, 0xCE3A, 0xCE43, 0xF453, 0xCE72, 0xB35D,
- 0xCF55, 0xCF62, 0xCF69, 0xCF6D, 0xF454, 0xF455, 0xF456, 0,
- 0xF457, 0xD065, 0xF458, 0xD069, 0xD168, 0xF459, 0xF45A, 0xD16C,
- 0xD23B, 0xF45B, 0xD361, 0xD368, 0xD427, 0xF45C, 0xF45D, 0xD454,
- 0xD472, 0xD52E, 0xF45E, 0xD75E, 0xF45F, 0xD822, 0xD837, 0xD841,
- 0xD851, 0xD874, 0xD946, 0xD948, 0xD951, 0xF460, 0xF461, 0xF462,
- 0xF463, 0xF464, 0xDC53, 0xDD48, 0xDD54, 0xDD6A, 0xDD7A, 0xDE24,
- 0xDE30, 0xF465, 0xDE35, 0xDE4B, 0xF466, 0xDF39, 0xF467, 0xDF43,
- 0xF468, 0xF469, 0xE059, 0xF46A, 0xF46B, 0xE162, 0xF46C, 0xF46D,
- 0xF46E, 0xE247, 0xE328, 0xE326, 0xE329, 0xE32F, 0xE330, 0xE32A,
- 0xE32B, 0xE33C, 0xE341, 0xE33F, 0xE355, 0xE358, 0xE356, 0xE35F,
- 0xE363, 0xE361, 0xE354, 0xE369, 0xE426, 0xE371, 0xE372, 0xE44B,
- 0xE441, 0xE443, 0xE43E, 0xF46F, 0xE440, 0xE447, 0xE43F, 0xE460,
- 0xE45E, 0xE451, 0xF470, 0xE45C, 0xE452, 0xE45B, 0xE454, 0xE47A,
- 0xE46F, 0xE533, 0xE53F, 0xE549, 0xE550, 0xE562, 0xE56A, 0xE56B,
- 0xF471, 0xF472, 0xF473, 0xE668, 0xE66F, 0xE72C, 0xF474, 0xE72E,
- 0xF475, 0xE731, 0xF476, 0xE732, 0xE831, 0xE836, 0xF477, 0xF478,
- 0xE85D, 0xF479, 0xF47A, 0xE951, 0xF47B,
- },
- {
- 0xE96D, 0xEA4D, 0xF47C, 0xEA5B, 0xEA66, 0xEA6A, 0xEB25, 0xEB7B,
- 0xEB7A, 0xF47D, 0xEC56, 0xF47E, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- },
-};
-
-static const unsigned short x0212_shiftjis_A2[] = {
- 0x819F, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x8143, 0, 0, 0x8150, 0, 0, 0x8160,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFA55, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_B0[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFA68, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFA69, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFA6B, 0, 0xFA6C, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFA6D, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFA6E, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_B1[] = {
- 0, 0, 0xFA70, 0, 0, 0, 0xFA6F,
- 0, 0xFA72, 0, 0, 0xFA71, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFA61, 0, 0, 0xFA73, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFA76, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xFA77,
- 0xFA75, 0, 0, 0, 0, 0, 0, 0xFA74,
- 0, 0xFA7A, 0, 0xFA78, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFA79, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_B2[] = {
- 0, 0, 0xFA7B, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFA7D, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFA7E, 0,
- 0, 0, 0, 0, 0, 0xFA80, 0, 0,
- 0, 0, 0, 0, 0, 0xFA81, 0, 0,
- 0, 0, 0, 0, 0xFA82, 0, 0,
-};
-static const unsigned short x0212_shiftjis_B3[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFA84, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFA85, 0, 0, 0xFA86, 0, 0xFB77, 0, 0,
- 0, 0, 0, 0, 0, 0xFA87, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFA88, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFA89, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_B4[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFA8C, 0, 0, 0, 0, 0, 0, 0xFA8D,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFA8E, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFA8F, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_B5[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFA91, 0, 0, 0, 0, 0xFA93,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFA94, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFA95, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_B7[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFA97, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFA98, 0, 0, 0xFA9A,
- 0xFA99, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_B8[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFA9E, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFA9F, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFAA0, 0, 0xFAA1,
- 0xFAA2, 0, 0, 0, 0xFAA3, 0, 0,
-};
-static const unsigned short x0212_shiftjis_B9[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xFAA4,
- 0, 0, 0, 0, 0, 0, 0, 0xFAA5,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_BA[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFAA6, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFAA7, 0, 0, 0, 0,
- 0, 0xFAA9, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFAAB, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_BB[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFAAC, 0, 0, 0, 0,
- 0xFAAD, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFAAF, 0, 0, 0, 0, 0,
- 0xFAB2, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFAB3, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFAB4, 0xFAB5, 0, 0,
- 0, 0xFAB6, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_BC[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFAB7, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFAB8, 0, 0,
- 0, 0, 0, 0, 0xFA67, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFAB9,
-};
-static const unsigned short x0212_shiftjis_BD[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFABB, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xFABC,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFABE, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_BE[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFAC0, 0, 0, 0,
- 0xFABF, 0, 0, 0xFAC2, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFAC3, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFAC5, 0, 0, 0, 0xFAC4, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFAC6, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_BF[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0xFAC7, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFAC8, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_C0[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFAC9, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFACA, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFACB, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_C1[] = {
- 0, 0, 0, 0, 0, 0xFACC, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFACE, 0, 0,
- 0xFAD1, 0, 0, 0, 0xFACF, 0, 0,
-};
-static const unsigned short x0212_shiftjis_C2[] = {
- 0xFAD3, 0, 0, 0, 0xFAD4, 0, 0,
- 0, 0, 0, 0xFAD2, 0, 0xFA63, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFAD6, 0, 0xFAD7, 0, 0, 0, 0, 0xFA66,
- 0, 0, 0, 0, 0xFAD9, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFADA, 0, 0, 0, 0, 0xFADB,
- 0, 0, 0, 0xFADC, 0, 0, 0xFADD, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFADE, 0, 0,
- 0xFADF, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_C3[] = {
- 0xFAE1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFAE2, 0, 0,
- 0, 0xFAE4, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFAE3, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFAE6, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFA64, 0, 0xFAE7,
-};
-static const unsigned short x0212_shiftjis_C4[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFAE9, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFAEB, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFAEC, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFAED, 0,
-};
-static const unsigned short x0212_shiftjis_C5[] = {
- 0, 0, 0, 0, 0, 0, 0xFAEF,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFAF0, 0xFAF1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFAF3, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_C6[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFAF4, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xFAF5,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFAF6, 0, 0, 0xFAF8, 0, 0, 0, 0,
- 0, 0, 0xFAF7, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_C7[] = {
- 0xFAF9, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFAFA, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFAFC, 0, 0, 0, 0xFAFB,
- 0, 0, 0, 0xFB40, 0, 0, 0, 0xFB41,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFB42, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFB45, 0,
- 0, 0, 0, 0xFB48, 0, 0, 0xFB46, 0,
- 0xFB49, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFB47, 0, 0,
-};
-static const unsigned short x0212_shiftjis_C8[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFB4A, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFB4B, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFB4C, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_C9[] = {
- 0, 0, 0, 0, 0, 0xFB4D, 0,
- 0, 0, 0, 0xFB4E, 0, 0xFB4F, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFB51, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFB52, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFB54, 0, 0, 0, 0,
- 0, 0xFB53, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFB56, 0xFB57, 0, 0,
- 0, 0, 0, 0, 0xFB55, 0, 0,
-};
-static const unsigned short x0212_shiftjis_CA[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFB59, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFB5A, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xFB5B,
- 0, 0xFB5C, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_CB[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFB5D, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFB5F, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFB60, 0,
- 0, 0, 0xFB61, 0, 0, 0, 0xFB64, 0,
- 0xFB62, 0, 0, 0, 0xFB63, 0, 0, 0,
- 0, 0xFB66, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_CC[] = {
- 0, 0, 0, 0, 0xFB65, 0, 0,
- 0, 0, 0, 0xFB67, 0, 0xFB69, 0xFB68, 0,
- 0, 0, 0xFB6A, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFB6B, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFB6C, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFB6D, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_CD[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFAA8, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFB6F, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_CE[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFB73, 0xFB71, 0, 0, 0, 0,
- 0, 0, 0, 0xFB74, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFB76, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_CF[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFB78, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFB79, 0, 0, 0, 0, 0,
- 0, 0xFB7A, 0, 0, 0, 0xFB7B, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_D0[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFB81, 0, 0,
- 0, 0xFB83, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_D1[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFB84, 0, 0, 0, 0xFB87, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_D2[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFB88, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_D3[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFB8A, 0, 0, 0, 0, 0, 0,
- 0xFB8B, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_D4[] = {
- 0, 0, 0, 0, 0, 0, 0xFB8C,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFB8F, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFA5C, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFB90, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_D5[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFB91, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_D7[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFB93, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_D8[] = {
- 0, 0xFB95, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xFB96,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFB97, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFB98, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFB99, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_D9[] = {
- 0xFA60, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFB9A, 0,
- 0xFB9B, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFB9C, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_DC[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFBA2, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xFA5D,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_DD[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFBA3, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFBA4, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFBA5, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFBA6, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_DE[] = {
- 0, 0, 0, 0xFBA7, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFBA8, 0, 0, 0, 0, 0xFBAA, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFBAB, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_DF[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFBAD, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFBAF, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_E0[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFBB2, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_E1[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFBB5, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_E2[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xFBB9,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_E3[] = {
- 0, 0, 0, 0, 0, 0xFBBB, 0,
- 0xFBBA, 0xFBBC, 0xFBBF, 0xFBC0, 0, 0, 0, 0xFBBD,
- 0xFBBE, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFBC1, 0, 0, 0xFBC3,
- 0, 0xFBC2, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFBCA, 0xFBC4, 0xFBC6, 0,
- 0xFBC5, 0, 0, 0, 0, 0, 0, 0xFBC7,
- 0, 0xFBC9, 0, 0xFBC8, 0, 0, 0, 0,
- 0, 0xFBCB, 0, 0, 0, 0, 0, 0,
- 0, 0xFBCD, 0xFBCE, 0, 0, 0, 0, 0,
- 0xFA5F, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_E4[] = {
- 0, 0, 0, 0, 0, 0xFBCC, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFBD2, 0xFBD6,
- 0xFBD4, 0xFBD0, 0, 0xFBD1, 0, 0, 0, 0xFBD5,
- 0, 0, 0, 0xFBCF, 0, 0, 0, 0,
- 0xFA65, 0xFBD9, 0xFBDC, 0, 0xFBDE, 0, 0, 0,
- 0, 0, 0, 0xFBDD, 0xFBDB, 0, 0xFBD8, 0,
- 0xFBD7, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFA5E, 0, 0, 0, 0, 0, 0xFBE0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFBDF, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_E5[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFBE1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0xFBE2,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFBE3, 0, 0, 0, 0, 0, 0,
- 0xFBE4, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFBE5, 0, 0, 0, 0, 0,
- 0, 0, 0xFBE6, 0xFBE7, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_E6[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFBEB, 0, 0, 0, 0, 0, 0, 0xFBEC,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_E7[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0xFBED, 0, 0xFBEF, 0,
- 0, 0xFBF1, 0xFBF3, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_E8[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFBF4, 0, 0, 0, 0, 0xFBF5, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFBF8, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_E9[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0xFBFB, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFC40, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_EA[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0xFC41, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFC43, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFC44, 0,
- 0, 0, 0xFC45, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_EB[] = {
- 0, 0, 0, 0, 0xFC46, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0xFC48, 0xFC47, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_EC[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0xFC4A, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
-};
-static const unsigned short x0212_shiftjis_F3[] = {
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0xFA40, 0xFA41, 0xFA42, 0xFA43, 0xFA44,
- 0xFA45, 0xFA46, 0xFA47, 0xFA48, 0xFA49, 0xFA4A, 0xFA4B,
-};
-static const unsigned short x0212_shiftjis_F4[] = {
- 0xFA4C, 0xFA4D, 0xFA4E, 0xFA4F, 0xFA50, 0xFA51, 0xFA52,
- 0xFA53, 0xFA56, 0xFA57, 0xFA58, 0xFA59, 0xFA5A, 0xFA62, 0xFA6A,
- 0xFA7C, 0xFA83, 0xFA8A, 0xFA8B, 0xFA90, 0xFA92, 0xFA96, 0xFA9B,
- 0xFA9C, 0xFA9D, 0xFAAA, 0xFAAE, 0xFAB0, 0xFAB1, 0xFABA, 0xFABD,
- 0xFAC1, 0xFACD, 0xFAD0, 0xFAD5, 0xFAD8, 0xFAE0, 0xFAE5, 0xFAE8,
- 0xFAEA, 0xFAEE, 0xFAF2, 0xFB43, 0xFB44, 0xFB50, 0xFB58, 0xFB5E,
- 0xFB6E, 0xFB70, 0xFB72, 0xFB75, 0xFB7C, 0xFB7D, 0xFB7E, 0xFB80,
- 0xFB82, 0xFB85, 0xFB86, 0xFB89, 0xFB8D, 0xFB8E, 0xFB92, 0xFB94,
- 0xFB9D, 0xFB9E, 0xFB9F, 0xFBA0, 0xFBA1, 0xFBA9, 0xFBAC, 0xFBAE,
- 0xFBB0, 0xFBB1, 0xFBB3, 0xFBB4, 0xFBB6, 0xFBB7, 0xFBB8, 0xFBD3,
- 0xFBDA, 0xFBE8, 0xFBE9, 0xFBEA, 0xFBEE, 0xFBF0, 0xFBF2, 0xFBF6,
- 0xFBF7, 0xFBF9, 0xFBFA, 0xFBFC, 0xFC42, 0xFC49, 0xFC4B,
-};
-const unsigned short *const x0212_shiftjis[] = {
- 0, x0212_shiftjis_A2, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- x0212_shiftjis_B0, x0212_shiftjis_B1, x0212_shiftjis_B2, x0212_shiftjis_B3,
- x0212_shiftjis_B4, x0212_shiftjis_B5, 0, x0212_shiftjis_B7,
- x0212_shiftjis_B8, x0212_shiftjis_B9, x0212_shiftjis_BA, x0212_shiftjis_BB,
- x0212_shiftjis_BC, x0212_shiftjis_BD, x0212_shiftjis_BE, x0212_shiftjis_BF,
- x0212_shiftjis_C0, x0212_shiftjis_C1, x0212_shiftjis_C2, x0212_shiftjis_C3,
- x0212_shiftjis_C4, x0212_shiftjis_C5, x0212_shiftjis_C6, x0212_shiftjis_C7,
- x0212_shiftjis_C8, x0212_shiftjis_C9, x0212_shiftjis_CA, x0212_shiftjis_CB,
- x0212_shiftjis_CC, x0212_shiftjis_CD, x0212_shiftjis_CE, x0212_shiftjis_CF,
- x0212_shiftjis_D0, x0212_shiftjis_D1, x0212_shiftjis_D2, x0212_shiftjis_D3,
- x0212_shiftjis_D4, x0212_shiftjis_D5, 0, x0212_shiftjis_D7,
- x0212_shiftjis_D8, x0212_shiftjis_D9, 0, 0,
- x0212_shiftjis_DC, x0212_shiftjis_DD, x0212_shiftjis_DE, x0212_shiftjis_DF,
- x0212_shiftjis_E0, x0212_shiftjis_E1, x0212_shiftjis_E2, x0212_shiftjis_E3,
- x0212_shiftjis_E4, x0212_shiftjis_E5, x0212_shiftjis_E6, x0212_shiftjis_E7,
- x0212_shiftjis_E8, x0212_shiftjis_E9, x0212_shiftjis_EA, x0212_shiftjis_EB,
- x0212_shiftjis_EC, 0, 0, 0,
- 0, 0, 0, x0212_shiftjis_F3,
- x0212_shiftjis_F4, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0,
-};
-#endif /* X0212_ENABLE */
diff --git a/ext/nkf/nkf-utf8/utf8tbl.h b/ext/nkf/nkf-utf8/utf8tbl.h
deleted file mode 100644
index 54a34271dd..0000000000
--- a/ext/nkf/nkf-utf8/utf8tbl.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * utf8tbl.h - Header file for Conversion Table
- *
- */
-
-#ifndef _UTF8TBL_H_
-#define _UTF8TBL_H_
-
-#ifdef UTF8_OUTPUT_ENABLE
-#define sizeof_euc_to_utf8_1byte 94
-#define sizeof_euc_to_utf8_2bytes 94
-extern const unsigned short euc_to_utf8_1byte[];
-extern const unsigned short *const euc_to_utf8_2bytes[];
-extern const unsigned short *const euc_to_utf8_2bytes_ms[];
-extern const unsigned short *const euc_to_utf8_2bytes_mac[];
-extern const unsigned short *const euc_to_utf8_2bytes_x0213[];
-extern const unsigned short *const x0212_to_utf8_2bytes[];
-extern const unsigned short *const x0212_to_utf8_2bytes_x0213[];
-#define sizeof_x0213_combining_chars 5
-#define sizeof_x0213_combining_table 25
-#define sizeof_x0213_1_surrogate_table 26
-#define sizeof_x0213_2_surrogate_table 277
-extern const unsigned short x0213_combining_chars[sizeof_x0213_combining_chars];
-extern const unsigned short x0213_combining_table[sizeof_x0213_combining_table][3];
-extern const unsigned short x0213_1_surrogate_table[sizeof_x0213_1_surrogate_table][3];
-extern const unsigned short x0213_2_surrogate_table[sizeof_x0213_2_surrogate_table][3];
-#endif /* UTF8_OUTPUT_ENABLE */
-
-#ifdef UTF8_INPUT_ENABLE
-#define sizeof_utf8_to_euc_C2 64
-#define sizeof_utf8_to_euc_E5B8 64
-#define sizeof_utf8_to_euc_2bytes 112
-#define sizeof_utf8_to_euc_3bytes 16
-extern const unsigned short *const utf8_to_euc_2bytes[];
-extern const unsigned short *const utf8_to_euc_2bytes_ms[];
-extern const unsigned short *const utf8_to_euc_2bytes_932[];
-extern const unsigned short *const utf8_to_euc_2bytes_mac[];
-extern const unsigned short *const utf8_to_euc_2bytes_x0213[];
-extern const unsigned short *const *const utf8_to_euc_3bytes[];
-extern const unsigned short *const *const utf8_to_euc_3bytes_ms[];
-extern const unsigned short *const *const utf8_to_euc_3bytes_932[];
-extern const unsigned short *const *const utf8_to_euc_3bytes_mac[];
-extern const unsigned short *const *const utf8_to_euc_3bytes_x0213[];
-#endif /* UTF8_INPUT_ENABLE */
-
-#ifdef UNICODE_NORMALIZATION
-
-#define NORMALIZATION_TABLE_LENGTH 942
-#define NORMALIZATION_TABLE_NFC_LENGTH 3
-#define NORMALIZATION_TABLE_NFD_LENGTH 9
-struct normalization_pair {
- const unsigned char nfc[NORMALIZATION_TABLE_NFC_LENGTH];
- const unsigned char nfd[NORMALIZATION_TABLE_NFD_LENGTH];
-};
-extern const struct normalization_pair normalization_table[];
-#endif
-
-#ifdef SHIFTJIS_CP932
-#define CP932_TABLE_BEGIN 0xFA
-#define CP932_TABLE_END 0xFC
-extern const unsigned short shiftjis_cp932[3][189];
-#define CP932INV_TABLE_BEGIN 0xED
-#define CP932INV_TABLE_END 0xEE
-extern const unsigned short cp932inv[2][189];
-#endif /* SHIFTJIS_CP932 */
-
-#ifdef X0212_ENABLE
-extern const unsigned short shiftjis_x0212[3][189];
-extern const unsigned short *const x0212_shiftjis[];
-#endif /* X0212_ENABLE */
-
-#endif
diff --git a/ext/nkf/nkf.c b/ext/nkf/nkf.c
deleted file mode 100644
index 73b616a54f..0000000000
--- a/ext/nkf/nkf.c
+++ /dev/null
@@ -1,506 +0,0 @@
-/*
- * NKF - Ruby extension for Network Kanji Filter
- *
- * original nkf2.x is maintained at http://sourceforge.jp/projects/nkf/
- *
- * $Id$
- *
- */
-
-#define RUBY_NKF_REVISION "$Revision$"
-#define RUBY_NKF_VERSION NKF_VERSION " (" NKF_RELEASE_DATE ")"
-#define NKF_GEM_VERSION "0.1.3"
-
-#include "ruby/ruby.h"
-#include "ruby/encoding.h"
-
-/* Replace nkf's getchar/putchar for variable modification */
-/* we never use getc, ungetc */
-
-#undef getc
-#undef ungetc
-#define getc(f) (input_ctr>=i_len?-1:input[input_ctr++])
-#define ungetc(c,f) input_ctr--
-
-#define INCSIZE 32
-#undef putchar
-#undef TRUE
-#undef FALSE
-#define putchar(c) rb_nkf_putchar(c)
-
-/* Input/Output pointers */
-
-static unsigned char *output;
-static unsigned char *input;
-static int input_ctr;
-static int i_len;
-static int output_ctr;
-static int o_len;
-static int incsize;
-
-static VALUE result;
-
-static int
-rb_nkf_putchar(unsigned int c)
-{
- if (output_ctr >= o_len) {
- o_len += incsize;
- rb_str_resize(result, o_len);
- incsize *= 2;
- output = (unsigned char *)RSTRING_PTR(result);
- }
- output[output_ctr++] = c;
-
- return c;
-}
-
-/* Include kanji filter main part */
-/* getchar and putchar will be replaced during inclusion */
-
-#define PERL_XS 1
-#include "nkf-utf8/config.h"
-#include "nkf-utf8/utf8tbl.c"
-#include "nkf-utf8/nkf.c"
-
-rb_encoding* rb_nkf_enc_get(const char *name)
-{
- int idx = rb_enc_find_index(name);
- if (idx < 0) {
- nkf_encoding *nkf_enc = nkf_enc_find(name);
- idx = rb_enc_find_index(nkf_enc_name(nkf_enc_to_base_encoding(nkf_enc)));
- if (idx < 0) {
- idx = rb_define_dummy_encoding(name);
- }
- }
- return rb_enc_from_index(idx);
-}
-
-int nkf_split_options(const char *arg)
-{
- int count = 0;
- unsigned char option[256];
- int i = 0, j = 0;
- int is_escaped = FALSE;
- int is_single_quoted = FALSE;
- int is_double_quoted = FALSE;
- for(i = 0; arg[i]; i++){
- if(j == 255){
- return -1;
- }else if(is_single_quoted){
- if(arg[i] == '\''){
- is_single_quoted = FALSE;
- }else{
- option[j++] = arg[i];
- }
- }else if(is_escaped){
- is_escaped = FALSE;
- option[j++] = arg[i];
- }else if(arg[i] == '\\'){
- is_escaped = TRUE;
- }else if(is_double_quoted){
- if(arg[i] == '"'){
- is_double_quoted = FALSE;
- }else{
- option[j++] = arg[i];
- }
- }else if(arg[i] == '\''){
- is_single_quoted = TRUE;
- }else if(arg[i] == '"'){
- is_double_quoted = TRUE;
- }else if(arg[i] == ' '){
- option[j] = '\0';
- options(option);
- j = 0;
- }else{
- option[j++] = arg[i];
- }
- }
- if(j){
- option[j] = '\0';
- options(option);
- }
- return count;
-}
-
-/*
- * call-seq:
- * NKF.nkf(opt, str) => string
- *
- * Convert _str_ and return converted result.
- * Conversion details are specified by _opt_ as String.
- *
- * require 'nkf'
- * output = NKF.nkf("-s", input)
- */
-
-static VALUE
-rb_nkf_convert(VALUE obj, VALUE opt, VALUE src)
-{
- VALUE tmp;
- reinit();
- nkf_split_options(StringValueCStr(opt));
- if (!output_encoding) rb_raise(rb_eArgError, "no output encoding given");
-
- switch (nkf_enc_to_index(output_encoding)) {
- case UTF_8_BOM: output_encoding = nkf_enc_from_index(UTF_8); break;
- case UTF_16BE_BOM: output_encoding = nkf_enc_from_index(UTF_16BE); break;
- case UTF_16LE_BOM: output_encoding = nkf_enc_from_index(UTF_16LE); break;
- case UTF_32BE_BOM: output_encoding = nkf_enc_from_index(UTF_32BE); break;
- case UTF_32LE_BOM: output_encoding = nkf_enc_from_index(UTF_32LE); break;
- }
- output_bom_f = FALSE;
-
- incsize = INCSIZE;
-
- input_ctr = 0;
- input = (unsigned char *)StringValuePtr(src);
- i_len = RSTRING_LENINT(src);
- tmp = rb_str_new(0, i_len*3 + 10);
-
- output_ctr = 0;
- output = (unsigned char *)RSTRING_PTR(tmp);
- o_len = RSTRING_LENINT(tmp);
- *output = '\0';
-
- /* use _result_ begin*/
- result = tmp;
- kanji_convert(NULL);
- result = Qnil;
- /* use _result_ end */
-
- rb_str_set_len(tmp, output_ctr);
-
- if (mimeout_f)
- rb_enc_associate(tmp, rb_usascii_encoding());
- else
- rb_enc_associate(tmp, rb_nkf_enc_get(nkf_enc_name(output_encoding)));
-
- return tmp;
-}
-
-
-/*
- * call-seq:
- * NKF.guess(str) => encoding
- *
- * Returns guessed encoding of _str_ by nkf routine.
- *
- */
-
-static VALUE
-rb_nkf_guess(VALUE obj, VALUE src)
-{
- reinit();
-
- input_ctr = 0;
- input = (unsigned char *)StringValuePtr(src);
- i_len = RSTRING_LENINT(src);
-
- guess_f = TRUE;
- kanji_convert( NULL );
- guess_f = FALSE;
-
- return rb_enc_from_encoding(rb_nkf_enc_get(get_guessed_code()));
-}
-
-
-/*
- * NKF - Ruby extension for Network Kanji Filter
- *
- * == Description
- *
- * This is a Ruby Extension version of nkf (Network Kanji Filter).
- * It converts the first argument and returns converted result. Conversion
- * details are specified by flags as the first argument.
- *
- * *Nkf* is a yet another kanji code converter among networks, hosts and terminals.
- * It converts input kanji code to designated kanji code
- * such as ISO-2022-JP, Shift_JIS, EUC-JP, UTF-8 or UTF-16.
- *
- * One of the most unique faculty of *nkf* is the guess of the input kanji encodings.
- * It currently recognizes ISO-2022-JP, Shift_JIS, EUC-JP, UTF-8 and UTF-16.
- * So users needn't set the input kanji code explicitly.
- *
- * By default, X0201 kana is converted into X0208 kana.
- * For X0201 kana, SO/SI, SSO and ESC-(-I methods are supported.
- * For automatic code detection, nkf assumes no X0201 kana in Shift_JIS.
- * To accept X0201 in Shift_JIS, use <b>-X</b>, <b>-x</b> or <b>-S</b>.
- *
- * == Flags
- *
- * === -b -u
- *
- * Output is buffered (DEFAULT), Output is unbuffered.
- *
- * === -j -s -e -w -w16 -w32
- *
- * Output code is ISO-2022-JP (7bit JIS), Shift_JIS, EUC-JP,
- * UTF-8N, UTF-16BE, UTF-32BE.
- * Without this option and compile option, ISO-2022-JP is assumed.
- *
- * === -J -S -E -W -W16 -W32
- *
- * Input assumption is JIS 7 bit, Shift_JIS, EUC-JP,
- * UTF-8, UTF-16, UTF-32.
- *
- * ==== -J
- *
- * Assume JIS input. It also accepts EUC-JP.
- * This is the default. This flag does not exclude Shift_JIS.
- *
- * ==== -S
- *
- * Assume Shift_JIS and X0201 kana input. It also accepts JIS.
- * EUC-JP is recognized as X0201 kana. Without <b>-x</b> flag,
- * X0201 kana (halfwidth kana) is converted into X0208.
- *
- * ==== -E
- *
- * Assume EUC-JP input. It also accepts JIS.
- * Same as -J.
- *
- * === -t
- *
- * No conversion.
- *
- * === -i_
- *
- * Output sequence to designate JIS-kanji. (DEFAULT B)
- *
- * === -o_
- *
- * Output sequence to designate ASCII. (DEFAULT B)
- *
- * === -r
- *
- * {de/en}crypt ROT13/47
- *
- * === \-h[123] --hiragana --katakana --katakana-hiragana
- *
- * [-h1 --hiragana] Katakana to Hiragana conversion.
- *
- * [-h2 --katakana] Hiragana to Katakana conversion.
- *
- * [-h3 --katakana-hiragana] Katakana to Hiragana and Hiragana to Katakana conversion.
- *
- * === -T
- *
- * Text mode output (MS-DOS)
- *
- * === -l
- *
- * ISO8859-1 (Latin-1) support
- *
- * === -f[<code>m</code> [- <code>n</code>]]
- *
- * Folding on <code>m</code> length with <code>n</code> margin in a line.
- * Without this option, fold length is 60 and fold margin is 10.
- *
- * === -F
- *
- * New line preserving line folding.
- *
- * === \-Z[0-3]
- *
- * Convert X0208 alphabet (Fullwidth Alphabets) to ASCII.
- *
- * [-Z -Z0] Convert X0208 alphabet to ASCII.
- *
- * [-Z1] Converts X0208 kankaku to single ASCII space.
- *
- * [-Z2] Converts X0208 kankaku to double ASCII spaces.
- *
- * [-Z3] Replacing Fullwidth >, <, ", & into '&gt;', '&lt;', '&quot;', '&amp;' as in HTML.
- *
- * === -X -x
- *
- * Assume X0201 kana in MS-Kanji.
- * With <b>-X</b> or without this option, X0201 is converted into X0208 Kana.
- * With <b>-x</b>, try to preserve X0208 kana and do not convert X0201 kana to X0208.
- * In JIS output, ESC-(-I is used. In EUC output, SSO is used.
- *
- * === \-B[0-2]
- *
- * Assume broken JIS-Kanji input, which lost ESC.
- * Useful when your site is using old B-News Nihongo patch.
- *
- * [-B1] allows any char after ESC-( or ESC-$.
- *
- * [-B2] forces ASCII after NL.
- *
- * === -I
- *
- * Replacing non iso-2022-jp char into a geta character
- * (substitute character in Japanese).
- *
- * === -d -c
- *
- * Delete \r in line feed, Add \r in line feed.
- *
- * === \-m[BQN0]
- *
- * MIME ISO-2022-JP/ISO8859-1 decode. (DEFAULT)
- * To see ISO8859-1 (Latin-1) -l is necessary.
- *
- * [-mB] Decode MIME base64 encoded stream. Remove header or other part before
- * conversion.
- *
- * [-mQ] Decode MIME quoted stream. '_' in quoted stream is converted to space.
- *
- * [-mN] Non-strict decoding.
- * It allows line break in the middle of the base64 encoding.
- *
- * [-m0] No MIME decode.
- *
- * === -M
- *
- * MIME encode. Header style. All ASCII code and control characters are intact.
- * Kanji conversion is performed before encoding, so this cannot be used as a picture encoder.
- *
- * [-MB] MIME encode Base64 stream.
- *
- * [-MQ] Perform quoted encoding.
- *
- * === -l
- *
- * Input and output code is ISO8859-1 (Latin-1) and ISO-2022-JP.
- * <b>-s</b>, <b>-e</b> and <b>-x</b> are not compatible with this option.
- *
- * === \-L[uwm]
- *
- * new line mode
- * Without this option, nkf doesn't convert line breaks.
- *
- * [-Lu] unix (LF)
- *
- * [-Lw] windows (CRLF)
- *
- * [-Lm] mac (CR)
- *
- * === --fj --unix --mac --msdos --windows
- *
- * convert for these system
- *
- * === --jis --euc --sjis --mime --base64
- *
- * convert for named code
- *
- * === --jis-input --euc-input --sjis-input --mime-input --base64-input
- *
- * assume input system
- *
- * === --ic=<code>input codeset</code> --oc=<code>output codeset</code>
- *
- * Set the input or output codeset.
- * NKF supports following codesets and those codeset name are case insensitive.
- *
- * [ISO-2022-JP] a.k.a. RFC1468, 7bit JIS, JUNET
- *
- * [EUC-JP (eucJP-nkf)] a.k.a. AT&T JIS, Japanese EUC, UJIS
- *
- * [eucJP-ascii] a.k.a. x-eucjp-open-19970715-ascii
- *
- * [eucJP-ms] a.k.a. x-eucjp-open-19970715-ms
- *
- * [CP51932] Microsoft Version of EUC-JP.
- *
- * [Shift_JIS] SJIS, MS-Kanji
- *
- * [Windows-31J] a.k.a. CP932
- *
- * [UTF-8] same as UTF-8N
- *
- * [UTF-8N] UTF-8 without BOM
- *
- * [UTF-8-BOM] UTF-8 with BOM
- *
- * [UTF-16] same as UTF-16BE
- *
- * [UTF-16BE] UTF-16 Big Endian without BOM
- *
- * [UTF-16BE-BOM] UTF-16 Big Endian with BOM
- *
- * [UTF-16LE] UTF-16 Little Endian without BOM
- *
- * [UTF-16LE-BOM] UTF-16 Little Endian with BOM
- *
- * [UTF-32] same as UTF-32BE
- *
- * [UTF-32BE] UTF-32 Big Endian without BOM
- *
- * [UTF-32BE-BOM] UTF-32 Big Endian with BOM
- *
- * [UTF-32LE] UTF-32 Little Endian without BOM
- *
- * [UTF-32LE-BOM] UTF-32 Little Endian with BOM
- *
- * [UTF8-MAC] NKDed UTF-8, a.k.a. UTF8-NFD (input only)
- *
- * === --fb-{skip, html, xml, perl, java, subchar}
- *
- * Specify the way that nkf handles unassigned characters.
- * Without this option, --fb-skip is assumed.
- *
- * === --prefix= <code>escape character</code> <code>target character</code> ..
- *
- * When nkf converts to Shift_JIS,
- * nkf adds a specified escape character to specified 2nd byte of Shift_JIS characters.
- * 1st byte of argument is the escape character and following bytes are target characters.
- *
- * === --no-cp932ext
- *
- * Handle the characters extended in CP932 as unassigned characters.
- *
- * == --no-best-fit-chars
- *
- * When Unicode to Encoded byte conversion,
- * don't convert characters which is not round trip safe.
- * When Unicode to Unicode conversion,
- * with this and -x option, nkf can be used as UTF converter.
- * (In other words, without this and -x option, nkf doesn't save some characters)
- *
- * When nkf convert string which related to path, you should use this option.
- *
- * === --cap-input
- *
- * Decode hex encoded characters.
- *
- * === --url-input
- *
- * Unescape percent escaped characters.
- *
- * === --
- *
- * Ignore rest of -option.
- */
-
-void
-Init_nkf(void)
-{
- VALUE mNKF = rb_define_module("NKF");
-
- rb_define_module_function(mNKF, "nkf", rb_nkf_convert, 2);
- rb_define_module_function(mNKF, "guess", rb_nkf_guess, 1);
- rb_define_alias(rb_singleton_class(mNKF), "guess", "guess");
-
- rb_define_const(mNKF, "AUTO", Qnil);
- rb_define_const(mNKF, "NOCONV", Qnil);
- rb_define_const(mNKF, "UNKNOWN", Qnil);
- rb_define_const(mNKF, "BINARY", rb_enc_from_encoding(rb_nkf_enc_get("BINARY")));
- rb_define_const(mNKF, "ASCII", rb_enc_from_encoding(rb_nkf_enc_get("US-ASCII")));
- rb_define_const(mNKF, "JIS", rb_enc_from_encoding(rb_nkf_enc_get("ISO-2022-JP")));
- rb_define_const(mNKF, "EUC", rb_enc_from_encoding(rb_nkf_enc_get("EUC-JP")));
- rb_define_const(mNKF, "SJIS", rb_enc_from_encoding(rb_nkf_enc_get("Shift_JIS")));
- rb_define_const(mNKF, "UTF8", rb_enc_from_encoding(rb_utf8_encoding()));
- rb_define_const(mNKF, "UTF16", rb_enc_from_encoding(rb_nkf_enc_get("UTF-16BE")));
- rb_define_const(mNKF, "UTF32", rb_enc_from_encoding(rb_nkf_enc_get("UTF-32BE")));
-
- /* Full version string of nkf */
- rb_define_const(mNKF, "VERSION", rb_str_new2(RUBY_NKF_VERSION));
- /* Version of nkf */
- rb_define_const(mNKF, "NKF_VERSION", rb_str_new2(NKF_VERSION));
- /* Release date of nkf */
- rb_define_const(mNKF, "NKF_RELEASE_DATE", rb_str_new2(NKF_RELEASE_DATE));
- /* Version of nkf library */
- rb_define_const(mNKF, "GEM_VERSION", rb_str_new_cstr(NKF_GEM_VERSION));
-}
diff --git a/ext/nkf/nkf.gemspec b/ext/nkf/nkf.gemspec
deleted file mode 100644
index 097a9485ed..0000000000
--- a/ext/nkf/nkf.gemspec
+++ /dev/null
@@ -1,35 +0,0 @@
-source_version = ["", "ext/nkf/"].find do |dir|
- begin
- break File.open(File.join(__dir__, "#{dir}nkf.c")) {|f|
- f.gets("\n#define NKF_GEM_VERSION ")
- f.gets[/\s*"(.+)"/, 1]
- }
- rescue Errno::ENOENT
- end
-end
-
-Gem::Specification.new do |spec|
- spec.name = "nkf"
- spec.version = source_version
- spec.authors = ["NARUSE Yui"]
- spec.email = ["naruse@airemix.jp"]
-
- spec.summary = %q{Ruby extension for Network Kanji Filter}
- spec.description = %q{Ruby extension for Network Kanji Filter}
- spec.homepage = "https://github.com/ruby/nkf"
- spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
- spec.licenses = ["Ruby", "BSD-2-Clause"]
-
- spec.metadata["homepage_uri"] = spec.homepage
- spec.metadata["source_code_uri"] = spec.homepage
-
- # Specify which files should be added to the gem when it is released.
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
- end
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
- spec.require_paths = ["lib"]
- spec.extensions = ["ext/nkf/extconf.rb"]
-end
diff --git a/ext/objspace/depend b/ext/objspace/depend
index 40c2f90a3c..a02168b06a 100644
--- a/ext/objspace/depend
+++ b/ext/objspace/depend
@@ -159,6 +159,7 @@ object_tracing.o: $(hdrdir)/ruby/internal/special_consts.h
object_tracing.o: $(hdrdir)/ruby/internal/static_assert.h
object_tracing.o: $(hdrdir)/ruby/internal/stdalign.h
object_tracing.o: $(hdrdir)/ruby/internal/stdbool.h
+object_tracing.o: $(hdrdir)/ruby/internal/stdckdint.h
object_tracing.o: $(hdrdir)/ruby/internal/symbol.h
object_tracing.o: $(hdrdir)/ruby/internal/value.h
object_tracing.o: $(hdrdir)/ruby/internal/value_type.h
@@ -182,6 +183,7 @@ object_tracing.o: $(top_srcdir)/internal/basic_operators.h
object_tracing.o: $(top_srcdir)/internal/compilers.h
object_tracing.o: $(top_srcdir)/internal/gc.h
object_tracing.o: $(top_srcdir)/internal/imemo.h
+object_tracing.o: $(top_srcdir)/internal/sanitizers.h
object_tracing.o: $(top_srcdir)/internal/serial.h
object_tracing.o: $(top_srcdir)/internal/static_assert.h
object_tracing.o: $(top_srcdir)/internal/vm.h
@@ -357,6 +359,7 @@ objspace.o: $(hdrdir)/ruby/internal/special_consts.h
objspace.o: $(hdrdir)/ruby/internal/static_assert.h
objspace.o: $(hdrdir)/ruby/internal/stdalign.h
objspace.o: $(hdrdir)/ruby/internal/stdbool.h
+objspace.o: $(hdrdir)/ruby/internal/stdckdint.h
objspace.o: $(hdrdir)/ruby/internal/symbol.h
objspace.o: $(hdrdir)/ruby/internal/value.h
objspace.o: $(hdrdir)/ruby/internal/value_type.h
@@ -378,6 +381,7 @@ objspace.o: $(top_srcdir)/ccan/container_of/container_of.h
objspace.o: $(top_srcdir)/ccan/list/list.h
objspace.o: $(top_srcdir)/ccan/str/str.h
objspace.o: $(top_srcdir)/constant.h
+objspace.o: $(top_srcdir)/debug_counter.h
objspace.o: $(top_srcdir)/id_table.h
objspace.o: $(top_srcdir)/internal.h
objspace.o: $(top_srcdir)/internal/array.h
@@ -402,7 +406,9 @@ objspace.o: $(top_srcdir)/shape.h
objspace.o: $(top_srcdir)/symbol.h
objspace.o: $(top_srcdir)/thread_pthread.h
objspace.o: $(top_srcdir)/vm_core.h
+objspace.o: $(top_srcdir)/vm_debug.h
objspace.o: $(top_srcdir)/vm_opts.h
+objspace.o: $(top_srcdir)/vm_sync.h
objspace.o: objspace.c
objspace.o: {$(VPATH)}id.h
objspace_dump.o: $(RUBY_EXTCONF_H)
@@ -565,6 +571,7 @@ objspace_dump.o: $(hdrdir)/ruby/internal/special_consts.h
objspace_dump.o: $(hdrdir)/ruby/internal/static_assert.h
objspace_dump.o: $(hdrdir)/ruby/internal/stdalign.h
objspace_dump.o: $(hdrdir)/ruby/internal/stdbool.h
+objspace_dump.o: $(hdrdir)/ruby/internal/stdckdint.h
objspace_dump.o: $(hdrdir)/ruby/internal/symbol.h
objspace_dump.o: $(hdrdir)/ruby/internal/value.h
objspace_dump.o: $(hdrdir)/ruby/internal/value_type.h
@@ -613,7 +620,9 @@ objspace_dump.o: $(top_srcdir)/symbol.h
objspace_dump.o: $(top_srcdir)/thread_pthread.h
objspace_dump.o: $(top_srcdir)/vm_callinfo.h
objspace_dump.o: $(top_srcdir)/vm_core.h
+objspace_dump.o: $(top_srcdir)/vm_debug.h
objspace_dump.o: $(top_srcdir)/vm_opts.h
+objspace_dump.o: $(top_srcdir)/vm_sync.h
objspace_dump.o: objspace.h
objspace_dump.o: objspace_dump.c
objspace_dump.o: {$(VPATH)}id.h
diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c
index ae869a3ed4..24d7bd419f 100644
--- a/ext/objspace/objspace.c
+++ b/ext/objspace/objspace.c
@@ -19,7 +19,6 @@
#include "internal/hash.h"
#include "internal/imemo.h"
#include "internal/sanitizers.h"
-#include "node.h"
#include "ruby/io.h"
#include "ruby/re.h"
#include "ruby/st.h"
@@ -170,8 +169,7 @@ setup_hash(int argc, VALUE *argv)
hash = rb_hash_new();
}
else if (!RHASH_EMPTY_P(hash)) {
- /* WB: no new reference */
- st_foreach(RHASH_TBL_RAW(hash), set_zero_i, hash);
+ rb_hash_foreach(hash, set_zero_i, (st_data_t)hash);
}
return hash;
@@ -337,17 +335,6 @@ count_symbols(int argc, VALUE *argv, VALUE os)
return hash;
}
-static void
-cn_i(VALUE v, void *n)
-{
- size_t *nodes = (size_t *)n;
-
- if (BUILTIN_TYPE(v) == T_NODE) {
- size_t s = nd_type((NODE *)v);
- nodes[s]++;
- }
-}
-
/*
* call-seq:
* ObjectSpace.count_nodes([result_hash]) -> hash
@@ -374,136 +361,7 @@ cn_i(VALUE v, void *n)
static VALUE
count_nodes(int argc, VALUE *argv, VALUE os)
{
- size_t nodes[NODE_LAST+1];
- enum node_type i;
- VALUE hash = setup_hash(argc, argv);
-
- for (i = 0; i <= NODE_LAST; i++) {
- nodes[i] = 0;
- }
-
- each_object_with_flags(cn_i, &nodes[0]);
-
- for (i=0; i<NODE_LAST; i++) {
- if (nodes[i] != 0) {
- VALUE node;
- switch (i) {
-#define COUNT_NODE(n) case n: node = ID2SYM(rb_intern(#n)); goto set
- COUNT_NODE(NODE_SCOPE);
- COUNT_NODE(NODE_BLOCK);
- COUNT_NODE(NODE_IF);
- COUNT_NODE(NODE_UNLESS);
- COUNT_NODE(NODE_CASE);
- COUNT_NODE(NODE_CASE2);
- COUNT_NODE(NODE_CASE3);
- COUNT_NODE(NODE_WHEN);
- COUNT_NODE(NODE_IN);
- COUNT_NODE(NODE_WHILE);
- COUNT_NODE(NODE_UNTIL);
- COUNT_NODE(NODE_ITER);
- COUNT_NODE(NODE_FOR);
- COUNT_NODE(NODE_FOR_MASGN);
- COUNT_NODE(NODE_BREAK);
- COUNT_NODE(NODE_NEXT);
- COUNT_NODE(NODE_REDO);
- COUNT_NODE(NODE_RETRY);
- COUNT_NODE(NODE_BEGIN);
- COUNT_NODE(NODE_RESCUE);
- COUNT_NODE(NODE_RESBODY);
- COUNT_NODE(NODE_ENSURE);
- COUNT_NODE(NODE_AND);
- COUNT_NODE(NODE_OR);
- COUNT_NODE(NODE_MASGN);
- COUNT_NODE(NODE_LASGN);
- COUNT_NODE(NODE_DASGN);
- COUNT_NODE(NODE_GASGN);
- COUNT_NODE(NODE_IASGN);
- COUNT_NODE(NODE_CDECL);
- COUNT_NODE(NODE_CVASGN);
- COUNT_NODE(NODE_OP_ASGN1);
- COUNT_NODE(NODE_OP_ASGN2);
- COUNT_NODE(NODE_OP_ASGN_AND);
- COUNT_NODE(NODE_OP_ASGN_OR);
- COUNT_NODE(NODE_OP_CDECL);
- COUNT_NODE(NODE_CALL);
- COUNT_NODE(NODE_OPCALL);
- COUNT_NODE(NODE_FCALL);
- COUNT_NODE(NODE_VCALL);
- COUNT_NODE(NODE_QCALL);
- COUNT_NODE(NODE_SUPER);
- COUNT_NODE(NODE_ZSUPER);
- COUNT_NODE(NODE_LIST);
- COUNT_NODE(NODE_ZLIST);
- COUNT_NODE(NODE_HASH);
- COUNT_NODE(NODE_RETURN);
- COUNT_NODE(NODE_YIELD);
- COUNT_NODE(NODE_LVAR);
- COUNT_NODE(NODE_DVAR);
- COUNT_NODE(NODE_GVAR);
- COUNT_NODE(NODE_IVAR);
- COUNT_NODE(NODE_CONST);
- COUNT_NODE(NODE_CVAR);
- COUNT_NODE(NODE_NTH_REF);
- COUNT_NODE(NODE_BACK_REF);
- COUNT_NODE(NODE_MATCH);
- COUNT_NODE(NODE_MATCH2);
- COUNT_NODE(NODE_MATCH3);
- COUNT_NODE(NODE_LIT);
- COUNT_NODE(NODE_STR);
- COUNT_NODE(NODE_DSTR);
- COUNT_NODE(NODE_XSTR);
- COUNT_NODE(NODE_DXSTR);
- COUNT_NODE(NODE_EVSTR);
- COUNT_NODE(NODE_DREGX);
- COUNT_NODE(NODE_ONCE);
- COUNT_NODE(NODE_ARGS);
- COUNT_NODE(NODE_ARGS_AUX);
- COUNT_NODE(NODE_OPT_ARG);
- COUNT_NODE(NODE_KW_ARG);
- COUNT_NODE(NODE_POSTARG);
- COUNT_NODE(NODE_ARGSCAT);
- COUNT_NODE(NODE_ARGSPUSH);
- COUNT_NODE(NODE_SPLAT);
- COUNT_NODE(NODE_BLOCK_PASS);
- COUNT_NODE(NODE_DEFN);
- COUNT_NODE(NODE_DEFS);
- COUNT_NODE(NODE_ALIAS);
- COUNT_NODE(NODE_VALIAS);
- COUNT_NODE(NODE_UNDEF);
- COUNT_NODE(NODE_CLASS);
- COUNT_NODE(NODE_MODULE);
- COUNT_NODE(NODE_SCLASS);
- COUNT_NODE(NODE_COLON2);
- COUNT_NODE(NODE_COLON3);
- COUNT_NODE(NODE_DOT2);
- COUNT_NODE(NODE_DOT3);
- COUNT_NODE(NODE_FLIP2);
- COUNT_NODE(NODE_FLIP3);
- COUNT_NODE(NODE_SELF);
- COUNT_NODE(NODE_NIL);
- COUNT_NODE(NODE_TRUE);
- COUNT_NODE(NODE_FALSE);
- COUNT_NODE(NODE_ERRINFO);
- COUNT_NODE(NODE_DEFINED);
- COUNT_NODE(NODE_POSTEXE);
- COUNT_NODE(NODE_DSYM);
- COUNT_NODE(NODE_ATTRASGN);
- COUNT_NODE(NODE_LAMBDA);
- COUNT_NODE(NODE_ARYPTN);
- COUNT_NODE(NODE_FNDPTN);
- COUNT_NODE(NODE_HSHPTN);
- COUNT_NODE(NODE_RIPPER);
- COUNT_NODE(NODE_RIPPER_VALUES);
- COUNT_NODE(NODE_ERROR);
-#undef COUNT_NODE
- case NODE_LAST: break;
- }
- UNREACHABLE;
- set:
- rb_hash_aset(hash, node, SIZET2NUM(nodes[i]));
- }
- }
- return hash;
+ return setup_hash(argc, argv);
}
static void
@@ -765,7 +623,7 @@ collect_values(st_data_t key, st_data_t value, st_data_t data)
*
* With this method, you can find memory leaks.
*
- * This method is only expected to work except with C Ruby.
+ * This method is only expected to work with C Ruby.
*
* Example:
* ObjectSpace.reachable_objects_from(['a', 'b', 'c'])
diff --git a/ext/objspace/objspace_dump.c b/ext/objspace/objspace_dump.c
index c80c38eba4..bb479b91c5 100644
--- a/ext/objspace/objspace_dump.c
+++ b/ext/objspace/objspace_dump.c
@@ -168,10 +168,8 @@ dump_append_c(struct dump_config *dc, unsigned char c)
}
static void
-dump_append_ref(struct dump_config *dc, VALUE ref)
+dump_append_ptr(struct dump_config *dc, VALUE ref)
{
- RUBY_ASSERT(ref > 0);
-
char buffer[roomof(sizeof(VALUE) * CHAR_BIT, 4) + rb_strlen_lit("\"0x\"")];
char *buffer_start, *buffer_end;
@@ -188,6 +186,14 @@ dump_append_ref(struct dump_config *dc, VALUE ref)
}
static void
+dump_append_ref(struct dump_config *dc, VALUE ref)
+{
+ RUBY_ASSERT(ref > 0);
+ dump_append_ptr(dc, ref);
+}
+
+
+static void
dump_append_string_value(struct dump_config *dc, VALUE obj)
{
long i;
@@ -360,8 +366,9 @@ dump_append_string_content(struct dump_config *dc, VALUE obj)
static inline void
dump_append_id(struct dump_config *dc, ID id)
{
- if (is_instance_id(id)) {
- dump_append_string_value(dc, rb_sym2str(ID2SYM(id)));
+ VALUE str = rb_sym2str(ID2SYM(id));
+ if (RTEST(str)) {
+ dump_append_string_value(dc, str);
}
else {
dump_append(dc, "\"ID_INTERNAL(");
@@ -437,7 +444,21 @@ dump_object(VALUE obj, struct dump_config *dc)
mid = vm_ci_mid((const struct rb_callinfo *)obj);
if (mid != 0) {
dump_append(dc, ", \"mid\":");
- dump_append_string_value(dc, rb_id2str(mid));
+ dump_append_id(dc, mid);
+ }
+ break;
+
+ case imemo_callcache:
+ mid = vm_cc_cme((const struct rb_callcache *)obj)->called_id;
+ if (mid != 0) {
+ dump_append(dc, ", \"called_id\":");
+ dump_append_id(dc, mid);
+
+ VALUE klass = ((const struct rb_callcache *)obj)->klass;
+ if (klass != 0) {
+ dump_append(dc, ", \"receiver_class\":");
+ dump_append_ref(dc, klass);
+ }
}
break;
@@ -455,6 +476,8 @@ dump_object(VALUE obj, struct dump_config *dc)
dump_append(dc, ", \"embedded\":true");
if (FL_TEST(obj, RSTRING_FSTR))
dump_append(dc, ", \"fstring\":true");
+ if (CHILLED_STRING_P(obj))
+ dump_append(dc, ", \"chilled\":true");
if (STR_SHARED_P(obj))
dump_append(dc, ", \"shared\":true");
else
@@ -539,7 +562,7 @@ dump_object(VALUE obj, struct dump_config *dc)
}
}
- if (FL_TEST(obj, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON_P(obj)) {
dump_append(dc, ", \"singleton\":true");
}
}
@@ -771,11 +794,6 @@ shape_i(rb_shape_t *shape, void *data)
case SHAPE_FROZEN:
dump_append(dc, "\"FROZEN\"");
break;
- case SHAPE_CAPACITY_CHANGE:
- dump_append(dc, "\"CAPACITY_CHANGE\"");
- dump_append(dc, ", \"capacity\":");
- dump_append_sizet(dc, shape->capacity);
- break;
case SHAPE_T_OBJECT:
dump_append(dc, "\"T_OBJECT\"");
break;
diff --git a/ext/openssl/History.md b/ext/openssl/History.md
index bd7b1ec1b1..3249f6617a 100644
--- a/ext/openssl/History.md
+++ b/ext/openssl/History.md
@@ -457,7 +457,7 @@ Security fixes
Bug fixes
---------
-* Fixed OpenSSL::PKey::*.{new,generate} immediately aborting if the thread is
+* Fixed OpenSSL::PKey::\*.{new,generate} immediately aborting if the thread is
interrupted.
[[Bug #14882]](https://bugs.ruby-lang.org/issues/14882)
[[GitHub #205]](https://github.com/ruby/openssl/pull/205)
diff --git a/ext/openssl/depend b/ext/openssl/depend
index 0d03c85b80..12c6793939 100644
--- a/ext/openssl/depend
+++ b/ext/openssl/depend
@@ -161,6 +161,7 @@ ossl.o: $(hdrdir)/ruby/internal/special_consts.h
ossl.o: $(hdrdir)/ruby/internal/static_assert.h
ossl.o: $(hdrdir)/ruby/internal/stdalign.h
ossl.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl.o: $(hdrdir)/ruby/internal/symbol.h
ossl.o: $(hdrdir)/ruby/internal/value.h
ossl.o: $(hdrdir)/ruby/internal/value_type.h
@@ -355,6 +356,7 @@ ossl_asn1.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_asn1.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_asn1.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_asn1.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_asn1.o: $(hdrdir)/ruby/internal/symbol.h
ossl_asn1.o: $(hdrdir)/ruby/internal/value.h
ossl_asn1.o: $(hdrdir)/ruby/internal/value_type.h
@@ -549,6 +551,7 @@ ossl_bio.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_bio.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_bio.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_bio.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_bio.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_bio.o: $(hdrdir)/ruby/internal/symbol.h
ossl_bio.o: $(hdrdir)/ruby/internal/value.h
ossl_bio.o: $(hdrdir)/ruby/internal/value_type.h
@@ -743,6 +746,7 @@ ossl_bn.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_bn.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_bn.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_bn.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_bn.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_bn.o: $(hdrdir)/ruby/internal/symbol.h
ossl_bn.o: $(hdrdir)/ruby/internal/value.h
ossl_bn.o: $(hdrdir)/ruby/internal/value_type.h
@@ -938,6 +942,7 @@ ossl_cipher.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_cipher.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_cipher.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_cipher.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_cipher.o: $(hdrdir)/ruby/internal/symbol.h
ossl_cipher.o: $(hdrdir)/ruby/internal/value.h
ossl_cipher.o: $(hdrdir)/ruby/internal/value_type.h
@@ -1132,6 +1137,7 @@ ossl_config.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_config.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_config.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_config.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_config.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_config.o: $(hdrdir)/ruby/internal/symbol.h
ossl_config.o: $(hdrdir)/ruby/internal/value.h
ossl_config.o: $(hdrdir)/ruby/internal/value_type.h
@@ -1326,6 +1332,7 @@ ossl_digest.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_digest.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_digest.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_digest.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_digest.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_digest.o: $(hdrdir)/ruby/internal/symbol.h
ossl_digest.o: $(hdrdir)/ruby/internal/value.h
ossl_digest.o: $(hdrdir)/ruby/internal/value_type.h
@@ -1520,6 +1527,7 @@ ossl_engine.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_engine.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_engine.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_engine.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_engine.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_engine.o: $(hdrdir)/ruby/internal/symbol.h
ossl_engine.o: $(hdrdir)/ruby/internal/value.h
ossl_engine.o: $(hdrdir)/ruby/internal/value_type.h
@@ -1714,6 +1722,7 @@ ossl_hmac.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_hmac.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_hmac.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_hmac.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_hmac.o: $(hdrdir)/ruby/internal/symbol.h
ossl_hmac.o: $(hdrdir)/ruby/internal/value.h
ossl_hmac.o: $(hdrdir)/ruby/internal/value_type.h
@@ -1908,6 +1917,7 @@ ossl_kdf.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_kdf.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_kdf.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_kdf.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_kdf.o: $(hdrdir)/ruby/internal/symbol.h
ossl_kdf.o: $(hdrdir)/ruby/internal/value.h
ossl_kdf.o: $(hdrdir)/ruby/internal/value_type.h
@@ -2102,6 +2112,7 @@ ossl_ns_spki.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_ns_spki.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_ns_spki.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_ns_spki.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_ns_spki.o: $(hdrdir)/ruby/internal/symbol.h
ossl_ns_spki.o: $(hdrdir)/ruby/internal/value.h
ossl_ns_spki.o: $(hdrdir)/ruby/internal/value_type.h
@@ -2296,6 +2307,7 @@ ossl_ocsp.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_ocsp.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_ocsp.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_ocsp.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_ocsp.o: $(hdrdir)/ruby/internal/symbol.h
ossl_ocsp.o: $(hdrdir)/ruby/internal/value.h
ossl_ocsp.o: $(hdrdir)/ruby/internal/value_type.h
@@ -2490,6 +2502,7 @@ ossl_pkcs12.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_pkcs12.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_pkcs12.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_pkcs12.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_pkcs12.o: $(hdrdir)/ruby/internal/symbol.h
ossl_pkcs12.o: $(hdrdir)/ruby/internal/value.h
ossl_pkcs12.o: $(hdrdir)/ruby/internal/value_type.h
@@ -2684,6 +2697,7 @@ ossl_pkcs7.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_pkcs7.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_pkcs7.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_pkcs7.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_pkcs7.o: $(hdrdir)/ruby/internal/symbol.h
ossl_pkcs7.o: $(hdrdir)/ruby/internal/value.h
ossl_pkcs7.o: $(hdrdir)/ruby/internal/value_type.h
@@ -2878,6 +2892,7 @@ ossl_pkey.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_pkey.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_pkey.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_pkey.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_pkey.o: $(hdrdir)/ruby/internal/symbol.h
ossl_pkey.o: $(hdrdir)/ruby/internal/value.h
ossl_pkey.o: $(hdrdir)/ruby/internal/value_type.h
@@ -3072,6 +3087,7 @@ ossl_pkey_dh.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_pkey_dh.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_pkey_dh.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_pkey_dh.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_pkey_dh.o: $(hdrdir)/ruby/internal/symbol.h
ossl_pkey_dh.o: $(hdrdir)/ruby/internal/value.h
ossl_pkey_dh.o: $(hdrdir)/ruby/internal/value_type.h
@@ -3266,6 +3282,7 @@ ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/symbol.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/value.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/value_type.h
@@ -3460,6 +3477,7 @@ ossl_pkey_ec.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_pkey_ec.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_pkey_ec.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_pkey_ec.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_pkey_ec.o: $(hdrdir)/ruby/internal/symbol.h
ossl_pkey_ec.o: $(hdrdir)/ruby/internal/value.h
ossl_pkey_ec.o: $(hdrdir)/ruby/internal/value_type.h
@@ -3654,6 +3672,7 @@ ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/symbol.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/value.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/value_type.h
@@ -3848,6 +3867,7 @@ ossl_provider.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_provider.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_provider.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_provider.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_provider.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_provider.o: $(hdrdir)/ruby/internal/symbol.h
ossl_provider.o: $(hdrdir)/ruby/internal/value.h
ossl_provider.o: $(hdrdir)/ruby/internal/value_type.h
@@ -4042,6 +4062,7 @@ ossl_rand.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_rand.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_rand.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_rand.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_rand.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_rand.o: $(hdrdir)/ruby/internal/symbol.h
ossl_rand.o: $(hdrdir)/ruby/internal/value.h
ossl_rand.o: $(hdrdir)/ruby/internal/value_type.h
@@ -4236,6 +4257,7 @@ ossl_ssl.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_ssl.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_ssl.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_ssl.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_ssl.o: $(hdrdir)/ruby/internal/symbol.h
ossl_ssl.o: $(hdrdir)/ruby/internal/value.h
ossl_ssl.o: $(hdrdir)/ruby/internal/value_type.h
@@ -4430,6 +4452,7 @@ ossl_ssl_session.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_ssl_session.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_ssl_session.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_ssl_session.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_ssl_session.o: $(hdrdir)/ruby/internal/symbol.h
ossl_ssl_session.o: $(hdrdir)/ruby/internal/value.h
ossl_ssl_session.o: $(hdrdir)/ruby/internal/value_type.h
@@ -4624,6 +4647,7 @@ ossl_ts.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_ts.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_ts.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_ts.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_ts.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_ts.o: $(hdrdir)/ruby/internal/symbol.h
ossl_ts.o: $(hdrdir)/ruby/internal/value.h
ossl_ts.o: $(hdrdir)/ruby/internal/value_type.h
@@ -4818,6 +4842,7 @@ ossl_x509.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_x509.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_x509.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_x509.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_x509.o: $(hdrdir)/ruby/internal/symbol.h
ossl_x509.o: $(hdrdir)/ruby/internal/value.h
ossl_x509.o: $(hdrdir)/ruby/internal/value_type.h
@@ -5012,6 +5037,7 @@ ossl_x509attr.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_x509attr.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_x509attr.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_x509attr.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_x509attr.o: $(hdrdir)/ruby/internal/symbol.h
ossl_x509attr.o: $(hdrdir)/ruby/internal/value.h
ossl_x509attr.o: $(hdrdir)/ruby/internal/value_type.h
@@ -5206,6 +5232,7 @@ ossl_x509cert.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_x509cert.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_x509cert.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_x509cert.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_x509cert.o: $(hdrdir)/ruby/internal/symbol.h
ossl_x509cert.o: $(hdrdir)/ruby/internal/value.h
ossl_x509cert.o: $(hdrdir)/ruby/internal/value_type.h
@@ -5400,6 +5427,7 @@ ossl_x509crl.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_x509crl.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_x509crl.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_x509crl.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_x509crl.o: $(hdrdir)/ruby/internal/symbol.h
ossl_x509crl.o: $(hdrdir)/ruby/internal/value.h
ossl_x509crl.o: $(hdrdir)/ruby/internal/value_type.h
@@ -5594,6 +5622,7 @@ ossl_x509ext.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_x509ext.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_x509ext.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_x509ext.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_x509ext.o: $(hdrdir)/ruby/internal/symbol.h
ossl_x509ext.o: $(hdrdir)/ruby/internal/value.h
ossl_x509ext.o: $(hdrdir)/ruby/internal/value_type.h
@@ -5788,6 +5817,7 @@ ossl_x509name.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_x509name.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_x509name.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_x509name.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_x509name.o: $(hdrdir)/ruby/internal/symbol.h
ossl_x509name.o: $(hdrdir)/ruby/internal/value.h
ossl_x509name.o: $(hdrdir)/ruby/internal/value_type.h
@@ -5982,6 +6012,7 @@ ossl_x509req.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_x509req.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_x509req.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_x509req.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_x509req.o: $(hdrdir)/ruby/internal/symbol.h
ossl_x509req.o: $(hdrdir)/ruby/internal/value.h
ossl_x509req.o: $(hdrdir)/ruby/internal/value_type.h
@@ -6176,6 +6207,7 @@ ossl_x509revoked.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_x509revoked.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_x509revoked.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_x509revoked.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_x509revoked.o: $(hdrdir)/ruby/internal/symbol.h
ossl_x509revoked.o: $(hdrdir)/ruby/internal/value.h
ossl_x509revoked.o: $(hdrdir)/ruby/internal/value_type.h
@@ -6370,6 +6402,7 @@ ossl_x509store.o: $(hdrdir)/ruby/internal/special_consts.h
ossl_x509store.o: $(hdrdir)/ruby/internal/static_assert.h
ossl_x509store.o: $(hdrdir)/ruby/internal/stdalign.h
ossl_x509store.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/stdckdint.h
ossl_x509store.o: $(hdrdir)/ruby/internal/symbol.h
ossl_x509store.o: $(hdrdir)/ruby/internal/value.h
ossl_x509store.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb
index 56f4a1c3ab..8d2eac0262 100644
--- a/ext/openssl/extconf.rb
+++ b/ext/openssl/extconf.rb
@@ -8,19 +8,12 @@
= Licence
This program is licensed under the same licence as Ruby.
- (See the file 'LICENCE'.)
+ (See the file 'COPYING'.)
=end
require "mkmf"
-ssl_dirs = nil
-if defined?(::TruffleRuby)
- # Always respect the openssl prefix chosen by truffle/openssl-prefix
- require 'truffle/openssl-prefix'
- ssl_dirs = dir_config("openssl", ENV["OPENSSL_PREFIX"])
-else
- ssl_dirs = dir_config("openssl")
-end
+ssl_dirs = dir_config("openssl")
dir_config_given = ssl_dirs.any?
_, ssl_ldir = ssl_dirs
@@ -49,6 +42,7 @@ $defs.push("-D""OPENSSL_SUPPRESS_DEPRECATED")
have_func("rb_io_descriptor")
have_func("rb_io_maybe_wait(0, Qnil, Qnil, Qnil)", "ruby/io.h") # Ruby 3.1
+have_func("rb_io_timeout", "ruby/io.h")
Logging::message "=== Checking for system dependent stuff... ===\n"
have_library("nsl", "t_open")
@@ -155,6 +149,9 @@ engines.each { |name|
have_func("ENGINE_load_#{name}()", "openssl/engine.h")
}
+# missing in libressl < 3.5
+have_func("i2d_re_X509_tbs(NULL, NULL)", x509_h)
+
# added in 1.1.0
if !have_struct_member("SSL", "ctx", "openssl/ssl.h") || is_libressl
$defs.push("-DHAVE_OPAQUE_OPENSSL")
diff --git a/ext/openssl/lib/openssl.rb b/ext/openssl/lib/openssl.rb
index 8a342f15b6..f5ca956d07 100644
--- a/ext/openssl/lib/openssl.rb
+++ b/ext/openssl/lib/openssl.rb
@@ -7,7 +7,7 @@
= Licence
This program is licensed under the same licence as Ruby.
- (See the file 'LICENCE'.)
+ (See the file 'COPYING'.)
=end
require 'openssl.so'
diff --git a/ext/openssl/lib/openssl/bn.rb b/ext/openssl/lib/openssl/bn.rb
index 0a5e11b4c2..e4889a140c 100644
--- a/ext/openssl/lib/openssl/bn.rb
+++ b/ext/openssl/lib/openssl/bn.rb
@@ -10,7 +10,7 @@
#
# = Licence
# This program is licensed under the same licence as Ruby.
-# (See the file 'LICENCE'.)
+# (See the file 'COPYING'.)
#++
module OpenSSL
diff --git a/ext/openssl/lib/openssl/buffering.rb b/ext/openssl/lib/openssl/buffering.rb
index 9570f14f37..d0b4b18038 100644
--- a/ext/openssl/lib/openssl/buffering.rb
+++ b/ext/openssl/lib/openssl/buffering.rb
@@ -8,7 +8,7 @@
#
#= Licence
# This program is licensed under the same licence as Ruby.
-# (See the file 'LICENCE'.)
+# (See the file 'COPYING'.)
#++
##
@@ -229,7 +229,7 @@ module OpenSSL::Buffering
#
# Unlike IO#gets the separator must be provided if a limit is provided.
- def gets(eol=$/, limit=nil)
+ def gets(eol=$/, limit=nil, chomp: false)
idx = @rbuffer.index(eol)
until @eof
break if idx
@@ -244,7 +244,11 @@ module OpenSSL::Buffering
if size && limit && limit >= 0
size = [size, limit].min
end
- consume_rbuff(size)
+ line = consume_rbuff(size)
+ if chomp && line
+ line.chomp!(eol)
+ end
+ line
end
##
@@ -345,13 +349,18 @@ module OpenSSL::Buffering
@wbuffer << s
@wbuffer.force_encoding(Encoding::BINARY)
@sync ||= false
- if @sync or @wbuffer.size > BLOCK_SIZE
- until @wbuffer.empty?
- begin
- nwrote = syswrite(@wbuffer)
- rescue Errno::EAGAIN
- retry
+ buffer_size = @wbuffer.size
+ if @sync or buffer_size > BLOCK_SIZE
+ nwrote = 0
+ begin
+ while nwrote < buffer_size do
+ begin
+ nwrote += syswrite(@wbuffer[nwrote, buffer_size - nwrote])
+ rescue Errno::EAGAIN
+ retry
+ end
end
+ ensure
@wbuffer[0, nwrote] = ""
end
end
diff --git a/ext/openssl/lib/openssl/cipher.rb b/ext/openssl/lib/openssl/cipher.rb
index 8ad8c35dd3..ab75ac8e1a 100644
--- a/ext/openssl/lib/openssl/cipher.rb
+++ b/ext/openssl/lib/openssl/cipher.rb
@@ -9,7 +9,7 @@
#
# = Licence
# This program is licensed under the same licence as Ruby.
-# (See the file 'LICENCE'.)
+# (See the file 'COPYING'.)
#++
module OpenSSL
diff --git a/ext/openssl/lib/openssl/digest.rb b/ext/openssl/lib/openssl/digest.rb
index 0f35ddadd3..5cda1e931c 100644
--- a/ext/openssl/lib/openssl/digest.rb
+++ b/ext/openssl/lib/openssl/digest.rb
@@ -9,7 +9,7 @@
#
# = Licence
# This program is licensed under the same licence as Ruby.
-# (See the file 'LICENCE'.)
+# (See the file 'COPYING'.)
#++
module OpenSSL
diff --git a/ext/openssl/lib/openssl/marshal.rb b/ext/openssl/lib/openssl/marshal.rb
index af5647192a..eb8eda4748 100644
--- a/ext/openssl/lib/openssl/marshal.rb
+++ b/ext/openssl/lib/openssl/marshal.rb
@@ -9,7 +9,7 @@
#
# = Licence
# This program is licensed under the same licence as Ruby.
-# (See the file 'LICENCE'.)
+# (See the file 'COPYING'.)
#++
module OpenSSL
module Marshal
diff --git a/ext/openssl/lib/openssl/ssl.rb b/ext/openssl/lib/openssl/ssl.rb
index e557b8b483..2186f5f43a 100644
--- a/ext/openssl/lib/openssl/ssl.rb
+++ b/ext/openssl/lib/openssl/ssl.rb
@@ -7,7 +7,7 @@
= Licence
This program is licensed under the same licence as Ruby.
- (See the file 'LICENCE'.)
+ (See the file 'COPYING'.)
=end
require "openssl/buffering"
@@ -22,7 +22,6 @@ module OpenSSL
module SSL
class SSLContext
DEFAULT_PARAMS = { # :nodoc:
- :min_version => OpenSSL::SSL::TLS1_VERSION,
:verify_mode => OpenSSL::SSL::VERIFY_PEER,
:verify_hostname => true,
:options => -> {
@@ -55,6 +54,7 @@ ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
if !(OpenSSL::OPENSSL_VERSION.start_with?("OpenSSL") &&
OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10100000)
DEFAULT_PARAMS.merge!(
+ min_version: OpenSSL::SSL::TLS1_VERSION,
ciphers: %w{
ECDHE-ECDSA-AES128-GCM-SHA256
ECDHE-RSA-AES128-GCM-SHA256
@@ -252,6 +252,14 @@ ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
to_io.peeraddr
end
+ def local_address
+ to_io.local_address
+ end
+
+ def remote_address
+ to_io.remote_address
+ end
+
def setsockopt(level, optname, optval)
to_io.setsockopt(level, optname, optval)
end
@@ -271,6 +279,36 @@ ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
def do_not_reverse_lookup=(flag)
to_io.do_not_reverse_lookup = flag
end
+
+ def close_on_exec=(value)
+ to_io.close_on_exec = value
+ end
+
+ def close_on_exec?
+ to_io.close_on_exec?
+ end
+
+ def wait(*args)
+ to_io.wait(*args)
+ end
+
+ def wait_readable(*args)
+ to_io.wait_readable(*args)
+ end
+
+ def wait_writable(*args)
+ to_io.wait_writable(*args)
+ end
+
+ if IO.method_defined?(:timeout)
+ def timeout
+ to_io.timeout
+ end
+
+ def timeout=(value)
+ to_io.timeout=(value)
+ end
+ end
end
def verify_certificate_identity(cert, hostname)
@@ -421,6 +459,32 @@ ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
nil
end
+ # Close the stream for reading.
+ # This method is ignored by OpenSSL as there is no reasonable way to
+ # implement it, but exists for compatibility with IO.
+ def close_read
+ # Unsupported and ignored.
+ # Just don't read any more.
+ end
+
+ # Closes the stream for writing. The behavior of this method depends on
+ # the version of OpenSSL and the TLS protocol in use.
+ #
+ # - Sends a 'close_notify' alert to the peer.
+ # - Does not wait for the peer's 'close_notify' alert in response.
+ #
+ # In TLS 1.2 and earlier:
+ # - On receipt of a 'close_notify' alert, responds with a 'close_notify'
+ # alert of its own and close down the connection immediately,
+ # discarding any pending writes.
+ #
+ # Therefore, on TLS 1.2, this method will cause the connection to be
+ # completely shut down. On TLS 1.3, the connection will remain open for
+ # reading only.
+ def close_write
+ stop
+ end
+
private
def using_anon_cipher?
diff --git a/ext/openssl/lib/openssl/x509.rb b/ext/openssl/lib/openssl/x509.rb
index f973f4f4dc..b66727420e 100644
--- a/ext/openssl/lib/openssl/x509.rb
+++ b/ext/openssl/lib/openssl/x509.rb
@@ -9,7 +9,7 @@
#
# = Licence
# This program is licensed under the same licence as Ruby.
-# (See the file 'LICENCE'.)
+# (See the file 'COPYING'.)
#++
require_relative 'marshal'
diff --git a/ext/openssl/openssl.gemspec b/ext/openssl/openssl.gemspec
index 2765f55401..e692e661c4 100644
--- a/ext/openssl/openssl.gemspec
+++ b/ext/openssl/openssl.gemspec
@@ -6,14 +6,14 @@ Gem::Specification.new do |spec|
spec.summary = %q{SSL/TLS and general-purpose cryptography for Ruby}
spec.description = %q{OpenSSL for Ruby provides access to SSL/TLS and general-purpose cryptography based on the OpenSSL library.}
spec.homepage = "https://github.com/ruby/openssl"
- spec.license = "Ruby"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
if Gem::Platform === spec.platform and spec.platform =~ 'java' or RUBY_ENGINE == 'jruby'
spec.platform = "java"
spec.files = []
spec.add_runtime_dependency('jruby-openssl', '~> 0.14')
else
- spec.files = Dir["lib/**/*.rb", "ext/**/*.{c,h,rb}", "*.md", "BSDL", "LICENSE.txt"]
+ spec.files = Dir["lib/**/*.rb", "ext/**/*.{c,h,rb}", "*.md", "BSDL", "COPYING"]
spec.require_paths = ["lib"]
spec.extensions = ["ext/openssl/extconf.rb"]
end
diff --git a/ext/openssl/openssl_missing.c b/ext/openssl/openssl_missing.c
index 4415703db4..5a6d23e106 100644
--- a/ext/openssl/openssl_missing.c
+++ b/ext/openssl/openssl_missing.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include RUBY_EXTCONF_H
diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h
index 8629bfe505..0711f924e5 100644
--- a/ext/openssl/openssl_missing.h
+++ b/ext/openssl/openssl_missing.h
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_OPENSSL_MISSING_H_)
#define _OSSL_OPENSSL_MISSING_H_
diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c
index 00eded55cb..59ad7d19a4 100644
--- a/ext/openssl/ossl.c
+++ b/ext/openssl/ossl.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
#include <stdarg.h> /* for ossl_raise */
diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h
index 68d42b71e2..c3140ac3ef 100644
--- a/ext/openssl/ossl.h
+++ b/ext/openssl/ossl.h
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_H_)
#define _OSSL_H_
diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c
index 71c452c88a..fb47684347 100644
--- a/ext/openssl/ossl_asn1.c
+++ b/ext/openssl/ossl_asn1.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -1163,9 +1163,12 @@ ossl_asn1prim_to_der(VALUE self)
rb_jump_tag(state);
}
p0 = p1 = (unsigned char *)RSTRING_PTR(str);
- i2d_ASN1_TYPE(asn1, &p0);
+ if (i2d_ASN1_TYPE(asn1, &p0) < 0) {
+ ASN1_TYPE_free(asn1);
+ ossl_raise(eASN1Error, "i2d_ASN1_TYPE");
+ }
ASN1_TYPE_free(asn1);
- assert(p0 - p1 == alllen);
+ ossl_str_adjust(str, p0);
/* Strip header since to_der_internal() wants only the payload */
j = ASN1_get_object((const unsigned char **)&p1, &bodylen, &tag, &tc, alllen);
diff --git a/ext/openssl/ossl_asn1.h b/ext/openssl/ossl_asn1.h
index 939a96ce74..f47e353948 100644
--- a/ext/openssl/ossl_asn1.h
+++ b/ext/openssl/ossl_asn1.h
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_ASN1_H_)
#define _OSSL_ASN1_H_
diff --git a/ext/openssl/ossl_bio.c b/ext/openssl/ossl_bio.c
index 42833d901a..2ef2080507 100644
--- a/ext/openssl/ossl_bio.c
+++ b/ext/openssl/ossl_bio.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
diff --git a/ext/openssl/ossl_bio.h b/ext/openssl/ossl_bio.h
index da68c5e5a2..1b871f1cd7 100644
--- a/ext/openssl/ossl_bio.h
+++ b/ext/openssl/ossl_bio.h
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_BIO_H_)
#define _OSSL_BIO_H_
diff --git a/ext/openssl/ossl_bn.c b/ext/openssl/ossl_bn.c
index ce0d3ec7ee..7393fdea56 100644
--- a/ext/openssl/ossl_bn.c
+++ b/ext/openssl/ossl_bn.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
/* modified by Michal Rokos <m.rokos@sh.cvut.cz> */
#include "ossl.h"
diff --git a/ext/openssl/ossl_bn.h b/ext/openssl/ossl_bn.h
index 1cc041fc22..800f84cb1e 100644
--- a/ext/openssl/ossl_bn.h
+++ b/ext/openssl/ossl_bn.h
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_BN_H_)
#define _OSSL_BN_H_
diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c
index 110610e1f9..cc0114f579 100644
--- a/ext/openssl/ossl_cipher.c
+++ b/ext/openssl/ossl_cipher.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -386,11 +386,23 @@ ossl_cipher_update(int argc, VALUE *argv, VALUE self)
in = (unsigned char *)RSTRING_PTR(data);
in_len = RSTRING_LEN(data);
GetCipher(self, ctx);
- out_len = in_len+EVP_CIPHER_CTX_block_size(ctx);
- if (out_len <= 0) {
+
+ /*
+ * As of OpenSSL 3.2, there is no reliable way to determine the required
+ * output buffer size for arbitrary cipher modes.
+ * https://github.com/openssl/openssl/issues/22628
+ *
+ * in_len+block_size is usually sufficient, but AES key wrap with padding
+ * ciphers require in_len+15 even though they have a block size of 8 bytes.
+ *
+ * Using EVP_MAX_BLOCK_LENGTH (32) as a safe upper bound for ciphers
+ * currently implemented in OpenSSL, but this can change in the future.
+ */
+ if (in_len > LONG_MAX - EVP_MAX_BLOCK_LENGTH) {
ossl_raise(rb_eRangeError,
"data too big to make output buffer: %ld bytes", in_len);
}
+ out_len = in_len + EVP_MAX_BLOCK_LENGTH;
if (NIL_P(str)) {
str = rb_str_new(0, out_len);
@@ -401,7 +413,7 @@ ossl_cipher_update(int argc, VALUE *argv, VALUE self)
if (!ossl_cipher_update_long(ctx, (unsigned char *)RSTRING_PTR(str), &out_len, in, in_len))
ossl_raise(eCipherError, NULL);
- assert(out_len < RSTRING_LEN(str));
+ assert(out_len <= RSTRING_LEN(str));
rb_str_set_len(str, out_len);
return str;
@@ -442,8 +454,8 @@ ossl_cipher_final(VALUE self)
* call-seq:
* cipher.name -> string
*
- * Returns the name of the cipher which may differ slightly from the original
- * name provided.
+ * Returns the short name of the cipher which may differ slightly from the
+ * original name provided.
*/
static VALUE
ossl_cipher_name(VALUE self)
diff --git a/ext/openssl/ossl_cipher.h b/ext/openssl/ossl_cipher.h
index 2392d41c6a..07b50c3bd5 100644
--- a/ext/openssl/ossl_cipher.h
+++ b/ext/openssl/ossl_cipher.h
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_CIPHER_H_)
#define _OSSL_CIPHER_H_
diff --git a/ext/openssl/ossl_config.c b/ext/openssl/ossl_config.c
index 0e598b4d51..55875028b2 100644
--- a/ext/openssl/ossl_config.c
+++ b/ext/openssl/ossl_config.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
diff --git a/ext/openssl/ossl_config.h b/ext/openssl/ossl_config.h
index 4e604f1aed..a254360c2c 100644
--- a/ext/openssl/ossl_config.h
+++ b/ext/openssl/ossl_config.h
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#ifndef OSSL_CONFIG_H
#define OSSL_CONFIG_H
diff --git a/ext/openssl/ossl_digest.c b/ext/openssl/ossl_digest.c
index 16aeeb8106..00ec8931ab 100644
--- a/ext/openssl/ossl_digest.c
+++ b/ext/openssl/ossl_digest.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -103,7 +103,8 @@ VALUE ossl_digest_update(VALUE, VALUE);
* Digest.new(string [, data]) -> Digest
*
* Creates a Digest instance based on _string_, which is either the ln
- * (long name) or sn (short name) of a supported digest algorithm.
+ * (long name) or sn (short name) of a supported digest algorithm. A list of
+ * supported algorithms can be obtained by calling OpenSSL::Digest.digests.
*
* If _data_ (a String) is given, it is used as the initial input to the
* Digest instance, i.e.
@@ -162,6 +163,32 @@ ossl_digest_copy(VALUE self, VALUE other)
return self;
}
+static void
+add_digest_name_to_ary(const OBJ_NAME *name, void *arg)
+{
+ VALUE ary = (VALUE)arg;
+ rb_ary_push(ary, rb_str_new2(name->name));
+}
+
+/*
+ * call-seq:
+ * OpenSSL::Digest.digests -> array[string...]
+ *
+ * Returns the names of all available digests in an array.
+ */
+static VALUE
+ossl_s_digests(VALUE self)
+{
+ VALUE ary;
+
+ ary = rb_ary_new();
+ OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH,
+ add_digest_name_to_ary,
+ (void*)ary);
+
+ return ary;
+}
+
/*
* call-seq:
* digest.reset -> self
@@ -245,7 +272,8 @@ ossl_digest_finish(int argc, VALUE *argv, VALUE self)
* call-seq:
* digest.name -> string
*
- * Returns the sn of this Digest algorithm.
+ * Returns the short name of this Digest algorithm which may differ slightly
+ * from the original name provided.
*
* === Example
* digest = OpenSSL::Digest.new('SHA512')
@@ -412,6 +440,7 @@ Init_ossl_digest(void)
rb_define_alloc_func(cDigest, ossl_digest_alloc);
+ rb_define_module_function(cDigest, "digests", ossl_s_digests, 0);
rb_define_method(cDigest, "initialize", ossl_digest_initialize, -1);
rb_define_method(cDigest, "initialize_copy", ossl_digest_copy, 1);
rb_define_method(cDigest, "reset", ossl_digest_reset, 0);
diff --git a/ext/openssl/ossl_digest.h b/ext/openssl/ossl_digest.h
index 50bf5666a3..99771b8ae1 100644
--- a/ext/openssl/ossl_digest.h
+++ b/ext/openssl/ossl_digest.h
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_DIGEST_H_)
#define _OSSL_DIGEST_H_
diff --git a/ext/openssl/ossl_engine.c b/ext/openssl/ossl_engine.c
index 9e86321d06..294d58adef 100644
--- a/ext/openssl/ossl_engine.c
+++ b/ext/openssl/ossl_engine.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
diff --git a/ext/openssl/ossl_engine.h b/ext/openssl/ossl_engine.h
index cd548beea3..f6f4ff4c1f 100644
--- a/ext/openssl/ossl_engine.h
+++ b/ext/openssl/ossl_engine.h
@@ -6,7 +6,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(OSSL_ENGINE_H)
#define OSSL_ENGINE_H
diff --git a/ext/openssl/ossl_hmac.c b/ext/openssl/ossl_hmac.c
index c485ba7e67..b1163f6127 100644
--- a/ext/openssl/ossl_hmac.c
+++ b/ext/openssl/ossl_hmac.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
diff --git a/ext/openssl/ossl_hmac.h b/ext/openssl/ossl_hmac.h
index 7c51f4722d..17427587b2 100644
--- a/ext/openssl/ossl_hmac.h
+++ b/ext/openssl/ossl_hmac.h
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_HMAC_H_)
#define _OSSL_HMAC_H_
diff --git a/ext/openssl/ossl_kdf.c b/ext/openssl/ossl_kdf.c
index 48b161d4f4..ba197a659e 100644
--- a/ext/openssl/ossl_kdf.c
+++ b/ext/openssl/ossl_kdf.c
@@ -18,7 +18,7 @@ static VALUE mKDF, eKDF;
* of _length_ bytes.
*
* For more information about PBKDF2, see RFC 2898 Section 5.2
- * (https://tools.ietf.org/html/rfc2898#section-5.2).
+ * (https://www.rfc-editor.org/rfc/rfc2898#section-5.2).
*
* === Parameters
* pass :: The password.
@@ -81,10 +81,10 @@ kdf_pbkdf2_hmac(int argc, VALUE *argv, VALUE self)
* bcrypt.
*
* The keyword arguments _N_, _r_ and _p_ can be used to tune scrypt. RFC 7914
- * (published on 2016-08, https://tools.ietf.org/html/rfc7914#section-2) states
+ * (published on 2016-08, https://www.rfc-editor.org/rfc/rfc7914#section-2) states
* that using values r=8 and p=1 appears to yield good results.
*
- * See RFC 7914 (https://tools.ietf.org/html/rfc7914) for more information.
+ * See RFC 7914 (https://www.rfc-editor.org/rfc/rfc7914) for more information.
*
* === Parameters
* pass :: Passphrase.
@@ -147,7 +147,7 @@ kdf_scrypt(int argc, VALUE *argv, VALUE self)
* KDF.hkdf(ikm, salt:, info:, length:, hash:) -> String
*
* HMAC-based Extract-and-Expand Key Derivation Function (HKDF) as specified in
- * {RFC 5869}[https://tools.ietf.org/html/rfc5869].
+ * {RFC 5869}[https://www.rfc-editor.org/rfc/rfc5869].
*
* New in OpenSSL 1.1.0.
*
@@ -165,7 +165,7 @@ kdf_scrypt(int argc, VALUE *argv, VALUE self)
* The hash function.
*
* === Example
- * # The values from https://datatracker.ietf.org/doc/html/rfc5869#appendix-A.1
+ * # The values from https://www.rfc-editor.org/rfc/rfc5869#appendix-A.1
* ikm = ["0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"].pack("H*")
* salt = ["000102030405060708090a0b0c"].pack("H*")
* info = ["f0f1f2f3f4f5f6f7f8f9"].pack("H*")
diff --git a/ext/openssl/ossl_ns_spki.c b/ext/openssl/ossl_ns_spki.c
index 9bed1f330e..e822d5e0a9 100644
--- a/ext/openssl/ossl_ns_spki.c
+++ b/ext/openssl/ossl_ns_spki.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -365,8 +365,8 @@ ossl_spki_verify(VALUE self, VALUE key)
*
* OpenSSL::Netscape is a namespace for SPKI (Simple Public Key
* Infrastructure) which implements Signed Public Key and Challenge.
- * See {RFC 2692}[http://tools.ietf.org/html/rfc2692] and {RFC
- * 2693}[http://tools.ietf.org/html/rfc2692] for details.
+ * See {RFC 2692}[https://www.rfc-editor.org/rfc/rfc2692] and {RFC
+ * 2693}[https://www.rfc-editor.org/rfc/rfc2692] for details.
*/
/* Document-class: OpenSSL::Netscape::SPKIError
diff --git a/ext/openssl/ossl_ns_spki.h b/ext/openssl/ossl_ns_spki.h
index 62ba8cb163..20d6857682 100644
--- a/ext/openssl/ossl_ns_spki.h
+++ b/ext/openssl/ossl_ns_spki.h
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_NS_SPKI_H_)
#define _OSSL_NS_SPKI_H_
diff --git a/ext/openssl/ossl_ocsp.c b/ext/openssl/ossl_ocsp.c
index df986bb3ee..9796d44a26 100644
--- a/ext/openssl/ossl_ocsp.c
+++ b/ext/openssl/ossl_ocsp.c
@@ -6,7 +6,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
diff --git a/ext/openssl/ossl_ocsp.h b/ext/openssl/ossl_ocsp.h
index 6d2aac8657..07da7d1684 100644
--- a/ext/openssl/ossl_ocsp.h
+++ b/ext/openssl/ossl_ocsp.h
@@ -6,7 +6,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_OCSP_H_)
#define _OSSL_OCSP_H_
diff --git a/ext/openssl/ossl_pkcs12.c b/ext/openssl/ossl_pkcs12.c
index 164b2da465..1fcb1a88d3 100644
--- a/ext/openssl/ossl_pkcs12.c
+++ b/ext/openssl/ossl_pkcs12.c
@@ -1,6 +1,6 @@
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -134,6 +134,10 @@ ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self)
if (!NIL_P(keytype))
ktype = NUM2INT(keytype);
+ if (ktype != 0 && ktype != KEY_SIG && ktype != KEY_EX) {
+ ossl_raise(rb_eArgError, "Unknown key usage type %"PRIsVALUE, INT2NUM(ktype));
+ }
+
obj = NewPKCS12(cPKCS12);
x509s = NIL_P(ca) ? NULL : ossl_x509_ary2sk(ca);
p12 = PKCS12_create(passphrase, friendlyname, key, x509, x509s,
@@ -272,4 +276,8 @@ Init_ossl_pkcs12(void)
rb_attr(cPKCS12, rb_intern("ca_certs"), 1, 0, Qfalse);
rb_define_method(cPKCS12, "initialize", ossl_pkcs12_initialize, -1);
rb_define_method(cPKCS12, "to_der", ossl_pkcs12_to_der, 0);
+
+ /* MSIE specific PKCS12 key usage extensions */
+ rb_define_const(cPKCS12, "KEY_EX", INT2NUM(KEY_EX));
+ rb_define_const(cPKCS12, "KEY_SIG", INT2NUM(KEY_SIG));
}
diff --git a/ext/openssl/ossl_pkcs12.h b/ext/openssl/ossl_pkcs12.h
index fe4f15ef60..d4003e81c9 100644
--- a/ext/openssl/ossl_pkcs12.h
+++ b/ext/openssl/ossl_pkcs12.h
@@ -1,6 +1,6 @@
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_PKCS12_H_)
#define _OSSL_PKCS12_H_
diff --git a/ext/openssl/ossl_pkcs7.c b/ext/openssl/ossl_pkcs7.c
index 78dcbd667a..b7e6d330b2 100644
--- a/ext/openssl/ossl_pkcs7.c
+++ b/ext/openssl/ossl_pkcs7.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -165,7 +165,11 @@ ossl_pkcs7_s_read_smime(VALUE klass, VALUE arg)
out = NULL;
pkcs7 = SMIME_read_PKCS7(in, &out);
BIO_free(in);
- if(!pkcs7) ossl_raise(ePKCS7Error, NULL);
+ if (!pkcs7)
+ ossl_raise(ePKCS7Error, "Could not parse the PKCS7");
+ if (!pkcs7->d.ptr)
+ ossl_raise(ePKCS7Error, "No content in PKCS7");
+
data = out ? ossl_membio2str(out) : Qnil;
SetPKCS7(ret, pkcs7);
ossl_pkcs7_set_data(ret, data);
@@ -346,6 +350,8 @@ ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self)
BIO_free(in);
if (!p7)
ossl_raise(rb_eArgError, "Could not parse the PKCS7");
+ if (!p7->d.ptr)
+ ossl_raise(rb_eArgError, "No content in PKCS7");
RTYPEDDATA_DATA(self) = p7;
PKCS7_free(p7_orig);
@@ -842,6 +848,25 @@ ossl_pkcs7_to_der(VALUE self)
}
static VALUE
+ossl_pkcs7_to_text(VALUE self)
+{
+ PKCS7 *pkcs7;
+ BIO *out;
+ VALUE str;
+
+ GetPKCS7(self, pkcs7);
+ if(!(out = BIO_new(BIO_s_mem())))
+ ossl_raise(ePKCS7Error, NULL);
+ if(!PKCS7_print_ctx(out, pkcs7, 0, NULL)) {
+ BIO_free(out);
+ ossl_raise(ePKCS7Error, NULL);
+ }
+ str = ossl_membio2str(out);
+
+ return str;
+}
+
+static VALUE
ossl_pkcs7_to_pem(VALUE self)
{
PKCS7 *pkcs7;
@@ -1050,6 +1075,7 @@ Init_ossl_pkcs7(void)
rb_define_method(cPKCS7, "to_pem", ossl_pkcs7_to_pem, 0);
rb_define_alias(cPKCS7, "to_s", "to_pem");
rb_define_method(cPKCS7, "to_der", ossl_pkcs7_to_der, 0);
+ rb_define_method(cPKCS7, "to_text", ossl_pkcs7_to_text, 0);
cPKCS7Signer = rb_define_class_under(cPKCS7, "SignerInfo", rb_cObject);
rb_define_const(cPKCS7, "Signer", cPKCS7Signer);
diff --git a/ext/openssl/ossl_pkcs7.h b/ext/openssl/ossl_pkcs7.h
index 3e1b094670..4cbbc6a1ae 100644
--- a/ext/openssl/ossl_pkcs7.h
+++ b/ext/openssl/ossl_pkcs7.h
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_PKCS7_H_)
#define _OSSL_PKCS7_H_
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
index 013412c27f..6af2245f39 100644
--- a/ext/openssl/ossl_pkey.c
+++ b/ext/openssl/ossl_pkey.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h
index 10669b824c..37d828e048 100644
--- a/ext/openssl/ossl_pkey.h
+++ b/ext/openssl/ossl_pkey.h
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(OSSL_PKEY_H)
#define OSSL_PKEY_H
diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c
index a231814a99..00699b9b07 100644
--- a/ext/openssl/ossl_pkey_dh.c
+++ b/ext/openssl/ossl_pkey_dh.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c
index 058ce73888..a7598d1e80 100644
--- a/ext/openssl/ossl_pkey_dsa.c
+++ b/ext/openssl/ossl_pkey_dsa.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c
index 389f76f309..7d986989e5 100644
--- a/ext/openssl/ossl_pkey_rsa.c
+++ b/ext/openssl/ossl_pkey_rsa.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
diff --git a/ext/openssl/ossl_provider.c b/ext/openssl/ossl_provider.c
index 981c6ccdc7..d1f6c5d427 100644
--- a/ext/openssl/ossl_provider.c
+++ b/ext/openssl/ossl_provider.c
@@ -1,6 +1,6 @@
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
diff --git a/ext/openssl/ossl_rand.c b/ext/openssl/ossl_rand.c
index 659dc818b6..774e7836dc 100644
--- a/ext/openssl/ossl_rand.c
+++ b/ext/openssl/ossl_rand.c
@@ -5,7 +5,7 @@
* All rights reserved.
*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
diff --git a/ext/openssl/ossl_rand.h b/ext/openssl/ossl_rand.h
index 8f77a3b239..874ab539b8 100644
--- a/ext/openssl/ossl_rand.h
+++ b/ext/openssl/ossl_rand.h
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_RAND_H_)
#define _OSSL_RAND_H_
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index 236d455ff2..457630ddc8 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -7,7 +7,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -1725,11 +1725,20 @@ no_exception_p(VALUE opts)
#define RUBY_IO_TIMEOUT_DEFAULT Qnil
#endif
+#ifdef HAVE_RB_IO_TIMEOUT
+#define IO_TIMEOUT_ERROR rb_eIOTimeoutError
+#else
+#define IO_TIMEOUT_ERROR rb_eIOError
+#endif
+
+
static void
io_wait_writable(VALUE io)
{
#ifdef HAVE_RB_IO_MAYBE_WAIT
- rb_io_maybe_wait_writable(errno, io, RUBY_IO_TIMEOUT_DEFAULT);
+ if (!rb_io_maybe_wait_writable(errno, io, RUBY_IO_TIMEOUT_DEFAULT)) {
+ rb_raise(IO_TIMEOUT_ERROR, "Timed out while waiting to become writable!");
+ }
#else
rb_io_t *fptr;
GetOpenFile(io, fptr);
@@ -1741,7 +1750,9 @@ static void
io_wait_readable(VALUE io)
{
#ifdef HAVE_RB_IO_MAYBE_WAIT
- rb_io_maybe_wait_readable(errno, io, RUBY_IO_TIMEOUT_DEFAULT);
+ if (!rb_io_maybe_wait_readable(errno, io, RUBY_IO_TIMEOUT_DEFAULT)) {
+ rb_raise(IO_TIMEOUT_ERROR, "Timed out while waiting to become readable!");
+ }
#else
rb_io_t *fptr;
GetOpenFile(io, fptr);
@@ -1947,9 +1958,11 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
else
rb_str_modify_expand(str, ilen - RSTRING_LEN(str));
}
- rb_str_set_len(str, 0);
- if (ilen == 0)
- return str;
+
+ if (ilen == 0) {
+ rb_str_set_len(str, 0);
+ return str;
+ }
VALUE io = rb_attr_get(self, id_i_io);
diff --git a/ext/openssl/ossl_ssl.h b/ext/openssl/ossl_ssl.h
index 535c56097c..a92985c601 100644
--- a/ext/openssl/ossl_ssl.h
+++ b/ext/openssl/ossl_ssl.h
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_SSL_H_)
#define _OSSL_SSL_H_
diff --git a/ext/openssl/ossl_ts.c b/ext/openssl/ossl_ts.c
index f698bdc7ff..d6a5fc9892 100644
--- a/ext/openssl/ossl_ts.c
+++ b/ext/openssl/ossl_ts.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -504,6 +504,25 @@ ossl_ts_req_to_der(VALUE self)
}
static VALUE
+ossl_ts_req_to_text(VALUE self)
+{
+ TS_REQ *req;
+ BIO *out;
+
+ GetTSRequest(self, req);
+
+ out = BIO_new(BIO_s_mem());
+ if (!out) ossl_raise(eTimestampError, NULL);
+
+ if (!TS_REQ_print_bio(out, req)) {
+ BIO_free(out);
+ ossl_raise(eTimestampError, NULL);
+ }
+
+ return ossl_membio2str(out);
+}
+
+static VALUE
ossl_ts_resp_alloc(VALUE klass)
{
TS_RESP *resp;
@@ -757,6 +776,25 @@ ossl_ts_resp_to_der(VALUE self)
return asn1_to_der((void *)resp, (int (*)(void *, unsigned char **))i2d_TS_RESP);
}
+static VALUE
+ossl_ts_resp_to_text(VALUE self)
+{
+ TS_RESP *resp;
+ BIO *out;
+
+ GetTSResponse(self, resp);
+
+ out = BIO_new(BIO_s_mem());
+ if (!out) ossl_raise(eTimestampError, NULL);
+
+ if (!TS_RESP_print_bio(out, resp)) {
+ BIO_free(out);
+ ossl_raise(eTimestampError, NULL);
+ }
+
+ return ossl_membio2str(out);
+}
+
/*
* Verifies a timestamp token by checking the signature, validating the
* certificate chain implied by tsa_certificate and by checking conformance to
@@ -1073,6 +1111,25 @@ ossl_ts_token_info_to_der(VALUE self)
return asn1_to_der((void *)info, (int (*)(void *, unsigned char **))i2d_TS_TST_INFO);
}
+static VALUE
+ossl_ts_token_info_to_text(VALUE self)
+{
+ TS_TST_INFO *info;
+ BIO *out;
+
+ GetTSTokenInfo(self, info);
+
+ out = BIO_new(BIO_s_mem());
+ if (!out) ossl_raise(eTimestampError, NULL);
+
+ if (!TS_TST_INFO_print_bio(out, info)) {
+ BIO_free(out);
+ ossl_raise(eTimestampError, NULL);
+ }
+
+ return ossl_membio2str(out);
+}
+
static ASN1_INTEGER *
ossl_tsfac_serial_cb(struct TS_resp_ctx *ctx, void *data)
{
@@ -1356,6 +1413,7 @@ Init_ossl_ts(void)
rb_define_method(cTimestampResponse, "token_info", ossl_ts_resp_get_token_info, 0);
rb_define_method(cTimestampResponse, "tsa_certificate", ossl_ts_resp_get_tsa_certificate, 0);
rb_define_method(cTimestampResponse, "to_der", ossl_ts_resp_to_der, 0);
+ rb_define_method(cTimestampResponse, "to_text", ossl_ts_resp_to_text, 0);
rb_define_method(cTimestampResponse, "verify", ossl_ts_resp_verify, -1);
/* Document-class: OpenSSL::Timestamp::TokenInfo
@@ -1374,6 +1432,7 @@ Init_ossl_ts(void)
rb_define_method(cTimestampTokenInfo, "ordering", ossl_ts_token_info_get_ordering, 0);
rb_define_method(cTimestampTokenInfo, "nonce", ossl_ts_token_info_get_nonce, 0);
rb_define_method(cTimestampTokenInfo, "to_der", ossl_ts_token_info_to_der, 0);
+ rb_define_method(cTimestampTokenInfo, "to_text", ossl_ts_token_info_to_text, 0);
/* Document-class: OpenSSL::Timestamp::Request
* Allows to create timestamp requests or parse existing ones. A Request is
@@ -1399,6 +1458,7 @@ Init_ossl_ts(void)
rb_define_method(cTimestampRequest, "cert_requested=", ossl_ts_req_set_cert_requested, 1);
rb_define_method(cTimestampRequest, "cert_requested?", ossl_ts_req_get_cert_requested, 0);
rb_define_method(cTimestampRequest, "to_der", ossl_ts_req_to_der, 0);
+ rb_define_method(cTimestampRequest, "to_text", ossl_ts_req_to_text, 0);
/*
* Indicates a successful response. Equal to +0+.
diff --git a/ext/openssl/ossl_ts.h b/ext/openssl/ossl_ts.h
index 25fb0e1d64..eeca3046eb 100644
--- a/ext/openssl/ossl_ts.h
+++ b/ext/openssl/ossl_ts.h
@@ -5,7 +5,7 @@
*/
/*
* This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_TS_H_)
diff --git a/ext/openssl/ossl_x509.c b/ext/openssl/ossl_x509.c
index f8470703fc..9686fc1a9c 100644
--- a/ext/openssl/ossl_x509.c
+++ b/ext/openssl/ossl_x509.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
diff --git a/ext/openssl/ossl_x509.h b/ext/openssl/ossl_x509.h
index 4fadfa6b82..88e3f16a1a 100644
--- a/ext/openssl/ossl_x509.h
+++ b/ext/openssl/ossl_x509.h
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_X509_H_)
#define _OSSL_X509_H_
diff --git a/ext/openssl/ossl_x509attr.c b/ext/openssl/ossl_x509attr.c
index d1d8bb5e95..be525c9e7c 100644
--- a/ext/openssl/ossl_x509attr.c
+++ b/ext/openssl/ossl_x509attr.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
diff --git a/ext/openssl/ossl_x509cert.c b/ext/openssl/ossl_x509cert.c
index aa6b9bb7ce..dbf83ff525 100644
--- a/ext/openssl/ossl_x509cert.c
+++ b/ext/openssl/ossl_x509cert.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -707,6 +707,38 @@ ossl_x509_eq(VALUE self, VALUE other)
return !X509_cmp(a, b) ? Qtrue : Qfalse;
}
+#ifdef HAVE_I2D_RE_X509_TBS
+/*
+ * call-seq:
+ * cert.tbs_bytes => string
+ *
+ * Returns the DER-encoded bytes of the certificate's to be signed certificate.
+ * This is mainly useful for validating embedded certificate transparency signatures.
+ */
+static VALUE
+ossl_x509_tbs_bytes(VALUE self)
+{
+ X509 *x509;
+ int len;
+ unsigned char *p0;
+ VALUE str;
+
+ GetX509(self, x509);
+ len = i2d_re_X509_tbs(x509, NULL);
+ if (len <= 0) {
+ ossl_raise(eX509CertError, "i2d_re_X509_tbs");
+ }
+ str = rb_str_new(NULL, len);
+ p0 = (unsigned char *)RSTRING_PTR(str);
+ if (i2d_re_X509_tbs(x509, &p0) <= 0) {
+ ossl_raise(eX509CertError, "i2d_re_X509_tbs");
+ }
+ ossl_str_adjust(str, p0);
+
+ return str;
+}
+#endif
+
struct load_chained_certificates_arguments {
VALUE certificates;
X509 *certificate;
@@ -999,4 +1031,7 @@ Init_ossl_x509cert(void)
rb_define_method(cX509Cert, "add_extension", ossl_x509_add_extension, 1);
rb_define_method(cX509Cert, "inspect", ossl_x509_inspect, 0);
rb_define_method(cX509Cert, "==", ossl_x509_eq, 1);
+#ifdef HAVE_I2D_RE_X509_TBS
+ rb_define_method(cX509Cert, "tbs_bytes", ossl_x509_tbs_bytes, 0);
+#endif
}
diff --git a/ext/openssl/ossl_x509crl.c b/ext/openssl/ossl_x509crl.c
index 80e29f9df2..368270ce11 100644
--- a/ext/openssl/ossl_x509crl.c
+++ b/ext/openssl/ossl_x509crl.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
diff --git a/ext/openssl/ossl_x509ext.c b/ext/openssl/ossl_x509ext.c
index 192d09bd3f..7f47cd7cce 100644
--- a/ext/openssl/ossl_x509ext.c
+++ b/ext/openssl/ossl_x509ext.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
diff --git a/ext/openssl/ossl_x509name.c b/ext/openssl/ossl_x509name.c
index 9591912f70..5060be92cc 100644
--- a/ext/openssl/ossl_x509name.c
+++ b/ext/openssl/ossl_x509name.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
diff --git a/ext/openssl/ossl_x509req.c b/ext/openssl/ossl_x509req.c
index f058185151..37ba03728f 100644
--- a/ext/openssl/ossl_x509req.c
+++ b/ext/openssl/ossl_x509req.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
diff --git a/ext/openssl/ossl_x509revoked.c b/ext/openssl/ossl_x509revoked.c
index 108447c868..5b82470c83 100644
--- a/ext/openssl/ossl_x509revoked.c
+++ b/ext/openssl/ossl_x509revoked.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
diff --git a/ext/openssl/ossl_x509store.c b/ext/openssl/ossl_x509store.c
index f27381ca90..31328ec47f 100644
--- a/ext/openssl/ossl_x509store.c
+++ b/ext/openssl/ossl_x509store.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
diff --git a/ext/pathname/depend b/ext/pathname/depend
index 5dd8b042de..cca7877dad 100644
--- a/ext/pathname/depend
+++ b/ext/pathname/depend
@@ -157,6 +157,7 @@ pathname.o: $(hdrdir)/ruby/internal/special_consts.h
pathname.o: $(hdrdir)/ruby/internal/static_assert.h
pathname.o: $(hdrdir)/ruby/internal/stdalign.h
pathname.o: $(hdrdir)/ruby/internal/stdbool.h
+pathname.o: $(hdrdir)/ruby/internal/stdckdint.h
pathname.o: $(hdrdir)/ruby/internal/symbol.h
pathname.o: $(hdrdir)/ruby/internal/value.h
pathname.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/pathname/extconf.rb b/ext/pathname/extconf.rb
index 84e68277aa..b4e1617b9e 100644
--- a/ext/pathname/extconf.rb
+++ b/ext/pathname/extconf.rb
@@ -1,4 +1,3 @@
# frozen_string_literal: false
require 'mkmf'
-have_func("rb_file_s_birthtime")
create_makefile('pathname')
diff --git a/ext/pathname/lib/pathname.rb b/ext/pathname/lib/pathname.rb
index 8eeba6aad2..dc639174d5 100644
--- a/ext/pathname/lib/pathname.rb
+++ b/ext/pathname/lib/pathname.rb
@@ -580,14 +580,13 @@ class Pathname # * Find *
end
-autoload(:FileUtils, 'fileutils')
-
class Pathname # * FileUtils *
# Creates a full path, including any intermediate directories that don't yet
# exist.
#
# See FileUtils.mkpath and FileUtils.mkdir_p
def mkpath(mode: nil)
+ require 'fileutils'
FileUtils.mkpath(@path, mode: mode)
nil
end
diff --git a/ext/pathname/pathname.c b/ext/pathname/pathname.c
index 878f216fb5..cdecb3f897 100644
--- a/ext/pathname/pathname.c
+++ b/ext/pathname/pathname.c
@@ -479,7 +479,6 @@ path_atime(VALUE self)
return rb_funcall(rb_cFile, id_atime, 1, get_strpath(self));
}
-#if defined(HAVE_RB_FILE_S_BIRTHTIME)
/*
* call-seq:
* pathname.birthtime -> time
@@ -494,10 +493,6 @@ path_birthtime(VALUE self)
{
return rb_funcall(rb_cFile, id_birthtime, 1, get_strpath(self));
}
-#else
-/* check at compilation time for `respond_to?` */
-# define path_birthtime rb_f_notimplement
-#endif
/*
* call-seq:
diff --git a/ext/psych/depend b/ext/psych/depend
index 13fbe3fb19..a4d9ca9a6a 100644
--- a/ext/psych/depend
+++ b/ext/psych/depend
@@ -171,6 +171,7 @@ psych.o: $(hdrdir)/ruby/internal/special_consts.h
psych.o: $(hdrdir)/ruby/internal/static_assert.h
psych.o: $(hdrdir)/ruby/internal/stdalign.h
psych.o: $(hdrdir)/ruby/internal/stdbool.h
+psych.o: $(hdrdir)/ruby/internal/stdckdint.h
psych.o: $(hdrdir)/ruby/internal/symbol.h
psych.o: $(hdrdir)/ruby/internal/value.h
psych.o: $(hdrdir)/ruby/internal/value_type.h
@@ -347,6 +348,7 @@ psych_emitter.o: $(hdrdir)/ruby/internal/special_consts.h
psych_emitter.o: $(hdrdir)/ruby/internal/static_assert.h
psych_emitter.o: $(hdrdir)/ruby/internal/stdalign.h
psych_emitter.o: $(hdrdir)/ruby/internal/stdbool.h
+psych_emitter.o: $(hdrdir)/ruby/internal/stdckdint.h
psych_emitter.o: $(hdrdir)/ruby/internal/symbol.h
psych_emitter.o: $(hdrdir)/ruby/internal/value.h
psych_emitter.o: $(hdrdir)/ruby/internal/value_type.h
@@ -523,6 +525,7 @@ psych_parser.o: $(hdrdir)/ruby/internal/special_consts.h
psych_parser.o: $(hdrdir)/ruby/internal/static_assert.h
psych_parser.o: $(hdrdir)/ruby/internal/stdalign.h
psych_parser.o: $(hdrdir)/ruby/internal/stdbool.h
+psych_parser.o: $(hdrdir)/ruby/internal/stdckdint.h
psych_parser.o: $(hdrdir)/ruby/internal/symbol.h
psych_parser.o: $(hdrdir)/ruby/internal/value.h
psych_parser.o: $(hdrdir)/ruby/internal/value_type.h
@@ -699,6 +702,7 @@ psych_to_ruby.o: $(hdrdir)/ruby/internal/special_consts.h
psych_to_ruby.o: $(hdrdir)/ruby/internal/static_assert.h
psych_to_ruby.o: $(hdrdir)/ruby/internal/stdalign.h
psych_to_ruby.o: $(hdrdir)/ruby/internal/stdbool.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/stdckdint.h
psych_to_ruby.o: $(hdrdir)/ruby/internal/symbol.h
psych_to_ruby.o: $(hdrdir)/ruby/internal/value.h
psych_to_ruby.o: $(hdrdir)/ruby/internal/value_type.h
@@ -875,6 +879,7 @@ psych_yaml_tree.o: $(hdrdir)/ruby/internal/special_consts.h
psych_yaml_tree.o: $(hdrdir)/ruby/internal/static_assert.h
psych_yaml_tree.o: $(hdrdir)/ruby/internal/stdalign.h
psych_yaml_tree.o: $(hdrdir)/ruby/internal/stdbool.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/stdckdint.h
psych_yaml_tree.o: $(hdrdir)/ruby/internal/symbol.h
psych_yaml_tree.o: $(hdrdir)/ruby/internal/value.h
psych_yaml_tree.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/psych/lib/psych.rb b/ext/psych/lib/psych.rb
index ae167472f2..d87bd9040a 100644
--- a/ext/psych/lib/psych.rb
+++ b/ext/psych/lib/psych.rb
@@ -489,6 +489,10 @@ module Psych
#
# Default: <tt>false</tt>.
#
+ # [<tt>:stringify_names</tt>] Dump symbol keys in Hash objects as string.
+ #
+ # Default: <tt>false</tt>.
+ #
# Example:
#
# # Dump an array, get back a YAML string
@@ -502,6 +506,9 @@ module Psych
#
# # Dump an array to an IO with indentation set
# Psych.dump(['a', ['b']], StringIO.new, indentation: 3)
+ #
+ # # Dump hash with symbol keys as string
+ # Psych.dump({a: "b"}, stringify_names: true) # => "---\na: b\n"
def self.dump o, io = nil, options = {}
if Hash === io
options = io
@@ -562,6 +569,10 @@ module Psych
#
# Default: <tt>false</tt>.
#
+ # [<tt>:stringify_names</tt>] Dump symbol keys in Hash objects as string.
+ #
+ # Default: <tt>false</tt>.
+ #
# Example:
#
# # Dump an array, get back a YAML string
@@ -575,6 +586,9 @@ module Psych
#
# # Dump an array to an IO with indentation set
# Psych.safe_dump(['a', ['b']], StringIO.new, indentation: 3)
+ #
+ # # Dump hash with symbol keys as string
+ # Psych.dump({a: "b"}, stringify_names: true) # => "---\na: b\n"
def self.safe_dump o, io = nil, options = {}
if Hash === io
options = io
diff --git a/ext/psych/lib/psych/versions.rb b/ext/psych/lib/psych/versions.rb
index ce9cdf448c..b9e8d9ef11 100644
--- a/ext/psych/lib/psych/versions.rb
+++ b/ext/psych/lib/psych/versions.rb
@@ -2,7 +2,7 @@
module Psych
# The version of Psych you are using
- VERSION = '5.1.1.1'
+ VERSION = '5.1.2'
if RUBY_ENGINE == 'jruby'
DEFAULT_SNAKEYAML_VERSION = '2.7'.freeze
diff --git a/ext/psych/lib/psych/visitors/to_ruby.rb b/ext/psych/lib/psych/visitors/to_ruby.rb
index 8614251ca9..f0fda9bdbc 100644
--- a/ext/psych/lib/psych/visitors/to_ruby.rb
+++ b/ext/psych/lib/psych/visitors/to_ruby.rb
@@ -101,7 +101,7 @@ module Psych
source = $1
options = 0
lang = nil
- ($2 || '').split('').each do |option|
+ $2&.each_char do |option|
case option
when 'x' then options |= Regexp::EXTENDED
when 'i' then options |= Regexp::IGNORECASE
diff --git a/ext/psych/lib/psych/visitors/yaml_tree.rb b/ext/psych/lib/psych/visitors/yaml_tree.rb
index 51491783c3..a2ebc4d781 100644
--- a/ext/psych/lib/psych/visitors/yaml_tree.rb
+++ b/ext/psych/lib/psych/visitors/yaml_tree.rb
@@ -15,30 +15,25 @@ module Psych
class YAMLTree < Psych::Visitors::Visitor
class Registrar # :nodoc:
def initialize
- @obj_to_id = {}
- @obj_to_node = {}
- @targets = []
+ @obj_to_id = {}.compare_by_identity
+ @obj_to_node = {}.compare_by_identity
@counter = 0
end
def register target, node
- return unless target.respond_to? :object_id
- @targets << target
- @obj_to_node[target.object_id] = node
+ @obj_to_node[target] = node
end
def key? target
- @obj_to_node.key? target.object_id
- rescue NoMethodError
- false
+ @obj_to_node.key? target
end
def id_for target
- @obj_to_id[target.object_id] ||= (@counter += 1)
+ @obj_to_id[target] ||= (@counter += 1)
end
def node_for target
- @obj_to_node[target.object_id]
+ @obj_to_node[target]
end
end
@@ -70,6 +65,7 @@ module Psych
fail(ArgumentError, "Invalid line_width #{@line_width}, must be non-negative or -1 for unlimited.")
end
end
+ @stringify_names = options[:stringify_names]
@coders = []
@dispatch_cache = Hash.new do |h,klass|
@@ -272,7 +268,7 @@ module Psych
tag = 'tag:yaml.org,2002:str'
plain = false
quote = false
- elsif o == 'y' || o == 'n'
+ elsif o == 'y' || o == 'Y' || o == 'n' || o == 'N'
style = Nodes::Scalar::DOUBLE_QUOTED
elsif @line_width && o.length > @line_width
style = Nodes::Scalar::FOLDED
@@ -328,7 +324,7 @@ module Psych
if o.class == ::Hash
register(o, @emitter.start_mapping(nil, nil, true, Psych::Nodes::Mapping::BLOCK))
o.each do |k,v|
- accept k
+ accept(@stringify_names && Symbol === k ? k.to_s : k)
accept v
end
@emitter.end_mapping
@@ -341,7 +337,7 @@ module Psych
register(o, @emitter.start_mapping(nil, '!set', false, Psych::Nodes::Mapping::BLOCK))
o.each do |k,v|
- accept k
+ accept(@stringify_names && Symbol === k ? k.to_s : k)
accept v
end
diff --git a/ext/psych/psych.gemspec b/ext/psych/psych.gemspec
index 34f70095d3..a3fc53a8b9 100644
--- a/ext/psych/psych.gemspec
+++ b/ext/psych/psych.gemspec
@@ -76,5 +76,5 @@ DESCRIPTION
end
s.metadata['msys2_mingw_dependencies'] = 'libyaml'
-
+ s.metadata['changelog_uri'] = s.homepage + '/releases'
end
diff --git a/ext/pty/depend b/ext/pty/depend
index d4d0d558ef..adecfff862 100644
--- a/ext/pty/depend
+++ b/ext/pty/depend
@@ -157,6 +157,7 @@ pty.o: $(hdrdir)/ruby/internal/special_consts.h
pty.o: $(hdrdir)/ruby/internal/static_assert.h
pty.o: $(hdrdir)/ruby/internal/stdalign.h
pty.o: $(hdrdir)/ruby/internal/stdbool.h
+pty.o: $(hdrdir)/ruby/internal/stdckdint.h
pty.o: $(hdrdir)/ruby/internal/symbol.h
pty.o: $(hdrdir)/ruby/internal/value.h
pty.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/pty/extconf.rb b/ext/pty/extconf.rb
index ba0c4286fd..da3655cf4d 100644
--- a/ext/pty/extconf.rb
+++ b/ext/pty/extconf.rb
@@ -13,10 +13,13 @@ if /mswin|mingw|bccwin/ !~ RUBY_PLATFORM
have_header("util.h") # OpenBSD openpty
util = have_library("util", "openpty")
end
- if have_func("posix_openpt") or
+ openpt = have_func("posix_openpt")
+ if openpt
+ have_func("ptsname_r") or have_func("ptsname")
+ end
+ if openpt or
(util or have_func("openpty")) or
have_func("_getpty") or
- have_func("ptsname") or
have_func("ioctl")
create_makefile('pty')
end
diff --git a/ext/pty/pty.c b/ext/pty/pty.c
index 0aca10bfa0..5ca55e41d6 100644
--- a/ext/pty/pty.c
+++ b/ext/pty/pty.c
@@ -92,9 +92,13 @@ struct pty_info {
static void getDevice(int*, int*, char [DEVICELEN], int);
+static int start_new_session(char *errbuf, size_t errbuf_len);
+static int obtain_ctty(int master, int slave, const char *slavename, char *errbuf, size_t errbuf_len);
+static int drop_privilige(char *errbuf, size_t errbuf_len);
+
struct child_info {
int master, slave;
- char *slavename;
+ const char *slavename;
VALUE execarg_obj;
struct rb_execarg *eargp;
};
@@ -102,26 +106,42 @@ struct child_info {
static int
chfunc(void *data, char *errbuf, size_t errbuf_len)
{
- struct child_info *carg = data;
+ const struct child_info *carg = data;
int master = carg->master;
int slave = carg->slave;
+ const char *slavename = carg->slavename;
+
+ if (start_new_session(errbuf, errbuf_len))
+ return -1;
+
+ if (obtain_ctty(master, slave, slavename, errbuf, errbuf_len))
+ return -1;
+
+ if (drop_privilige(errbuf, errbuf_len))
+ return -1;
+
+ return rb_exec_async_signal_safe(carg->eargp, errbuf, errbuf_len);
+}
#define ERROR_EXIT(str) do { \
strlcpy(errbuf, (str), errbuf_len); \
return -1; \
} while (0)
- /*
- * Set free from process group and controlling terminal
- */
+/*
+ * Set free from process group and controlling terminal
+ */
+static int
+start_new_session(char *errbuf, size_t errbuf_len)
+{
#ifdef HAVE_SETSID
(void) setsid();
#else /* HAS_SETSID */
# ifdef HAVE_SETPGRP
-# ifdef SETGRP_VOID
+# ifdef SETPGRP_VOID
if (setpgrp() == -1)
ERROR_EXIT("setpgrp()");
-# else /* SETGRP_VOID */
+# else /* SETPGRP_VOID */
if (setpgrp(0, getpid()) == -1)
ERROR_EXIT("setpgrp()");
{
@@ -132,20 +152,25 @@ chfunc(void *data, char *errbuf, size_t errbuf_len)
ERROR_EXIT("ioctl(TIOCNOTTY)");
close(i);
}
-# endif /* SETGRP_VOID */
+# endif /* SETPGRP_VOID */
# endif /* HAVE_SETPGRP */
#endif /* HAS_SETSID */
+ return 0;
+}
- /*
- * obtain new controlling terminal
- */
+/*
+ * obtain new controlling terminal
+ */
+static int
+obtain_ctty(int master, int slave, const char *slavename, char *errbuf, size_t errbuf_len)
+{
#if defined(TIOCSCTTY)
close(master);
(void) ioctl(slave, TIOCSCTTY, (char *)0);
/* errors ignored for sun */
#else
close(slave);
- slave = rb_cloexec_open(carg->slavename, O_RDWR, 0);
+ slave = rb_cloexec_open(slavename, O_RDWR, 0);
if (slave < 0) {
ERROR_EXIT("open: pty slave");
}
@@ -156,13 +181,19 @@ chfunc(void *data, char *errbuf, size_t errbuf_len)
dup2(slave,1);
dup2(slave,2);
if (slave < 0 || slave > 2) (void)!close(slave);
+ return 0;
+}
+
+static int
+drop_privilige(char *errbuf, size_t errbuf_len)
+{
#if defined(HAVE_SETEUID) || defined(HAVE_SETREUID) || defined(HAVE_SETRESUID)
if (seteuid(getuid())) ERROR_EXIT("seteuid()");
#endif
+ return 0;
+}
- return rb_exec_async_signal_safe(carg->eargp, errbuf, sizeof(errbuf_len));
#undef ERROR_EXIT
-}
static void
establishShell(int argc, VALUE *argv, struct pty_info *info,
@@ -225,7 +256,21 @@ establishShell(int argc, VALUE *argv, struct pty_info *info,
RB_GC_GUARD(carg.execarg_obj);
}
-#if defined(HAVE_POSIX_OPENPT) || defined(HAVE_OPENPTY) || defined(HAVE_PTSNAME)
+#if (defined(HAVE_POSIX_OPENPT) || defined(HAVE_PTSNAME)) && !defined(HAVE_PTSNAME_R)
+/* glibc only, not obsolete interface on Tru64 or HP-UX */
+static int
+ptsname_r(int fd, char *buf, size_t buflen)
+{
+ extern char *ptsname(int);
+ char *name = ptsname(fd);
+ if (!name) return -1;
+ strlcpy(buf, name, buflen);
+ return 0;
+}
+# define HAVE_PTSNAME_R 1
+#endif
+
+#if defined(HAVE_POSIX_OPENPT) || defined(HAVE_OPENPTY) || defined(HAVE_PTSNAME_R)
static int
no_mesg(char *slavedevice, int nomesg)
{
@@ -258,13 +303,19 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg,
/* Unix98 PTY */
int masterfd = -1, slavefd = -1;
char *slavedevice;
+ struct sigaction dfl, old;
+
+ dfl.sa_handler = SIG_DFL;
+ dfl.sa_flags = 0;
+ sigemptyset(&dfl.sa_mask);
#if defined(__sun) || defined(__OpenBSD__) || (defined(__FreeBSD__) && __FreeBSD_version < 902000)
/* workaround for Solaris 10: grantpt() doesn't work if FD_CLOEXEC is set. [ruby-dev:44688] */
/* FreeBSD 9.2 or later supports O_CLOEXEC
* http://www.freebsd.org/cgi/query-pr.cgi?pr=162374 */
if ((masterfd = posix_openpt(O_RDWR|O_NOCTTY)) == -1) goto error;
- if (rb_grantpt(masterfd) == -1) goto error;
+ if (sigaction(SIGCHLD, &dfl, &old) == -1) goto error;
+ if (grantpt(masterfd) == -1) goto grantpt_error;
rb_fd_fix_cloexec(masterfd);
#else
{
@@ -278,10 +329,13 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg,
if ((masterfd = posix_openpt(flags)) == -1) goto error;
}
rb_fd_fix_cloexec(masterfd);
- if (rb_grantpt(masterfd) == -1) goto error;
+ if (sigaction(SIGCHLD, &dfl, &old) == -1) goto error;
+ if (grantpt(masterfd) == -1) goto grantpt_error;
#endif
+ if (sigaction(SIGCHLD, &old, NULL) == -1) goto error;
if (unlockpt(masterfd) == -1) goto error;
- if ((slavedevice = ptsname(masterfd)) == NULL) goto error;
+ if (ptsname_r(masterfd, SlaveName, DEVICELEN) != 0) goto error;
+ slavedevice = SlaveName;
if (no_mesg(slavedevice, nomesg) == -1) goto error;
if ((slavefd = rb_cloexec_open(slavedevice, O_RDWR|O_NOCTTY, 0)) == -1) goto error;
rb_update_max_fd(slavefd);
@@ -294,9 +348,10 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg,
*master = masterfd;
*slave = slavefd;
- strlcpy(SlaveName, slavedevice, DEVICELEN);
return 0;
+ grantpt_error:
+ sigaction(SIGCHLD, &old, NULL);
error:
if (slavefd != -1) close(slavefd);
if (masterfd != -1) close(masterfd);
@@ -346,21 +401,25 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg,
char *slavedevice;
void (*s)();
- extern char *ptsname(int);
extern int unlockpt(int);
+ extern int grantpt(int);
#if defined(__sun)
/* workaround for Solaris 10: grantpt() doesn't work if FD_CLOEXEC is set. [ruby-dev:44688] */
if((masterfd = open("/dev/ptmx", O_RDWR, 0)) == -1) goto error;
- if(rb_grantpt(masterfd) == -1) goto error;
+ s = signal(SIGCHLD, SIG_DFL);
+ if(grantpt(masterfd) == -1) goto error;
rb_fd_fix_cloexec(masterfd);
#else
if((masterfd = rb_cloexec_open("/dev/ptmx", O_RDWR, 0)) == -1) goto error;
rb_update_max_fd(masterfd);
- if(rb_grantpt(masterfd) == -1) goto error;
+ s = signal(SIGCHLD, SIG_DFL);
+ if(grantpt(masterfd) == -1) goto error;
#endif
+ signal(SIGCHLD, s);
if(unlockpt(masterfd) == -1) goto error;
- if((slavedevice = ptsname(masterfd)) == NULL) goto error;
+ if (ptsname_r(masterfd, SlaveName, DEVICELEN) != 0) goto error;
+ slavedevice = SlaveName;
if (no_mesg(slavedevice, nomesg) == -1) goto error;
if((slavefd = rb_cloexec_open(slavedevice, O_RDWR, 0)) == -1) goto error;
rb_update_max_fd(slavefd);
@@ -371,7 +430,6 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg,
#endif
*master = masterfd;
*slave = slavefd;
- strlcpy(SlaveName, slavedevice, DEVICELEN);
return 0;
error:
@@ -745,8 +803,13 @@ void
Init_pty(void)
{
cPTY = rb_define_module("PTY");
- /* :nodoc: */
- rb_define_module_function(cPTY,"getpty",pty_getpty,-1);
+#if 1
+ rb_define_module_function(cPTY,"get""pty",pty_getpty,-1);
+#else /* for RDoc */
+ /* show getpty as an alias of spawn */
+ VALUE sPTY = rb_singleton_class(cPTY);
+ rb_define_alias(sPTY, "getpty", "spawn");
+#endif
rb_define_module_function(cPTY,"spawn",pty_getpty,-1);
rb_define_singleton_method(cPTY,"check",pty_check,-1);
rb_define_singleton_method(cPTY,"open",pty_open,0);
diff --git a/ext/rbconfig/sizeof/depend b/ext/rbconfig/sizeof/depend
index 4e4ebd4ae5..5f75fa8c76 100644
--- a/ext/rbconfig/sizeof/depend
+++ b/ext/rbconfig/sizeof/depend
@@ -161,6 +161,7 @@ limits.o: $(hdrdir)/ruby/internal/special_consts.h
limits.o: $(hdrdir)/ruby/internal/static_assert.h
limits.o: $(hdrdir)/ruby/internal/stdalign.h
limits.o: $(hdrdir)/ruby/internal/stdbool.h
+limits.o: $(hdrdir)/ruby/internal/stdckdint.h
limits.o: $(hdrdir)/ruby/internal/symbol.h
limits.o: $(hdrdir)/ruby/internal/value.h
limits.o: $(hdrdir)/ruby/internal/value_type.h
@@ -319,6 +320,7 @@ sizes.o: $(hdrdir)/ruby/internal/special_consts.h
sizes.o: $(hdrdir)/ruby/internal/static_assert.h
sizes.o: $(hdrdir)/ruby/internal/stdalign.h
sizes.o: $(hdrdir)/ruby/internal/stdbool.h
+sizes.o: $(hdrdir)/ruby/internal/stdckdint.h
sizes.o: $(hdrdir)/ruby/internal/symbol.h
sizes.o: $(hdrdir)/ruby/internal/value.h
sizes.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/ripper/depend b/ext/ripper/depend
index a2de09f280..fe6bd872bd 100644
--- a/ext/ripper/depend
+++ b/ext/ripper/depend
@@ -200,6 +200,7 @@ eventids1.o: $(hdrdir)/ruby/internal/special_consts.h
eventids1.o: $(hdrdir)/ruby/internal/static_assert.h
eventids1.o: $(hdrdir)/ruby/internal/stdalign.h
eventids1.o: $(hdrdir)/ruby/internal/stdbool.h
+eventids1.o: $(hdrdir)/ruby/internal/stdckdint.h
eventids1.o: $(hdrdir)/ruby/internal/symbol.h
eventids1.o: $(hdrdir)/ruby/internal/value.h
eventids1.o: $(hdrdir)/ruby/internal/value_type.h
@@ -370,6 +371,7 @@ eventids2.o: $(hdrdir)/ruby/internal/special_consts.h
eventids2.o: $(hdrdir)/ruby/internal/static_assert.h
eventids2.o: $(hdrdir)/ruby/internal/stdalign.h
eventids2.o: $(hdrdir)/ruby/internal/stdbool.h
+eventids2.o: $(hdrdir)/ruby/internal/stdckdint.h
eventids2.o: $(hdrdir)/ruby/internal/symbol.h
eventids2.o: $(hdrdir)/ruby/internal/value.h
eventids2.o: $(hdrdir)/ruby/internal/value_type.h
@@ -549,6 +551,7 @@ ripper.o: $(hdrdir)/ruby/internal/special_consts.h
ripper.o: $(hdrdir)/ruby/internal/static_assert.h
ripper.o: $(hdrdir)/ruby/internal/stdalign.h
ripper.o: $(hdrdir)/ruby/internal/stdbool.h
+ripper.o: $(hdrdir)/ruby/internal/stdckdint.h
ripper.o: $(hdrdir)/ruby/internal/symbol.h
ripper.o: $(hdrdir)/ruby/internal/value.h
ripper.o: $(hdrdir)/ruby/internal/value_type.h
@@ -566,6 +569,7 @@ ripper.o: $(hdrdir)/ruby/st.h
ripper.o: $(hdrdir)/ruby/subst.h
ripper.o: $(hdrdir)/ruby/thread_native.h
ripper.o: $(hdrdir)/ruby/util.h
+ripper.o: $(hdrdir)/ruby/version.h
ripper.o: $(top_srcdir)/ccan/check_type/check_type.h
ripper.o: $(top_srcdir)/ccan/container_of/container_of.h
ripper.o: $(top_srcdir)/ccan/list/list.h
@@ -592,6 +596,7 @@ ripper.o: $(top_srcdir)/internal/parse.h
ripper.o: $(top_srcdir)/internal/rational.h
ripper.o: $(top_srcdir)/internal/re.h
ripper.o: $(top_srcdir)/internal/ruby_parser.h
+ripper.o: $(top_srcdir)/internal/sanitizers.h
ripper.o: $(top_srcdir)/internal/serial.h
ripper.o: $(top_srcdir)/internal/static_assert.h
ripper.o: $(top_srcdir)/internal/string.h
@@ -633,6 +638,7 @@ ripper_init.o: $(hdrdir)/ruby/backward.h
ripper_init.o: $(hdrdir)/ruby/backward/2/assume.h
ripper_init.o: $(hdrdir)/ruby/backward/2/attributes.h
ripper_init.o: $(hdrdir)/ruby/backward/2/bool.h
+ripper_init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
ripper_init.o: $(hdrdir)/ruby/backward/2/inttypes.h
ripper_init.o: $(hdrdir)/ruby/backward/2/limits.h
ripper_init.o: $(hdrdir)/ruby/backward/2/long_long.h
@@ -783,6 +789,7 @@ ripper_init.o: $(hdrdir)/ruby/internal/special_consts.h
ripper_init.o: $(hdrdir)/ruby/internal/static_assert.h
ripper_init.o: $(hdrdir)/ruby/internal/stdalign.h
ripper_init.o: $(hdrdir)/ruby/internal/stdbool.h
+ripper_init.o: $(hdrdir)/ruby/internal/stdckdint.h
ripper_init.o: $(hdrdir)/ruby/internal/symbol.h
ripper_init.o: $(hdrdir)/ruby/internal/value.h
ripper_init.o: $(hdrdir)/ruby/internal/value_type.h
@@ -797,13 +804,21 @@ ripper_init.o: $(hdrdir)/ruby/st.h
ripper_init.o: $(hdrdir)/ruby/subst.h
ripper_init.o: $(top_srcdir)/internal.h
ripper_init.o: $(top_srcdir)/internal/array.h
+ripper_init.o: $(top_srcdir)/internal/bignum.h
+ripper_init.o: $(top_srcdir)/internal/bits.h
+ripper_init.o: $(top_srcdir)/internal/compilers.h
+ripper_init.o: $(top_srcdir)/internal/complex.h
+ripper_init.o: $(top_srcdir)/internal/fixnum.h
ripper_init.o: $(top_srcdir)/internal/imemo.h
+ripper_init.o: $(top_srcdir)/internal/numeric.h
ripper_init.o: $(top_srcdir)/internal/parse.h
+ripper_init.o: $(top_srcdir)/internal/rational.h
ripper_init.o: $(top_srcdir)/internal/ruby_parser.h
ripper_init.o: $(top_srcdir)/internal/serial.h
ripper_init.o: $(top_srcdir)/internal/static_assert.h
ripper_init.o: $(top_srcdir)/internal/vm.h
ripper_init.o: $(top_srcdir)/node.h
+ripper_init.o: $(top_srcdir)/ruby_assert.h
ripper_init.o: $(top_srcdir)/rubyparser.h
ripper_init.o: eventids1.h
ripper_init.o: eventids2.h
diff --git a/ext/ripper/eventids2.c b/ext/ripper/eventids2.c
index ac54955857..439663f0fd 100644
--- a/ext/ripper/eventids2.c
+++ b/ext/ripper/eventids2.c
@@ -65,6 +65,8 @@ static ripper_scanner_ids_t ripper_scanner_ids;
#include "eventids2table.c"
+STATIC_ASSERT(eventids2_table_size, RIPPER_EVENTIDS2_TABLE_SIZE == sizeof(ripper_scanner_ids)/sizeof(ID));
+
void
ripper_init_eventids2(void)
{
diff --git a/ext/ripper/ripper_init.c.tmpl b/ext/ripper/ripper_init.c.tmpl
index 5c1a4e5bb5..fc98c067b8 100644
--- a/ext/ripper/ripper_init.c.tmpl
+++ b/ext/ripper/ripper_init.c.tmpl
@@ -2,14 +2,13 @@
#include "ruby/ruby.h"
#include "ruby/encoding.h"
#include "internal.h"
-#include "internal/imemo.h" /* needed by ruby_parser.h */
+#include "rubyparser.h"
+#define YYSTYPE_IS_DECLARED
+#include "parse.h"
#include "internal/parse.h"
#include "internal/ruby_parser.h"
#include "node.h"
-#include "rubyparser.h"
#include "eventids1.h"
-#define YYSTYPE_IS_DECLARED
-#include "parse.h"
#include "eventids2.h"
#include "ripper_init.h"
@@ -18,15 +17,40 @@
ID id_warn, id_warning, id_gets, id_assoc;
+enum lex_type {
+ lex_type_str,
+ lex_type_io,
+ lex_type_generic,
+};
+
struct ripper {
rb_parser_t *p;
+ enum lex_type type;
+ union {
+ struct lex_pointer_string ptr_str;
+ VALUE val;
+ } data;
};
static void
ripper_parser_mark2(void *ptr)
{
struct ripper *r = (struct ripper*)ptr;
- if (r->p) ripper_parser_mark(r->p);
+ if (r->p) {
+ ripper_parser_mark(r->p);
+
+ switch (r->type) {
+ case lex_type_str:
+ rb_gc_mark(r->data.ptr_str.str);
+ break;
+ case lex_type_io:
+ rb_gc_mark(r->data.val);
+ break;
+ case lex_type_generic:
+ rb_gc_mark(r->data.val);
+ break;
+ }
+ }
}
static void
@@ -54,37 +78,18 @@ static const rb_data_type_t parser_data_type = {
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};
-ID
-ripper_get_id(VALUE v)
-{
- NODE *nd;
- if (!RB_TYPE_P(v, T_NODE)) return 0;
- nd = (NODE *)v;
- if (!nd_type_p(nd, NODE_RIPPER)) return 0;
- return RNODE_RIPPER(nd)->nd_vid;
-}
-
-VALUE
-ripper_get_value(VALUE v)
-{
- NODE *nd;
- if (UNDEF_P(v)) return Qnil;
- if (!RB_TYPE_P(v, T_NODE)) return v;
- nd = (NODE *)v;
- if (!nd_type_p(nd, NODE_RIPPER)) return Qnil;
- return RNODE_RIPPER(nd)->nd_rval;
-}
-
-static VALUE
-ripper_lex_get_generic(struct parser_params *p, VALUE src)
+static rb_parser_string_t *
+ripper_lex_get_generic(struct parser_params *p, rb_parser_input_data input, int line_count)
{
+ VALUE src = (VALUE)input;
VALUE line = rb_funcallv_public(src, id_gets, 0, 0);
- if (!NIL_P(line) && !RB_TYPE_P(line, T_STRING)) {
+ if (NIL_P(line)) return 0;
+ if (!RB_TYPE_P(line, T_STRING)) {
rb_raise(rb_eTypeError,
"gets returned %"PRIsVALUE" (expected String or nil)",
rb_obj_class(line));
}
- return line;
+ return rb_str_to_parser_string(p, line);
}
void
@@ -100,10 +105,19 @@ ripper_compile_error(struct parser_params *p, const char *fmt, ...)
ripper_error(p);
}
-static VALUE
-ripper_lex_io_get(struct parser_params *p, VALUE src)
+static rb_parser_string_t *
+ripper_lex_io_get(struct parser_params *p, rb_parser_input_data input, int line_count)
+{
+ VALUE src = (VALUE)input;
+ VALUE line = rb_io_gets(src);
+ if (NIL_P(line)) return 0;
+ return rb_str_to_parser_string(p, line);
+}
+
+static rb_parser_string_t *
+ripper_lex_get_str(struct parser_params *p, rb_parser_input_data input, int line_count)
{
- return rb_io_gets(src);
+ return rb_parser_lex_get_str(p, (struct lex_pointer_string *)input);
}
static VALUE
@@ -115,10 +129,8 @@ ripper_s_allocate(VALUE klass)
&parser_data_type, r);
#ifdef UNIVERSAL_PARSER
- rb_parser_config_t *config;
- config = rb_ruby_parser_config_new(ruby_xmalloc);
- rb_parser_config_initialize(config);
- r->p = rb_ruby_parser_allocate(config);
+ const rb_parser_config_t *config = rb_ruby_parser_config();
+ r->p = rb_ripper_parser_params_allocate(config);
#else
r->p = rb_ruby_ripper_parser_allocate();
#endif
@@ -179,7 +191,7 @@ ripper_parser_encoding(VALUE vparser)
{
struct parser_params *p = ripper_parser_params(vparser, false);
- return rb_ruby_parser_encoding(p);
+ return rb_enc_from_encoding(rb_ruby_parser_encoding(p));
}
/*
@@ -260,11 +272,11 @@ parser_dedent_string0(VALUE a)
}
static VALUE
-parser_config_free(VALUE a)
+parser_free(VALUE a)
{
- rb_parser_config_t *config = (void *)a;
+ struct parser_params *p = (void *)a;
- rb_ruby_parser_config_free(config);
+ rb_ruby_parser_free(p);
return Qnil;
}
#endif
@@ -283,17 +295,14 @@ static VALUE
parser_dedent_string(VALUE self, VALUE input, VALUE width)
{
struct parser_params *p;
- rb_parser_config_t *config;
struct dedent_string_arg args;
- config = rb_ruby_parser_config_new(ruby_xmalloc);
- rb_parser_config_initialize(config);
- p = rb_ruby_parser_new(config);
+ p = rb_parser_params_new();
args.p = p;
args.input = input;
args.width = width;
- return rb_ensure(parser_dedent_string0, (VALUE)&args, parser_config_free, (VALUE)config);
+ return rb_ensure(parser_dedent_string0, (VALUE)&args, parser_free, (VALUE)p);
}
#else
static VALUE
@@ -321,26 +330,38 @@ parser_dedent_string(VALUE self, VALUE input, VALUE width)
static VALUE
ripper_initialize(int argc, VALUE *argv, VALUE self)
{
+ struct ripper *r;
struct parser_params *p;
VALUE src, fname, lineno;
- VALUE (*gets)(struct parser_params*,VALUE);
- VALUE input, sourcefile_string;
+ rb_parser_lex_gets_func *gets;
+ VALUE sourcefile_string;
const char *sourcefile;
int sourceline;
+ rb_parser_input_data input;
p = ripper_parser_params(self, false);
+ TypedData_Get_Struct(self, struct ripper, &parser_data_type, r);
rb_scan_args(argc, argv, "12", &src, &fname, &lineno);
if (RB_TYPE_P(src, T_FILE)) {
gets = ripper_lex_io_get;
+ r->type = lex_type_io;
+ r->data.val = src;
+ input = (rb_parser_input_data)src;
}
else if (rb_respond_to(src, id_gets)) {
gets = ripper_lex_get_generic;
+ r->type = lex_type_generic;
+ r->data.val = src;
+ input = (rb_parser_input_data)src;
}
else {
StringValue(src);
- gets = rb_ruby_ripper_lex_get_str;
+ gets = ripper_lex_get_str;
+ r->type = lex_type_str;
+ r->data.ptr_str.str = src;
+ r->data.ptr_str.ptr = 0;
+ input = (rb_parser_input_data)&r->data.ptr_str;
}
- input = src;
if (NIL_P(fname)) {
fname = STR_NEW2("(ripper)");
OBJ_FREEZE(fname);
@@ -477,11 +498,13 @@ ripper_token(VALUE self)
{
struct parser_params *p = ripper_parser_params(self, true);
long pos, len;
+ VALUE str;
if (NIL_P(rb_ruby_parser_parsing_thread(p))) return Qnil;
pos = rb_ruby_ripper_column(p);
len = rb_ruby_ripper_token_len(p);
- return rb_str_subseq(rb_ruby_ripper_lex_lastline(p), pos, len);
+ str = rb_str_new_parser_string(rb_ruby_ripper_lex_lastline(p));
+ return rb_str_subseq(str, pos, len);
}
#ifdef RIPPER_DEBUG
@@ -502,6 +525,37 @@ ripper_raw_value(VALUE self, VALUE obj)
{
return ULONG2NUM(obj);
}
+
+/* :nodoc: */
+static VALUE
+ripper_validate_object(VALUE self, VALUE x)
+{
+ if (x == Qfalse) return x;
+ if (x == Qtrue) return x;
+ if (NIL_P(x)) return x;
+ if (UNDEF_P(x))
+ rb_raise(rb_eArgError, "Qundef given");
+ if (FIXNUM_P(x)) return x;
+ if (SYMBOL_P(x)) return x;
+ switch (BUILTIN_TYPE(x)) {
+ case T_STRING:
+ case T_OBJECT:
+ case T_ARRAY:
+ case T_BIGNUM:
+ case T_FLOAT:
+ case T_COMPLEX:
+ case T_RATIONAL:
+ break;
+ default:
+ rb_raise(rb_eArgError, "wrong type of ruby object: %p (%s)",
+ (void *)x, rb_obj_classname(x));
+ }
+ if (!RBASIC_CLASS(x)) {
+ rb_raise(rb_eArgError, "hidden ruby object: %p (%s)",
+ (void *)x, rb_builtin_type_name(TYPE(x)));
+ }
+ return x;
+}
#endif
#ifdef UNIVERSAL_PARSER
@@ -530,17 +584,14 @@ static VALUE
ripper_lex_state_name(VALUE self, VALUE state)
{
struct parser_params *p;
- rb_parser_config_t *config;
struct lex_state_name_arg args;
- config = rb_ruby_parser_config_new(ruby_xmalloc);
- rb_parser_config_initialize(config);
- p = rb_ruby_parser_new(config);
+ p = rb_parser_params_new();
args.p = p;
args.state = state;
- return rb_ensure(lex_state_name0, (VALUE)&args, parser_config_free, (VALUE)config);
+ return rb_ensure(lex_state_name0, (VALUE)&args, parser_free, (VALUE)p);
}
#else
static VALUE
@@ -614,5 +665,4 @@ InitVM_ripper(void)
*/
rb_define_global_const("SCRIPT_LINES__", Qnil);
#endif
-
}
diff --git a/ext/ripper/ripper_init.h b/ext/ripper/ripper_init.h
index 82ff13b95f..9d228107d1 100644
--- a/ext/ripper/ripper_init.h
+++ b/ext/ripper/ripper_init.h
@@ -1,8 +1,6 @@
#ifndef RIPPER_INIT_H
#define RIPPER_INIT_H
-VALUE ripper_get_value(VALUE v);
-ID ripper_get_id(VALUE v);
PRINTF_ARGS(void ripper_compile_error(struct parser_params*, const char *fmt, ...), 2, 3);
#endif /* RIPPER_INIT_H */
diff --git a/ext/ripper/tools/dsl.rb b/ext/ripper/tools/dsl.rb
index 6d662b3fb8..38f859dd97 100644
--- a/ext/ripper/tools/dsl.rb
+++ b/ext/ripper/tools/dsl.rb
@@ -1,6 +1,8 @@
+# frozen_string_literal: true
+
# Simple DSL implementation for Ripper code generation
#
-# input: /*% ripper: stmts_add(stmts_new, void_stmt) %*/
+# input: /*% ripper: stmts_add!(stmts_new!, void_stmt!) %*/
# output:
# VALUE v1, v2;
# v1 = dispatch0(stmts_new);
@@ -18,69 +20,158 @@ class DSL
NAME_PATTERN = /(?>\$|\d+|[a-zA-Z_][a-zA-Z0-9_]*|\[[a-zA-Z_.][-a-zA-Z0-9_.]*\])(?>(?:\.|->)[a-zA-Z_][a-zA-Z0-9_]*)*/.source
NOT_REF_PATTERN = /(?>\#.*|[^\"$@]*|"(?>\\.|[^\"])*")/.source
- def initialize(code, options)
+ def self.line?(line, lineno = nil, indent: nil)
+ if %r<(?<space>\s*)/\*% *ripper(?:\[(?<option>.*?)\])?: *(?<code>.*?) *%\*/> =~ line
+ new(code, comma_split(option), lineno, indent: indent || space)
+ end
+ end
+
+ def self.comma_split(str)
+ str or return []
+ str.scan(/(([^(,)]+|\((?:,|\g<0>)*\))+)/).map(&:first)
+ end
+
+ using Module.new {
+ refine Array do
+ def to_s
+ if empty?
+ "rb_ary_new()"
+ else
+ "rb_ary_new_from_args(#{size}, #{map(&:to_s).join(', ')})"
+ end
+ end
+ end
+ }
+
+ class Var
+ class Table < Hash
+ def initialize(&block)
+ super() {|tbl, arg|
+ tbl.fetch(arg, &block)
+ }
+ end
+
+ def fetch(arg, &block)
+ super {
+ self[arg] = Var.new(self, arg, &block)
+ }
+ end
+
+ def add(&block)
+ v = new_var
+ self[v] = Var.new(self, v, &block)
+ end
+
+ def defined?(name)
+ name = name.to_s
+ any? {|_, v| v.var == name}
+ end
+
+ def new_var
+ "v#{size+1}"
+ end
+ end
+
+ attr_reader :var, :value
+
+ PRETTY_PRINT_INSTANCE_VARIABLES = instance_methods(false).freeze
+
+ def pretty_print_instance_variables
+ PRETTY_PRINT_INSTANCE_VARIABLES
+ end
+
+ alias to_s var
+
+ def initialize(table, arg, &block)
+ @var = table.new_var
+ @value = yield arg
+ @table = table
+ end
+
+ # Indexing.
+ #
+ # $:1 -> v1=get_value($:1)
+ # $:1[0] -> rb_ary_entry(v1, 0)
+ # $:1[0..1] -> [rb_ary_entry(v1, 0), rb_ary_entry(v1, 1)]
+ # *$:1[0..1] -> rb_ary_entry(v1, 0), rb_ary_entry(v1, 1)
+ #
+ # Splat needs `[range]` because `Var` does not have the length info.
+ def [](idx)
+ if ::Range === idx
+ idx.map {|i| self[i]}
+ else
+ @table.fetch("#@var[#{idx}]") {"rb_ary_entry(#{@var}, #{idx})"}
+ end
+ end
+ end
+
+ def initialize(code, options, lineno = nil, indent: "\t\t\t")
+ @lineno = lineno
+ @indent = indent
@events = {}
@error = options.include?("error")
- @brace = options.include?("brace")
if options.include?("final")
@final = "p->result"
else
- @final = (options.grep(/\A\$#{NAME_PATTERN}\z/o)[0] || "$$")
+ @final = (options.grep(/\A\$#{NAME_PATTERN}\z/o)[0] || "p->s_lvalue")
end
- @vars = 0
- # struct parser_params *p
- p = p = "p"
+ bind = dsl_binding
+ @var_table = Var::Table.new {|arg| "get_value(#{arg})"}
+ code = code.gsub(%r[\G#{NOT_REF_PATTERN}\K(\$|\$:|@)#{TAG_PATTERN}?#{NAME_PATTERN}]o) {
+ if (arg = $&) == "$:$"
+ '"p->s_lvalue"'
+ elsif arg.start_with?("$:")
+ "(#{@var_table[arg]}=@var_table[#{arg.dump}])"
+ else
+ arg.dump
+ end
+ }
+ @last_value = bind.eval(code)
+ rescue SyntaxError
+ $stderr.puts "error on line #{@lineno}" if @lineno
+ raise
+ end
- @code = ""
- code = code.gsub(%r[\G#{NOT_REF_PATTERN}\K[$@]#{TAG_PATTERN}?#{NAME_PATTERN}]o, '"\&"')
- @last_value = eval(code)
+ def dsl_binding(p = "p")
+ # struct parser_params *p
+ binding
end
attr_reader :events
undef lambda
undef hash
- undef class
+ undef :class
def generate
- s = "#@code#@final=#@last_value;"
- s = "{VALUE #{ (1..@vars).map {|v| "v#{ v }" }.join(",") };#{ s }}" if @vars > 0
+ s = "#@final=#@last_value;"
s << "ripper_error(p);" if @error
- s = "{#{ s }}" if @brace
- "\t\t\t#{s}"
- end
-
- def new_var
- "v#{ @vars += 1 }"
- end
-
- def opt_event(event, default, addend)
- add_event(event, [default, addend], true)
+ unless @var_table.empty?
+ vars = @var_table.map {|_, v| "#{v.var}=#{v.value}"}.join(", ")
+ s = "VALUE #{ vars }; #{ s }"
+ end
+ "#{@indent}{#{s}}"
end
- def add_event(event, args, qundef_check = false)
+ def add_event(event, args)
event = event.to_s.sub(/!\z/, "")
@events[event] = args.size
vars = []
args.each do |arg|
- vars << v = new_var
- @code << "#{ v }=#{ arg };"
+ arg = @var_table.add {arg} unless Var === arg
+ vars << arg
end
- v = new_var
- d = "dispatch#{ args.size }(#{ [event, *vars].join(",") })"
- d = "#{ vars.last }==Qundef ? #{ vars.first } : #{ d }" if qundef_check
- @code << "#{ v }=#{ d };"
- v
+ @var_table.add {"dispatch#{ args.size }(#{ [event, *vars].join(",") })"}
end
def method_missing(event, *args)
if event.to_s =~ /!\z/
add_event(event, args)
- elsif args.empty? and /\Aid[A-Z_]/ =~ event.to_s
+ elsif args.empty? and (/\Aid[A-Z_]/ =~ event or @var_table.defined?(event))
event
else
- "#{ event }(#{ args.join(", ") })"
+ "#{ event }(#{ args.map(&:to_s).join(", ") })"
end
end
@@ -88,4 +179,3 @@ class DSL
name
end
end
-
diff --git a/ext/ripper/tools/generate.rb b/ext/ripper/tools/generate.rb
index bb64d2fe8b..57ecac0b39 100644
--- a/ext/ripper/tools/generate.rb
+++ b/ext/ripper/tools/generate.rb
@@ -75,6 +75,7 @@ def generate_eventids1_h(ids)
buf << %Q[#ifndef RIPPER_EVENTIDS1\n]
buf << %Q[#define RIPPER_EVENTIDS1\n]
buf << %Q[\n]
+ buf << %Q[#define RIPPER_ID(n) ripper_parser_ids.id_ ## n\n]
buf << %Q[void ripper_init_eventids1(void);\n]
buf << %Q[void ripper_init_eventids1_table(VALUE self);\n]
buf << %Q[\n]
@@ -84,9 +85,6 @@ def generate_eventids1_h(ids)
end
buf << %Q[};\n]
buf << %Q[\n]
- ids.each do |id, arity|
- buf << %Q[#define ripper_id_#{id} ripper_parser_ids.id_#{id}\n]
- end
buf << %Q[#endif /* RIPPER_EVENTIDS1 */\n]
buf << %Q[\n]
end
@@ -101,7 +99,7 @@ def generate_eventids1(ids)
buf << %Q[void\n]
buf << %Q[ripper_init_eventids1(void)\n]
buf << %Q[{\n]
- buf << %Q[#define set_id1(name) ripper_id_##name = rb_intern_const("on_"#name)\n]
+ buf << %Q[#define set_id1(name) RIPPER_ID(name) = rb_intern_const("on_"#name)\n]
ids.each do |id, arity|
buf << %Q[ set_id1(#{id});\n]
end
@@ -136,6 +134,8 @@ def generate_eventids2_table(ids)
buf << %Q[ rb_hash_aset(h, intern_sym("#{id}"), INT2FIX(1));\n]
end
buf << %Q[}\n]
+ buf << %Q[\n]
+ buf << %Q[#define RIPPER_EVENTIDS2_TABLE_SIZE #{ids.size}\n]
buf
end
@@ -171,9 +171,7 @@ def read_ids1_with_locations(path)
line.scan(/\bdispatch(\d)\((\w+)/) do |arity, event|
(h[event] ||= []).push [f.lineno, arity.to_i]
end
- if line =~ %r</\*% *ripper(?:\[(.*?)\])?: *(.*?) *%\*/>
- gen = DSL.new($2, ($1 || "").split(","))
- gen.generate
+ if gen = DSL.line?(line, f.lineno)
gen.events.each do |event, arity|
(h[event] ||= []).push [f.lineno, arity.to_i]
end
diff --git a/ext/ripper/tools/preproc.rb b/ext/ripper/tools/preproc.rb
index a0d5e79d7d..5e8a6e0cb5 100644
--- a/ext/ripper/tools/preproc.rb
+++ b/ext/ripper/tools/preproc.rb
@@ -51,27 +51,26 @@ def process(f, out, path, template)
usercode f, out, path, template
end
-def prelude(f, out)
- @exprs = {}
- lex_state_def = false
+require_relative 'dsl'
+
+def generate_line(f, out)
while line = f.gets
- case line
- when /\A%%/
+ case
+ when gen = DSL.line?(line, f.lineno)
+ out << gen.generate << "\n"
+ when line.start_with?("%%")
out << "%%\n"
- return
- when /\A%token/, /\A%type/, /\A} <node(?>_\w+)?>/
- # types in %union which have corresponding set_yylval_* macro.
- out << line.sub(/<(?:node(?>_\w+)?|num|id)>/, '<val>')
- when /^enum lex_state_(?:bits|e) \{/
- lex_state_def = true
- out << line
- when /^\}/
- lex_state_def = false
- out << line
+ break
else
- out << line
+ out << yield(line)
end
- if lex_state_def
+ end
+end
+
+def prelude(f, out)
+ @exprs = {}
+ generate_line(f, out) do |line|
+ if (/^enum lex_state_(?:bits|e) \{/ =~ line)..(/^\}/ =~ line)
case line
when /^\s*(EXPR_\w+),\s+\/\*(.+)\*\//
@exprs[$1.chomp("_bit")] = $2.strip
@@ -81,27 +80,21 @@ def prelude(f, out)
@exprs[name] = "equals to " + (val.start_with?("(") ? "<tt>#{val}</tt>" : "+#{val}+")
end
end
+ line
end
end
-require_relative "dsl"
-
def grammar(f, out)
- while line = f.gets
+ generate_line(f, out) do |line|
case line
- when %r</\*% *ripper(?:\[(.*?)\])?: *(.*?) *%\*/>
- out << DSL.new($2, ($1 || "").split(",")).generate << "\n"
when %r</\*%%%\*/>
- out << "#if 0\n"
+ "#if 0\n"
when %r</\*%>
- out << "#endif\n"
+ "#endif\n"
when %r<%\*/>
- out << "\n"
- when /\A%%/
- out << "%%\n"
- return
+ "\n"
else
- out << line
+ line
end
end
end
diff --git a/ext/socket/depend b/ext/socket/depend
index 675520c0b5..750bb0734f 100644
--- a/ext/socket/depend
+++ b/ext/socket/depend
@@ -170,6 +170,7 @@ ancdata.o: $(hdrdir)/ruby/internal/special_consts.h
ancdata.o: $(hdrdir)/ruby/internal/static_assert.h
ancdata.o: $(hdrdir)/ruby/internal/stdalign.h
ancdata.o: $(hdrdir)/ruby/internal/stdbool.h
+ancdata.o: $(hdrdir)/ruby/internal/stdckdint.h
ancdata.o: $(hdrdir)/ruby/internal/symbol.h
ancdata.o: $(hdrdir)/ruby/internal/value.h
ancdata.o: $(hdrdir)/ruby/internal/value_type.h
@@ -186,6 +187,7 @@ ancdata.o: $(hdrdir)/ruby/subst.h
ancdata.o: $(hdrdir)/ruby/thread.h
ancdata.o: $(hdrdir)/ruby/thread_native.h
ancdata.o: $(hdrdir)/ruby/util.h
+ancdata.o: $(hdrdir)/ruby/version.h
ancdata.o: $(top_srcdir)/ccan/check_type/check_type.h
ancdata.o: $(top_srcdir)/ccan/container_of/container_of.h
ancdata.o: $(top_srcdir)/ccan/list/list.h
@@ -198,6 +200,7 @@ ancdata.o: $(top_srcdir)/internal/error.h
ancdata.o: $(top_srcdir)/internal/gc.h
ancdata.o: $(top_srcdir)/internal/imemo.h
ancdata.o: $(top_srcdir)/internal/io.h
+ancdata.o: $(top_srcdir)/internal/sanitizers.h
ancdata.o: $(top_srcdir)/internal/serial.h
ancdata.o: $(top_srcdir)/internal/static_assert.h
ancdata.o: $(top_srcdir)/internal/string.h
@@ -378,6 +381,7 @@ basicsocket.o: $(hdrdir)/ruby/internal/special_consts.h
basicsocket.o: $(hdrdir)/ruby/internal/static_assert.h
basicsocket.o: $(hdrdir)/ruby/internal/stdalign.h
basicsocket.o: $(hdrdir)/ruby/internal/stdbool.h
+basicsocket.o: $(hdrdir)/ruby/internal/stdckdint.h
basicsocket.o: $(hdrdir)/ruby/internal/symbol.h
basicsocket.o: $(hdrdir)/ruby/internal/value.h
basicsocket.o: $(hdrdir)/ruby/internal/value_type.h
@@ -394,6 +398,7 @@ basicsocket.o: $(hdrdir)/ruby/subst.h
basicsocket.o: $(hdrdir)/ruby/thread.h
basicsocket.o: $(hdrdir)/ruby/thread_native.h
basicsocket.o: $(hdrdir)/ruby/util.h
+basicsocket.o: $(hdrdir)/ruby/version.h
basicsocket.o: $(top_srcdir)/ccan/check_type/check_type.h
basicsocket.o: $(top_srcdir)/ccan/container_of/container_of.h
basicsocket.o: $(top_srcdir)/ccan/list/list.h
@@ -406,6 +411,7 @@ basicsocket.o: $(top_srcdir)/internal/error.h
basicsocket.o: $(top_srcdir)/internal/gc.h
basicsocket.o: $(top_srcdir)/internal/imemo.h
basicsocket.o: $(top_srcdir)/internal/io.h
+basicsocket.o: $(top_srcdir)/internal/sanitizers.h
basicsocket.o: $(top_srcdir)/internal/serial.h
basicsocket.o: $(top_srcdir)/internal/static_assert.h
basicsocket.o: $(top_srcdir)/internal/string.h
@@ -586,6 +592,7 @@ constants.o: $(hdrdir)/ruby/internal/special_consts.h
constants.o: $(hdrdir)/ruby/internal/static_assert.h
constants.o: $(hdrdir)/ruby/internal/stdalign.h
constants.o: $(hdrdir)/ruby/internal/stdbool.h
+constants.o: $(hdrdir)/ruby/internal/stdckdint.h
constants.o: $(hdrdir)/ruby/internal/symbol.h
constants.o: $(hdrdir)/ruby/internal/value.h
constants.o: $(hdrdir)/ruby/internal/value_type.h
@@ -602,6 +609,7 @@ constants.o: $(hdrdir)/ruby/subst.h
constants.o: $(hdrdir)/ruby/thread.h
constants.o: $(hdrdir)/ruby/thread_native.h
constants.o: $(hdrdir)/ruby/util.h
+constants.o: $(hdrdir)/ruby/version.h
constants.o: $(top_srcdir)/ccan/check_type/check_type.h
constants.o: $(top_srcdir)/ccan/container_of/container_of.h
constants.o: $(top_srcdir)/ccan/list/list.h
@@ -614,6 +622,7 @@ constants.o: $(top_srcdir)/internal/error.h
constants.o: $(top_srcdir)/internal/gc.h
constants.o: $(top_srcdir)/internal/imemo.h
constants.o: $(top_srcdir)/internal/io.h
+constants.o: $(top_srcdir)/internal/sanitizers.h
constants.o: $(top_srcdir)/internal/serial.h
constants.o: $(top_srcdir)/internal/static_assert.h
constants.o: $(top_srcdir)/internal/string.h
@@ -795,6 +804,7 @@ ifaddr.o: $(hdrdir)/ruby/internal/special_consts.h
ifaddr.o: $(hdrdir)/ruby/internal/static_assert.h
ifaddr.o: $(hdrdir)/ruby/internal/stdalign.h
ifaddr.o: $(hdrdir)/ruby/internal/stdbool.h
+ifaddr.o: $(hdrdir)/ruby/internal/stdckdint.h
ifaddr.o: $(hdrdir)/ruby/internal/symbol.h
ifaddr.o: $(hdrdir)/ruby/internal/value.h
ifaddr.o: $(hdrdir)/ruby/internal/value_type.h
@@ -811,6 +821,7 @@ ifaddr.o: $(hdrdir)/ruby/subst.h
ifaddr.o: $(hdrdir)/ruby/thread.h
ifaddr.o: $(hdrdir)/ruby/thread_native.h
ifaddr.o: $(hdrdir)/ruby/util.h
+ifaddr.o: $(hdrdir)/ruby/version.h
ifaddr.o: $(top_srcdir)/ccan/check_type/check_type.h
ifaddr.o: $(top_srcdir)/ccan/container_of/container_of.h
ifaddr.o: $(top_srcdir)/ccan/list/list.h
@@ -823,6 +834,7 @@ ifaddr.o: $(top_srcdir)/internal/error.h
ifaddr.o: $(top_srcdir)/internal/gc.h
ifaddr.o: $(top_srcdir)/internal/imemo.h
ifaddr.o: $(top_srcdir)/internal/io.h
+ifaddr.o: $(top_srcdir)/internal/sanitizers.h
ifaddr.o: $(top_srcdir)/internal/serial.h
ifaddr.o: $(top_srcdir)/internal/static_assert.h
ifaddr.o: $(top_srcdir)/internal/string.h
@@ -1003,6 +1015,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h
init.o: $(hdrdir)/ruby/internal/static_assert.h
init.o: $(hdrdir)/ruby/internal/stdalign.h
init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
init.o: $(hdrdir)/ruby/internal/symbol.h
init.o: $(hdrdir)/ruby/internal/value.h
init.o: $(hdrdir)/ruby/internal/value_type.h
@@ -1019,6 +1032,7 @@ init.o: $(hdrdir)/ruby/subst.h
init.o: $(hdrdir)/ruby/thread.h
init.o: $(hdrdir)/ruby/thread_native.h
init.o: $(hdrdir)/ruby/util.h
+init.o: $(hdrdir)/ruby/version.h
init.o: $(top_srcdir)/ccan/check_type/check_type.h
init.o: $(top_srcdir)/ccan/container_of/container_of.h
init.o: $(top_srcdir)/ccan/list/list.h
@@ -1031,6 +1045,7 @@ init.o: $(top_srcdir)/internal/error.h
init.o: $(top_srcdir)/internal/gc.h
init.o: $(top_srcdir)/internal/imemo.h
init.o: $(top_srcdir)/internal/io.h
+init.o: $(top_srcdir)/internal/sanitizers.h
init.o: $(top_srcdir)/internal/serial.h
init.o: $(top_srcdir)/internal/static_assert.h
init.o: $(top_srcdir)/internal/string.h
@@ -1211,6 +1226,7 @@ ipsocket.o: $(hdrdir)/ruby/internal/special_consts.h
ipsocket.o: $(hdrdir)/ruby/internal/static_assert.h
ipsocket.o: $(hdrdir)/ruby/internal/stdalign.h
ipsocket.o: $(hdrdir)/ruby/internal/stdbool.h
+ipsocket.o: $(hdrdir)/ruby/internal/stdckdint.h
ipsocket.o: $(hdrdir)/ruby/internal/symbol.h
ipsocket.o: $(hdrdir)/ruby/internal/value.h
ipsocket.o: $(hdrdir)/ruby/internal/value_type.h
@@ -1227,6 +1243,7 @@ ipsocket.o: $(hdrdir)/ruby/subst.h
ipsocket.o: $(hdrdir)/ruby/thread.h
ipsocket.o: $(hdrdir)/ruby/thread_native.h
ipsocket.o: $(hdrdir)/ruby/util.h
+ipsocket.o: $(hdrdir)/ruby/version.h
ipsocket.o: $(top_srcdir)/ccan/check_type/check_type.h
ipsocket.o: $(top_srcdir)/ccan/container_of/container_of.h
ipsocket.o: $(top_srcdir)/ccan/list/list.h
@@ -1239,6 +1256,7 @@ ipsocket.o: $(top_srcdir)/internal/error.h
ipsocket.o: $(top_srcdir)/internal/gc.h
ipsocket.o: $(top_srcdir)/internal/imemo.h
ipsocket.o: $(top_srcdir)/internal/io.h
+ipsocket.o: $(top_srcdir)/internal/sanitizers.h
ipsocket.o: $(top_srcdir)/internal/serial.h
ipsocket.o: $(top_srcdir)/internal/static_assert.h
ipsocket.o: $(top_srcdir)/internal/string.h
@@ -1419,6 +1437,7 @@ option.o: $(hdrdir)/ruby/internal/special_consts.h
option.o: $(hdrdir)/ruby/internal/static_assert.h
option.o: $(hdrdir)/ruby/internal/stdalign.h
option.o: $(hdrdir)/ruby/internal/stdbool.h
+option.o: $(hdrdir)/ruby/internal/stdckdint.h
option.o: $(hdrdir)/ruby/internal/symbol.h
option.o: $(hdrdir)/ruby/internal/value.h
option.o: $(hdrdir)/ruby/internal/value_type.h
@@ -1435,6 +1454,7 @@ option.o: $(hdrdir)/ruby/subst.h
option.o: $(hdrdir)/ruby/thread.h
option.o: $(hdrdir)/ruby/thread_native.h
option.o: $(hdrdir)/ruby/util.h
+option.o: $(hdrdir)/ruby/version.h
option.o: $(top_srcdir)/ccan/check_type/check_type.h
option.o: $(top_srcdir)/ccan/container_of/container_of.h
option.o: $(top_srcdir)/ccan/list/list.h
@@ -1447,6 +1467,7 @@ option.o: $(top_srcdir)/internal/error.h
option.o: $(top_srcdir)/internal/gc.h
option.o: $(top_srcdir)/internal/imemo.h
option.o: $(top_srcdir)/internal/io.h
+option.o: $(top_srcdir)/internal/sanitizers.h
option.o: $(top_srcdir)/internal/serial.h
option.o: $(top_srcdir)/internal/static_assert.h
option.o: $(top_srcdir)/internal/string.h
@@ -1627,6 +1648,7 @@ raddrinfo.o: $(hdrdir)/ruby/internal/special_consts.h
raddrinfo.o: $(hdrdir)/ruby/internal/static_assert.h
raddrinfo.o: $(hdrdir)/ruby/internal/stdalign.h
raddrinfo.o: $(hdrdir)/ruby/internal/stdbool.h
+raddrinfo.o: $(hdrdir)/ruby/internal/stdckdint.h
raddrinfo.o: $(hdrdir)/ruby/internal/symbol.h
raddrinfo.o: $(hdrdir)/ruby/internal/value.h
raddrinfo.o: $(hdrdir)/ruby/internal/value_type.h
@@ -1643,6 +1665,7 @@ raddrinfo.o: $(hdrdir)/ruby/subst.h
raddrinfo.o: $(hdrdir)/ruby/thread.h
raddrinfo.o: $(hdrdir)/ruby/thread_native.h
raddrinfo.o: $(hdrdir)/ruby/util.h
+raddrinfo.o: $(hdrdir)/ruby/version.h
raddrinfo.o: $(top_srcdir)/ccan/check_type/check_type.h
raddrinfo.o: $(top_srcdir)/ccan/container_of/container_of.h
raddrinfo.o: $(top_srcdir)/ccan/list/list.h
@@ -1655,6 +1678,7 @@ raddrinfo.o: $(top_srcdir)/internal/error.h
raddrinfo.o: $(top_srcdir)/internal/gc.h
raddrinfo.o: $(top_srcdir)/internal/imemo.h
raddrinfo.o: $(top_srcdir)/internal/io.h
+raddrinfo.o: $(top_srcdir)/internal/sanitizers.h
raddrinfo.o: $(top_srcdir)/internal/serial.h
raddrinfo.o: $(top_srcdir)/internal/static_assert.h
raddrinfo.o: $(top_srcdir)/internal/string.h
@@ -1835,6 +1859,7 @@ socket.o: $(hdrdir)/ruby/internal/special_consts.h
socket.o: $(hdrdir)/ruby/internal/static_assert.h
socket.o: $(hdrdir)/ruby/internal/stdalign.h
socket.o: $(hdrdir)/ruby/internal/stdbool.h
+socket.o: $(hdrdir)/ruby/internal/stdckdint.h
socket.o: $(hdrdir)/ruby/internal/symbol.h
socket.o: $(hdrdir)/ruby/internal/value.h
socket.o: $(hdrdir)/ruby/internal/value_type.h
@@ -1851,6 +1876,7 @@ socket.o: $(hdrdir)/ruby/subst.h
socket.o: $(hdrdir)/ruby/thread.h
socket.o: $(hdrdir)/ruby/thread_native.h
socket.o: $(hdrdir)/ruby/util.h
+socket.o: $(hdrdir)/ruby/version.h
socket.o: $(top_srcdir)/ccan/check_type/check_type.h
socket.o: $(top_srcdir)/ccan/container_of/container_of.h
socket.o: $(top_srcdir)/ccan/list/list.h
@@ -1863,6 +1889,7 @@ socket.o: $(top_srcdir)/internal/error.h
socket.o: $(top_srcdir)/internal/gc.h
socket.o: $(top_srcdir)/internal/imemo.h
socket.o: $(top_srcdir)/internal/io.h
+socket.o: $(top_srcdir)/internal/sanitizers.h
socket.o: $(top_srcdir)/internal/serial.h
socket.o: $(top_srcdir)/internal/static_assert.h
socket.o: $(top_srcdir)/internal/string.h
@@ -2043,6 +2070,7 @@ sockssocket.o: $(hdrdir)/ruby/internal/special_consts.h
sockssocket.o: $(hdrdir)/ruby/internal/static_assert.h
sockssocket.o: $(hdrdir)/ruby/internal/stdalign.h
sockssocket.o: $(hdrdir)/ruby/internal/stdbool.h
+sockssocket.o: $(hdrdir)/ruby/internal/stdckdint.h
sockssocket.o: $(hdrdir)/ruby/internal/symbol.h
sockssocket.o: $(hdrdir)/ruby/internal/value.h
sockssocket.o: $(hdrdir)/ruby/internal/value_type.h
@@ -2059,6 +2087,7 @@ sockssocket.o: $(hdrdir)/ruby/subst.h
sockssocket.o: $(hdrdir)/ruby/thread.h
sockssocket.o: $(hdrdir)/ruby/thread_native.h
sockssocket.o: $(hdrdir)/ruby/util.h
+sockssocket.o: $(hdrdir)/ruby/version.h
sockssocket.o: $(top_srcdir)/ccan/check_type/check_type.h
sockssocket.o: $(top_srcdir)/ccan/container_of/container_of.h
sockssocket.o: $(top_srcdir)/ccan/list/list.h
@@ -2071,6 +2100,7 @@ sockssocket.o: $(top_srcdir)/internal/error.h
sockssocket.o: $(top_srcdir)/internal/gc.h
sockssocket.o: $(top_srcdir)/internal/imemo.h
sockssocket.o: $(top_srcdir)/internal/io.h
+sockssocket.o: $(top_srcdir)/internal/sanitizers.h
sockssocket.o: $(top_srcdir)/internal/serial.h
sockssocket.o: $(top_srcdir)/internal/static_assert.h
sockssocket.o: $(top_srcdir)/internal/string.h
@@ -2251,6 +2281,7 @@ tcpserver.o: $(hdrdir)/ruby/internal/special_consts.h
tcpserver.o: $(hdrdir)/ruby/internal/static_assert.h
tcpserver.o: $(hdrdir)/ruby/internal/stdalign.h
tcpserver.o: $(hdrdir)/ruby/internal/stdbool.h
+tcpserver.o: $(hdrdir)/ruby/internal/stdckdint.h
tcpserver.o: $(hdrdir)/ruby/internal/symbol.h
tcpserver.o: $(hdrdir)/ruby/internal/value.h
tcpserver.o: $(hdrdir)/ruby/internal/value_type.h
@@ -2267,6 +2298,7 @@ tcpserver.o: $(hdrdir)/ruby/subst.h
tcpserver.o: $(hdrdir)/ruby/thread.h
tcpserver.o: $(hdrdir)/ruby/thread_native.h
tcpserver.o: $(hdrdir)/ruby/util.h
+tcpserver.o: $(hdrdir)/ruby/version.h
tcpserver.o: $(top_srcdir)/ccan/check_type/check_type.h
tcpserver.o: $(top_srcdir)/ccan/container_of/container_of.h
tcpserver.o: $(top_srcdir)/ccan/list/list.h
@@ -2279,6 +2311,7 @@ tcpserver.o: $(top_srcdir)/internal/error.h
tcpserver.o: $(top_srcdir)/internal/gc.h
tcpserver.o: $(top_srcdir)/internal/imemo.h
tcpserver.o: $(top_srcdir)/internal/io.h
+tcpserver.o: $(top_srcdir)/internal/sanitizers.h
tcpserver.o: $(top_srcdir)/internal/serial.h
tcpserver.o: $(top_srcdir)/internal/static_assert.h
tcpserver.o: $(top_srcdir)/internal/string.h
@@ -2459,6 +2492,7 @@ tcpsocket.o: $(hdrdir)/ruby/internal/special_consts.h
tcpsocket.o: $(hdrdir)/ruby/internal/static_assert.h
tcpsocket.o: $(hdrdir)/ruby/internal/stdalign.h
tcpsocket.o: $(hdrdir)/ruby/internal/stdbool.h
+tcpsocket.o: $(hdrdir)/ruby/internal/stdckdint.h
tcpsocket.o: $(hdrdir)/ruby/internal/symbol.h
tcpsocket.o: $(hdrdir)/ruby/internal/value.h
tcpsocket.o: $(hdrdir)/ruby/internal/value_type.h
@@ -2475,6 +2509,7 @@ tcpsocket.o: $(hdrdir)/ruby/subst.h
tcpsocket.o: $(hdrdir)/ruby/thread.h
tcpsocket.o: $(hdrdir)/ruby/thread_native.h
tcpsocket.o: $(hdrdir)/ruby/util.h
+tcpsocket.o: $(hdrdir)/ruby/version.h
tcpsocket.o: $(top_srcdir)/ccan/check_type/check_type.h
tcpsocket.o: $(top_srcdir)/ccan/container_of/container_of.h
tcpsocket.o: $(top_srcdir)/ccan/list/list.h
@@ -2487,6 +2522,7 @@ tcpsocket.o: $(top_srcdir)/internal/error.h
tcpsocket.o: $(top_srcdir)/internal/gc.h
tcpsocket.o: $(top_srcdir)/internal/imemo.h
tcpsocket.o: $(top_srcdir)/internal/io.h
+tcpsocket.o: $(top_srcdir)/internal/sanitizers.h
tcpsocket.o: $(top_srcdir)/internal/serial.h
tcpsocket.o: $(top_srcdir)/internal/static_assert.h
tcpsocket.o: $(top_srcdir)/internal/string.h
@@ -2667,6 +2703,7 @@ udpsocket.o: $(hdrdir)/ruby/internal/special_consts.h
udpsocket.o: $(hdrdir)/ruby/internal/static_assert.h
udpsocket.o: $(hdrdir)/ruby/internal/stdalign.h
udpsocket.o: $(hdrdir)/ruby/internal/stdbool.h
+udpsocket.o: $(hdrdir)/ruby/internal/stdckdint.h
udpsocket.o: $(hdrdir)/ruby/internal/symbol.h
udpsocket.o: $(hdrdir)/ruby/internal/value.h
udpsocket.o: $(hdrdir)/ruby/internal/value_type.h
@@ -2683,6 +2720,7 @@ udpsocket.o: $(hdrdir)/ruby/subst.h
udpsocket.o: $(hdrdir)/ruby/thread.h
udpsocket.o: $(hdrdir)/ruby/thread_native.h
udpsocket.o: $(hdrdir)/ruby/util.h
+udpsocket.o: $(hdrdir)/ruby/version.h
udpsocket.o: $(top_srcdir)/ccan/check_type/check_type.h
udpsocket.o: $(top_srcdir)/ccan/container_of/container_of.h
udpsocket.o: $(top_srcdir)/ccan/list/list.h
@@ -2695,6 +2733,7 @@ udpsocket.o: $(top_srcdir)/internal/error.h
udpsocket.o: $(top_srcdir)/internal/gc.h
udpsocket.o: $(top_srcdir)/internal/imemo.h
udpsocket.o: $(top_srcdir)/internal/io.h
+udpsocket.o: $(top_srcdir)/internal/sanitizers.h
udpsocket.o: $(top_srcdir)/internal/serial.h
udpsocket.o: $(top_srcdir)/internal/static_assert.h
udpsocket.o: $(top_srcdir)/internal/string.h
@@ -2875,6 +2914,7 @@ unixserver.o: $(hdrdir)/ruby/internal/special_consts.h
unixserver.o: $(hdrdir)/ruby/internal/static_assert.h
unixserver.o: $(hdrdir)/ruby/internal/stdalign.h
unixserver.o: $(hdrdir)/ruby/internal/stdbool.h
+unixserver.o: $(hdrdir)/ruby/internal/stdckdint.h
unixserver.o: $(hdrdir)/ruby/internal/symbol.h
unixserver.o: $(hdrdir)/ruby/internal/value.h
unixserver.o: $(hdrdir)/ruby/internal/value_type.h
@@ -2891,6 +2931,7 @@ unixserver.o: $(hdrdir)/ruby/subst.h
unixserver.o: $(hdrdir)/ruby/thread.h
unixserver.o: $(hdrdir)/ruby/thread_native.h
unixserver.o: $(hdrdir)/ruby/util.h
+unixserver.o: $(hdrdir)/ruby/version.h
unixserver.o: $(top_srcdir)/ccan/check_type/check_type.h
unixserver.o: $(top_srcdir)/ccan/container_of/container_of.h
unixserver.o: $(top_srcdir)/ccan/list/list.h
@@ -2903,6 +2944,7 @@ unixserver.o: $(top_srcdir)/internal/error.h
unixserver.o: $(top_srcdir)/internal/gc.h
unixserver.o: $(top_srcdir)/internal/imemo.h
unixserver.o: $(top_srcdir)/internal/io.h
+unixserver.o: $(top_srcdir)/internal/sanitizers.h
unixserver.o: $(top_srcdir)/internal/serial.h
unixserver.o: $(top_srcdir)/internal/static_assert.h
unixserver.o: $(top_srcdir)/internal/string.h
@@ -3083,6 +3125,7 @@ unixsocket.o: $(hdrdir)/ruby/internal/special_consts.h
unixsocket.o: $(hdrdir)/ruby/internal/static_assert.h
unixsocket.o: $(hdrdir)/ruby/internal/stdalign.h
unixsocket.o: $(hdrdir)/ruby/internal/stdbool.h
+unixsocket.o: $(hdrdir)/ruby/internal/stdckdint.h
unixsocket.o: $(hdrdir)/ruby/internal/symbol.h
unixsocket.o: $(hdrdir)/ruby/internal/value.h
unixsocket.o: $(hdrdir)/ruby/internal/value_type.h
@@ -3099,6 +3142,7 @@ unixsocket.o: $(hdrdir)/ruby/subst.h
unixsocket.o: $(hdrdir)/ruby/thread.h
unixsocket.o: $(hdrdir)/ruby/thread_native.h
unixsocket.o: $(hdrdir)/ruby/util.h
+unixsocket.o: $(hdrdir)/ruby/version.h
unixsocket.o: $(top_srcdir)/ccan/check_type/check_type.h
unixsocket.o: $(top_srcdir)/ccan/container_of/container_of.h
unixsocket.o: $(top_srcdir)/ccan/list/list.h
@@ -3111,6 +3155,7 @@ unixsocket.o: $(top_srcdir)/internal/error.h
unixsocket.o: $(top_srcdir)/internal/gc.h
unixsocket.o: $(top_srcdir)/internal/imemo.h
unixsocket.o: $(top_srcdir)/internal/io.h
+unixsocket.o: $(top_srcdir)/internal/sanitizers.h
unixsocket.o: $(top_srcdir)/internal/serial.h
unixsocket.o: $(top_srcdir)/internal/static_assert.h
unixsocket.o: $(top_srcdir)/internal/string.h
diff --git a/ext/socket/extconf.rb b/ext/socket/extconf.rb
index 1ca52da366..d44ce31b0a 100644
--- a/ext/socket/extconf.rb
+++ b/ext/socket/extconf.rb
@@ -704,8 +704,6 @@ SRC
have_func("pthread_create")
have_func("pthread_detach")
- have_func("pthread_attr_setaffinity_np")
- have_func("sched_getcpu")
$VPATH << '$(topdir)' << '$(top_srcdir)'
create_makefile("socket")
diff --git a/ext/socket/init.c b/ext/socket/init.c
index e9dc6f8483..0e312b540e 100644
--- a/ext/socket/init.c
+++ b/ext/socket/init.c
@@ -27,6 +27,7 @@ VALUE rb_cSocket;
VALUE rb_cAddrinfo;
VALUE rb_eSocket;
+VALUE rb_eResolution;
#ifdef SOCKS
VALUE rb_cSOCKSSocket;
@@ -34,9 +35,10 @@ VALUE rb_cSOCKSSocket;
int rsock_do_not_reverse_lookup = 1;
static VALUE sym_wait_readable;
+static ID id_error_code;
void
-rsock_raise_socket_error(const char *reason, int error)
+rsock_raise_resolution_error(const char *reason, int error)
{
#ifdef EAI_SYSTEM
int e;
@@ -48,10 +50,14 @@ rsock_raise_socket_error(const char *reason, int error)
VALUE msg = rb_sprintf("%s: ", reason);
if (!enc) enc = rb_default_internal_encoding();
rb_str_concat(msg, rb_w32_conv_from_wchar(gai_strerrorW(error), enc));
- rb_exc_raise(rb_exc_new_str(rb_eSocket, msg));
#else
- rb_raise(rb_eSocket, "%s: %s", reason, gai_strerror(error));
+ VALUE msg = rb_sprintf("%s: %s", reason, gai_strerror(error));
#endif
+
+ StringValue(msg);
+ VALUE self = rb_class_new_instance(1, &msg, rb_eResolution);
+ rb_ivar_set(self, id_error_code, INT2NUM(error));
+ rb_exc_raise(self);
}
#if defined __APPLE__
@@ -198,7 +204,8 @@ rsock_s_recvfrom(VALUE socket, int argc, VALUE *argv, enum sock_recv_type from)
rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_READABLE), Qnil);
#endif
- slen = (long)rb_str_locktmp_ensure(str, recvfrom_locktmp, (VALUE)&arg);
+ rb_str_locktmp(str);
+ slen = (long)rb_ensure(recvfrom_locktmp, (VALUE)&arg, rb_str_unlocktmp, str);
if (slen == 0 && !rsock_is_dgram(fptr)) {
return Qnil;
@@ -412,7 +419,7 @@ rsock_write_nonblock(VALUE sock, VALUE str, VALUE ex)
if (e == EWOULDBLOCK || e == EAGAIN) {
if (ex == Qfalse) return sym_wait_writable;
rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e,
- "write would block");
+ "write would block");
}
rb_syserr_fail_path(e, fptr->pathv);
}
@@ -453,9 +460,9 @@ rsock_socket(int domain, int type, int proto)
fd = rsock_socket0(domain, type, proto);
if (fd < 0) {
- if (rb_gc_for_fd(errno)) {
- fd = rsock_socket0(domain, type, proto);
- }
+ if (rb_gc_for_fd(errno)) {
+ fd = rsock_socket0(domain, type, proto);
+ }
}
if (0 <= fd)
rb_update_max_fd(fd);
@@ -512,10 +519,10 @@ wait_connectable(int fd, struct timeval *timeout)
switch (sockerr) {
case 0:
- /*
- * be defensive in case some platforms set SO_ERROR on the original,
- * interrupted connect()
- */
+ /*
+ * be defensive in case some platforms set SO_ERROR on the original,
+ * interrupted connect()
+ */
/* when the connection timed out, no errno is set and revents is 0. */
if (timeout && revents == 0) {
@@ -701,9 +708,9 @@ rsock_s_accept(VALUE klass, VALUE io, struct sockaddr *sockaddr, socklen_t *len)
RB_IO_POINTER(io, fptr);
struct accept_arg accept_arg = {
- .fd = fptr->fd,
- .sockaddr = sockaddr,
- .len = len
+ .fd = fptr->fd,
+ .sockaddr = sockaddr,
+ .len = len
};
int retry = 0, peer;
@@ -750,10 +757,10 @@ rsock_getfamily(rb_io_t *fptr)
if (cached) {
switch (cached) {
#ifdef AF_UNIX
- case FMODE_UNIX: return AF_UNIX;
+ case FMODE_UNIX: return AF_UNIX;
#endif
- case FMODE_INET: return AF_INET;
- case FMODE_INET6: return AF_INET6;
+ case FMODE_INET: return AF_INET;
+ case FMODE_INET6: return AF_INET6;
}
}
@@ -772,6 +779,18 @@ rsock_getfamily(rb_io_t *fptr)
return ss.addr.sa_family;
}
+/*
+ * call-seq:
+ * error_code -> integer
+ *
+ * Returns the raw error code occurred at name resolution.
+ */
+static VALUE
+sock_resolv_error_code(VALUE self)
+{
+ return rb_attr_get(self, id_error_code);
+}
+
void
rsock_init_socket_init(void)
{
@@ -779,6 +798,11 @@ rsock_init_socket_init(void)
* SocketError is the error class for socket.
*/
rb_eSocket = rb_define_class("SocketError", rb_eStandardError);
+ /*
+ * ResolutionError is the error class for socket name resolution.
+ */
+ rb_eResolution = rb_define_class_under(rb_cSocket, "ResolutionError", rb_eSocket);
+ rb_define_method(rb_eResolution, "error_code", sock_resolv_error_code, 0);
rsock_init_ipsocket();
rsock_init_tcpsocket();
rsock_init_tcpserver();
@@ -792,6 +816,8 @@ rsock_init_socket_init(void)
rsock_init_sockifaddr();
rsock_init_socket_constants();
+ id_error_code = rb_intern_const("error_code");
+
#undef rb_intern
sym_wait_readable = ID2SYM(rb_intern("wait_readable"));
diff --git a/ext/socket/lib/socket.rb b/ext/socket/lib/socket.rb
index eecdc7d4b8..e953077fe6 100644
--- a/ext/socket/lib/socket.rb
+++ b/ext/socket/lib/socket.rb
@@ -333,9 +333,10 @@ class BasicSocket < IO
# _flags_ is zero or more of the +MSG_+ options.
# The result, _mesg_, is the data received.
#
- # When recvfrom(2) returns 0, Socket#recv_nonblock returns
- # an empty string as data.
- # The meaning depends on the socket: EOF on TCP, empty packet on UDP, etc.
+ # When recvfrom(2) returns 0, Socket#recv_nonblock returns nil.
+ # In most cases it means the connection was closed, but for UDP connections
+ # it may mean an empty packet was received, as the underlying API makes
+ # it impossible to distinguish these two cases.
#
# === Parameters
# * +maxlen+ - the number of bytes to receive from the socket
@@ -480,9 +481,10 @@ class Socket < BasicSocket
# The second element, _sender_addrinfo_, contains protocol-specific address
# information of the sender.
#
- # When recvfrom(2) returns 0, Socket#recvfrom_nonblock returns
- # an empty string as data.
- # The meaning depends on the socket: EOF on TCP, empty packet on UDP, etc.
+ # When recvfrom(2) returns 0, Socket#recv_nonblock returns nil.
+ # In most cases it means the connection was closed, but for UDP connections
+ # it may mean an empty packet was received, as the underlying API makes
+ # it impossible to distinguish these two cases.
#
# === Parameters
# * +maxlen+ - the maximum number of bytes to receive from the socket
@@ -597,6 +599,30 @@ class Socket < BasicSocket
__accept_nonblock(exception)
end
+ RESOLUTION_DELAY = 0.05
+ private_constant :RESOLUTION_DELAY
+
+ CONNECTION_ATTEMPT_DELAY = 0.25
+ private_constant :CONNECTION_ATTEMPT_DELAY
+
+ ADDRESS_FAMILIES = {
+ ipv6: Socket::AF_INET6,
+ ipv4: Socket::AF_INET
+ }.freeze
+ private_constant :ADDRESS_FAMILIES
+
+ HOSTNAME_RESOLUTION_QUEUE_UPDATED = 0
+ private_constant :HOSTNAME_RESOLUTION_QUEUE_UPDATED
+
+ IPV6_ADRESS_FORMAT = /(?i)(?:(?:[0-9A-F]{1,4}:){7}(?:[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){6}(?:[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,5}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){5}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,4}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){4}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,3}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){3}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,2}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){2}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:)[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){1}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|::(?:[0-9A-F]{1,4}:){1,5}[0-9A-F]{1,4}|:)|::(?:[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,6}[0-9A-F]{1,4}|:))(?:%.+)?/
+ private_constant :IPV6_ADRESS_FORMAT
+
+ @tcp_fast_fallback = true
+
+ class << self
+ attr_accessor :tcp_fast_fallback
+ end
+
# :call-seq:
# Socket.tcp(host, port, local_host=nil, local_port=nil, [opts]) {|socket| ... }
# Socket.tcp(host, port, local_host=nil, local_port=nil, [opts])
@@ -622,8 +648,491 @@ class Socket < BasicSocket
# sock.close_write
# puts sock.read
# }
- #
- def self.tcp(host, port, local_host = nil, local_port = nil, connect_timeout: nil, resolv_timeout: nil) # :yield: socket
+ def self.tcp(host, port, local_host = nil, local_port = nil, connect_timeout: nil, resolv_timeout: nil, fast_fallback: tcp_fast_fallback, &block) # :yield: socket
+ unless fast_fallback
+ return tcp_without_fast_fallback(host, port, local_host, local_port, connect_timeout:, resolv_timeout:, &block)
+ end
+
+ # Happy Eyeballs' states
+ # - :start
+ # - :v6c
+ # - :v4w
+ # - :v4c
+ # - :v46c
+ # - :v46w
+ # - :success
+ # - :failure
+ # - :timeout
+
+ specified_family_name = nil
+ hostname_resolution_threads = []
+ hostname_resolution_queue = nil
+ hostname_resolution_waiting = nil
+ hostname_resolution_expires_at = nil
+ selectable_addrinfos = SelectableAddrinfos.new
+ connecting_sockets = ConnectingSockets.new
+ local_addrinfos = []
+ connection_attempt_delay_expires_at = nil
+ connection_attempt_started_at = nil
+ state = :start
+ connected_socket = nil
+ last_error = nil
+ is_windows_environment ||= (RUBY_PLATFORM =~ /mswin|mingw|cygwin/)
+
+ ret = loop do
+ case state
+ when :start
+ specified_family_name, next_state = host && specified_family_name_and_next_state(host)
+
+ if local_host && local_port
+ specified_family_name, next_state = specified_family_name_and_next_state(local_host) unless specified_family_name
+ local_addrinfos = Addrinfo.getaddrinfo(local_host, local_port, ADDRESS_FAMILIES[specified_family_name], :STREAM, timeout: resolv_timeout)
+ end
+
+ if specified_family_name
+ addrinfos = Addrinfo.getaddrinfo(host, port, ADDRESS_FAMILIES[specified_family_name], :STREAM, timeout: resolv_timeout)
+ selectable_addrinfos.add(specified_family_name, addrinfos)
+ hostname_resolution_queue = NoHostnameResolutionQueue.new
+ state = next_state
+ next
+ end
+
+ resolving_family_names = ADDRESS_FAMILIES.keys
+ hostname_resolution_queue = HostnameResolutionQueue.new(resolving_family_names.size)
+ hostname_resolution_waiting = hostname_resolution_queue.waiting_pipe
+ hostname_resolution_started_at = current_clocktime if resolv_timeout
+ hostname_resolution_args = [host, port, hostname_resolution_queue]
+
+ hostname_resolution_threads.concat(
+ resolving_family_names.map { |family|
+ thread_args = [family, *hostname_resolution_args]
+ thread = Thread.new(*thread_args) { |*thread_args| hostname_resolution(*thread_args) }
+ Thread.pass
+ thread
+ }
+ )
+
+ hostname_resolution_retry_count = resolving_family_names.size - 1
+ hostname_resolution_expires_at = hostname_resolution_started_at + resolv_timeout if resolv_timeout
+
+ while hostname_resolution_retry_count >= 0
+ remaining = resolv_timeout ? second_to_timeout(hostname_resolution_started_at + resolv_timeout) : nil
+ hostname_resolved, _, = IO.select(hostname_resolution_waiting, nil, nil, remaining)
+
+ unless hostname_resolved
+ state = :timeout
+ break
+ end
+
+ family_name, res = hostname_resolution_queue.get
+
+ if res.is_a? Exception
+ unless (Socket.const_defined?(:EAI_ADDRFAMILY)) &&
+ (res.is_a?(Socket::ResolutionError)) &&
+ (res.error_code == Socket::EAI_ADDRFAMILY)
+ last_error = res
+ end
+
+ if hostname_resolution_retry_count.zero?
+ state = :failure
+ break
+ end
+ hostname_resolution_retry_count -= 1
+ else
+ state = case family_name
+ when :ipv6 then :v6c
+ when :ipv4 then hostname_resolution_queue.closed? ? :v4c : :v4w
+ end
+ selectable_addrinfos.add(family_name, res)
+ last_error = nil
+ break
+ end
+ end
+
+ next
+ when :v4w
+ ipv6_resolved, _, = IO.select(hostname_resolution_waiting, nil, nil, RESOLUTION_DELAY)
+
+ if ipv6_resolved
+ family_name, res = hostname_resolution_queue.get
+ selectable_addrinfos.add(family_name, res) unless res.is_a? Exception
+ state = :v46c
+ else
+ state = :v4c
+ end
+
+ next
+ when :v4c, :v6c, :v46c
+ connection_attempt_started_at = current_clocktime unless connection_attempt_started_at
+ addrinfo = selectable_addrinfos.get
+
+ if local_addrinfos.any?
+ local_addrinfo = local_addrinfos.find { |lai| lai.afamily == addrinfo.afamily }
+
+ if local_addrinfo.nil?
+ if selectable_addrinfos.empty? && connecting_sockets.empty? && hostname_resolution_queue.closed?
+ last_error = SocketError.new 'no appropriate local address'
+ state = :failure
+ elsif selectable_addrinfos.any?
+ # Try other Addrinfo in next loop
+ else
+ if resolv_timeout && hostname_resolution_queue.opened? &&
+ (current_clocktime >= hostname_resolution_expires_at)
+ state = :timeout
+ else
+ # Wait for connection to be established or hostname resolution in next loop
+ connection_attempt_delay_expires_at = nil
+ state = :v46w
+ end
+ end
+ next
+ end
+ end
+
+ connection_attempt_delay_expires_at = current_clocktime + CONNECTION_ATTEMPT_DELAY
+
+ begin
+ result = if specified_family_name && selectable_addrinfos.empty? &&
+ connecting_sockets.empty? && hostname_resolution_queue.closed?
+ local_addrinfo ?
+ addrinfo.connect_from(local_addrinfo, timeout: connect_timeout) :
+ addrinfo.connect(timeout: connect_timeout)
+ else
+ socket = Socket.new(addrinfo.pfamily, addrinfo.socktype, addrinfo.protocol)
+ socket.bind(local_addrinfo) if local_addrinfo
+ socket.connect_nonblock(addrinfo, exception: false)
+ end
+
+ case result
+ when 0
+ connected_socket = socket
+ state = :success
+ when Socket
+ connected_socket = result
+ state = :success
+ when :wait_writable
+ connecting_sockets.add(socket, addrinfo)
+ state = :v46w
+ end
+ rescue SystemCallError => e
+ last_error = e
+ socket.close if socket && !socket.closed?
+
+ if selectable_addrinfos.empty? && connecting_sockets.empty? && hostname_resolution_queue.closed?
+ state = :failure
+ elsif selectable_addrinfos.any?
+ # Try other Addrinfo in next loop
+ else
+ if resolv_timeout && hostname_resolution_queue.opened? &&
+ (current_clocktime >= hostname_resolution_expires_at)
+ state = :timeout
+ else
+ # Wait for connection to be established or hostname resolution in next loop
+ connection_attempt_delay_expires_at = nil
+ state = :v46w
+ end
+ end
+ end
+
+ next
+ when :v46w
+ if connect_timeout && second_to_timeout(connection_attempt_started_at + connect_timeout).zero?
+ state = :timeout
+ next
+ end
+
+ remaining = second_to_timeout(connection_attempt_delay_expires_at)
+ hostname_resolution_waiting = hostname_resolution_waiting && hostname_resolution_queue.closed? ? nil : hostname_resolution_waiting
+ hostname_resolved, connectable_sockets, = IO.select(hostname_resolution_waiting, connecting_sockets.all, nil, remaining)
+
+ if connectable_sockets&.any?
+ while (connectable_socket = connectable_sockets.pop)
+ is_connected =
+ if is_windows_environment
+ sockopt = connectable_socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_CONNECT_TIME)
+ sockopt.unpack('i').first >= 0
+ else
+ sockopt = connectable_socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_ERROR)
+ sockopt.int.zero?
+ end
+
+ if is_connected
+ connected_socket = connectable_socket
+ connecting_sockets.delete connectable_socket
+ connectable_sockets.each do |other_connectable_socket|
+ other_connectable_socket.close unless other_connectable_socket.closed?
+ end
+ state = :success
+ break
+ else
+ failed_ai = connecting_sockets.delete connectable_socket
+ inspected_ip_address = failed_ai.ipv6? ? "[#{failed_ai.ip_address}]" : failed_ai.ip_address
+ last_error = SystemCallError.new("connect(2) for #{inspected_ip_address}:#{failed_ai.ip_port}", sockopt.int)
+ connectable_socket.close unless connectable_socket.closed?
+
+ next if connectable_sockets.any?
+
+ if selectable_addrinfos.empty? && connecting_sockets.empty? && hostname_resolution_queue.closed?
+ state = :failure
+ elsif selectable_addrinfos.any?
+ # Wait for connection attempt delay timeout in next loop
+ else
+ if resolv_timeout && hostname_resolution_queue.opened? &&
+ (current_clocktime >= hostname_resolution_expires_at)
+ state = :timeout
+ else
+ # Wait for connection to be established or hostname resolution in next loop
+ connection_attempt_delay_expires_at = nil
+ end
+ end
+ end
+ end
+ elsif hostname_resolved&.any?
+ family_name, res = hostname_resolution_queue.get
+ selectable_addrinfos.add(family_name, res) unless res.is_a? Exception
+ else
+ if selectable_addrinfos.empty? && connecting_sockets.empty? && hostname_resolution_queue.closed?
+ state = :failure
+ elsif selectable_addrinfos.any?
+ # Try other Addrinfo in next loop
+ state = :v46c
+ else
+ if resolv_timeout && hostname_resolution_queue.opened? &&
+ (current_clocktime >= hostname_resolution_expires_at)
+ state = :timeout
+ else
+ # Wait for connection to be established or hostname resolution in next loop
+ connection_attempt_delay_expires_at = nil
+ end
+ end
+ end
+
+ next
+ when :success
+ break connected_socket
+ when :failure
+ raise last_error
+ when :timeout
+ raise Errno::ETIMEDOUT, 'user specified timeout'
+ end
+ end
+
+ if block_given?
+ begin
+ yield ret
+ ensure
+ ret.close
+ end
+ else
+ ret
+ end
+ ensure
+ if fast_fallback
+ hostname_resolution_threads.each do |thread|
+ thread&.exit
+ end
+
+ hostname_resolution_queue&.close_all
+
+ connecting_sockets.each do |connecting_socket|
+ connecting_socket.close unless connecting_socket.closed?
+ end
+ end
+ end
+
+ def self.specified_family_name_and_next_state(hostname)
+ if hostname.match?(IPV6_ADRESS_FORMAT) then [:ipv6, :v6c]
+ elsif hostname.match?(/^([0-9]{1,3}\.){3}[0-9]{1,3}$/) then [:ipv4, :v4c]
+ end
+ end
+ private_class_method :specified_family_name_and_next_state
+
+ def self.hostname_resolution(family, host, port, hostname_resolution_queue)
+ begin
+ resolved_addrinfos = Addrinfo.getaddrinfo(host, port, ADDRESS_FAMILIES[family], :STREAM)
+ hostname_resolution_queue.add_resolved(family, resolved_addrinfos)
+ rescue => e
+ hostname_resolution_queue.add_error(family, e)
+ end
+ end
+ private_class_method :hostname_resolution
+
+ def self.second_to_timeout(ends_at)
+ return 0 unless ends_at
+
+ remaining = (ends_at - current_clocktime)
+ remaining.negative? ? 0 : remaining
+ end
+ private_class_method :second_to_timeout
+
+ def self.current_clocktime
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ end
+ private_class_method :current_clocktime
+
+ class SelectableAddrinfos
+ PRIORITY_ON_V6 = [:ipv6, :ipv4]
+ PRIORITY_ON_V4 = [:ipv4, :ipv6]
+
+ def initialize
+ @addrinfo_dict = {}
+ @last_family = nil
+ end
+
+ def add(family_name, addrinfos)
+ @addrinfo_dict[family_name] = addrinfos
+ end
+
+ def get
+ return nil if empty?
+
+ if @addrinfo_dict.size == 1
+ @addrinfo_dict.each { |_, addrinfos| return addrinfos.shift }
+ end
+
+ precedences = case @last_family
+ when :ipv4, nil then PRIORITY_ON_V6
+ when :ipv6 then PRIORITY_ON_V4
+ end
+
+ precedences.each do |family_name|
+ addrinfo = @addrinfo_dict[family_name]&.shift
+ next unless addrinfo
+
+ @last_family = family_name
+ return addrinfo
+ end
+ end
+
+ def empty?
+ @addrinfo_dict.all? { |_, addrinfos| addrinfos.empty? }
+ end
+
+ def any?
+ !empty?
+ end
+ end
+ private_constant :SelectableAddrinfos
+
+ class NoHostnameResolutionQueue
+ def waiting_pipe
+ nil
+ end
+
+ def add_resolved(_, _)
+ raise StandardError, "This #{self.class} cannot respond to:"
+ end
+
+ def add_error(_, _)
+ raise StandardError, "This #{self.class} cannot respond to:"
+ end
+
+ def get
+ nil
+ end
+
+ def opened?
+ false
+ end
+
+ def closed?
+ true
+ end
+
+ def close_all
+ # Do nothing
+ end
+ end
+ private_constant :NoHostnameResolutionQueue
+
+ class HostnameResolutionQueue
+ def initialize(size)
+ @size = size
+ @taken_count = 0
+ @rpipe, @wpipe = IO.pipe
+ @queue = Queue.new
+ @mutex = Mutex.new
+ end
+
+ def waiting_pipe
+ [@rpipe]
+ end
+
+ def add_resolved(family, resolved_addrinfos)
+ @mutex.synchronize do
+ @queue.push [family, resolved_addrinfos]
+ @wpipe.putc HOSTNAME_RESOLUTION_QUEUE_UPDATED
+ end
+ end
+
+ def add_error(family, error)
+ @mutex.synchronize do
+ @queue.push [family, error]
+ @wpipe.putc HOSTNAME_RESOLUTION_QUEUE_UPDATED
+ end
+ end
+
+ def get
+ return nil if @queue.empty?
+
+ res = nil
+
+ @mutex.synchronize do
+ @rpipe.getbyte
+ res = @queue.pop
+ end
+
+ @taken_count += 1
+ close_all if @taken_count == @size
+ res
+ end
+
+ def closed?
+ @rpipe.closed?
+ end
+
+ def opened?
+ !closed?
+ end
+
+ def close_all
+ @queue.close unless @queue.closed?
+ @rpipe.close unless @rpipe.closed?
+ @wpipe.close unless @wpipe.closed?
+ end
+ end
+ private_constant :HostnameResolutionQueue
+
+ class ConnectingSockets
+ def initialize
+ @socket_dict = {}
+ end
+
+ def all
+ @socket_dict.keys
+ end
+
+ def add(socket, addrinfo)
+ @socket_dict[socket] = addrinfo
+ end
+
+ def delete(socket)
+ @socket_dict.delete socket
+ end
+
+ def empty?
+ @socket_dict.empty?
+ end
+
+ def each
+ @socket_dict.keys.each do |socket|
+ yield socket
+ end
+ end
+ end
+ private_constant :ConnectingSockets
+
+ def self.tcp_without_fast_fallback(host, port, local_host, local_port, connect_timeout:, resolv_timeout:, &block)
last_error = nil
ret = nil
@@ -667,6 +1176,7 @@ class Socket < BasicSocket
ret
end
end
+ private_class_method :tcp_without_fast_fallback
# :stopdoc:
def self.ip_sockets_port0(ai_list, reuseaddr)
@@ -1229,9 +1739,10 @@ class UDPSocket < IPSocket
# The first element of the results, _mesg_, is the data received.
# The second element, _sender_inet_addr_, is an array to represent the sender address.
#
- # When recvfrom(2) returns 0,
- # Socket#recvfrom_nonblock returns an empty string as data.
- # It means an empty packet.
+ # When recvfrom(2) returns 0, Socket#recv_nonblock returns nil.
+ # In most cases it means the connection was closed, but it may also mean
+ # an empty packet was received, as the underlying API makes
+ # it impossible to distinguish these two cases.
#
# === Parameters
# * +maxlen+ - the number of bytes to receive from the socket
diff --git a/ext/socket/mkconstants.rb b/ext/socket/mkconstants.rb
index 5e6c0668f6..4271e40cd8 100644
--- a/ext/socket/mkconstants.rb
+++ b/ext/socket/mkconstants.rb
@@ -51,7 +51,10 @@ DATA.each_line {|s|
next
end
h[name] = default_value
- COMMENTS[name] = comment
+ if comment
+ # Stop unintentional references
+ COMMENTS[name] = comment.gsub(/\b(Data|Kernel|Process|Set|Socket|Time)\b/, '\\\\\\&')
+ end
}
DEFS = h.to_a
@@ -73,15 +76,11 @@ def each_name(pat)
}
end
-erb_new = lambda do |src, safe, trim|
- if ERB.instance_method(:initialize).parameters.assoc(:key) # Ruby 2.6+
- ERB.new(src, trim_mode: trim)
- else
- ERB.new(src, safe, trim)
- end
+erb_new = lambda do |src, trim|
+ ERB.new(src, trim_mode: trim)
end
-erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_const_decls")
+erb_new.call(<<'EOS', '%').def_method(Object, "gen_const_decls")
% each_const {|guard, name, default_value|
#if !defined(<%=name%>)
# if defined(HAVE_CONST_<%=name.upcase%>)
@@ -95,7 +94,7 @@ erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_const_decls")
% }
EOS
-erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_const_defs_in_guard(name, default_value)")
+erb_new.call(<<'EOS', '%').def_method(Object, "gen_const_defs_in_guard(name, default_value)")
#if defined(<%=name%>)
/* <%= COMMENTS[name] %> */
rb_define_const(rb_cSocket, <%=c_str name%>, INTEGER2NUM(<%=name%>));
@@ -104,7 +103,7 @@ erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_const_defs_in_guard(name
#endif
EOS
-erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_const_defs")
+erb_new.call(<<'EOS', '%').def_method(Object, "gen_const_defs")
% each_const {|guard, name, default_value|
% if guard
#if <%=guard%>
@@ -154,7 +153,7 @@ def each_names_with_len(pat, prefix_optional=nil)
}
end
-erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_name_to_int_decl(funcname, pat, prefix_optional, guard=nil)")
+erb_new.call(<<'EOS', '%').def_method(Object, "gen_name_to_int_decl(funcname, pat, prefix_optional, guard=nil)")
%if guard
#ifdef <%=guard%>
int <%=funcname%>(const char *str, long len, int *valp);
@@ -164,7 +163,7 @@ int <%=funcname%>(const char *str, long len, int *valp);
%end
EOS
-erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_name_to_int_func_in_guard(funcname, pat, prefix_optional, guard=nil)")
+erb_new.call(<<'EOS', '%').def_method(Object, "gen_name_to_int_func_in_guard(funcname, pat, prefix_optional, guard=nil)")
int
<%=funcname%>(const char *str, long len, int *valp)
{
@@ -186,7 +185,7 @@ int
}
EOS
-erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_name_to_int_func(funcname, pat, prefix_optional, guard=nil)")
+erb_new.call(<<'EOS', '%').def_method(Object, "gen_name_to_int_func(funcname, pat, prefix_optional, guard=nil)")
%if guard
#ifdef <%=guard%>
<%=gen_name_to_int_func_in_guard(funcname, pat, prefix_optional, guard)%>
@@ -215,7 +214,7 @@ def reverse_each_name_with_prefix_optional(pat, prefix_pat)
end
end
-erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_int_to_name_hash(hash_var, pat, prefix_pat)")
+erb_new.call(<<'EOS', '%').def_method(Object, "gen_int_to_name_hash(hash_var, pat, prefix_pat)")
<%=hash_var%> = st_init_numtable();
% reverse_each_name_with_prefix_optional(pat, prefix_pat) {|n,s|
#ifdef <%=n%>
@@ -224,7 +223,7 @@ erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_int_to_name_hash(hash_va
% }
EOS
-erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_int_to_name_func(func_name, hash_var)")
+erb_new.call(<<'EOS', '%').def_method(Object, "gen_int_to_name_func(func_name, hash_var)")
ID
<%=func_name%>(int val)
{
@@ -235,7 +234,7 @@ ID
}
EOS
-erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_int_to_name_decl(func_name, hash_var)")
+erb_new.call(<<'EOS', '%').def_method(Object, "gen_int_to_name_decl(func_name, hash_var)")
ID <%=func_name%>(int val);
EOS
@@ -284,7 +283,7 @@ def_intern('rsock_intern_udp_optname', /\AUDP_/, "UDP_")
def_intern('rsock_intern_scm_optname', /\ASCM_/, "SCM_")
def_intern('rsock_intern_local_optname', /\ALOCAL_/, "LOCAL_")
-result = erb_new.call(<<'EOS', nil, '%').result(binding)
+result = erb_new.call(<<'EOS', '%').result(binding)
/* autogenerated file */
<%= INTERN_DEFS.map {|vardef, gen_hash, decl, func| vardef }.join("\n") %>
@@ -327,7 +326,7 @@ init_constants(void)
EOS
-header_result = erb_new.call(<<'EOS', nil, '%').result(binding)
+header_result = erb_new.call(<<'EOS', '%').result(binding)
/* autogenerated file */
<%= gen_const_decls %>
<%= NAME_TO_INT_DEFS.map {|decl, func| decl }.join("\n") %>
@@ -423,8 +422,8 @@ AF_ISDN nil Integrated Services Digital Network
PF_ISDN nil Integrated Services Digital Network
AF_NATM nil Native ATM access
PF_NATM nil Native ATM access
-AF_SYSTEM
-PF_SYSTEM
+AF_SYSTEM nil Kernel event messages
+PF_SYSTEM nil Kernel event messages
AF_NETBIOS nil NetBIOS
PF_NETBIOS nil NetBIOS
AF_PPP nil Point-to-Point Protocol
@@ -440,8 +439,8 @@ PF_PACKET nil Direct link-layer access
AF_E164 nil CCITT (ITU-T) E.164 recommendation
PF_XTP nil eXpress Transfer Protocol
-PF_RTIP
-PF_PIP
+PF_RTIP nil Help Identify RTIP packets
+PF_PIP nil Help Identify PIP packets
AF_KEY nil Key management protocol, originally developed for usage with IPsec
PF_KEY nil Key management protocol, originally developed for usage with IPsec
AF_NETLINK nil Kernel user interface device
@@ -666,6 +665,7 @@ SO_SETFIB nil Set the associated routing table for the socket (FreeBSD
SO_RTABLE nil Set the routing table for this socket (OpenBSD)
SO_INCOMING_CPU nil Receive the cpu attached to the socket (Linux 3.19)
SO_INCOMING_NAPI_ID nil Receive the napi ID attached to a RX queue (Linux 4.12)
+SO_CONNECT_TIME nil Returns the number of seconds a socket has been connected. This option is only valid for connection-oriented protocols (Windows)
SOPRI_INTERACTIVE nil Interactive socket priority
SOPRI_NORMAL nil Normal socket priority
@@ -745,6 +745,7 @@ SHUT_RDWR 2 Shut down the both sides of the socket
IPV6_JOIN_GROUP nil Join a group membership
IPV6_LEAVE_GROUP nil Leave a group membership
+IPV6_MTU_DISCOVER nil Path MTU discovery
IPV6_MULTICAST_HOPS nil IP6 multicast hops
IPV6_MULTICAST_IF nil IP6 multicast interface
IPV6_MULTICAST_LOOP nil IP6 multicast loopback
@@ -759,6 +760,7 @@ IPV6_NEXTHOP nil Next hop address
IPV6_PATHMTU nil Retrieve current path MTU
IPV6_PKTINFO nil Receive packet information with datagram
IPV6_RECVDSTOPTS nil Receive all IP6 options for response
+IPV6_RECVERR nil Enable extended reliable error message passing
IPV6_RECVHOPLIMIT nil Receive hop limit with datagram
IPV6_RECVHOPOPTS nil Receive hop-by-hop options
IPV6_RECVPKTINFO nil Receive destination IP address and incoming interface
diff --git a/ext/socket/raddrinfo.c b/ext/socket/raddrinfo.c
index 18585c2181..090ba1a0c0 100644
--- a/ext/socket/raddrinfo.c
+++ b/ext/socket/raddrinfo.c
@@ -345,7 +345,7 @@ struct getaddrinfo_arg
char *node, *service;
struct addrinfo hints;
struct addrinfo *ai;
- int err, refcount, done, cancelled;
+ int err, gai_errno, refcount, done, cancelled;
rb_nativethread_lock_t lock;
rb_nativethread_cond_t cond;
};
@@ -406,8 +406,9 @@ do_getaddrinfo(void *ptr)
{
struct getaddrinfo_arg *arg = (struct getaddrinfo_arg *)ptr;
- int err;
+ int err, gai_errno;
err = getaddrinfo(arg->node, arg->service, &arg->hints, &arg->ai);
+ gai_errno = errno;
#ifdef __linux__
/* On Linux (mainly Ubuntu 13.04) /etc/nsswitch.conf has mdns4 and
* it cause getaddrinfo to return EAI_SYSTEM/ENOENT. [ruby-list:49420]
@@ -420,6 +421,7 @@ do_getaddrinfo(void *ptr)
rb_nativethread_lock_lock(&arg->lock);
{
arg->err = err;
+ arg->gai_errno = gai_errno;
if (arg->cancelled) {
freeaddrinfo(arg->ai);
}
@@ -461,11 +463,25 @@ cancel_getaddrinfo(void *ptr)
}
static int
+do_pthread_create(pthread_t *th, void *(*start_routine) (void *), void *arg)
+{
+ int limit = 3, ret;
+ do {
+ // It is said that pthread_create may fail spuriously, so we follow the JDK and retry several times.
+ //
+ // https://bugs.openjdk.org/browse/JDK-8268605
+ // https://github.com/openjdk/jdk/commit/e35005d5ce383ddd108096a3079b17cb0bcf76f1
+ ret = pthread_create(th, 0, start_routine, arg);
+ } while (ret == EAGAIN && limit-- > 0);
+ return ret;
+}
+
+static int
rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hints, struct addrinfo **ai)
{
int retry;
struct getaddrinfo_arg *arg;
- int err;
+ int err = 0, gai_errno = 0;
start:
retry = 0;
@@ -475,25 +491,12 @@ start:
return EAI_MEMORY;
}
- pthread_attr_t attr;
- if (pthread_attr_init(&attr) != 0) {
- free_getaddrinfo_arg(arg);
- return EAI_AGAIN;
- }
-#if defined(HAVE_PTHREAD_ATTR_SETAFFINITY_NP) && defined(HAVE_SCHED_GETCPU)
- cpu_set_t tmp_cpu_set;
- CPU_ZERO(&tmp_cpu_set);
- int cpu = sched_getcpu();
- if (cpu < CPU_SETSIZE) {
- CPU_SET(cpu, &tmp_cpu_set);
- pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &tmp_cpu_set);
- }
-#endif
-
pthread_t th;
- if (pthread_create(&th, &attr, do_getaddrinfo, arg) != 0) {
+ if (do_pthread_create(&th, do_getaddrinfo, arg) != 0) {
+ int err = errno;
free_getaddrinfo_arg(arg);
- return EAI_AGAIN;
+ errno = err;
+ return EAI_SYSTEM;
}
pthread_detach(th);
@@ -504,6 +507,7 @@ start:
{
if (arg->done) {
err = arg->err;
+ gai_errno = arg->gai_errno;
if (err == 0) *ai = arg->ai;
}
else if (arg->cancelled) {
@@ -526,6 +530,10 @@ start:
rb_thread_check_ints();
if (retry) goto start;
+ /* Because errno is threadlocal, the errno value we got from the call to getaddrinfo() in the thread
+ * (in case of EAI_SYSTEM return value) is not propagated to the caller of _this_ function. Set errno
+ * explicitly, as round-tripped through struct getaddrinfo_arg, to deal with that */
+ if (gai_errno) errno = gai_errno;
return err;
}
@@ -592,7 +600,7 @@ struct getnameinfo_arg
size_t hostlen;
char *serv;
size_t servlen;
- int err, refcount, done, cancelled;
+ int err, gni_errno, refcount, done, cancelled;
rb_nativethread_lock_t lock;
rb_nativethread_cond_t cond;
};
@@ -645,12 +653,14 @@ do_getnameinfo(void *ptr)
{
struct getnameinfo_arg *arg = (struct getnameinfo_arg *)ptr;
- int err;
+ int err, gni_errno;
err = getnameinfo(arg->sa, arg->salen, arg->host, (socklen_t)arg->hostlen, arg->serv, (socklen_t)arg->servlen, arg->flags);
+ gni_errno = errno;
int need_free = 0;
rb_nativethread_lock_lock(&arg->lock);
arg->err = err;
+ arg->gni_errno = gni_errno;
if (!arg->cancelled) {
arg->done = 1;
rb_native_cond_signal(&arg->cond);
@@ -692,7 +702,7 @@ rb_getnameinfo(const struct sockaddr *sa, socklen_t salen,
{
int retry;
struct getnameinfo_arg *arg;
- int err;
+ int err, gni_errno = 0;
start:
retry = 0;
@@ -702,25 +712,12 @@ start:
return EAI_MEMORY;
}
- pthread_attr_t attr;
- if (pthread_attr_init(&attr) != 0) {
- free_getnameinfo_arg(arg);
- return EAI_AGAIN;
- }
-#if defined(HAVE_PTHREAD_ATTR_SETAFFINITY_NP) && defined(HAVE_SCHED_GETCPU)
- cpu_set_t tmp_cpu_set;
- CPU_ZERO(&tmp_cpu_set);
- int cpu = sched_getcpu();
- if (cpu < CPU_SETSIZE) {
- CPU_SET(cpu, &tmp_cpu_set);
- pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &tmp_cpu_set);
- }
-#endif
-
pthread_t th;
- if (pthread_create(&th, 0, do_getnameinfo, arg) != 0) {
+ if (do_pthread_create(&th, do_getnameinfo, arg) != 0) {
+ int err = errno;
free_getnameinfo_arg(arg);
- return EAI_AGAIN;
+ errno = err;
+ return EAI_SYSTEM;
}
pthread_detach(th);
@@ -730,6 +727,7 @@ start:
rb_nativethread_lock_lock(&arg->lock);
if (arg->done) {
err = arg->err;
+ gni_errno = arg->gni_errno;
if (err == 0) {
if (host) memcpy(host, arg->host, hostlen);
if (serv) memcpy(serv, arg->serv, servlen);
@@ -754,6 +752,9 @@ start:
rb_thread_check_ints();
if (retry) goto start;
+ /* Make sure we copy the thread-local errno value from the getnameinfo thread back to this thread, so
+ * calling code sees the correct errno */
+ if (gni_errno) errno = gni_errno;
return err;
}
@@ -766,7 +767,7 @@ make_ipaddr0(struct sockaddr *addr, socklen_t addrlen, char *buf, size_t buflen)
error = rb_getnameinfo(addr, addrlen, buf, buflen, NULL, 0, NI_NUMERICHOST);
if (error) {
- rsock_raise_socket_error("getnameinfo", error);
+ rsock_raise_resolution_error("getnameinfo", error);
}
}
@@ -975,7 +976,7 @@ rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_h
if (hostp && hostp[strlen(hostp)-1] == '\n') {
rb_raise(rb_eSocket, "newline at the end of hostname");
}
- rsock_raise_socket_error("getaddrinfo", error);
+ rsock_raise_resolution_error("getaddrinfo", error);
}
return res;
@@ -1034,7 +1035,7 @@ rsock_ipaddr(struct sockaddr *sockaddr, socklen_t sockaddrlen, int norevlookup)
error = rb_getnameinfo(sockaddr, sockaddrlen, hbuf, sizeof(hbuf),
pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV);
if (error) {
- rsock_raise_socket_error("getnameinfo", error);
+ rsock_raise_resolution_error("getnameinfo", error);
}
addr2 = rb_str_new2(hbuf);
if (addr1 == Qnil) {
@@ -1672,7 +1673,7 @@ rsock_inspect_sockaddr(struct sockaddr *sockaddr_arg, socklen_t socklen, VALUE r
hbuf, (socklen_t)sizeof(hbuf), NULL, 0,
NI_NUMERICHOST|NI_NUMERICSERV);
if (error) {
- rsock_raise_socket_error("getnameinfo", error);
+ rsock_raise_resolution_error("getnameinfo", error);
}
if (addr->sin6_port == 0) {
rb_str_cat2(ret, hbuf);
@@ -2040,7 +2041,7 @@ addrinfo_mdump(VALUE self)
hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf),
NI_NUMERICHOST|NI_NUMERICSERV);
if (error) {
- rsock_raise_socket_error("getnameinfo", error);
+ rsock_raise_resolution_error("getnameinfo", error);
}
sockaddr = rb_assoc_new(rb_str_new_cstr(hbuf), rb_str_new_cstr(pbuf));
break;
@@ -2386,7 +2387,7 @@ addrinfo_getnameinfo(int argc, VALUE *argv, VALUE self)
hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf),
flags);
if (error) {
- rsock_raise_socket_error("getnameinfo", error);
+ rsock_raise_resolution_error("getnameinfo", error);
}
return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf));
@@ -3016,12 +3017,12 @@ rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len)
void
rsock_init_addrinfo(void)
{
+ id_timeout = rb_intern("timeout");
+
/*
* The Addrinfo class maps <tt>struct addrinfo</tt> to ruby. This
* structure identifies an Internet host and a service.
*/
- id_timeout = rb_intern("timeout");
-
rb_cAddrinfo = rb_define_class("Addrinfo", rb_cObject);
rb_define_alloc_func(rb_cAddrinfo, addrinfo_s_allocate);
rb_define_method(rb_cAddrinfo, "initialize", addrinfo_initialize, -1);
diff --git a/ext/socket/rubysocket.h b/ext/socket/rubysocket.h
index 7c5739808d..f486db4262 100644
--- a/ext/socket/rubysocket.h
+++ b/ext/socket/rubysocket.h
@@ -35,6 +35,7 @@
#ifdef _WIN32
# include <winsock2.h>
# include <ws2tcpip.h>
+# include <mswsock.h>
# include <iphlpapi.h>
# if defined(_MSC_VER)
# undef HAVE_TYPE_STRUCT_SOCKADDR_DL
@@ -285,6 +286,7 @@ extern VALUE rb_cAddrinfo;
extern VALUE rb_cSockOpt;
extern VALUE rb_eSocket;
+extern VALUE rb_eResolution;
#ifdef SOCKS
extern VALUE rb_cSOCKSSocket;
@@ -307,7 +309,7 @@ VALUE rsock_sockaddr_string_value_with_addrinfo(volatile VALUE *v, VALUE *ai_ret
VALUE rb_check_sockaddr_string_type(VALUE);
-NORETURN(void rsock_raise_socket_error(const char *, int));
+NORETURN(void rsock_raise_resolution_error(const char *, int));
int rsock_family_arg(VALUE domain);
int rsock_socktype_arg(VALUE type);
diff --git a/ext/socket/socket.c b/ext/socket/socket.c
index 74cb0644e6..c780d77cf6 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -1313,7 +1313,7 @@ sock_s_getnameinfo(int argc, VALUE *argv, VALUE _)
saved_errno = errno;
if (res) rb_freeaddrinfo(res);
errno = saved_errno;
- rsock_raise_socket_error("getnameinfo", error);
+ rsock_raise_resolution_error("getnameinfo", error);
UNREACHABLE_RETURN(Qnil);
}
diff --git a/ext/stringio/.document b/ext/stringio/.document
new file mode 100644
index 0000000000..decba0135a
--- /dev/null
+++ b/ext/stringio/.document
@@ -0,0 +1 @@
+*.[ch]
diff --git a/ext/stringio/depend b/ext/stringio/depend
index ba2b812041..b9fba7e9fa 100644
--- a/ext/stringio/depend
+++ b/ext/stringio/depend
@@ -157,6 +157,7 @@ stringio.o: $(hdrdir)/ruby/internal/special_consts.h
stringio.o: $(hdrdir)/ruby/internal/static_assert.h
stringio.o: $(hdrdir)/ruby/internal/stdalign.h
stringio.o: $(hdrdir)/ruby/internal/stdbool.h
+stringio.o: $(hdrdir)/ruby/internal/stdckdint.h
stringio.o: $(hdrdir)/ruby/internal/symbol.h
stringio.o: $(hdrdir)/ruby/internal/value.h
stringio.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/stringio/extconf.rb b/ext/stringio/extconf.rb
index ad8650dce2..553732f79c 100644
--- a/ext/stringio/extconf.rb
+++ b/ext/stringio/extconf.rb
@@ -1,3 +1,7 @@
# frozen_string_literal: false
require 'mkmf'
-create_makefile('stringio')
+if RUBY_ENGINE == 'ruby'
+ create_makefile('stringio')
+else
+ File.write('Makefile', dummy_makefile("").join)
+end
diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c
index 7eade5bcba..c149811e05 100644
--- a/ext/stringio/stringio.c
+++ b/ext/stringio/stringio.c
@@ -13,7 +13,9 @@
**********************************************************************/
static const char *const
-STRINGIO_VERSION = "3.1.0";
+STRINGIO_VERSION = "3.1.1";
+
+#include <stdbool.h>
#include "ruby.h"
#include "ruby/io.h"
@@ -48,7 +50,13 @@ static long strio_write(VALUE self, VALUE str);
#define IS_STRIO(obj) (rb_typeddata_is_kind_of((obj), &strio_data_type))
#define error_inval(msg) (rb_syserr_fail(EINVAL, msg))
-#define get_enc(ptr) ((ptr)->enc ? (ptr)->enc : rb_enc_get((ptr)->string))
+#define get_enc(ptr) ((ptr)->enc ? (ptr)->enc : !NIL_P((ptr)->string) ? rb_enc_get((ptr)->string) : NULL)
+
+static bool
+readonly_string_p(VALUE string)
+{
+ return OBJ_FROZEN_RAW(string);
+}
static struct StringIO *
strio_alloc(void)
@@ -166,7 +174,10 @@ writable(VALUE strio)
static void
check_modifiable(struct StringIO *ptr)
{
- if (OBJ_FROZEN(ptr->string)) {
+ if (NIL_P(ptr->string)) {
+ /* Null device StringIO */
+ }
+ else if (OBJ_FROZEN_RAW(ptr->string)) {
rb_raise(rb_eIOError, "not modifiable string");
}
}
@@ -281,13 +292,14 @@ strio_init(int argc, VALUE *argv, struct StringIO *ptr, VALUE self)
argc = rb_scan_args(argc, argv, "02:", &string, &vmode, &opt);
rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &ptr->flags, &convconfig);
- if (argc) {
+ if (!NIL_P(string)) {
StringValue(string);
}
- else {
+ else if (!argc) {
string = rb_enc_str_new("", 0, rb_default_external_encoding());
}
- if (OBJ_FROZEN_RAW(string)) {
+
+ if (!NIL_P(string) && readonly_string_p(string)) {
if (ptr->flags & FMODE_WRITABLE) {
rb_syserr_fail(EACCES, 0);
}
@@ -297,11 +309,11 @@ strio_init(int argc, VALUE *argv, struct StringIO *ptr, VALUE self)
ptr->flags |= FMODE_WRITABLE;
}
}
- if (ptr->flags & FMODE_TRUNC) {
+ if (!NIL_P(string) && (ptr->flags & FMODE_TRUNC)) {
rb_str_resize(string, 0);
}
RB_OBJ_WRITE(self, &ptr->string, string);
- if (argc == 1) {
+ if (argc == 1 && !NIL_P(string)) {
ptr->enc = rb_enc_get(string);
}
else {
@@ -481,7 +493,7 @@ strio_set_string(VALUE self, VALUE string)
rb_io_taint_check(self);
ptr->flags &= ~FMODE_READWRITE;
StringValue(string);
- ptr->flags = OBJ_FROZEN(string) ? FMODE_READABLE : FMODE_READWRITE;
+ ptr->flags = readonly_string_p(string) ? FMODE_READABLE : FMODE_READWRITE;
ptr->pos = 0;
ptr->lineno = 0;
RB_OBJ_WRITE(self, &ptr->string, string);
@@ -595,6 +607,7 @@ static struct StringIO *
strio_to_read(VALUE self)
{
struct StringIO *ptr = readable(self);
+ if (NIL_P(ptr->string)) return NULL;
if (ptr->pos < RSTRING_LEN(ptr->string)) return ptr;
return NULL;
}
@@ -872,7 +885,7 @@ strio_getc(VALUE self)
int len;
char *p;
- if (pos >= RSTRING_LEN(str)) {
+ if (NIL_P(str) || pos >= RSTRING_LEN(str)) {
return Qnil;
}
p = RSTRING_PTR(str)+pos;
@@ -893,7 +906,7 @@ strio_getbyte(VALUE self)
{
struct StringIO *ptr = readable(self);
int c;
- if (ptr->pos >= RSTRING_LEN(ptr->string)) {
+ if (NIL_P(ptr->string) || ptr->pos >= RSTRING_LEN(ptr->string)) {
return Qnil;
}
c = RSTRING_PTR(ptr->string)[ptr->pos++];
@@ -915,9 +928,6 @@ strio_extend(struct StringIO *ptr, long pos, long len)
if (pos > olen)
MEMZERO(RSTRING_PTR(ptr->string) + olen, char, pos - olen);
}
- else {
- rb_str_modify(ptr->string);
- }
}
/*
@@ -934,6 +944,7 @@ strio_ungetc(VALUE self, VALUE c)
rb_encoding *enc, *enc2;
check_modifiable(ptr);
+ if (NIL_P(ptr->string)) return Qnil;
if (NIL_P(c)) return Qnil;
if (RB_INTEGER_TYPE_P(c)) {
int len, cc = NUM2INT(c);
@@ -971,12 +982,13 @@ strio_ungetbyte(VALUE self, VALUE c)
struct StringIO *ptr = readable(self);
check_modifiable(ptr);
+ if (NIL_P(ptr->string)) return Qnil;
if (NIL_P(c)) return Qnil;
if (RB_INTEGER_TYPE_P(c)) {
- /* rb_int_and() not visible from exts */
- VALUE v = rb_funcall(c, '&', 1, INT2FIX(0xff));
- const char cc = NUM2INT(v) & 0xFF;
- strio_unget_bytes(ptr, &cc, 1);
+ /* rb_int_and() not visible from exts */
+ VALUE v = rb_funcall(c, '&', 1, INT2FIX(0xff));
+ const char cc = NUM2INT(v) & 0xFF;
+ strio_unget_bytes(ptr, &cc, 1);
}
else {
long cl;
@@ -1157,41 +1169,41 @@ prepare_getline_args(struct StringIO *ptr, struct getline_arg *arg, int argc, VA
break;
case 1:
- if (!NIL_P(rs) && !RB_TYPE_P(rs, T_STRING)) {
- VALUE tmp = rb_check_string_type(rs);
+ if (!NIL_P(rs) && !RB_TYPE_P(rs, T_STRING)) {
+ VALUE tmp = rb_check_string_type(rs);
if (NIL_P(tmp)) {
- limit = NUM2LONG(rs);
- rs = rb_rs;
+ limit = NUM2LONG(rs);
+ rs = rb_rs;
}
else {
- rs = tmp;
+ rs = tmp;
}
}
break;
case 2:
- if (!NIL_P(rs)) StringValue(rs);
+ if (!NIL_P(rs)) StringValue(rs);
if (!NIL_P(lim)) limit = NUM2LONG(lim);
break;
}
- if (!NIL_P(rs)) {
- rb_encoding *enc_rs, *enc_io;
- enc_rs = rb_enc_get(rs);
- enc_io = get_enc(ptr);
- if (enc_rs != enc_io &&
- (rb_enc_str_coderange(rs) != ENC_CODERANGE_7BIT ||
- (RSTRING_LEN(rs) > 0 && !rb_enc_asciicompat(enc_io)))) {
- if (rs == rb_rs) {
- rs = rb_enc_str_new(0, 0, enc_io);
- rb_str_buf_cat_ascii(rs, "\n");
- rs = rs;
- }
- else {
- rb_raise(rb_eArgError, "encoding mismatch: %s IO with %s RS",
- rb_enc_name(enc_io),
- rb_enc_name(enc_rs));
- }
- }
+ if (!NIL_P(ptr->string) && !NIL_P(rs)) {
+ rb_encoding *enc_rs, *enc_io;
+ enc_rs = rb_enc_get(rs);
+ enc_io = get_enc(ptr);
+ if (enc_rs != enc_io &&
+ (rb_enc_str_coderange(rs) != ENC_CODERANGE_7BIT ||
+ (RSTRING_LEN(rs) > 0 && !rb_enc_asciicompat(enc_io)))) {
+ if (rs == rb_rs) {
+ rs = rb_enc_str_new(0, 0, enc_io);
+ rb_str_buf_cat_ascii(rs, "\n");
+ rs = rs;
+ }
+ else {
+ rb_raise(rb_eArgError, "encoding mismatch: %s IO with %s RS",
+ rb_enc_name(enc_io),
+ rb_enc_name(enc_rs));
+ }
+ }
}
arg->rs = rs;
arg->limit = limit;
@@ -1203,9 +1215,9 @@ prepare_getline_args(struct StringIO *ptr, struct getline_arg *arg, int argc, VA
keywords[0] = rb_intern_const("chomp");
}
rb_get_kwargs(opts, keywords, 0, 1, &vchomp);
- if (respect_chomp) {
+ if (respect_chomp) {
arg->chomp = (vchomp != Qundef) && RTEST(vchomp);
- }
+ }
}
return arg;
}
@@ -1229,7 +1241,7 @@ strio_getline(struct getline_arg *arg, struct StringIO *ptr)
long w = 0;
rb_encoding *enc = get_enc(ptr);
- if (ptr->pos >= (n = RSTRING_LEN(ptr->string))) {
+ if (NIL_P(ptr->string) || ptr->pos >= (n = RSTRING_LEN(ptr->string))) {
return Qnil;
}
s = RSTRING_PTR(ptr->string);
@@ -1245,7 +1257,7 @@ strio_getline(struct getline_arg *arg, struct StringIO *ptr)
str = strio_substr(ptr, ptr->pos, e - s - w, enc);
}
else if ((n = RSTRING_LEN(str)) == 0) {
- const char *paragraph_end = NULL;
+ const char *paragraph_end = NULL;
p = s;
while (p[(p + 1 < e) && (*p == '\r') && 0] == '\n') {
p += *p == '\r';
@@ -1255,18 +1267,18 @@ strio_getline(struct getline_arg *arg, struct StringIO *ptr)
}
s = p;
while ((p = memchr(p, '\n', e - p)) && (p != e)) {
- p++;
- if (!((p < e && *p == '\n') ||
- (p + 1 < e && *p == '\r' && *(p+1) == '\n'))) {
- continue;
- }
- paragraph_end = p - ((*(p-2) == '\r') ? 2 : 1);
- while ((p < e && *p == '\n') ||
- (p + 1 < e && *p == '\r' && *(p+1) == '\n')) {
- p += (*p == '\r') ? 2 : 1;
- }
- e = p;
- break;
+ p++;
+ if (!((p < e && *p == '\n') ||
+ (p + 1 < e && *p == '\r' && *(p+1) == '\n'))) {
+ continue;
+ }
+ paragraph_end = p - ((*(p-2) == '\r') ? 2 : 1);
+ while ((p < e && *p == '\n') ||
+ (p + 1 < e && *p == '\r' && *(p+1) == '\n')) {
+ p += (*p == '\r') ? 2 : 1;
+ }
+ e = p;
+ break;
}
if (arg->chomp && paragraph_end) {
w = e - paragraph_end;
@@ -1326,6 +1338,7 @@ strio_gets(int argc, VALUE *argv, VALUE self)
VALUE str;
if (prepare_getline_args(ptr, &arg, argc, argv)->limit == 0) {
+ if (NIL_P(ptr->string)) return Qnil;
return rb_enc_str_new(0, 0, get_enc(ptr));
}
@@ -1440,6 +1453,7 @@ strio_write(VALUE self, VALUE str)
if (!RB_TYPE_P(str, T_STRING))
str = rb_obj_as_string(str);
enc = get_enc(ptr);
+ if (!enc) return 0;
enc2 = rb_enc_get(str);
if (enc != enc2 && enc != ascii8bit && enc != (usascii = rb_usascii_encoding())) {
VALUE converted = rb_str_conv_enc(str, enc2, enc);
@@ -1465,6 +1479,7 @@ strio_write(VALUE self, VALUE str)
}
else {
strio_extend(ptr, ptr->pos, len);
+ rb_str_modify(ptr->string);
memmove(RSTRING_PTR(ptr->string)+ptr->pos, RSTRING_PTR(str), len);
}
RB_GC_GUARD(str);
@@ -1511,10 +1526,12 @@ strio_putc(VALUE self, VALUE ch)
check_modifiable(ptr);
if (RB_TYPE_P(ch, T_STRING)) {
+ if (NIL_P(ptr->string)) return ch;
str = rb_str_substr(ch, 0, 1);
}
else {
char c = NUM2CHR(ch);
+ if (NIL_P(ptr->string)) return ch;
str = rb_str_new(&c, 1);
}
strio_write(self, str);
@@ -1557,7 +1574,8 @@ strio_read(int argc, VALUE *argv, VALUE self)
if (len < 0) {
rb_raise(rb_eArgError, "negative length %ld given", len);
}
- if (len > 0 && ptr->pos >= RSTRING_LEN(ptr->string)) {
+ if (len > 0 &&
+ (NIL_P(ptr->string) || ptr->pos >= RSTRING_LEN(ptr->string))) {
if (!NIL_P(str)) rb_str_resize(str, 0);
return Qnil;
}
@@ -1566,6 +1584,7 @@ strio_read(int argc, VALUE *argv, VALUE self)
}
/* fall through */
case 0:
+ if (NIL_P(ptr->string)) return Qnil;
len = RSTRING_LEN(ptr->string);
if (len <= ptr->pos) {
rb_encoding *enc = get_enc(ptr);
@@ -1583,7 +1602,7 @@ strio_read(int argc, VALUE *argv, VALUE self)
}
break;
default:
- rb_error_arity(argc, 0, 2);
+ rb_error_arity(argc, 0, 2);
}
if (NIL_P(str)) {
rb_encoding *enc = binary ? rb_ascii8bit_encoding() : get_enc(ptr);
@@ -1594,10 +1613,9 @@ strio_read(int argc, VALUE *argv, VALUE self)
if (len > rest) len = rest;
rb_str_resize(str, len);
MEMCPY(RSTRING_PTR(str), RSTRING_PTR(ptr->string) + ptr->pos, char, len);
- if (binary)
- rb_enc_associate(str, rb_ascii8bit_encoding());
- else
+ if (!binary) {
rb_enc_copy(str, ptr->string);
+ }
}
ptr->pos += RSTRING_LEN(str);
return str;
@@ -1619,28 +1637,28 @@ strio_pread(int argc, VALUE *argv, VALUE self)
long offset = NUM2LONG(rb_offset);
if (len < 0) {
- rb_raise(rb_eArgError, "negative string size (or size too big): %" PRIsVALUE, rb_len);
+ rb_raise(rb_eArgError, "negative string size (or size too big): %" PRIsVALUE, rb_len);
}
if (len == 0) {
- if (NIL_P(rb_buf)) {
- return rb_str_new("", 0);
- }
- return rb_buf;
+ if (NIL_P(rb_buf)) {
+ return rb_str_new("", 0);
+ }
+ return rb_buf;
}
if (offset < 0) {
- rb_syserr_fail_str(EINVAL, rb_sprintf("pread: Invalid offset argument: %" PRIsVALUE, rb_offset));
+ rb_syserr_fail_str(EINVAL, rb_sprintf("pread: Invalid offset argument: %" PRIsVALUE, rb_offset));
}
struct StringIO *ptr = readable(self);
if (offset >= RSTRING_LEN(ptr->string)) {
- rb_eof_error();
+ rb_eof_error();
}
if (NIL_P(rb_buf)) {
- return strio_substr(ptr, offset, len, rb_ascii8bit_encoding());
+ return strio_substr(ptr, offset, len, rb_ascii8bit_encoding());
}
long rest = RSTRING_LEN(ptr->string) - offset;
@@ -1700,8 +1718,14 @@ strio_read_nonblock(int argc, VALUE *argv, VALUE self)
return val;
}
+/*
+ * See IO#write
+ */
#define strio_syswrite rb_io_write
+/*
+ * See IO#write_nonblock
+ */
static VALUE
strio_syswrite_nonblock(int argc, VALUE *argv, VALUE self)
{
@@ -1729,7 +1753,7 @@ strio_size(VALUE self)
{
VALUE string = StringIO(self)->string;
if (NIL_P(string)) {
- rb_raise(rb_eIOError, "not opened");
+ return INT2FIX(0);
}
return ULONG2NUM(RSTRING_LEN(string));
}
@@ -1746,10 +1770,12 @@ strio_truncate(VALUE self, VALUE len)
{
VALUE string = writable(self)->string;
long l = NUM2LONG(len);
- long plen = RSTRING_LEN(string);
+ long plen;
if (l < 0) {
error_inval("negative length");
}
+ if (NIL_P(string)) return 0;
+ plen = RSTRING_LEN(string);
rb_str_resize(string, l);
if (plen < l) {
MEMZERO(RSTRING_PTR(string) + plen, char, l - plen);
@@ -1820,13 +1846,22 @@ strio_set_encoding(int argc, VALUE *argv, VALUE self)
}
}
ptr->enc = enc;
- if (WRITABLE(self)) {
+ if (!NIL_P(ptr->string) && WRITABLE(self)) {
rb_enc_associate(ptr->string, enc);
}
return self;
}
+/*
+ * call-seq:
+ * strio.set_encoding_by_bom => strio or nil
+ *
+ * Sets the encoding according to the BOM (Byte Order Mark) in the
+ * string.
+ *
+ * Returns +self+ if the BOM is found, otherwise +nil.
+ */
static VALUE
strio_set_encoding_by_bom(VALUE self)
{
@@ -1859,10 +1894,15 @@ Init_stringio(void)
VALUE StringIO = rb_define_class("StringIO", rb_cObject);
+ /* The version string */
rb_define_const(StringIO, "VERSION", rb_str_new_cstr(STRINGIO_VERSION));
rb_include_module(StringIO, rb_mEnumerable);
rb_define_alloc_func(StringIO, strio_s_allocate);
+
+ /* Maximum length that a StringIO instance can hold */
+ rb_define_const(StringIO, "MAX_LENGTH", LONG2NUM(LONG_MAX));
+
rb_define_singleton_method(StringIO, "new", strio_s_new, -1);
rb_define_singleton_method(StringIO, "open", strio_s_open, -1);
rb_define_method(StringIO, "initialize", strio_initialize, -1);
diff --git a/ext/stringio/stringio.gemspec b/ext/stringio/stringio.gemspec
index 8c950f8ff9..b40b7fc824 100644
--- a/ext/stringio/stringio.gemspec
+++ b/ext/stringio/stringio.gemspec
@@ -28,6 +28,12 @@ Gem::Specification.new do |s|
s.extensions = ["ext/stringio/extconf.rb"]
s.files += ["ext/stringio/extconf.rb", "ext/stringio/stringio.c"]
end
+
+ s.extra_rdoc_files = [
+ ".document", ".rdoc_options", "COPYING", "LICENSE.txt",
+ "NEWS.md", "README.md", "docs/io.rb", "ext/stringio/.document",
+ ]
+
s.homepage = "https://github.com/ruby/stringio"
s.licenses = ["Ruby", "BSD-2-Clause"]
s.required_ruby_version = ">= 2.7"
diff --git a/ext/strscan/depend b/ext/strscan/depend
index 8d985b59e8..8dbae206d4 100644
--- a/ext/strscan/depend
+++ b/ext/strscan/depend
@@ -157,6 +157,7 @@ strscan.o: $(hdrdir)/ruby/internal/special_consts.h
strscan.o: $(hdrdir)/ruby/internal/static_assert.h
strscan.o: $(hdrdir)/ruby/internal/stdalign.h
strscan.o: $(hdrdir)/ruby/internal/stdbool.h
+strscan.o: $(hdrdir)/ruby/internal/stdckdint.h
strscan.o: $(hdrdir)/ruby/internal/symbol.h
strscan.o: $(hdrdir)/ruby/internal/value.h
strscan.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/strscan/strscan.c b/ext/strscan/strscan.c
index a2bf56ce4f..fad35925a8 100644
--- a/ext/strscan/strscan.c
+++ b/ext/strscan/strscan.c
@@ -22,7 +22,7 @@ extern size_t onig_region_memsize(const struct re_registers *regs);
#include <stdbool.h>
-#define STRSCAN_VERSION "3.0.8"
+#define STRSCAN_VERSION "3.1.1"
/* =======================================================================
Data Type Definitions
@@ -218,16 +218,28 @@ strscan_s_allocate(VALUE klass)
}
/*
- * call-seq:
- * StringScanner.new(string, fixed_anchor: false)
- * StringScanner.new(string, dup = false)
- *
- * Creates a new StringScanner object to scan over the given +string+.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
*
- * If +fixed_anchor+ is +true+, +\A+ always matches the beginning of
- * the string. Otherwise, +\A+ always matches the current position.
+ * call-seq:
+ * StringScanner.new(string, fixed_anchor: false) -> string_scanner
+ *
+ * Returns a new `StringScanner` object whose [stored string][1]
+ * is the given `string`;
+ * sets the [fixed-anchor property][10]:
+ *
+ * ```
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.string # => "foobarbaz"
+ * scanner.fixed_anchor? # => false
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 0
+ * # charpos: 0
+ * # rest: "foobarbaz"
+ * # rest_size: 9
+ * ```
*
- * +dup+ argument is obsolete and not used now.
*/
static VALUE
strscan_initialize(int argc, VALUE *argv, VALUE self)
@@ -266,11 +278,14 @@ check_strscan(VALUE obj)
}
/*
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
* call-seq:
- * dup
- * clone
+ * dup -> shallow_copy
*
- * Duplicates a StringScanner object.
+ * Returns a shallow copy of `self`;
+ * the [stored string][1] in the copy is the same string as in `self`.
*/
static VALUE
strscan_init_copy(VALUE vself, VALUE vorig)
@@ -297,10 +312,13 @@ strscan_init_copy(VALUE vself, VALUE vorig)
======================================================================= */
/*
- * call-seq: StringScanner.must_C_version
+ * call-seq:
+ * StringScanner.must_C_version -> self
*
- * This method is defined for backward compatibility.
+ * Returns +self+; defined for backward compatibility.
*/
+
+ /* :nodoc: */
static VALUE
strscan_s_mustc(VALUE self)
{
@@ -308,7 +326,30 @@ strscan_s_mustc(VALUE self)
}
/*
- * Reset the scan pointer (index 0) and clear matching data.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * reset -> self
+ *
+ * Sets both [byte position][2] and [character position][7] to zero,
+ * and clears [match values][9];
+ * returns +self+:
+ *
+ * ```
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.exist?(/bar/) # => 6
+ * scanner.reset # => #<StringScanner 0/9 @ "fooba...">
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 0
+ * # charpos: 0
+ * # rest: "foobarbaz"
+ * # rest_size: 9
+ * # => nil
+ * match_values_cleared?(scanner) # => true
+ * ```
+ *
*/
static VALUE
strscan_reset(VALUE self)
@@ -322,11 +363,9 @@ strscan_reset(VALUE self)
}
/*
- * call-seq:
- * terminate
- * clear
- *
- * Sets the scan pointer to the end of the string and clear matching data.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/terminate.md
*/
static VALUE
strscan_terminate(VALUE self)
@@ -340,9 +379,13 @@ strscan_terminate(VALUE self)
}
/*
- * Equivalent to #terminate.
- * This method is obsolete; use #terminate instead.
+ * call-seq:
+ * clear -> self
+ *
+ * This method is obsolete; use the equivalent method StringScanner#terminate.
*/
+
+ /* :nodoc: */
static VALUE
strscan_clear(VALUE self)
{
@@ -351,7 +394,21 @@ strscan_clear(VALUE self)
}
/*
- * Returns the string being scanned.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * string -> stored_string
+ *
+ * Returns the [stored string][1]:
+ *
+ * ```
+ * scanner = StringScanner.new('foobar')
+ * scanner.string # => "foobar"
+ * scanner.concat('baz')
+ * scanner.string # => "foobarbaz"
+ * ```
+ *
*/
static VALUE
strscan_get_string(VALUE self)
@@ -363,10 +420,39 @@ strscan_get_string(VALUE self)
}
/*
- * call-seq: string=(str)
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * string = other_string -> other_string
+ *
+ * Replaces the [stored string][1] with the given `other_string`:
+ *
+ * - Sets both [positions][11] to zero.
+ * - Clears [match values][9].
+ * - Returns `other_string`.
+ *
+ * ```
+ * scanner = StringScanner.new('foobar')
+ * scanner.scan(/foo/)
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 3
+ * # charpos: 3
+ * # rest: "bar"
+ * # rest_size: 3
+ * match_values_cleared?(scanner) # => false
+ *
+ * scanner.string = 'baz' # => "baz"
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 0
+ * # charpos: 0
+ * # rest: "baz"
+ * # rest_size: 3
+ * match_values_cleared?(scanner) # => true
+ * ```
*
- * Changes the string being scanned to +str+ and resets the scanner.
- * Returns +str+.
*/
static VALUE
strscan_set_string(VALUE self, VALUE str)
@@ -381,18 +467,33 @@ strscan_set_string(VALUE self, VALUE str)
}
/*
- * call-seq:
- * concat(str)
- * <<(str)
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
*
- * Appends +str+ to the string being scanned.
- * This method does not affect scan pointer.
+ * call-seq:
+ * concat(more_string) -> self
+ *
+ * - Appends the given `more_string`
+ * to the [stored string][1].
+ * - Returns `self`.
+ * - Does not affect the [positions][11]
+ * or [match values][9].
+ *
+ *
+ * ```
+ * scanner = StringScanner.new('foo')
+ * scanner.string # => "foo"
+ * scanner.terminate
+ * scanner.concat('barbaz') # => #<StringScanner 3/9 "foo" @ "barba...">
+ * scanner.string # => "foobarbaz"
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 3
+ * # charpos: 3
+ * # rest: "barbaz"
+ * # rest_size: 6
+ * ```
*
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.scan(/Fri /)
- * s << " +1000 GMT"
- * s.string # -> "Fri Dec 12 1975 14:39 +1000 GMT"
- * s.scan(/Dec/) # -> "Dec"
*/
static VALUE
strscan_concat(VALUE self, VALUE str)
@@ -406,18 +507,9 @@ strscan_concat(VALUE self, VALUE str)
}
/*
- * Returns the byte position of the scan pointer. In the 'reset' position, this
- * value is zero. In the 'terminated' position (i.e. the string is exhausted),
- * this value is the bytesize of the string.
- *
- * In short, it's a 0-based index into bytes of the string.
- *
- * s = StringScanner.new('test string')
- * s.pos # -> 0
- * s.scan_until /str/ # -> "test str"
- * s.pos # -> 8
- * s.terminate # -> #<StringScanner fin>
- * s.pos # -> 11
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/get_pos.md
*/
static VALUE
strscan_get_pos(VALUE self)
@@ -429,17 +521,9 @@ strscan_get_pos(VALUE self)
}
/*
- * Returns the character position of the scan pointer. In the 'reset' position, this
- * value is zero. In the 'terminated' position (i.e. the string is exhausted),
- * this value is the size of the string.
- *
- * In short, it's a 0-based index into the string.
- *
- * s = StringScanner.new("abc\u00e4def\u00f6ghi")
- * s.charpos # -> 0
- * s.scan_until(/\u00e4/) # -> "abc\u00E4"
- * s.pos # -> 5
- * s.charpos # -> 4
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/get_charpos.md
*/
static VALUE
strscan_get_charpos(VALUE self)
@@ -452,13 +536,9 @@ strscan_get_charpos(VALUE self)
}
/*
- * call-seq: pos=(n)
- *
- * Sets the byte position of the scan pointer.
- *
- * s = StringScanner.new('test string')
- * s.pos = 7 # -> 7
- * s.rest # -> "ring"
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/set_pos.md
*/
static VALUE
strscan_set_pos(VALUE self, VALUE v)
@@ -662,20 +742,9 @@ strscan_do_scan(VALUE self, VALUE pattern, int succptr, int getstr, int headonly
}
/*
- * call-seq: scan(pattern) => String
- *
- * Tries to match with +pattern+ at the current position. If there's a match,
- * the scanner advances the "scan pointer" and returns the matched string.
- * Otherwise, the scanner returns +nil+.
- *
- * s = StringScanner.new('test string')
- * p s.scan(/\w+/) # -> "test"
- * p s.scan(/\w+/) # -> nil
- * p s.scan(/\s+/) # -> " "
- * p s.scan("str") # -> "str"
- * p s.scan(/\w+/) # -> "ing"
- * p s.scan(/./) # -> nil
- *
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/scan.md
*/
static VALUE
strscan_scan(VALUE self, VALUE re)
@@ -684,16 +753,60 @@ strscan_scan(VALUE self, VALUE re)
}
/*
- * call-seq: match?(pattern)
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
*
- * Tests whether the given +pattern+ is matched from the current scan pointer.
- * Returns the length of the match, or +nil+. The scan pointer is not advanced.
+ * call-seq:
+ * match?(pattern) -> updated_position or nil
+ *
+ * Attempts to [match][17] the given `pattern`
+ * at the beginning of the [target substring][3];
+ * does not modify the [positions][11].
+ *
+ * If the match succeeds:
+ *
+ * - Sets [match values][9].
+ * - Returns the size in bytes of the matched substring.
+ *
+ *
+ * ```
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.pos = 3
+ * scanner.match?(/bar/) => 3
+ * put_match_values(scanner)
+ * # Basic match values:
+ * # matched?: true
+ * # matched_size: 3
+ * # pre_match: "foo"
+ * # matched : "bar"
+ * # post_match: "baz"
+ * # Captured match values:
+ * # size: 1
+ * # captures: []
+ * # named_captures: {}
+ * # values_at: ["bar", nil]
+ * # []:
+ * # [0]: "bar"
+ * # [1]: nil
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 3
+ * # charpos: 3
+ * # rest: "barbaz"
+ * # rest_size: 6
+ * ```
+ *
+ * If the match fails:
+ *
+ * - Clears match values.
+ * - Returns `nil`.
+ * - Does not increment positions.
+ *
+ * ```
+ * scanner.match?(/nope/) # => nil
+ * match_values_cleared?(scanner) # => true
+ * ```
*
- * s = StringScanner.new('test string')
- * p s.match?(/\w+/) # -> 4
- * p s.match?(/\w+/) # -> 4
- * p s.match?("test") # -> 4
- * p s.match?(/\s+/) # -> nil
*/
static VALUE
strscan_match_p(VALUE self, VALUE re)
@@ -702,22 +815,9 @@ strscan_match_p(VALUE self, VALUE re)
}
/*
- * call-seq: skip(pattern)
- *
- * Attempts to skip over the given +pattern+ beginning with the scan pointer.
- * If it matches, the scan pointer is advanced to the end of the match, and the
- * length of the match is returned. Otherwise, +nil+ is returned.
- *
- * It's similar to #scan, but without returning the matched string.
- *
- * s = StringScanner.new('test string')
- * p s.skip(/\w+/) # -> 4
- * p s.skip(/\w+/) # -> nil
- * p s.skip(/\s+/) # -> 1
- * p s.skip("st") # -> 2
- * p s.skip(/\w+/) # -> 4
- * p s.skip(/./) # -> nil
- *
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/skip.md
*/
static VALUE
strscan_skip(VALUE self, VALUE re)
@@ -726,19 +826,59 @@ strscan_skip(VALUE self, VALUE re)
}
/*
- * call-seq: check(pattern)
- *
- * This returns the value that #scan would return, without advancing the scan
- * pointer. The match register is affected, though.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
*
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.check /Fri/ # -> "Fri"
- * s.pos # -> 0
- * s.matched # -> "Fri"
- * s.check /12/ # -> nil
- * s.matched # -> nil
+ * call-seq:
+ * check(pattern) -> matched_substring or nil
+ *
+ * Attempts to [match][17] the given `pattern`
+ * at the beginning of the [target substring][3];
+ * does not modify the [positions][11].
+ *
+ * If the match succeeds:
+ *
+ * - Returns the matched substring.
+ * - Sets all [match values][9].
+ *
+ * ```
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.pos = 3
+ * scanner.check('bar') # => "bar"
+ * put_match_values(scanner)
+ * # Basic match values:
+ * # matched?: true
+ * # matched_size: 3
+ * # pre_match: "foo"
+ * # matched : "bar"
+ * # post_match: "baz"
+ * # Captured match values:
+ * # size: 1
+ * # captures: []
+ * # named_captures: {}
+ * # values_at: ["bar", nil]
+ * # []:
+ * # [0]: "bar"
+ * # [1]: nil
+ * # => 0..1
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 3
+ * # charpos: 3
+ * # rest: "barbaz"
+ * # rest_size: 6
+ * ```
+ *
+ * If the match fails:
+ *
+ * - Returns `nil`.
+ * - Clears all [match values][9].
+ *
+ * ```
+ * scanner.check(/nope/) # => nil
+ * match_values_cleared?(scanner) # => true
+ * ```
*
- * Mnemonic: it "checks" to see whether a #scan will return a value.
*/
static VALUE
strscan_check(VALUE self, VALUE re)
@@ -747,15 +887,24 @@ strscan_check(VALUE self, VALUE re)
}
/*
- * call-seq: scan_full(pattern, advance_pointer_p, return_string_p)
+ * call-seq:
+ * scan_full(pattern, advance_pointer_p, return_string_p) -> matched_substring or nil
+ *
+ * Equivalent to one of the following:
+ *
+ * - +advance_pointer_p+ +true+:
*
- * Tests whether the given +pattern+ is matched from the current scan pointer.
- * Advances the scan pointer if +advance_pointer_p+ is true.
- * Returns the matched string if +return_string_p+ is true.
- * The match register is affected.
+ * - +return_string_p+ +true+: StringScanner#scan(pattern).
+ * - +return_string_p+ +false+: StringScanner#skip(pattern).
+ *
+ * - +advance_pointer_p+ +false+:
+ *
+ * - +return_string_p+ +true+: StringScanner#check(pattern).
+ * - +return_string_p+ +false+: StringScanner#match?(pattern).
*
- * "full" means "#scan with full parameters".
*/
+
+ /* :nodoc: */
static VALUE
strscan_scan_full(VALUE self, VALUE re, VALUE s, VALUE f)
{
@@ -763,16 +912,9 @@ strscan_scan_full(VALUE self, VALUE re, VALUE s, VALUE f)
}
/*
- * call-seq: scan_until(pattern)
- *
- * Scans the string _until_ the +pattern+ is matched. Returns the substring up
- * to and including the end of the match, advancing the scan pointer to that
- * location. If there is no match, +nil+ is returned.
- *
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.scan_until(/1/) # -> "Fri Dec 1"
- * s.pre_match # -> "Fri Dec "
- * s.scan_until(/XYZ/) # -> nil
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/scan_until.md
*/
static VALUE
strscan_scan_until(VALUE self, VALUE re)
@@ -781,17 +923,61 @@ strscan_scan_until(VALUE self, VALUE re)
}
/*
- * call-seq: exist?(pattern)
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
*
- * Looks _ahead_ to see if the +pattern+ exists _anywhere_ in the string,
- * without advancing the scan pointer. This predicates whether a #scan_until
- * will return a value.
+ * call-seq:
+ * exist?(pattern) -> byte_offset or nil
+ *
+ * Attempts to [match][17] the given `pattern`
+ * anywhere (at any [position][2])
+ * n the [target substring][3];
+ * does not modify the [positions][11].
+ *
+ * If the match succeeds:
+ *
+ * - Returns a byte offset:
+ * the distance in bytes between the current [position][2]
+ * and the end of the matched substring.
+ * - Sets all [match values][9].
+ *
+ * ```
+ * scanner = StringScanner.new('foobarbazbatbam')
+ * scanner.pos = 6
+ * scanner.exist?(/bat/) # => 6
+ * put_match_values(scanner)
+ * # Basic match values:
+ * # matched?: true
+ * # matched_size: 3
+ * # pre_match: "foobarbaz"
+ * # matched : "bat"
+ * # post_match: "bam"
+ * # Captured match values:
+ * # size: 1
+ * # captures: []
+ * # named_captures: {}
+ * # values_at: ["bat", nil]
+ * # []:
+ * # [0]: "bat"
+ * # [1]: nil
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 6
+ * # charpos: 6
+ * # rest: "bazbatbam"
+ * # rest_size: 9
+ * ```
+ *
+ * If the match fails:
+ *
+ * - Returns `nil`.
+ * - Clears all [match values][9].
+ *
+ * ```
+ * scanner.exist?(/nope/) # => nil
+ * match_values_cleared?(scanner) # => true
+ * ```
*
- * s = StringScanner.new('test string')
- * s.exist? /s/ # -> 3
- * s.scan /test/ # -> "test"
- * s.exist? /s/ # -> 2
- * s.exist? /e/ # -> nil
*/
static VALUE
strscan_exist_p(VALUE self, VALUE re)
@@ -800,20 +986,9 @@ strscan_exist_p(VALUE self, VALUE re)
}
/*
- * call-seq: skip_until(pattern)
- *
- * Advances the scan pointer until +pattern+ is matched and consumed. Returns
- * the number of bytes advanced, or +nil+ if no match was found.
- *
- * Look ahead to match +pattern+, and advance the scan pointer to the _end_
- * of the match. Return the number of characters advanced, or +nil+ if the
- * match was unsuccessful.
- *
- * It's similar to #scan_until, but without returning the intervening string.
- *
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.skip_until /12/ # -> 10
- * s #
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/skip_until.md
*/
static VALUE
strscan_skip_until(VALUE self, VALUE re)
@@ -822,17 +997,61 @@ strscan_skip_until(VALUE self, VALUE re)
}
/*
- * call-seq: check_until(pattern)
- *
- * This returns the value that #scan_until would return, without advancing the
- * scan pointer. The match register is affected, though.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
*
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.check_until /12/ # -> "Fri Dec 12"
- * s.pos # -> 0
- * s.matched # -> 12
+ * call-seq:
+ * check_until(pattern) -> substring or nil
+ *
+ * Attempts to [match][17] the given `pattern`
+ * anywhere (at any [position][2])
+ * in the [target substring][3];
+ * does not modify the [positions][11].
+ *
+ * If the match succeeds:
+ *
+ * - Sets all [match values][9].
+ * - Returns the matched substring,
+ * which extends from the current [position][2]
+ * to the end of the matched substring.
+ *
+ * ```
+ * scanner = StringScanner.new('foobarbazbatbam')
+ * scanner.pos = 6
+ * scanner.check_until(/bat/) # => "bazbat"
+ * put_match_values(scanner)
+ * # Basic match values:
+ * # matched?: true
+ * # matched_size: 3
+ * # pre_match: "foobarbaz"
+ * # matched : "bat"
+ * # post_match: "bam"
+ * # Captured match values:
+ * # size: 1
+ * # captures: []
+ * # named_captures: {}
+ * # values_at: ["bat", nil]
+ * # []:
+ * # [0]: "bat"
+ * # [1]: nil
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 6
+ * # charpos: 6
+ * # rest: "bazbatbam"
+ * # rest_size: 9
+ * ```
+ *
+ * If the match fails:
+ *
+ * - Clears all [match values][9].
+ * - Returns `nil`.
+ *
+ * ```
+ * scanner.check_until(/nope/) # => nil
+ * match_values_cleared?(scanner) # => true
+ * ```
*
- * Mnemonic: it "checks" to see whether a #scan_until will return a value.
*/
static VALUE
strscan_check_until(VALUE self, VALUE re)
@@ -841,14 +1060,24 @@ strscan_check_until(VALUE self, VALUE re)
}
/*
- * call-seq: search_full(pattern, advance_pointer_p, return_string_p)
+ * call-seq:
+ * search_full(pattern, advance_pointer_p, return_string_p) -> matched_substring or position_delta or nil
+ *
+ * Equivalent to one of the following:
+ *
+ * - +advance_pointer_p+ +true+:
+ *
+ * - +return_string_p+ +true+: StringScanner#scan_until(pattern).
+ * - +return_string_p+ +false+: StringScanner#skip_until(pattern).
+ *
+ * - +advance_pointer_p+ +false+:
+ *
+ * - +return_string_p+ +true+: StringScanner#check_until(pattern).
+ * - +return_string_p+ +false+: StringScanner#exist?(pattern).
*
- * Scans the string _until_ the +pattern+ is matched.
- * Advances the scan pointer if +advance_pointer_p+, otherwise not.
- * Returns the matched string if +return_string_p+ is true, otherwise
- * returns the number of bytes advanced.
- * This method does affect the match register.
*/
+
+ /* :nodoc: */
static VALUE
strscan_search_full(VALUE self, VALUE re, VALUE s, VALUE f)
{
@@ -868,17 +1097,9 @@ adjust_registers_to_matched(struct strscanner *p)
}
/*
- * Scans one character and returns it.
- * This method is multibyte character sensitive.
- *
- * s = StringScanner.new("ab")
- * s.getch # => "a"
- * s.getch # => "b"
- * s.getch # => nil
- *
- * s = StringScanner.new("\244\242".force_encoding("euc-jp"))
- * s.getch # => "\x{A4A2}" # Japanese hira-kana "A" in EUC-JP
- * s.getch # => nil
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/getch.md
*/
static VALUE
strscan_getch(VALUE self)
@@ -903,19 +1124,54 @@ strscan_getch(VALUE self)
}
/*
- * Scans one byte and returns it.
+ * call-seq:
+ * scan_byte -> integer_byte
+ *
+ * Scans one byte and returns it as an integer.
* This method is not multibyte character sensitive.
* See also: #getch.
*
+ */
+static VALUE
+strscan_scan_byte(VALUE self)
+{
+ struct strscanner *p;
+
+ GET_SCANNER(self, p);
+ CLEAR_MATCH_STATUS(p);
+ if (EOS_P(p))
+ return Qnil;
+
+ VALUE byte = INT2FIX((unsigned char)*CURPTR(p));
+ p->prev = p->curr;
+ p->curr++;
+ MATCHED(p);
+ adjust_registers_to_matched(p);
+ return byte;
+}
+
+/*
+ * Peeks at the current byte and returns it as an integer.
+ *
* s = StringScanner.new('ab')
- * s.get_byte # => "a"
- * s.get_byte # => "b"
- * s.get_byte # => nil
- *
- * s = StringScanner.new("\244\242".force_encoding("euc-jp"))
- * s.get_byte # => "\xA4"
- * s.get_byte # => "\xA2"
- * s.get_byte # => nil
+ * s.peek_byte # => 97
+ */
+static VALUE
+strscan_peek_byte(VALUE self)
+{
+ struct strscanner *p;
+
+ GET_SCANNER(self, p);
+ if (EOS_P(p))
+ return Qnil;
+
+ return INT2FIX((unsigned char)*CURPTR(p));
+}
+
+/*
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/get_byte.md
*/
static VALUE
strscan_get_byte(VALUE self)
@@ -937,9 +1193,14 @@ strscan_get_byte(VALUE self)
}
/*
+ * call-seq:
+ * getbyte
+ *
* Equivalent to #get_byte.
* This method is obsolete; use #get_byte instead.
*/
+
+ /* :nodoc: */
static VALUE
strscan_getbyte(VALUE self)
{
@@ -948,14 +1209,22 @@ strscan_getbyte(VALUE self)
}
/*
- * call-seq: peek(len)
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
*
- * Extracts a string corresponding to <tt>string[pos,len]</tt>, without
- * advancing the scan pointer.
+ * call-seq:
+ * peek(length) -> substring
*
- * s = StringScanner.new('test string')
- * s.peek(7) # => "test st"
- * s.peek(7) # => "test st"
+ * Returns the substring `string[pos, length]`;
+ * does not update [match values][9] or [positions][11]:
+ *
+ * ```
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.pos = 3
+ * scanner.peek(3) # => "bar"
+ * scanner.terminate
+ * scanner.peek(3) # => ""
+ * ```
*
*/
static VALUE
@@ -975,9 +1244,14 @@ strscan_peek(VALUE self, VALUE vlen)
}
/*
+ * call-seq:
+ * peep
+ *
* Equivalent to #peek.
* This method is obsolete; use #peek instead.
*/
+
+ /* :nodoc: */
static VALUE
strscan_peep(VALUE self, VALUE vlen)
{
@@ -986,15 +1260,42 @@ strscan_peep(VALUE self, VALUE vlen)
}
/*
- * Sets the scan pointer to the previous position. Only one previous position is
- * remembered, and it changes with each scanning operation.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * unscan -> self
+ *
+ * Sets the [position][2] to its value previous to the recent successful
+ * [match][17] attempt:
+ *
+ * ```
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.scan(/foo/)
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 3
+ * # charpos: 3
+ * # rest: "barbaz"
+ * # rest_size: 6
+ * scanner.unscan
+ * # => #<StringScanner 0/9 @ "fooba...">
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 0
+ * # charpos: 0
+ * # rest: "foobarbaz"
+ * # rest_size: 9
+ * ```
+ *
+ * Raises an exception if match values are clear:
+ *
+ * ```
+ * scanner.scan(/nope/) # => nil
+ * match_values_cleared?(scanner) # => true
+ * scanner.unscan # Raises StringScanner::Error.
+ * ```
*
- * s = StringScanner.new('test string')
- * s.scan(/\w+/) # => "test"
- * s.unscan
- * s.scan(/../) # => "te"
- * s.scan(/\d/) # => nil
- * s.unscan # ScanError: unscan failed: previous match record not exist
*/
static VALUE
strscan_unscan(VALUE self)
@@ -1010,16 +1311,37 @@ strscan_unscan(VALUE self)
}
/*
- * Returns +true+ if and only if the scan pointer is at the beginning of the line.
- *
- * s = StringScanner.new("test\ntest\n")
- * s.bol? # => true
- * s.scan(/te/)
- * s.bol? # => false
- * s.scan(/st\n/)
- * s.bol? # => true
- * s.terminate
- * s.bol? # => true
+ *
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * beginning_of_line? -> true or false
+ *
+ * Returns whether the [position][2] is at the beginning of a line;
+ * that is, at the beginning of the [stored string][1]
+ * or immediately after a newline:
+ *
+ * scanner = StringScanner.new(MULTILINE_TEXT)
+ * scanner.string
+ * # => "Go placidly amid the noise and haste,\nand remember what peace there may be in silence.\n"
+ * scanner.pos # => 0
+ * scanner.beginning_of_line? # => true
+ *
+ * scanner.scan_until(/,/) # => "Go placidly amid the noise and haste,"
+ * scanner.beginning_of_line? # => false
+ *
+ * scanner.scan(/\n/) # => "\n"
+ * scanner.beginning_of_line? # => true
+ *
+ * scanner.terminate
+ * scanner.beginning_of_line? # => true
+ *
+ * scanner.concat('x')
+ * scanner.terminate
+ * scanner.beginning_of_line? # => false
+ *
+ * StringScanner#bol? is an alias for StringScanner#beginning_of_line?.
*/
static VALUE
strscan_bol_p(VALUE self)
@@ -1033,14 +1355,24 @@ strscan_bol_p(VALUE self)
}
/*
- * Returns +true+ if the scan pointer is at the end of the string.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * eos? -> true or false
+ *
+ * Returns whether the [position][2]
+ * is at the end of the [stored string][1]:
+ *
+ * ```
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.eos? # => false
+ * pos = 3
+ * scanner.eos? # => false
+ * scanner.terminate
+ * scanner.eos? # => true
+ * ```
*
- * s = StringScanner.new('test string')
- * p s.eos? # => false
- * s.scan(/test/)
- * p s.eos? # => false
- * s.terminate
- * p s.eos? # => true
*/
static VALUE
strscan_eos_p(VALUE self)
@@ -1052,9 +1384,14 @@ strscan_eos_p(VALUE self)
}
/*
+ * call-seq:
+ * empty?
+ *
* Equivalent to #eos?.
* This method is obsolete, use #eos? instead.
*/
+
+ /* :nodoc: */
static VALUE
strscan_empty_p(VALUE self)
{
@@ -1063,6 +1400,9 @@ strscan_empty_p(VALUE self)
}
/*
+ * call-seq:
+ * rest?
+ *
* Returns true if and only if there is more data in the string. See #eos?.
* This method is obsolete; use #eos? instead.
*
@@ -1071,6 +1411,8 @@ strscan_empty_p(VALUE self)
* s.eos? # => false
* s.rest? # => true
*/
+
+ /* :nodoc: */
static VALUE
strscan_rest_p(VALUE self)
{
@@ -1081,13 +1423,26 @@ strscan_rest_p(VALUE self)
}
/*
- * Returns +true+ if and only if the last match was successful.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * matched? -> true or false
+ *
+ * Returns `true` of the most recent [match attempt][17] was successful,
+ * `false` otherwise;
+ * see [Basic Matched Values][18]:
+ *
+ * ```
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.matched? # => false
+ * scanner.pos = 3
+ * scanner.exist?(/baz/) # => 6
+ * scanner.matched? # => true
+ * scanner.exist?(/nope/) # => nil
+ * scanner.matched? # => false
+ * ```
*
- * s = StringScanner.new('test string')
- * s.match?(/\w+/) # => 4
- * s.matched? # => true
- * s.match?(/\d+/) # => nil
- * s.matched? # => false
*/
static VALUE
strscan_matched_p(VALUE self)
@@ -1099,11 +1454,27 @@ strscan_matched_p(VALUE self)
}
/*
- * Returns the last matched string.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * matched -> matched_substring or nil
+ *
+ * Returns the matched substring from the most recent [match][17] attempt
+ * if it was successful,
+ * or `nil` otherwise;
+ * see [Basic Matched Values][18]:
+ *
+ * ```
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.matched # => nil
+ * scanner.pos = 3
+ * scanner.match?(/bar/) # => 3
+ * scanner.matched # => "bar"
+ * scanner.match?(/nope/) # => nil
+ * scanner.matched # => nil
+ * ```
*
- * s = StringScanner.new('test string')
- * s.match?(/\w+/) # -> 4
- * s.matched # -> "test"
*/
static VALUE
strscan_matched(VALUE self)
@@ -1118,15 +1489,29 @@ strscan_matched(VALUE self)
}
/*
- * Returns the size of the most recent match in bytes, or +nil+ if there
- * was no recent match. This is different than <tt>matched.size</tt>,
- * which will return the size in characters.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * matched_size -> substring_size or nil
+ *
+ * Returns the size (in bytes) of the matched substring
+ * from the most recent match [match attempt][17] if it was successful,
+ * or `nil` otherwise;
+ * see [Basic Matched Values][18]:
+ *
+ * ```
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.matched_size # => nil
+ *
+ * pos = 3
+ * scanner.exist?(/baz/) # => 9
+ * scanner.matched_size # => 3
+ *
+ * scanner.exist?(/nope/) # => nil
+ * scanner.matched_size # => nil
+ * ```
*
- * s = StringScanner.new('test string')
- * s.check /\w+/ # -> "test"
- * s.matched_size # -> 4
- * s.check /\d+/ # -> nil
- * s.matched_size # -> nil
*/
static VALUE
strscan_matched_size(VALUE self)
@@ -1157,30 +1542,75 @@ name_to_backref_number(struct re_registers *regs, VALUE regexp, const char* name
}
/*
- * call-seq: [](n)
- *
- * Returns the n-th subgroup in the most recent match.
- *
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.scan(/(\w+) (\w+) (\d+) /) # -> "Fri Dec 12 "
- * s[0] # -> "Fri Dec 12 "
- * s[1] # -> "Fri"
- * s[2] # -> "Dec"
- * s[3] # -> "12"
- * s.post_match # -> "1975 14:39"
- * s.pre_match # -> ""
- *
- * s.reset
- * s.scan(/(?<wday>\w+) (?<month>\w+) (?<day>\d+) /) # -> "Fri Dec 12 "
- * s[0] # -> "Fri Dec 12 "
- * s[1] # -> "Fri"
- * s[2] # -> "Dec"
- * s[3] # -> "12"
- * s[:wday] # -> "Fri"
- * s[:month] # -> "Dec"
- * s[:day] # -> "12"
- * s.post_match # -> "1975 14:39"
- * s.pre_match # -> ""
+ *
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * [](specifier) -> substring or nil
+ *
+ * Returns a captured substring or `nil`;
+ * see [Captured Match Values][13].
+ *
+ * When there are captures:
+ *
+ * ```
+ * scanner = StringScanner.new('Fri Dec 12 1975 14:39')
+ * scanner.scan(/(?<wday>\w+) (?<month>\w+) (?<day>\d+) /)
+ * ```
+ *
+ * - `specifier` zero: returns the entire matched substring:
+ *
+ * ```
+ * scanner[0] # => "Fri Dec 12 "
+ * scanner.pre_match # => ""
+ * scanner.post_match # => "1975 14:39"
+ * ```
+ *
+ * - `specifier` positive integer. returns the `n`th capture, or `nil` if out of range:
+ *
+ * ```
+ * scanner[1] # => "Fri"
+ * scanner[2] # => "Dec"
+ * scanner[3] # => "12"
+ * scanner[4] # => nil
+ * ```
+ *
+ * - `specifier` negative integer. counts backward from the last subgroup:
+ *
+ * ```
+ * scanner[-1] # => "12"
+ * scanner[-4] # => "Fri Dec 12 "
+ * scanner[-5] # => nil
+ * ```
+ *
+ * - `specifier` symbol or string. returns the named subgroup, or `nil` if no such:
+ *
+ * ```
+ * scanner[:wday] # => "Fri"
+ * scanner['wday'] # => "Fri"
+ * scanner[:month] # => "Dec"
+ * scanner[:day] # => "12"
+ * scanner[:nope] # => nil
+ * ```
+ *
+ * When there are no captures, only `[0]` returns non-`nil`:
+ *
+ * ```
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.exist?(/bar/)
+ * scanner[0] # => "bar"
+ * scanner[1] # => nil
+ * ```
+ *
+ * For a failed match, even `[0]` returns `nil`:
+ *
+ * ```
+ * scanner.scan(/nope/) # => nil
+ * scanner[0] # => nil
+ * scanner[1] # => nil
+ * ```
+ *
*/
static VALUE
strscan_aref(VALUE self, VALUE idx)
@@ -1217,14 +1647,28 @@ strscan_aref(VALUE self, VALUE idx)
}
/*
- * call-seq: size
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * size -> captures_count
+ *
+ * Returns the count of captures if the most recent match attempt succeeded, `nil` otherwise;
+ * see [Captures Match Values][13]:
*
- * Returns the amount of subgroups in the most recent match.
- * The full match counts as a subgroup.
+ * ```
+ * scanner = StringScanner.new('Fri Dec 12 1975 14:39')
+ * scanner.size # => nil
+ *
+ * pattern = /(?<wday>\w+) (?<month>\w+) (?<day>\d+) /
+ * scanner.match?(pattern)
+ * scanner.values_at(*0..scanner.size) # => ["Fri Dec 12 ", "Fri", "Dec", "12", nil]
+ * scanner.size # => 4
+ *
+ * scanner.match?(/nope/) # => nil
+ * scanner.size # => nil
+ * ```
*
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.scan(/(\w+) (\w+) (\d+) /) # -> "Fri Dec 12 "
- * s.size # -> 4
*/
static VALUE
strscan_size(VALUE self)
@@ -1237,16 +1681,30 @@ strscan_size(VALUE self)
}
/*
- * call-seq: captures
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * captures -> substring_array or nil
+ *
+ * Returns the array of [captured match values][13] at indexes `(1..)`
+ * if the most recent match attempt succeeded, or `nil` otherwise:
+ *
+ * ```
+ * scanner = StringScanner.new('Fri Dec 12 1975 14:39')
+ * scanner.captures # => nil
+ *
+ * scanner.exist?(/(?<wday>\w+) (?<month>\w+) (?<day>\d+) /)
+ * scanner.captures # => ["Fri", "Dec", "12"]
+ * scanner.values_at(*0..4) # => ["Fri Dec 12 ", "Fri", "Dec", "12", nil]
+ *
+ * scanner.exist?(/Fri/)
+ * scanner.captures # => []
*
- * Returns the subgroups in the most recent match (not including the full match).
- * If nothing was priorly matched, it returns nil.
+ * scanner.scan(/nope/)
+ * scanner.captures # => nil
+ * ```
*
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.scan(/(\w+) (\w+) (\d+) /) # -> "Fri Dec 12 "
- * s.captures # -> ["Fri", "Dec", "12"]
- * s.scan(/(\w+) (\w+) (\d+) /) # -> nil
- * s.captures # -> nil
*/
static VALUE
strscan_captures(VALUE self)
@@ -1262,9 +1720,13 @@ strscan_captures(VALUE self)
new_ary = rb_ary_new2(num_regs);
for (i = 1; i < num_regs; i++) {
- VALUE str = extract_range(p,
- adjust_register_position(p, p->regs.beg[i]),
- adjust_register_position(p, p->regs.end[i]));
+ VALUE str;
+ if (p->regs.beg[i] == -1)
+ str = Qnil;
+ else
+ str = extract_range(p,
+ adjust_register_position(p, p->regs.beg[i]),
+ adjust_register_position(p, p->regs.end[i]));
rb_ary_push(new_ary, str);
}
@@ -1272,17 +1734,25 @@ strscan_captures(VALUE self)
}
/*
- * call-seq:
- * scanner.values_at( i1, i2, ... iN ) -> an_array
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
*
- * Returns the subgroups in the most recent match at the given indices.
- * If nothing was priorly matched, it returns nil.
+ * call-seq:
+ * values_at(*specifiers) -> array_of_captures or nil
+ *
+ * Returns an array of captured substrings, or `nil` of none.
+ *
+ * For each `specifier`, the returned substring is `[specifier]`;
+ * see #[].
+ *
+ * ```
+ * scanner = StringScanner.new('Fri Dec 12 1975 14:39')
+ * pattern = /(?<wday>\w+) (?<month>\w+) (?<day>\d+) /
+ * scanner.match?(pattern)
+ * scanner.values_at(*0..3) # => ["Fri Dec 12 ", "Fri", "Dec", "12"]
+ * scanner.values_at(*%i[wday month day]) # => ["Fri", "Dec", "12"]
+ * ```
*
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.scan(/(\w+) (\w+) (\d+) /) # -> "Fri Dec 12 "
- * s.values_at 0, -1, 5, 2 # -> ["Fri Dec 12 ", "12", nil, "Dec"]
- * s.scan(/(\w+) (\w+) (\d+) /) # -> nil
- * s.values_at 0, -1, 5, 2 # -> nil
*/
static VALUE
@@ -1304,13 +1774,29 @@ strscan_values_at(int argc, VALUE *argv, VALUE self)
}
/*
- * Returns the <i><b>pre</b>-match</i> (in the regular expression sense) of the last scan.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * pre_match -> substring
+ *
+ * Returns the substring that precedes the matched substring
+ * from the most recent match attempt if it was successful,
+ * or `nil` otherwise;
+ * see [Basic Match Values][18]:
+ *
+ * ```
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.pre_match # => nil
+ *
+ * scanner.pos = 3
+ * scanner.exist?(/baz/) # => 6
+ * scanner.pre_match # => "foobar" # Substring of entire string, not just target string.
+ *
+ * scanner.exist?(/nope/) # => nil
+ * scanner.pre_match # => nil
+ * ```
*
- * s = StringScanner.new('test string')
- * s.scan(/\w+/) # -> "test"
- * s.scan(/\s+/) # -> " "
- * s.pre_match # -> "test"
- * s.post_match # -> "string"
*/
static VALUE
strscan_pre_match(VALUE self)
@@ -1325,13 +1811,29 @@ strscan_pre_match(VALUE self)
}
/*
- * Returns the <i><b>post</b>-match</i> (in the regular expression sense) of the last scan.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * post_match -> substring
+ *
+ * Returns the substring that follows the matched substring
+ * from the most recent match attempt if it was successful,
+ * or `nil` otherwise;
+ * see [Basic Match Values][18]:
+ *
+ * ```
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.post_match # => nil
+ *
+ * scanner.pos = 3
+ * scanner.match?(/bar/) # => 3
+ * scanner.post_match # => "baz"
+ *
+ * scanner.match?(/nope/) # => nil
+ * scanner.post_match # => nil
+ * ```
*
- * s = StringScanner.new('test string')
- * s.scan(/\w+/) # -> "test"
- * s.scan(/\s+/) # -> " "
- * s.pre_match # -> "test"
- * s.post_match # -> "string"
*/
static VALUE
strscan_post_match(VALUE self)
@@ -1346,8 +1848,24 @@ strscan_post_match(VALUE self)
}
/*
- * Returns the "rest" of the string (i.e. everything after the scan pointer).
- * If there is no more data (eos? = true), it returns <tt>""</tt>.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * rest -> target_substring
+ *
+ * Returns the 'rest' of the [stored string][1] (all after the current [position][2]),
+ * which is the [target substring][3]:
+ *
+ * ```
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.rest # => "foobarbaz"
+ * scanner.pos = 3
+ * scanner.rest # => "barbaz"
+ * scanner.terminate
+ * scanner.rest # => ""
+ * ```
+ *
*/
static VALUE
strscan_rest(VALUE self)
@@ -1362,7 +1880,26 @@ strscan_rest(VALUE self)
}
/*
- * <tt>s.rest_size</tt> is equivalent to <tt>s.rest.size</tt>.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * rest_size -> integer
+ *
+ * Returns the size (in bytes) of the #rest of the [stored string][1]:
+ *
+ * ```
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.rest # => "foobarbaz"
+ * scanner.rest_size # => 9
+ * scanner.pos = 3
+ * scanner.rest # => "barbaz"
+ * scanner.rest_size # => 6
+ * scanner.terminate
+ * scanner.rest # => ""
+ * scanner.rest_size # => 0
+ * ```
+ *
*/
static VALUE
strscan_rest_size(VALUE self)
@@ -1379,9 +1916,14 @@ strscan_rest_size(VALUE self)
}
/*
+ * call-seq:
+ * restsize
+ *
* <tt>s.restsize</tt> is equivalent to <tt>s.rest_size</tt>.
* This method is obsolete; use #rest_size instead.
*/
+
+ /* :nodoc: */
static VALUE
strscan_restsize(VALUE self)
{
@@ -1392,15 +1934,39 @@ strscan_restsize(VALUE self)
#define INSPECT_LENGTH 5
/*
- * Returns a string that represents the StringScanner object, showing:
- * - the current position
- * - the size of the string
- * - the characters surrounding the scan pointer
- *
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.inspect # -> '#<StringScanner 0/21 @ "Fri D...">'
- * s.scan_until /12/ # -> "Fri Dec 12"
- * s.inspect # -> '#<StringScanner 10/21 "...ec 12" @ " 1975...">'
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * inspect -> string
+ *
+ * Returns a string representation of `self` that may show:
+ *
+ * 1. The current [position][2].
+ * 2. The size (in bytes) of the [stored string][1].
+ * 3. The substring preceding the current position.
+ * 4. The substring following the current position (which is also the [target substring][3]).
+ *
+ * ```
+ * scanner = StringScanner.new("Fri Dec 12 1975 14:39")
+ * scanner.pos = 11
+ * scanner.inspect # => "#<StringScanner 11/21 \"...c 12 \" @ \"1975 ...\">"
+ * ```
+ *
+ * If at beginning-of-string, item 4 above (following substring) is omitted:
+ *
+ * ```
+ * scanner.reset
+ * scanner.inspect # => "#<StringScanner 0/21 @ \"Fri D...\">"
+ * ```
+ *
+ * If at end-of-string, all items above are omitted:
+ *
+ * ```
+ * scanner.terminate
+ * scanner.inspect # => "#<StringScanner fin>"
+ * ```
+ *
*/
static VALUE
strscan_inspect(VALUE self)
@@ -1472,13 +2038,13 @@ inspect2(struct strscanner *p)
}
/*
- * call-seq:
- * scanner.fixed_anchor? -> true or false
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
*
- * Whether +scanner+ uses fixed anchor mode or not.
+ * call-seq:
+ * fixed_anchor? -> true or false
*
- * If fixed anchor mode is used, +\A+ always matches the beginning of
- * the string. Otherwise, +\A+ always matches the current position.
+ * Returns whether the [fixed-anchor property][10] is set.
*/
static VALUE
strscan_fixed_anchor_p(VALUE self)
@@ -1514,14 +2080,32 @@ named_captures_iter(const OnigUChar *name,
}
/*
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
* call-seq:
- * scanner.named_captures -> hash
+ * named_captures -> hash
+ *
+ * Returns the array of captured match values at indexes (1..)
+ * if the most recent match attempt succeeded, or nil otherwise;
+ * see [Captured Match Values][13]:
+ *
+ * ```
+ * scanner = StringScanner.new('Fri Dec 12 1975 14:39')
+ * scanner.named_captures # => {}
+ *
+ * pattern = /(?<wday>\w+) (?<month>\w+) (?<day>\d+) /
+ * scanner.match?(pattern)
+ * scanner.named_captures # => {"wday"=>"Fri", "month"=>"Dec", "day"=>"12"}
+ *
+ * scanner.string = 'nope'
+ * scanner.match?(pattern)
+ * scanner.named_captures # => {"wday"=>nil, "month"=>nil, "day"=>nil}
*
- * Returns a hash of string variables matching the regular expression.
+ * scanner.match?(/nosuch/)
+ * scanner.named_captures # => {}
+ * ```
*
- * scan = StringScanner.new('foobarbaz')
- * scan.match?(/(?<f>foo)(?<r>bar)(?<z>baz)/)
- * scan.named_captures # -> {"f"=>"foo", "r"=>"bar", "z"=>"baz"}
*/
static VALUE
strscan_named_captures(VALUE self)
@@ -1545,107 +2129,11 @@ strscan_named_captures(VALUE self)
/*
* Document-class: StringScanner
*
- * StringScanner provides for lexical scanning operations on a String. Here is
- * an example of its usage:
- *
- * require 'strscan'
- *
- * s = StringScanner.new('This is an example string')
- * s.eos? # -> false
- *
- * p s.scan(/\w+/) # -> "This"
- * p s.scan(/\w+/) # -> nil
- * p s.scan(/\s+/) # -> " "
- * p s.scan(/\s+/) # -> nil
- * p s.scan(/\w+/) # -> "is"
- * s.eos? # -> false
- *
- * p s.scan(/\s+/) # -> " "
- * p s.scan(/\w+/) # -> "an"
- * p s.scan(/\s+/) # -> " "
- * p s.scan(/\w+/) # -> "example"
- * p s.scan(/\s+/) # -> " "
- * p s.scan(/\w+/) # -> "string"
- * s.eos? # -> true
- *
- * p s.scan(/\s+/) # -> nil
- * p s.scan(/\w+/) # -> nil
- *
- * Scanning a string means remembering the position of a <i>scan pointer</i>,
- * which is just an index. The point of scanning is to move forward a bit at
- * a time, so matches are sought after the scan pointer; usually immediately
- * after it.
- *
- * Given the string "test string", here are the pertinent scan pointer
- * positions:
- *
- * t e s t s t r i n g
- * 0 1 2 ... 1
- * 0
- *
- * When you #scan for a pattern (a regular expression), the match must occur
- * at the character after the scan pointer. If you use #scan_until, then the
- * match can occur anywhere after the scan pointer. In both cases, the scan
- * pointer moves <i>just beyond</i> the last character of the match, ready to
- * scan again from the next character onwards. This is demonstrated by the
- * example above.
- *
- * == Method Categories
- *
- * There are other methods besides the plain scanners. You can look ahead in
- * the string without actually scanning. You can access the most recent match.
- * You can modify the string being scanned, reset or terminate the scanner,
- * find out or change the position of the scan pointer, skip ahead, and so on.
- *
- * === Advancing the Scan Pointer
- *
- * - #getch
- * - #get_byte
- * - #scan
- * - #scan_until
- * - #skip
- * - #skip_until
- *
- * === Looking Ahead
- *
- * - #check
- * - #check_until
- * - #exist?
- * - #match?
- * - #peek
- *
- * === Finding Where we Are
- *
- * - #beginning_of_line? (<tt>#bol?</tt>)
- * - #eos?
- * - #rest?
- * - #rest_size
- * - #pos
- *
- * === Setting Where we Are
- *
- * - #reset
- * - #terminate
- * - #pos=
- *
- * === Match Data
- *
- * - #matched
- * - #matched?
- * - #matched_size
- * - <tt>#[]</tt>
- * - #pre_match
- * - #post_match
- *
- * === Miscellaneous
+ * :markup: markdown
*
- * - <tt><<</tt>
- * - #concat
- * - #string
- * - #string=
- * - #unscan
+ * :include: strscan/link_refs.txt
+ * :include: strscan/strscan.md
*
- * There are aliases to several of the methods.
*/
void
Init_strscan(void)
@@ -1704,7 +2192,9 @@ Init_strscan(void)
rb_define_method(StringScanner, "getch", strscan_getch, 0);
rb_define_method(StringScanner, "get_byte", strscan_get_byte, 0);
rb_define_method(StringScanner, "getbyte", strscan_getbyte, 0);
+ rb_define_method(StringScanner, "scan_byte", strscan_scan_byte, 0);
rb_define_method(StringScanner, "peek", strscan_peek, 1);
+ rb_define_method(StringScanner, "peek_byte", strscan_peek_byte, 0);
rb_define_method(StringScanner, "peep", strscan_peep, 1);
rb_define_method(StringScanner, "unscan", strscan_unscan, 0);
diff --git a/ext/strscan/strscan.gemspec b/ext/strscan/strscan.gemspec
index 8a61c7abe6..925edcd2d3 100644
--- a/ext/strscan/strscan.gemspec
+++ b/ext/strscan/strscan.gemspec
@@ -29,6 +29,11 @@ Gem::Specification.new do |s|
s.require_paths = %w{lib}
files << "ext/strscan/extconf.rb"
files << "ext/strscan/strscan.c"
+ s.rdoc_options << "-idoc"
+ s.extra_rdoc_files = [
+ ".rdoc_options",
+ *Dir.glob("doc/strscan/**/*")
+ ]
s.extensions = %w{ext/strscan/extconf.rb}
end
s.files = files
diff --git a/ext/syslog/depend b/ext/syslog/depend
deleted file mode 100644
index ee4ac5f47d..0000000000
--- a/ext/syslog/depend
+++ /dev/null
@@ -1,161 +0,0 @@
-# AUTOGENERATED DEPENDENCIES START
-syslog.o: $(RUBY_EXTCONF_H)
-syslog.o: $(arch_hdrdir)/ruby/config.h
-syslog.o: $(hdrdir)/ruby/assert.h
-syslog.o: $(hdrdir)/ruby/backward.h
-syslog.o: $(hdrdir)/ruby/backward/2/assume.h
-syslog.o: $(hdrdir)/ruby/backward/2/attributes.h
-syslog.o: $(hdrdir)/ruby/backward/2/bool.h
-syslog.o: $(hdrdir)/ruby/backward/2/inttypes.h
-syslog.o: $(hdrdir)/ruby/backward/2/limits.h
-syslog.o: $(hdrdir)/ruby/backward/2/long_long.h
-syslog.o: $(hdrdir)/ruby/backward/2/stdalign.h
-syslog.o: $(hdrdir)/ruby/backward/2/stdarg.h
-syslog.o: $(hdrdir)/ruby/defines.h
-syslog.o: $(hdrdir)/ruby/intern.h
-syslog.o: $(hdrdir)/ruby/internal/abi.h
-syslog.o: $(hdrdir)/ruby/internal/anyargs.h
-syslog.o: $(hdrdir)/ruby/internal/arithmetic.h
-syslog.o: $(hdrdir)/ruby/internal/arithmetic/char.h
-syslog.o: $(hdrdir)/ruby/internal/arithmetic/double.h
-syslog.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
-syslog.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
-syslog.o: $(hdrdir)/ruby/internal/arithmetic/int.h
-syslog.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
-syslog.o: $(hdrdir)/ruby/internal/arithmetic/long.h
-syslog.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
-syslog.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
-syslog.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
-syslog.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
-syslog.o: $(hdrdir)/ruby/internal/arithmetic/short.h
-syslog.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
-syslog.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
-syslog.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
-syslog.o: $(hdrdir)/ruby/internal/assume.h
-syslog.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
-syslog.o: $(hdrdir)/ruby/internal/attr/artificial.h
-syslog.o: $(hdrdir)/ruby/internal/attr/cold.h
-syslog.o: $(hdrdir)/ruby/internal/attr/const.h
-syslog.o: $(hdrdir)/ruby/internal/attr/constexpr.h
-syslog.o: $(hdrdir)/ruby/internal/attr/deprecated.h
-syslog.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
-syslog.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
-syslog.o: $(hdrdir)/ruby/internal/attr/error.h
-syslog.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
-syslog.o: $(hdrdir)/ruby/internal/attr/forceinline.h
-syslog.o: $(hdrdir)/ruby/internal/attr/format.h
-syslog.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
-syslog.o: $(hdrdir)/ruby/internal/attr/noalias.h
-syslog.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
-syslog.o: $(hdrdir)/ruby/internal/attr/noexcept.h
-syslog.o: $(hdrdir)/ruby/internal/attr/noinline.h
-syslog.o: $(hdrdir)/ruby/internal/attr/nonnull.h
-syslog.o: $(hdrdir)/ruby/internal/attr/noreturn.h
-syslog.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
-syslog.o: $(hdrdir)/ruby/internal/attr/pure.h
-syslog.o: $(hdrdir)/ruby/internal/attr/restrict.h
-syslog.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
-syslog.o: $(hdrdir)/ruby/internal/attr/warning.h
-syslog.o: $(hdrdir)/ruby/internal/attr/weakref.h
-syslog.o: $(hdrdir)/ruby/internal/cast.h
-syslog.o: $(hdrdir)/ruby/internal/compiler_is.h
-syslog.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
-syslog.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
-syslog.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
-syslog.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
-syslog.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
-syslog.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
-syslog.o: $(hdrdir)/ruby/internal/compiler_since.h
-syslog.o: $(hdrdir)/ruby/internal/config.h
-syslog.o: $(hdrdir)/ruby/internal/constant_p.h
-syslog.o: $(hdrdir)/ruby/internal/core.h
-syslog.o: $(hdrdir)/ruby/internal/core/rarray.h
-syslog.o: $(hdrdir)/ruby/internal/core/rbasic.h
-syslog.o: $(hdrdir)/ruby/internal/core/rbignum.h
-syslog.o: $(hdrdir)/ruby/internal/core/rclass.h
-syslog.o: $(hdrdir)/ruby/internal/core/rdata.h
-syslog.o: $(hdrdir)/ruby/internal/core/rfile.h
-syslog.o: $(hdrdir)/ruby/internal/core/rhash.h
-syslog.o: $(hdrdir)/ruby/internal/core/robject.h
-syslog.o: $(hdrdir)/ruby/internal/core/rregexp.h
-syslog.o: $(hdrdir)/ruby/internal/core/rstring.h
-syslog.o: $(hdrdir)/ruby/internal/core/rstruct.h
-syslog.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
-syslog.o: $(hdrdir)/ruby/internal/ctype.h
-syslog.o: $(hdrdir)/ruby/internal/dllexport.h
-syslog.o: $(hdrdir)/ruby/internal/dosish.h
-syslog.o: $(hdrdir)/ruby/internal/error.h
-syslog.o: $(hdrdir)/ruby/internal/eval.h
-syslog.o: $(hdrdir)/ruby/internal/event.h
-syslog.o: $(hdrdir)/ruby/internal/fl_type.h
-syslog.o: $(hdrdir)/ruby/internal/gc.h
-syslog.o: $(hdrdir)/ruby/internal/glob.h
-syslog.o: $(hdrdir)/ruby/internal/globals.h
-syslog.o: $(hdrdir)/ruby/internal/has/attribute.h
-syslog.o: $(hdrdir)/ruby/internal/has/builtin.h
-syslog.o: $(hdrdir)/ruby/internal/has/c_attribute.h
-syslog.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
-syslog.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
-syslog.o: $(hdrdir)/ruby/internal/has/extension.h
-syslog.o: $(hdrdir)/ruby/internal/has/feature.h
-syslog.o: $(hdrdir)/ruby/internal/has/warning.h
-syslog.o: $(hdrdir)/ruby/internal/intern/array.h
-syslog.o: $(hdrdir)/ruby/internal/intern/bignum.h
-syslog.o: $(hdrdir)/ruby/internal/intern/class.h
-syslog.o: $(hdrdir)/ruby/internal/intern/compar.h
-syslog.o: $(hdrdir)/ruby/internal/intern/complex.h
-syslog.o: $(hdrdir)/ruby/internal/intern/cont.h
-syslog.o: $(hdrdir)/ruby/internal/intern/dir.h
-syslog.o: $(hdrdir)/ruby/internal/intern/enum.h
-syslog.o: $(hdrdir)/ruby/internal/intern/enumerator.h
-syslog.o: $(hdrdir)/ruby/internal/intern/error.h
-syslog.o: $(hdrdir)/ruby/internal/intern/eval.h
-syslog.o: $(hdrdir)/ruby/internal/intern/file.h
-syslog.o: $(hdrdir)/ruby/internal/intern/hash.h
-syslog.o: $(hdrdir)/ruby/internal/intern/io.h
-syslog.o: $(hdrdir)/ruby/internal/intern/load.h
-syslog.o: $(hdrdir)/ruby/internal/intern/marshal.h
-syslog.o: $(hdrdir)/ruby/internal/intern/numeric.h
-syslog.o: $(hdrdir)/ruby/internal/intern/object.h
-syslog.o: $(hdrdir)/ruby/internal/intern/parse.h
-syslog.o: $(hdrdir)/ruby/internal/intern/proc.h
-syslog.o: $(hdrdir)/ruby/internal/intern/process.h
-syslog.o: $(hdrdir)/ruby/internal/intern/random.h
-syslog.o: $(hdrdir)/ruby/internal/intern/range.h
-syslog.o: $(hdrdir)/ruby/internal/intern/rational.h
-syslog.o: $(hdrdir)/ruby/internal/intern/re.h
-syslog.o: $(hdrdir)/ruby/internal/intern/ruby.h
-syslog.o: $(hdrdir)/ruby/internal/intern/select.h
-syslog.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
-syslog.o: $(hdrdir)/ruby/internal/intern/signal.h
-syslog.o: $(hdrdir)/ruby/internal/intern/sprintf.h
-syslog.o: $(hdrdir)/ruby/internal/intern/string.h
-syslog.o: $(hdrdir)/ruby/internal/intern/struct.h
-syslog.o: $(hdrdir)/ruby/internal/intern/thread.h
-syslog.o: $(hdrdir)/ruby/internal/intern/time.h
-syslog.o: $(hdrdir)/ruby/internal/intern/variable.h
-syslog.o: $(hdrdir)/ruby/internal/intern/vm.h
-syslog.o: $(hdrdir)/ruby/internal/interpreter.h
-syslog.o: $(hdrdir)/ruby/internal/iterator.h
-syslog.o: $(hdrdir)/ruby/internal/memory.h
-syslog.o: $(hdrdir)/ruby/internal/method.h
-syslog.o: $(hdrdir)/ruby/internal/module.h
-syslog.o: $(hdrdir)/ruby/internal/newobj.h
-syslog.o: $(hdrdir)/ruby/internal/scan_args.h
-syslog.o: $(hdrdir)/ruby/internal/special_consts.h
-syslog.o: $(hdrdir)/ruby/internal/static_assert.h
-syslog.o: $(hdrdir)/ruby/internal/stdalign.h
-syslog.o: $(hdrdir)/ruby/internal/stdbool.h
-syslog.o: $(hdrdir)/ruby/internal/symbol.h
-syslog.o: $(hdrdir)/ruby/internal/value.h
-syslog.o: $(hdrdir)/ruby/internal/value_type.h
-syslog.o: $(hdrdir)/ruby/internal/variable.h
-syslog.o: $(hdrdir)/ruby/internal/warning_push.h
-syslog.o: $(hdrdir)/ruby/internal/xmalloc.h
-syslog.o: $(hdrdir)/ruby/missing.h
-syslog.o: $(hdrdir)/ruby/ruby.h
-syslog.o: $(hdrdir)/ruby/st.h
-syslog.o: $(hdrdir)/ruby/subst.h
-syslog.o: $(hdrdir)/ruby/util.h
-syslog.o: syslog.c
-# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/syslog/extconf.rb b/ext/syslog/extconf.rb
deleted file mode 100644
index 1230a4d52e..0000000000
--- a/ext/syslog/extconf.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: false
-# $RoughId: extconf.rb,v 1.3 2001/11/24 17:49:26 knu Exp $
-# $Id$
-
-require 'mkmf'
-
-have_library("log") # for Android
-
-have_header("syslog.h") &&
- have_func("openlog") &&
- have_func("setlogmask") &&
- create_makefile("syslog")
-
diff --git a/ext/syslog/lib/syslog/logger.rb b/ext/syslog/lib/syslog/logger.rb
deleted file mode 100644
index 453ca2785c..0000000000
--- a/ext/syslog/lib/syslog/logger.rb
+++ /dev/null
@@ -1,209 +0,0 @@
-# frozen_string_literal: false
-require 'syslog'
-require 'logger'
-
-##
-# Syslog::Logger is a Logger work-alike that logs via syslog instead of to a
-# file. You can use Syslog::Logger to aggregate logs between multiple
-# machines.
-#
-# By default, Syslog::Logger uses the program name 'ruby', but this can be
-# changed via the first argument to Syslog::Logger.new.
-#
-# NOTE! You can only set the Syslog::Logger program name when you initialize
-# Syslog::Logger for the first time. This is a limitation of the way
-# Syslog::Logger uses syslog (and in some ways, a limitation of the way
-# syslog(3) works). Attempts to change Syslog::Logger's program name after
-# the first initialization will be ignored.
-#
-# === Example
-#
-# The following will log to syslogd on your local machine:
-#
-# require 'syslog/logger'
-#
-# log = Syslog::Logger.new 'my_program'
-# log.info 'this line will be logged via syslog(3)'
-#
-# Also the facility may be set to specify the facility level which will be used:
-#
-# log.info 'this line will be logged using Syslog default facility level'
-#
-# log_local1 = Syslog::Logger.new 'my_program', Syslog::LOG_LOCAL1
-# log_local1.info 'this line will be logged using local1 facility level'
-#
-#
-# You may need to perform some syslog.conf setup first. For a BSD machine add
-# the following lines to /etc/syslog.conf:
-#
-# !my_program
-# *.* /var/log/my_program.log
-#
-# Then touch /var/log/my_program.log and signal syslogd with a HUP
-# (killall -HUP syslogd, on FreeBSD).
-#
-# If you wish to have logs automatically roll over and archive, see the
-# newsyslog.conf(5) and newsyslog(8) man pages.
-
-class Syslog::Logger
- # Default formatter for log messages.
- class Formatter
- def call severity, time, progname, msg
- clean msg
- end
-
- private
-
- ##
- # Clean up messages so they're nice and pretty.
-
- def clean message
- message = message.to_s.strip
- message.gsub!(/\e\[[0-9;]*m/, '') # remove useless ansi color codes
- return message
- end
- end
-
- ##
- # The version of Syslog::Logger you are using.
-
- VERSION = '2.1.0'
-
- ##
- # Maps Logger warning types to syslog(3) warning types.
- #
- # Messages from Ruby applications are not considered as critical as messages
- # from other system daemons using syslog(3), so most messages are reduced by
- # one level. For example, a fatal message for Ruby's Logger is considered
- # an error for syslog(3).
-
- LEVEL_MAP = {
- ::Logger::UNKNOWN => Syslog::LOG_ALERT,
- ::Logger::FATAL => Syslog::LOG_ERR,
- ::Logger::ERROR => Syslog::LOG_WARNING,
- ::Logger::WARN => Syslog::LOG_NOTICE,
- ::Logger::INFO => Syslog::LOG_INFO,
- ::Logger::DEBUG => Syslog::LOG_DEBUG,
- }
-
- ##
- # Returns the internal Syslog object that is initialized when the
- # first instance is created.
-
- def self.syslog
- @@syslog
- end
-
- ##
- # Specifies the internal Syslog object to be used.
-
- def self.syslog= syslog
- @@syslog = syslog
- end
-
- ##
- # Builds a methods for level +meth+.
-
- def self.make_methods meth
- level = ::Logger.const_get(meth.upcase)
- eval <<-EOM, nil, __FILE__, __LINE__ + 1
- def #{meth}(message = nil, &block)
- add(#{level}, message, &block)
- end
-
- def #{meth}?
- level <= #{level}
- end
- EOM
- end
-
- ##
- # :method: unknown
- #
- # Logs a +message+ at the unknown (syslog alert) log level, or logs the
- # message returned from the block.
-
- ##
- # :method: fatal
- #
- # Logs a +message+ at the fatal (syslog err) log level, or logs the message
- # returned from the block.
-
- ##
- # :method: error
- #
- # Logs a +message+ at the error (syslog warning) log level, or logs the
- # message returned from the block.
-
- ##
- # :method: warn
- #
- # Logs a +message+ at the warn (syslog notice) log level, or logs the
- # message returned from the block.
-
- ##
- # :method: info
- #
- # Logs a +message+ at the info (syslog info) log level, or logs the message
- # returned from the block.
-
- ##
- # :method: debug
- #
- # Logs a +message+ at the debug (syslog debug) log level, or logs the
- # message returned from the block.
-
- Logger::Severity::constants.each do |severity|
- make_methods severity.downcase
- end
-
- ##
- # Log level for Logger compatibility.
-
- attr_accessor :level
-
- # Logging formatter, as a +Proc+ that will take four arguments and
- # return the formatted message. The arguments are:
- #
- # +severity+:: The Severity of the log message.
- # +time+:: A Time instance representing when the message was logged.
- # +progname+:: The #progname configured, or passed to the logger method.
- # +msg+:: The _Object_ the user passed to the log message; not necessarily a
- # String.
- #
- # The block should return an Object that can be written to the logging
- # device via +write+. The default formatter is used when no formatter is
- # set.
- attr_accessor :formatter
-
- ##
- # The facility argument is used to specify what type of program is logging the message.
-
- attr_accessor :facility
-
- ##
- # Fills in variables for Logger compatibility. If this is the first
- # instance of Syslog::Logger, +program_name+ may be set to change the logged
- # program name. The +facility+ may be set to specify the facility level which will be used.
- #
- # Due to the way syslog works, only one program name may be chosen.
-
- def initialize program_name = 'ruby', facility = nil
- @level = ::Logger::DEBUG
- @formatter = Formatter.new
-
- @@syslog ||= Syslog.open(program_name)
-
- @facility = (facility || @@syslog.facility)
- end
-
- ##
- # Almost duplicates Logger#add. +progname+ is ignored.
-
- def add severity, message = nil, progname = nil, &block
- severity ||= ::Logger::UNKNOWN
- level <= severity and
- @@syslog.log( (LEVEL_MAP[severity] | @facility), '%s', formatter.call(severity, Time.now, progname, (message || block.call)) )
- true
- end
-end
diff --git a/ext/syslog/syslog.c b/ext/syslog/syslog.c
deleted file mode 100644
index 6a97c15811..0000000000
--- a/ext/syslog/syslog.c
+++ /dev/null
@@ -1,592 +0,0 @@
-/*
- * UNIX Syslog extension for Ruby
- * Amos Gouaux, University of Texas at Dallas
- * <amos+ruby@utdallas.edu>
- * Documented by mathew <meta@pobox.com>
- *
- * $RoughId: syslog.c,v 1.21 2002/02/25 12:21:17 knu Exp $
- * $Id$
- */
-
-#include "ruby/ruby.h"
-#include "ruby/util.h"
-#include <syslog.h>
-
-#define SYSLOG_VERSION "0.1.1"
-
-/* Syslog class */
-static VALUE mSyslog;
-/*
- * Module holding all Syslog constants. See Syslog::log and
- * Syslog::open for constant descriptions.
- */
-static VALUE mSyslogConstants;
-/* Module holding Syslog option constants */
-static VALUE mSyslogOption;
-/* Module holding Syslog facility constants */
-static VALUE mSyslogFacility;
-/* Module holding Syslog level constants */
-static VALUE mSyslogLevel;
-/* Module holding Syslog utility macros */
-static VALUE mSyslogMacros;
-
-static const char *syslog_ident = NULL;
-static int syslog_options = -1, syslog_facility = -1, syslog_mask = -1;
-static int syslog_opened = 0;
-
-/* Package helper routines */
-static void syslog_write(int pri, int argc, VALUE *argv)
-{
- VALUE str;
-
- if (argc < 1) {
- rb_raise(rb_eArgError, "no log message supplied");
- }
-
- if (!syslog_opened) {
- rb_raise(rb_eRuntimeError, "must open syslog before write");
- }
-
- str = rb_f_sprintf(argc, argv);
-
- syslog(pri, "%s", RSTRING_PTR(str));
-}
-
-/* Closes the syslog facility.
- * Raises a runtime exception if it is not open.
- */
-static VALUE mSyslog_close(VALUE self)
-{
- if (!syslog_opened) {
- rb_raise(rb_eRuntimeError, "syslog not opened");
- }
-
- closelog();
-
- xfree((void *)syslog_ident);
- syslog_ident = NULL;
- syslog_options = syslog_facility = syslog_mask = -1;
- syslog_opened = 0;
-
- return Qnil;
-}
-
-/* call-seq:
- * open(ident, options, facility) => syslog
- *
- * :yields: syslog
- *
- * Open the syslog facility.
- * Raises a runtime exception if it is already open.
- *
- * Can be called with or without a code block. If called with a block, the
- * Syslog object created is passed to the block.
- *
- * If the syslog is already open, raises a RuntimeError.
- *
- * +ident+ is a String which identifies the calling program.
- *
- * +options+ is the logical OR of any of the following:
- *
- * LOG_CONS:: If there is an error while sending to the system logger,
- * write directly to the console instead.
- *
- * LOG_NDELAY:: Open the connection now, rather than waiting for the first
- * message to be written.
- *
- * LOG_NOWAIT:: Don't wait for any child processes created while logging
- * messages. (Has no effect on Linux.)
- *
- * LOG_ODELAY:: Opposite of LOG_NDELAY; wait until a message is sent before
- * opening the connection. (This is the default.)
- *
- * LOG_PERROR:: Print the message to stderr as well as sending it to syslog.
- * (Not in POSIX.1-2001.)
- *
- * LOG_PID:: Include the current process ID with each message.
- *
- * +facility+ describes the type of program opening the syslog, and is
- * the logical OR of any of the following which are defined for the host OS:
- *
- * LOG_AUTH:: Security or authorization. Deprecated, use LOG_AUTHPRIV
- * instead.
- *
- * LOG_AUTHPRIV:: Security or authorization messages which should be kept
- * private.
- *
- * LOG_CONSOLE:: System console message.
- *
- * LOG_CRON:: System task scheduler (cron or at).
- *
- * LOG_DAEMON:: A system daemon which has no facility value of its own.
- *
- * LOG_FTP:: An FTP server.
- *
- * LOG_KERN:: A kernel message (not sendable by user processes, so not of
- * much use to Ruby, but listed here for completeness).
- *
- * LOG_LPR:: Line printer subsystem.
- *
- * LOG_MAIL:: Mail delivery or transport subsystem.
- *
- * LOG_NEWS:: Usenet news system.
- *
- * LOG_NTP:: Network Time Protocol server.
- *
- * LOG_SECURITY:: General security message.
- *
- * LOG_SYSLOG:: Messages generated internally by syslog.
- *
- * LOG_USER:: Generic user-level message.
- *
- * LOG_UUCP:: UUCP subsystem.
- *
- * LOG_LOCAL0 to LOG_LOCAL7:: Locally-defined facilities.
- *
- * Example:
- *
- * Syslog.open("webrick", Syslog::LOG_PID,
- * Syslog::LOG_DAEMON | Syslog::LOG_LOCAL3)
- *
- */
-static VALUE mSyslog_open(int argc, VALUE *argv, VALUE self)
-{
- VALUE ident, opt, fac;
- const char *ident_ptr;
-
- if (syslog_opened) {
- rb_raise(rb_eRuntimeError, "syslog already open");
- }
-
- rb_scan_args(argc, argv, "03", &ident, &opt, &fac);
-
- if (NIL_P(ident)) {
- ident = rb_gv_get("$0");
- }
- ident_ptr = StringValueCStr(ident);
- syslog_ident = strdup(ident_ptr);
-
- if (NIL_P(opt)) {
- syslog_options = LOG_PID | LOG_CONS;
- } else {
- syslog_options = NUM2INT(opt);
- }
-
- if (NIL_P(fac)) {
- syslog_facility = LOG_USER;
- } else {
- syslog_facility = NUM2INT(fac);
- }
-
- openlog(syslog_ident, syslog_options, syslog_facility);
-
- syslog_opened = 1;
-
- setlogmask(syslog_mask = setlogmask(0));
-
- /* be like File.new.open {...} */
- if (rb_block_given_p()) {
- rb_ensure(rb_yield, self, mSyslog_close, self);
- }
-
- return self;
-}
-
-/* call-seq:
- * reopen(ident, options, facility) => syslog
- *
- * :yields: syslog
- *
- * Closes and then reopens the syslog.
- *
- * Arguments are the same as for open().
- */
-static VALUE mSyslog_reopen(int argc, VALUE *argv, VALUE self)
-{
- mSyslog_close(self);
-
- return mSyslog_open(argc, argv, self);
-}
-
-/* call-seq:
- * opened?
- *
- * Returns true if the syslog is open.
- */
-static VALUE mSyslog_isopen(VALUE self)
-{
- return syslog_opened ? Qtrue : Qfalse;
-}
-
-/* Returns the identity string used in the last call to open()
- */
-static VALUE mSyslog_ident(VALUE self)
-{
- return syslog_opened ? rb_str_new2(syslog_ident) : Qnil;
-}
-
-/* Returns the options bitmask used in the last call to open()
- */
-static VALUE mSyslog_options(VALUE self)
-{
- return syslog_opened ? INT2NUM(syslog_options) : Qnil;
-}
-
-/* Returns the facility number used in the last call to open()
- */
-static VALUE mSyslog_facility(VALUE self)
-{
- return syslog_opened ? INT2NUM(syslog_facility) : Qnil;
-}
-
-/* Returns the log priority mask in effect. The mask is not reset by opening
- * or closing syslog.
- */
-static VALUE mSyslog_get_mask(VALUE self)
-{
- return syslog_opened ? INT2NUM(syslog_mask) : Qnil;
-}
-
-/* call-seq:
- * mask=(priority_mask)
- *
- * Sets the log priority mask. A method LOG_UPTO is defined to make it easier
- * to set mask values. Example:
- *
- * Syslog.mask = Syslog::LOG_UPTO(Syslog::LOG_ERR)
- *
- * Alternatively, specific priorities can be selected and added together using
- * binary OR. Example:
- *
- * Syslog.mask = Syslog::LOG_MASK(Syslog::LOG_ERR) | Syslog::LOG_MASK(Syslog::LOG_CRIT)
- *
- * The priority mask persists through calls to open() and close().
- */
-static VALUE mSyslog_set_mask(VALUE self, VALUE mask)
-{
- if (!syslog_opened) {
- rb_raise(rb_eRuntimeError, "must open syslog before setting log mask");
- }
-
- setlogmask(syslog_mask = NUM2INT(mask));
-
- return mask;
-}
-
-/* call-seq:
- * log(priority, format_string, *format_args)
- *
- * Log a message with the specified priority. Example:
- *
- * Syslog.log(Syslog::LOG_CRIT, "Out of disk space")
- * Syslog.log(Syslog::LOG_CRIT, "User %s logged in", ENV['USER'])
- *
- * The priority levels, in descending order, are:
- *
- * LOG_EMERG:: System is unusable
- * LOG_ALERT:: Action needs to be taken immediately
- * LOG_CRIT:: A critical condition has occurred
- * LOG_ERR:: An error occurred
- * LOG_WARNING:: Warning of a possible problem
- * LOG_NOTICE:: A normal but significant condition occurred
- * LOG_INFO:: Informational message
- * LOG_DEBUG:: Debugging information
- *
- * Each priority level also has a shortcut method that logs with it's named priority.
- * As an example, the two following statements would produce the same result:
- *
- * Syslog.log(Syslog::LOG_ALERT, "Out of memory")
- * Syslog.alert("Out of memory")
- *
- */
-static VALUE mSyslog_log(int argc, VALUE *argv, VALUE self)
-{
- VALUE pri;
-
- rb_check_arity(argc, 2, UNLIMITED_ARGUMENTS);
-
- argc--;
- pri = *argv++;
-
- if (!FIXNUM_P(pri)) {
- rb_raise(rb_eTypeError, "type mismatch: %"PRIsVALUE" given", rb_obj_class(pri));
- }
-
- syslog_write(FIX2INT(pri), argc, argv);
-
- return self;
-}
-
-/* Returns an inspect() string summarizing the object state.
- */
-static VALUE mSyslog_inspect(VALUE self)
-{
- Check_Type(self, T_MODULE);
-
- if (!syslog_opened)
- return rb_sprintf("<#%"PRIsVALUE": opened=false>", self);
-
- return rb_sprintf("<#%"PRIsVALUE": opened=true, ident=\"%s\", options=%d, facility=%d, mask=%d>",
- self,
- syslog_ident,
- syslog_options,
- syslog_facility,
- syslog_mask);
-}
-
-/* Returns self, for backward compatibility.
- */
-static VALUE mSyslog_instance(VALUE self)
-{
- return self;
-}
-
-#define define_syslog_shortcut_method(pri, name) \
-static VALUE mSyslog_##name(int argc, VALUE *argv, VALUE self) \
-{ \
- syslog_write((pri), argc, argv); \
-\
- return self; \
-}
-
-#ifdef LOG_EMERG
-define_syslog_shortcut_method(LOG_EMERG, emerg)
-#endif
-#ifdef LOG_ALERT
-define_syslog_shortcut_method(LOG_ALERT, alert)
-#endif
-#ifdef LOG_CRIT
-define_syslog_shortcut_method(LOG_CRIT, crit)
-#endif
-#ifdef LOG_ERR
-define_syslog_shortcut_method(LOG_ERR, err)
-#endif
-#ifdef LOG_WARNING
-define_syslog_shortcut_method(LOG_WARNING, warning)
-#endif
-#ifdef LOG_NOTICE
-define_syslog_shortcut_method(LOG_NOTICE, notice)
-#endif
-#ifdef LOG_INFO
-define_syslog_shortcut_method(LOG_INFO, info)
-#endif
-#ifdef LOG_DEBUG
-define_syslog_shortcut_method(LOG_DEBUG, debug)
-#endif
-
-/* call-seq:
- * LOG_MASK(priority_level) => priority_mask
- *
- * Generates a mask bit for a priority level. See #mask=
- */
-static VALUE mSyslogMacros_LOG_MASK(VALUE mod, VALUE pri)
-{
- return INT2FIX(LOG_MASK(NUM2INT(pri)));
-}
-
-/* call-seq:
- * LOG_UPTO(priority_level) => priority_mask
- *
- * Generates a mask value for priority levels at or below the level specified.
- * See #mask=
- */
-static VALUE mSyslogMacros_LOG_UPTO(VALUE mod, VALUE pri)
-{
- return INT2FIX(LOG_UPTO(NUM2INT(pri)));
-}
-
-static VALUE mSyslogMacros_included(VALUE mod, VALUE target)
-{
- rb_extend_object(target, mSyslogMacros);
- return mod;
-}
-
-/* The syslog package provides a Ruby interface to the POSIX system logging
- * facility.
- *
- * Syslog messages are typically passed to a central logging daemon.
- * The daemon may filter them; route them into different files (usually
- * found under /var/log); place them in SQL databases; forward
- * them to centralized logging servers via TCP or UDP; or even alert the
- * system administrator via email, pager or text message.
- *
- * Unlike application-level logging via Logger or Log4r, syslog is designed
- * to allow secure tamper-proof logging.
- *
- * The syslog protocol is standardized in RFC 5424.
- */
-void Init_syslog(void)
-{
-#undef rb_intern
- mSyslog = rb_define_module("Syslog");
-
- mSyslogConstants = rb_define_module_under(mSyslog, "Constants");
-
- mSyslogOption = rb_define_module_under(mSyslog, "Option");
- mSyslogFacility = rb_define_module_under(mSyslog, "Facility");
- mSyslogLevel = rb_define_module_under(mSyslog, "Level");
- mSyslogMacros = rb_define_module_under(mSyslog, "Macros");
-
- rb_define_module_function(mSyslog, "open", mSyslog_open, -1);
- rb_define_module_function(mSyslog, "reopen", mSyslog_reopen, -1);
- rb_define_module_function(mSyslog, "open!", mSyslog_reopen, -1);
- rb_define_module_function(mSyslog, "opened?", mSyslog_isopen, 0);
-
- rb_define_module_function(mSyslog, "ident", mSyslog_ident, 0);
- rb_define_module_function(mSyslog, "options", mSyslog_options, 0);
- rb_define_module_function(mSyslog, "facility", mSyslog_facility, 0);
-
- rb_define_module_function(mSyslog, "log", mSyslog_log, -1);
- rb_define_module_function(mSyslog, "close", mSyslog_close, 0);
- rb_define_module_function(mSyslog, "mask", mSyslog_get_mask, 0);
- rb_define_module_function(mSyslog, "mask=", mSyslog_set_mask, 1);
-
- rb_define_singleton_method(mSyslog, "inspect", mSyslog_inspect, 0);
- rb_define_module_function(mSyslog, "instance", mSyslog_instance, 0);
-
- /* Syslog options */
-
-#define rb_define_syslog_option(c) \
- rb_define_const(mSyslogOption, #c, INT2NUM(c))
-
-#ifdef LOG_PID
- rb_define_syslog_option(LOG_PID);
-#endif
-#ifdef LOG_CONS
- rb_define_syslog_option(LOG_CONS);
-#endif
-#ifdef LOG_ODELAY
- rb_define_syslog_option(LOG_ODELAY); /* deprecated */
-#endif
-#ifdef LOG_NDELAY
- rb_define_syslog_option(LOG_NDELAY);
-#endif
-#ifdef LOG_NOWAIT
- rb_define_syslog_option(LOG_NOWAIT); /* deprecated */
-#endif
-#ifdef LOG_PERROR
- rb_define_syslog_option(LOG_PERROR);
-#endif
-
- /* Syslog facilities */
-
-#define rb_define_syslog_facility(c) \
- rb_define_const(mSyslogFacility, #c, INT2NUM(c))
-
-#ifdef LOG_AUTH
- rb_define_syslog_facility(LOG_AUTH);
-#endif
-#ifdef LOG_AUTHPRIV
- rb_define_syslog_facility(LOG_AUTHPRIV);
-#endif
-#ifdef LOG_CONSOLE
- rb_define_syslog_facility(LOG_CONSOLE);
-#endif
-#ifdef LOG_CRON
- rb_define_syslog_facility(LOG_CRON);
-#endif
-#ifdef LOG_DAEMON
- rb_define_syslog_facility(LOG_DAEMON);
-#endif
-#ifdef LOG_FTP
- rb_define_syslog_facility(LOG_FTP);
-#endif
-#ifdef LOG_KERN
- rb_define_syslog_facility(LOG_KERN);
-#endif
-#ifdef LOG_LPR
- rb_define_syslog_facility(LOG_LPR);
-#endif
-#ifdef LOG_MAIL
- rb_define_syslog_facility(LOG_MAIL);
-#endif
-#ifdef LOG_NEWS
- rb_define_syslog_facility(LOG_NEWS);
-#endif
-#ifdef LOG_NTP
- rb_define_syslog_facility(LOG_NTP);
-#endif
-#ifdef LOG_SECURITY
- rb_define_syslog_facility(LOG_SECURITY);
-#endif
-#ifdef LOG_SYSLOG
- rb_define_syslog_facility(LOG_SYSLOG);
-#endif
-#ifdef LOG_USER
- rb_define_syslog_facility(LOG_USER);
-#endif
-#ifdef LOG_UUCP
- rb_define_syslog_facility(LOG_UUCP);
-#endif
-#ifdef LOG_LOCAL0
- rb_define_syslog_facility(LOG_LOCAL0);
-#endif
-#ifdef LOG_LOCAL1
- rb_define_syslog_facility(LOG_LOCAL1);
-#endif
-#ifdef LOG_LOCAL2
- rb_define_syslog_facility(LOG_LOCAL2);
-#endif
-#ifdef LOG_LOCAL3
- rb_define_syslog_facility(LOG_LOCAL3);
-#endif
-#ifdef LOG_LOCAL4
- rb_define_syslog_facility(LOG_LOCAL4);
-#endif
-#ifdef LOG_LOCAL5
- rb_define_syslog_facility(LOG_LOCAL5);
-#endif
-#ifdef LOG_LOCAL6
- rb_define_syslog_facility(LOG_LOCAL6);
-#endif
-#ifdef LOG_LOCAL7
- rb_define_syslog_facility(LOG_LOCAL7);
-#endif
-
- /* Syslog levels and the shortcut methods */
-
-#define rb_define_syslog_level(c, m) \
- rb_define_const(mSyslogLevel, #c, INT2NUM(c)); \
- rb_define_module_function(mSyslog, #m, mSyslog_##m, -1)
-
-#ifdef LOG_EMERG
- rb_define_syslog_level(LOG_EMERG, emerg);
-#endif
-#ifdef LOG_ALERT
- rb_define_syslog_level(LOG_ALERT, alert);
-#endif
-#ifdef LOG_CRIT
- rb_define_syslog_level(LOG_CRIT, crit);
-#endif
-#ifdef LOG_ERR
- rb_define_syslog_level(LOG_ERR, err);
-#endif
-#ifdef LOG_WARNING
- rb_define_syslog_level(LOG_WARNING, warning);
-#endif
-#ifdef LOG_NOTICE
- rb_define_syslog_level(LOG_NOTICE, notice);
-#endif
-#ifdef LOG_INFO
- rb_define_syslog_level(LOG_INFO, info);
-#endif
-#ifdef LOG_DEBUG
- rb_define_syslog_level(LOG_DEBUG, debug);
-#endif
-
- /* Syslog macros */
-
- rb_define_const(mSyslog, "VERSION", rb_str_new_cstr(SYSLOG_VERSION));
-
- rb_define_method(mSyslogMacros, "LOG_MASK", mSyslogMacros_LOG_MASK, 1);
- rb_define_method(mSyslogMacros, "LOG_UPTO", mSyslogMacros_LOG_UPTO, 1);
- rb_define_singleton_method(mSyslogMacros, "included", mSyslogMacros_included, 1);
-
- rb_include_module(mSyslogConstants, mSyslogOption);
- rb_include_module(mSyslogConstants, mSyslogFacility);
- rb_include_module(mSyslogConstants, mSyslogLevel);
- rb_funcall(mSyslogConstants, rb_intern("include"), 1, mSyslogMacros);
-
- rb_define_singleton_method(mSyslogConstants, "included", mSyslogMacros_included, 1);
- rb_funcall(mSyslog, rb_intern("include"), 1, mSyslogConstants);
-}
diff --git a/ext/syslog/syslog.gemspec b/ext/syslog/syslog.gemspec
deleted file mode 100644
index 10a6d1f25c..0000000000
--- a/ext/syslog/syslog.gemspec
+++ /dev/null
@@ -1,28 +0,0 @@
-source_version = %w[. ext/syslog].find do |dir|
- break $1 if File.foreach(File.join(__dir__, dir, "syslog.c")).any?(/^#define\s+SYSLOG_VERSION\s+"(.+)"/)
-rescue Errno::ENOENT
-end
-
-Gem::Specification.new do |spec|
- spec.name = "syslog"
- spec.version = source_version
- spec.authors = ["Akinori MUSHA"]
- spec.email = ["knu@idaemons.org"]
-
- spec.summary = %q{Ruby interface for the POSIX system logging facility.}
- spec.description = %q{Ruby interface for the POSIX system logging facility.}
- spec.homepage = "https://github.com/ruby/syslog"
- spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
- spec.licenses = ["Ruby", "BSD-2-Clause"]
-
- spec.metadata["homepage_uri"] = spec.homepage
- spec.metadata["source_code_uri"] = spec.homepage
-
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
- end
- spec.extensions = ["ext/syslog/extconf.rb"]
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
- spec.require_paths = ["lib"]
-end
diff --git a/ext/syslog/syslog.txt b/ext/syslog/syslog.txt
deleted file mode 100644
index 1507a87924..0000000000
--- a/ext/syslog/syslog.txt
+++ /dev/null
@@ -1,124 +0,0 @@
-.\" syslog.txt - -*- Indented-Text -*-
-$RoughId: syslog.txt,v 1.18 2002/02/25 08:20:14 knu Exp $
-$Id$
-
-UNIX Syslog extension for Ruby
-Amos Gouaux, University of Texas at Dallas
-<amos+ruby@utdallas.edu>
-&
-Akinori MUSHA
-<knu@iDaemons.org>
-
-Contact:
- - Akinori MUSHA <knu@iDaemons.org> (current maintainer)
-
-** Syslog(Module)
-
-Included Modules: Syslog::Constants
-
-require 'syslog'
-
-A Simple wrapper for the UNIX syslog system calls that might be handy
-if you're writing a server in Ruby. For the details of the syslog(8)
-architecture and constants, see the syslog(3) manual page of your
-platform.
-
-Module Methods:
-
- open(ident = $0, logopt = Syslog::LOG_PID | Syslog::LOG_CONS,
- facility = Syslog::LOG_USER) [{ |syslog| ... }]
-
- Opens syslog with the given options and returns the module
- itself. If a block is given, calls it with an argument of
- itself. If syslog is already opened, raises RuntimeError.
-
- Example:
- Syslog.open('ftpd', Syslog::LOG_PID | Syslog::LOG_NDELAY,
- Syslog::LOG_FTP)
-
- open!(ident = $0, logopt = Syslog::LOG_PID | Syslog::LOG_CONS,
- facility = Syslog::LOG_USER)
- reopen(ident = $0, logopt = Syslog::LOG_PID | Syslog::LOG_CONS,
- facility = Syslog::LOG_USER)
-
- Same as open, but does a close first.
-
- opened?
-
- Returns true if syslog opened, otherwise false.
-
- ident
- options
- facility
-
- Returns the parameters given in the last open, respectively.
- Every call of Syslog::open resets these values.
-
- log(pri, message, ...)
-
- Writes message to syslog.
-
- Example:
- Syslog.log(Syslog::LOG_CRIT, "the sky is falling in %d seconds!", 10)
-
- crit(message, ...)
- emerg(message, ...)
- alert(message, ...)
- err(message, ...)
- warning(message, ...)
- notice(message, ...)
- info(message, ...)
- debug(message, ...)
-
- These are shortcut methods of Syslog::log(). The lineup may
- vary depending on what priorities are defined on your system.
-
- Example:
- Syslog.crit("the sky is falling in %d seconds!", 5)
-
- mask
- mask=(mask)
-
- Returns or sets the log priority mask. The value of the mask
- is persistent and will not be reset by Syslog::open or
- Syslog::close.
-
- Example:
- Syslog.mask = Syslog::LOG_UPTO(Syslog::LOG_ERR)
-
- close
-
- Closes syslog.
-
- inspect
-
- Returns the "inspect" string of the Syslog module.
-
- instance
-
- Returns the module itself. (Just for backward compatibility)
-
- LOG_MASK(pri)
-
- Creates a mask for one priority.
-
- LOG_UPTO(pri)
-
- Creates a mask for all priorities up to pri.
-
-** Syslog::Constants(Module)
-
-require 'syslog'
-include Syslog::Constants
-
-This module includes the LOG_* constants available on the system.
-
-Module Methods:
-
- LOG_MASK(pri)
-
- Creates a mask for one priority.
-
- LOG_UPTO(pri)
-
- Creates a mask for all priorities up to pri.
diff --git a/ext/win32/lib/win32/registry.rb b/ext/win32/lib/win32/registry.rb
index b5b99ff684..92b95d1bf7 100644
--- a/ext/win32/lib/win32/registry.rb
+++ b/ext/win32/lib/win32/registry.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require 'fiddle/import'
module Win32
@@ -254,30 +254,34 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
/^(?:x64|x86_64)/ =~ RUBY_PLATFORM
end
+ TEMPLATE_HANDLE = 'J<'
+
def packhandle(h)
- win64? ? packqw(h) : packdw(h)
+ [h].pack(TEMPLATE_HANDLE)
end
def unpackhandle(h)
- win64? ? unpackqw(h) : unpackdw(h)
+ (h + [0].pack(TEMPLATE_HANDLE)).unpack1(TEMPLATE_HANDLE)
end
+ TEMPLATE_DWORD = 'V'
+
def packdw(dw)
- [dw].pack('V')
+ [dw].pack(TEMPLATE_DWORD)
end
def unpackdw(dw)
- dw += [0].pack('V')
- dw.unpack('V')[0]
+ (dw + [0].pack(TEMPLATE_DWORD)).unpack1(TEMPLATE_DWORD)
end
+ TEMPLATE_QWORD = 'Q<'
+
def packqw(qw)
- [ qw & 0xFFFFFFFF, qw >> 32 ].pack('VV')
+ [qw].pack(TEMPLATE_QWORD)
end
def unpackqw(qw)
- qw = qw.unpack('VV')
- (qw[1] << 32) | qw[0]
+ (qw + [0].pack(TEMPLATE_QWORD)).unpack1(TEMPLATE_QWORD)
end
def make_wstr(str)
@@ -318,7 +322,7 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
size = packdw(0)
name = make_wstr(name)
check RegQueryValueExW.call(hkey, name, 0, type, 0, size)
- data = "\0".force_encoding('ASCII-8BIT') * unpackdw(size)
+ data = "\0".b * unpackdw(size)
check RegQueryValueExW.call(hkey, name, 0, type, data, size)
[ unpackdw(type), data[0, unpackdw(size)] ]
end
@@ -373,8 +377,7 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
def self.expand_environ(str)
str.gsub(Regexp.compile("%([^%]+)%".encode(str.encoding))) {
v = $1.encode(LOCALE)
- (e = ENV[v] || ENV[v.upcase]; e.encode(str.encoding) if e) ||
- $&
+ (ENV[v] || ENV[v.upcase])&.encode(str.encoding) || $&
}
end
@@ -384,7 +387,6 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
REG_RESOURCE_LIST REG_FULL_RESOURCE_DESCRIPTOR
REG_RESOURCE_REQUIREMENTS_LIST REG_QWORD
].inject([]) do |ary, type|
- type.freeze
ary[Constants.const_get(type)] = type
ary
end.freeze
@@ -657,7 +659,7 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
when REG_DWORD
[ type, API.unpackdw(data) ]
when REG_DWORD_BIG_ENDIAN
- [ type, data.unpack('N')[0] ]
+ [ type, data.unpack1('N') ]
when REG_QWORD
[ type, API.unpackqw(data) ]
else
@@ -740,14 +742,11 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
# method returns.
#
def write(name, type, data)
- termsize = 0
case type
when REG_SZ, REG_EXPAND_SZ
- data = data.encode(WCHAR)
- termsize = WCHAR_SIZE
+ data = data.encode(WCHAR) << WCHAR_NUL
when REG_MULTI_SZ
data = data.to_a.map {|s| s.encode(WCHAR)}.join(WCHAR_NUL) << WCHAR_NUL
- termsize = WCHAR_SIZE
when REG_BINARY, REG_NONE
data = data.to_s
when REG_DWORD
@@ -759,7 +758,7 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
else
raise TypeError, "Unsupported type #{Registry.type2name(type)}"
end
- API.SetValue(@hkey, name, type, data, data.bytesize + termsize)
+ API.SetValue(@hkey, name, type, data, data.bytesize)
end
#
diff --git a/ext/win32ole/.document b/ext/win32ole/.document
new file mode 100644
index 0000000000..decba0135a
--- /dev/null
+++ b/ext/win32ole/.document
@@ -0,0 +1 @@
+*.[ch]
diff --git a/ext/win32ole/lib/win32ole.rb b/ext/win32ole/lib/win32ole.rb
index d7034f7845..f5c8a52c4a 100644
--- a/ext/win32ole/lib/win32ole.rb
+++ b/ext/win32ole/lib/win32ole.rb
@@ -5,7 +5,6 @@ rescue LoadError
end
if defined?(WIN32OLE)
- # WIN32OLE
class WIN32OLE
#
@@ -26,7 +25,7 @@ if defined?(WIN32OLE)
def ole_methods_safely
ole_methods
- rescue WIN32OLEQueryInterfaceError
+ rescue WIN32OLE::QueryInterfaceError
[]
end
end
diff --git a/ext/win32ole/lib/win32ole/property.rb b/ext/win32ole/lib/win32ole/property.rb
index fea047cd19..558056b32b 100644
--- a/ext/win32ole/lib/win32ole/property.rb
+++ b/ext/win32ole/lib/win32ole/property.rb
@@ -1,7 +1,12 @@
# frozen_string_literal: false
-# OLEProperty
-# helper class of Property with arguments.
-class OLEProperty
+
+class WIN32OLE
+end
+
+# OLEProperty is a helper class of Property with arguments, used by
+# `olegen.rb`-generated files.
+class WIN32OLE::Property
+ # :stopdoc:
def initialize(obj, dispid, gettypes, settypes)
@obj = obj
@dispid = dispid
@@ -14,4 +19,11 @@ class OLEProperty
def []=(*args)
@obj._setproperty(@dispid, args, @settypes)
end
+ # :stopdoc:
+end
+
+module WIN32OLE::VariantType
+ # Alias for `olegen.rb`-generated files, that should include
+ # WIN32OLE::VARIANT.
+ OLEProperty = WIN32OLE::Property
end
diff --git a/ext/win32ole/sample/olegen.rb b/ext/win32ole/sample/olegen.rb
deleted file mode 100644
index 4b088a774f..0000000000
--- a/ext/win32ole/sample/olegen.rb
+++ /dev/null
@@ -1,348 +0,0 @@
-# frozen_string_literal: false
-#-----------------------------
-# olegen.rb
-# $Revision$
-#-----------------------------
-
-require 'win32ole'
-
-class WIN32COMGen
- def initialize(typelib)
- @typelib = typelib
- @receiver = ""
- end
- attr_reader :typelib
-
- def ole_classes(typelib)
- begin
- @ole = WIN32OLE.new(typelib)
- [@ole.ole_obj_help]
- rescue
- WIN32OLE_TYPE.ole_classes(typelib)
- end
- end
-
- def generate_args(method)
- args = []
- if method.size_opt_params >= 0
- size_required_params = method.size_params - method.size_opt_params
- else
- size_required_params = method.size_params - 1
- end
- size_required_params.times do |i|
- if method.params[i] && method.params[i].optional?
- args.push "arg#{i}=nil"
- else
- args.push "arg#{i}"
- end
- end
- if method.size_opt_params >= 0
- method.size_opt_params.times do |i|
- args.push "arg#{i + size_required_params}=nil"
- end
- else
- args.push "*arg"
- end
- args.join(", ")
- end
-
- def generate_argtype(typedetails)
- ts = ''
- typedetails.each do |t|
- case t
- when 'CARRAY', 'VOID', 'UINT', 'RESULT', 'DECIMAL', 'I8', 'UI8'
-# raise "Sorry type\"" + t + "\" not supported"
- ts << "\"??? NOT SUPPORTED TYPE:`#{t}'\""
- when 'USERDEFINED', 'Unknown Type 9'
- ts << 'VT_DISPATCH'
- break;
- when 'SAFEARRAY'
- ts << 'VT_ARRAY|'
- when 'PTR'
- ts << 'VT_BYREF|'
- when 'INT'
- ts << 'VT_I4'
- else
- if String === t
- ts << 'VT_' + t
- end
- end
- end
- if ts.empty?
- ts = 'VT_VARIANT'
- elsif ts[-1] == ?|
- ts += 'VT_VARIANT'
- end
- ts
- end
-
- def generate_argtypes(method, proptypes)
- types = method.params.collect{|param|
- generate_argtype(param.ole_type_detail)
- }.join(", ")
- if proptypes
- types += ", " if types.size > 0
- types += generate_argtype(proptypes)
- end
- types
- end
-
- def generate_method_body(method, disptype, types=nil)
- " ret = #{@receiver}#{disptype}(#{method.dispid}, [" +
- generate_args(method).gsub("=nil", "") +
- "], [" +
- generate_argtypes(method, types) +
- "])\n" +
- " @lastargs = WIN32OLE::ARGV\n" +
- " ret"
- end
-
- def generate_method_help(method, type = nil)
- str = " # "
- if type
- str += type
- else
- str += method.return_type
- end
- str += " #{method.name}"
- if method.event?
- str += " EVENT"
- str += " in #{method.event_interface}"
- end
- if method.helpstring && method.helpstring != ""
- str += "\n # "
- str += method.helpstring
- end
- args_help = generate_method_args_help(method)
- if args_help
- str += "\n"
- str += args_help
- end
- str
- end
-
- def generate_method_args_help(method)
- args = []
- method.params.each_with_index {|param, i|
- h = " # #{param.ole_type} arg#{i} --- #{param.name}"
- inout = []
- inout.push "IN" if param.input?
- inout.push "OUT" if param.output?
- h += " [#{inout.join('/')}]"
- h += " ( = #{param.default})" if param.default
- args.push h
- }
- if args.size > 0
- args.join("\n")
- else
- nil
- end
- end
-
- def generate_method(method, disptype, io = STDOUT, types = nil)
- io.puts "\n"
- io.puts generate_method_help(method)
- if method.invoke_kind == 'PROPERTYPUT'
- io.print " def #{method.name}=("
- else
- io.print " def #{method.name}("
- end
- io.print generate_args(method)
- io.puts ")"
- io.puts generate_method_body(method, disptype, types)
- io.puts " end"
- end
-
- def generate_propputref_methods(klass, io = STDOUT)
- klass.ole_methods.select {|method|
- method.invoke_kind == 'PROPERTYPUTREF' && method.visible?
- }.each do |method|
- generate_method(method, io)
- end
- end
-
- def generate_properties_with_args(klass, io = STDOUT)
- klass.ole_methods.select {|method|
- method.invoke_kind == 'PROPERTYGET' &&
- method.visible? &&
- method.size_params > 0
- }.each do |method|
- types = method.return_type_detail
- io.puts "\n"
- io.puts generate_method_help(method, types[0])
- io.puts " def #{method.name}"
- if klass.ole_type == "Class"
- io.print " OLEProperty.new(@dispatch, #{method.dispid}, ["
- else
- io.print " OLEProperty.new(self, #{method.dispid}, ["
- end
- io.print generate_argtypes(method, nil)
- io.print "], ["
- io.print generate_argtypes(method, types)
- io.puts "])"
- io.puts " end"
- end
- end
-
- def generate_propput_methods(klass, io = STDOUT)
- klass.ole_methods.select {|method|
- method.invoke_kind == 'PROPERTYPUT' && method.visible? &&
- method.size_params == 1
- }.each do |method|
- ms = klass.ole_methods.select {|m|
- m.invoke_kind == 'PROPERTYGET' &&
- m.dispid == method.dispid
- }
- types = []
- if ms.size == 1
- types = ms[0].return_type_detail
- end
- generate_method(method, '_setproperty', io, types)
- end
- end
-
- def generate_propget_methods(klass, io = STDOUT)
- klass.ole_methods.select {|method|
- method.invoke_kind == 'PROPERTYGET' && method.visible? &&
- method.size_params == 0
- }.each do |method|
- generate_method(method, '_getproperty', io)
- end
- end
-
- def generate_func_methods(klass, io = STDOUT)
- klass.ole_methods.select {|method|
- method.invoke_kind == "FUNC" && method.visible?
- }.each do |method|
- generate_method(method, '_invoke', io)
- end
- end
-
- def generate_methods(klass, io = STDOUT)
- generate_propget_methods(klass, io)
- generate_propput_methods(klass, io)
- generate_properties_with_args(klass, io)
- generate_func_methods(klass, io)
-# generate_propputref_methods(klass, io)
- end
-
- def generate_constants(klass, io = STDOUT)
- klass.variables.select {|v|
- v.visible? && v.variable_kind == 'CONSTANT'
- }.each do |v|
- io.print " "
- io.print v.name.sub(/^./){$&.upcase}
- io.print " = "
- io.puts v.value
- end
- end
-
- def class_name(klass)
- klass_name = klass.name
- if klass.ole_type == "Class" &&
- klass.guid &&
- klass.progid
- klass_name = klass.progid.gsub(/\./, '_')
- end
- if /^[A-Z]/ !~ klass_name || Module.constants.include?(klass_name)
- klass_name = 'OLE' + klass_name
- end
- klass_name
- end
-
- def define_initialize(klass)
- <<STR
-
- def initialize(obj = nil)
- @clsid = "#{klass.guid}"
- @progid = "#{klass.progid}"
- if obj.nil?
- @dispatch = WIN32OLE.new @progid
- else
- @dispatch = obj
- end
- end
-STR
- end
-
- def define_include
- " include WIN32OLE::VARIANT"
- end
-
- def define_instance_variables
- " attr_reader :lastargs"
- end
-
- def define_method_missing
- <<STR
-
- def method_missing(cmd, *arg)
- @dispatch.method_missing(cmd, *arg)
- end
-STR
- end
-
- def define_class(klass, io = STDOUT)
- io.puts "class #{class_name(klass)} # #{klass.name}"
- io.puts define_include
- io.puts define_instance_variables
- io.puts " attr_reader :dispatch"
- io.puts " attr_reader :clsid"
- io.puts " attr_reader :progid"
- io.puts define_initialize(klass)
- io.puts define_method_missing
- end
-
- def define_module(klass, io = STDOUT)
- io.puts "module #{class_name(klass)}"
- io.puts define_include
- io.puts define_instance_variables
- end
-
- def generate_class(klass, io = STDOUT)
- io.puts "\n# #{klass.helpstring}"
- if klass.ole_type == "Class" &&
- klass.guid &&
- klass.progid
- @receiver = "@dispatch."
- define_class(klass, io)
- else
- @receiver = ""
- define_module(klass, io)
- end
- generate_constants(klass, io)
- generate_methods(klass, io)
- io.puts "end"
- end
-
- def generate(io = STDOUT)
- io.puts "require 'win32ole'"
- io.puts "require 'win32ole/property'"
-
- ole_classes(typelib).select{|klass|
- klass.visible? &&
- (klass.ole_type == "Class" ||
- klass.ole_type == "Interface" ||
- klass.ole_type == "Dispatch" ||
- klass.ole_type == "Enum")
- }.each do |klass|
- generate_class(klass, io)
- end
- begin
- @ole.quit if @ole
- rescue
- end
- end
-end
-
-require 'win32ole'
-if __FILE__ == $0
- if ARGV.size == 0
- $stderr.puts "usage: #{$0} Type Library [...]"
- exit 1
- end
- ARGV.each do |typelib|
- comgen = WIN32COMGen.new(typelib)
- comgen.generate
- end
-end
diff --git a/ext/win32ole/win32ole.c b/ext/win32ole/win32ole.c
index a060165a1c..e0342d1e9d 100644
--- a/ext/win32ole/win32ole.c
+++ b/ext/win32ole/win32ole.c
@@ -1962,7 +1962,7 @@ ole_bind_obj(VALUE moniker, int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * WIN32OLE.connect( ole ) --> aWIN32OLE
+ * connect(ole) --> aWIN32OLE
*
* Returns running OLE Automation object or WIN32OLE object from moniker.
* 1st argument should be OLE program id or class id or moniker.
@@ -2019,7 +2019,7 @@ fole_s_connect(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * WIN32OLE.const_load( ole, mod = WIN32OLE)
+ * const_load(ole, mod = WIN32OLE)
*
* Defines the constants of OLE Automation server as mod's constants.
* The first argument is WIN32OLE object or type library name.
@@ -2124,7 +2124,7 @@ reference_count(struct oledata * pole)
/*
* call-seq:
- * WIN32OLE.ole_reference_count(aWIN32OLE) --> number
+ * ole_reference_count(aWIN32OLE) --> number
*
* Returns reference counter of Dispatch interface of WIN32OLE object.
* You should not use this method because this method
@@ -2140,7 +2140,7 @@ fole_s_reference_count(VALUE self, VALUE obj)
/*
* call-seq:
- * WIN32OLE.ole_free(aWIN32OLE) --> number
+ * ole_free(aWIN32OLE) --> number
*
* Invokes Release method of Dispatch interface of WIN32OLE object.
* You should not use this method because this method
@@ -2184,10 +2184,10 @@ ole_show_help(VALUE helpfile, VALUE helpcontext)
/*
* call-seq:
- * WIN32OLE.ole_show_help(obj [,helpcontext])
+ * ole_show_help(obj [,helpcontext])
*
- * Displays helpfile. The 1st argument specifies WIN32OLE_TYPE
- * object or WIN32OLE_METHOD object or helpfile.
+ * Displays helpfile. The 1st argument specifies WIN32OLE::Type
+ * object or WIN32OLE::Method object or helpfile.
*
* excel = WIN32OLE.new('Excel.Application')
* typeobj = excel.ole_type
@@ -2215,7 +2215,7 @@ fole_s_show_help(int argc, VALUE *argv, VALUE self)
helpfile = target;
}
if (!RB_TYPE_P(helpfile, T_STRING)) {
- rb_raise(rb_eTypeError, "1st parameter must be (String|WIN32OLE_TYPE|WIN32OLE_METHOD)");
+ rb_raise(rb_eTypeError, "1st parameter must be (String|WIN32OLE::Type|WIN32OLE::Method)");
}
hwnd = ole_show_help(helpfile, helpcontext);
if(hwnd == 0) {
@@ -2227,7 +2227,7 @@ fole_s_show_help(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * WIN32OLE.codepage
+ * codepage
*
* Returns current codepage.
* WIN32OLE.codepage # => WIN32OLE::CP_ACP
@@ -2258,7 +2258,7 @@ code_page_installed(UINT cp)
/*
* call-seq:
- * WIN32OLE.codepage = CP
+ * codepage = CP
*
* Sets current codepage.
* The WIN32OLE.codepage is initialized according to
@@ -2282,7 +2282,7 @@ fole_s_set_code_page(VALUE self, VALUE vcp)
/*
* call-seq:
- * WIN32OLE.locale -> locale id.
+ * locale -> locale id.
*
* Returns current locale id (lcid). The default locale is
* WIN32OLE::LOCALE_SYSTEM_DEFAULT.
@@ -2316,12 +2316,12 @@ lcid_installed(LCID lcid)
/*
* call-seq:
- * WIN32OLE.locale = lcid
+ * locale = lcid
*
* Sets current locale id (lcid).
*
* WIN32OLE.locale = 1033 # set locale English(U.S)
- * obj = WIN32OLE_VARIANT.new("$100,000", WIN32OLE::VARIANT::VT_CY)
+ * obj = WIN32OLE::Variant.new("$100,000", WIN32OLE::VARIANT::VT_CY)
*
*/
static VALUE
@@ -2345,7 +2345,7 @@ fole_s_set_locale(VALUE self, VALUE vlcid)
/*
* call-seq:
- * WIN32OLE.create_guid
+ * create_guid
*
* Creates GUID.
* WIN32OLE.create_guid # => {1CB530F1-F6B1-404D-BCE6-1959BF91F4A8}
@@ -2393,9 +2393,9 @@ fole_s_ole_uninitialize(VALUE self)
/*
* Document-class: WIN32OLE
*
- * <code>WIN32OLE</code> objects represent OLE Automation object in Ruby.
+ * +WIN32OLE+ objects represent OLE Automation object in Ruby.
*
- * By using WIN32OLE, you can access OLE server like VBScript.
+ * By using +WIN32OLE+, you can access OLE server like VBScript.
*
* Here is sample script.
*
@@ -2419,18 +2419,18 @@ fole_s_ole_uninitialize(VALUE self)
* excel.ActiveWorkbook.Close(0);
* excel.Quit();
*
- * Unfortunately, Win32OLE doesn't support the argument passed by
+ * Unfortunately, +WIN32OLE+ doesn't support the argument passed by
* reference directly.
- * Instead, Win32OLE provides WIN32OLE::ARGV or WIN32OLE_VARIANT object.
+ * Instead, +WIN32OLE+ provides WIN32OLE::ARGV or WIN32OLE::Variant object.
* If you want to get the result value of argument passed by reference,
- * you can use WIN32OLE::ARGV or WIN32OLE_VARIANT.
+ * you can use WIN32OLE::ARGV or WIN32OLE::Variant.
*
* oleobj.method(arg1, arg2, refargv3)
* puts WIN32OLE::ARGV[2] # the value of refargv3 after called oleobj.method
*
* or
*
- * refargv3 = WIN32OLE_VARIANT.new(XXX,
+ * refargv3 = WIN32OLE::Variant.new(XXX,
* WIN32OLE::VARIANT::VT_BYREF|WIN32OLE::VARIANT::VT_XXX)
* oleobj.method(arg1, arg2, refargv3)
* p refargv3.value # the value of refargv3 after called oleobj.method.
@@ -2439,7 +2439,7 @@ fole_s_ole_uninitialize(VALUE self)
/*
* call-seq:
- * WIN32OLE.new(server, [host]) -> WIN32OLE object
+ * new(server, [host]) -> WIN32OLE object
* WIN32OLE.new(server, license: 'key') -> WIN32OLE object
*
* Returns a new WIN32OLE object(OLE Automation object).
@@ -2826,7 +2826,7 @@ ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket)
/*
* call-seq:
- * WIN32OLE#invoke(method, [arg1,...]) => return value of method.
+ * invoke(method, [arg1,...]) => return value of method.
*
* Runs OLE method.
* The first argument specifies the method name of OLE Automation object.
@@ -3038,7 +3038,7 @@ ole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types, USHORT dispkind)
/*
* call-seq:
- * WIN32OLE#_invoke(dispid, args, types)
+ * _invoke(dispid, args, types)
*
* Runs the early binding method.
* The 1st argument specifies dispatch ID,
@@ -3056,7 +3056,7 @@ fole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types)
/*
* call-seq:
- * WIN32OLE#_getproperty(dispid, args, types)
+ * _getproperty(dispid, args, types)
*
* Runs the early binding method to get property.
* The 1st argument specifies dispatch ID,
@@ -3074,7 +3074,7 @@ fole_getproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types)
/*
* call-seq:
- * WIN32OLE#_setproperty(dispid, args, types)
+ * _setproperty(dispid, args, types)
*
* Runs the early binding method to set property.
* The 1st argument specifies dispatch ID,
@@ -3120,7 +3120,7 @@ fole_setproperty_with_bracket(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * WIN32OLE.setproperty('property', [arg1, arg2,...] val)
+ * setproperty('property', [arg1, arg2,...] val)
*
* Sets property of OLE object.
* When you want to set property with argument, you can use this method.
@@ -3226,7 +3226,7 @@ ole_propertyput(VALUE self, VALUE property, VALUE value)
/*
* call-seq:
- * WIN32OLE#ole_free
+ * ole_free
*
* invokes Release method of Dispatch interface of WIN32OLE object.
* Usually, you do not need to call this method because Release method
@@ -3269,7 +3269,7 @@ ole_ienum_free(VALUE pEnumV)
/*
* call-seq:
- * WIN32OLE#each {|i|...}
+ * each {|i|...}
*
* Iterates over each item of OLE collection which has IEnumVARIANT interface.
*
@@ -3340,7 +3340,7 @@ fole_each(VALUE self)
/*
* call-seq:
- * WIN32OLE#method_missing(id [,arg1, arg2, ...])
+ * method_missing(id [,arg1, arg2, ...])
*
* Calls WIN32OLE#invoke method.
*/
@@ -3438,9 +3438,9 @@ ole_methods(VALUE self, int mask)
/*
* call-seq:
- * WIN32OLE#ole_methods
+ * ole_methods
*
- * Returns the array of WIN32OLE_METHOD object.
+ * Returns the array of WIN32OLE::Method object.
* The element is OLE method of WIN32OLE object.
*
* excel = WIN32OLE.new('Excel.Application')
@@ -3455,9 +3455,9 @@ fole_methods(VALUE self)
/*
* call-seq:
- * WIN32OLE#ole_get_methods
+ * ole_get_methods
*
- * Returns the array of WIN32OLE_METHOD object .
+ * Returns the array of WIN32OLE::Method object .
* The element of the array is property (gettable) of WIN32OLE object.
*
* excel = WIN32OLE.new('Excel.Application')
@@ -3471,9 +3471,9 @@ fole_get_methods(VALUE self)
/*
* call-seq:
- * WIN32OLE#ole_put_methods
+ * ole_put_methods
*
- * Returns the array of WIN32OLE_METHOD object .
+ * Returns the array of WIN32OLE::Method object .
* The element of the array is property (settable) of WIN32OLE object.
*
* excel = WIN32OLE.new('Excel.Application')
@@ -3487,9 +3487,9 @@ fole_put_methods(VALUE self)
/*
* call-seq:
- * WIN32OLE#ole_func_methods
+ * ole_func_methods
*
- * Returns the array of WIN32OLE_METHOD object .
+ * Returns the array of WIN32OLE::Method object .
* The element of the array is property (settable) of WIN32OLE object.
*
* excel = WIN32OLE.new('Excel.Application')
@@ -3504,9 +3504,9 @@ fole_func_methods(VALUE self)
/*
* call-seq:
- * WIN32OLE#ole_type
+ * ole_type
*
- * Returns WIN32OLE_TYPE object.
+ * Returns WIN32OLE::Type object.
*
* excel = WIN32OLE.new('Excel.Application')
* tobj = excel.ole_type
@@ -3529,16 +3529,16 @@ fole_type(VALUE self)
type = ole_type_from_itypeinfo(pTypeInfo);
OLE_RELEASE(pTypeInfo);
if (type == Qnil) {
- rb_raise(rb_eRuntimeError, "failed to create WIN32OLE_TYPE obj from ITypeInfo");
+ rb_raise(rb_eRuntimeError, "failed to create WIN32OLE::Type obj from ITypeInfo");
}
return type;
}
/*
* call-seq:
- * WIN32OLE#ole_typelib -> The WIN32OLE_TYPELIB object
+ * ole_typelib -> The WIN32OLE_TYPELIB object
*
- * Returns the WIN32OLE_TYPELIB object. The object represents the
+ * Returns the WIN32OLE::TypeLib object. The object represents the
* type library which contains the WIN32OLE object.
*
* excel = WIN32OLE.new('Excel.Application')
@@ -3570,7 +3570,7 @@ fole_typelib(VALUE self)
/*
* call-seq:
- * WIN32OLE#ole_query_interface(iid) -> WIN32OLE object
+ * ole_query_interface(iid) -> WIN32OLE object
*
* Returns WIN32OLE object for a specific dispatch or dual
* interface specified by iid.
@@ -3616,7 +3616,7 @@ fole_query_interface(VALUE self, VALUE str_iid)
/*
* call-seq:
- * WIN32OLE#ole_respond_to?(method) -> true or false
+ * ole_respond_to?(method) -> true or false
*
* Returns true when OLE object has OLE method, otherwise returns false.
*
@@ -3825,9 +3825,9 @@ ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails)
/*
* call-seq:
- * WIN32OLE#ole_method_help(method)
+ * ole_method_help(method)
*
- * Returns WIN32OLE_METHOD object corresponding with method
+ * Returns WIN32OLE::Method object corresponding with method
* specified by 1st argument.
*
* excel = WIN32OLE.new('Excel.Application')
@@ -3859,7 +3859,7 @@ fole_method_help(VALUE self, VALUE cmdname)
/*
* call-seq:
- * WIN32OLE#ole_activex_initialize() -> Qnil
+ * ole_activex_initialize() -> Qnil
*
* Initialize WIN32OLE object(ActiveX Control) by calling
* IPersistMemory::InitNew.
@@ -4073,7 +4073,7 @@ Init_win32ole(void)
* p c # => 0
* p WIN32OLE::ARGV # => [10, 20, 30]
*
- * You can use WIN32OLE_VARIANT object to retrieve the value of reference
+ * You can use WIN32OLE::Variant object to retrieve the value of reference
* arguments instead of referring WIN32OLE::ARGV.
*
*/
diff --git a/ext/win32ole/win32ole.gemspec b/ext/win32ole/win32ole.gemspec
index 9c137a5d70..425942d5a0 100644
--- a/ext/win32ole/win32ole.gemspec
+++ b/ext/win32ole/win32ole.gemspec
@@ -23,10 +23,13 @@ Gem::Specification.new do |spec|
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
- end
+ pathspecs = %W[
+ :(exclude,literal)#{File.basename(__FILE__)}
+ :^/bin/ :^/test/ :^/rakelib/ :^/.git* :^/Gemfile* :^/Rakefile*
+ ]
+ spec.files = IO.popen(%w[git ls-files -z --] + pathspecs, chdir: __dir__, err: IO::NULL, exception: false, &:read).split("\x0")
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.extensions = "ext/win32ole/extconf.rb"
spec.require_paths = ["lib"]
end
diff --git a/ext/win32ole/win32ole_error.c b/ext/win32ole/win32ole_error.c
index 2bb5156263..66b5136dee 100644
--- a/ext/win32ole/win32ole_error.c
+++ b/ext/win32ole/win32ole_error.c
@@ -67,7 +67,7 @@ void
Init_win32ole_error(void)
{
/*
- * Document-class: WIN32OLERuntimeError
+ * Document-class: WIN32OLE::RuntimeError
*
* Raised when OLE processing failed.
*
@@ -77,11 +77,20 @@ Init_win32ole_error(void)
*
* raises the exception:
*
- * WIN32OLERuntimeError: unknown OLE server: `NonExistProgID'
+ * WIN32OLE::RuntimeError: unknown OLE server: `NonExistProgID'
* HRESULT error code:0x800401f3
* Invalid class string
*
*/
- eWIN32OLERuntimeError = rb_define_class("WIN32OLERuntimeError", rb_eRuntimeError);
- eWIN32OLEQueryInterfaceError = rb_define_class("WIN32OLEQueryInterfaceError", eWIN32OLERuntimeError);
+ eWIN32OLERuntimeError = rb_define_class_under(cWIN32OLE, "RuntimeError", rb_eRuntimeError);
+ /* Alias of WIN32OLE::RuntimeError, for the backward compatibility */
+ rb_define_const(rb_cObject, "WIN32OLERuntimeError", eWIN32OLERuntimeError);
+ /*
+ * Document-class: WIN32OLE::QueryInterfaceError
+ *
+ * Raised when OLE query failed.
+ */
+ eWIN32OLEQueryInterfaceError = rb_define_class_under(cWIN32OLE, "QueryInterfaceError", eWIN32OLERuntimeError);
+ /* Alias of WIN32OLE::QueryInterfaceError, for the backward compatibility */
+ rb_define_const(rb_cObject, "WIN32OLEQueryInterfaceError", eWIN32OLEQueryInterfaceError);
}
diff --git a/ext/win32ole/win32ole_event.c b/ext/win32ole/win32ole_event.c
index 45ebf13433..ff6835e3e4 100644
--- a/ext/win32ole/win32ole_event.c
+++ b/ext/win32ole/win32ole_event.c
@@ -1,9 +1,9 @@
#include "win32ole.h"
/*
- * Document-class: WIN32OLE_EVENT
+ * Document-class: WIN32OLE::Event
*
- * <code>WIN32OLE_EVENT</code> objects controls OLE event.
+ * +WIN32OLE::Event+ objects controls OLE event.
*/
RUBY_EXTERN void rb_write_error_str(VALUE mesg);
@@ -974,13 +974,13 @@ ev_advise(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * WIN32OLE_EVENT.new(ole, event) #=> WIN32OLE_EVENT object.
+ * new(ole, event) #=> WIN32OLE::Event object.
*
* Returns OLE event object.
* The first argument specifies WIN32OLE object.
* The second argument specifies OLE event name.
* ie = WIN32OLE.new('InternetExplorer.Application')
- * ev = WIN32OLE_EVENT.new(ie, 'DWebBrowserEvents')
+ * ev = WIN32OLE::Event.new(ie, 'DWebBrowserEvents')
*/
static VALUE
fev_initialize(int argc, VALUE *argv, VALUE self)
@@ -1004,7 +1004,7 @@ ole_msg_loop(void)
/*
* call-seq:
- * WIN32OLE_EVENT.message_loop
+ * message_loop
*
* Translates and dispatches Windows message.
*/
@@ -1052,7 +1052,7 @@ ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg)
/*
* call-seq:
- * WIN32OLE_EVENT#on_event([event]){...}
+ * on_event([event]){...}
*
* Defines the callback event.
* If argument is omitted, this method defines the callback of all events.
@@ -1061,12 +1061,12 @@ ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg)
* use `return' or :return.
*
* ie = WIN32OLE.new('InternetExplorer.Application')
- * ev = WIN32OLE_EVENT.new(ie)
+ * ev = WIN32OLE::Event.new(ie)
* ev.on_event("NavigateComplete") {|url| puts url}
* ev.on_event() {|ev, *args| puts "#{ev} fired"}
*
* ev.on_event("BeforeNavigate2") {|*args|
- * ...
+ * # ...
* # set true to BeforeNavigate reference argument `Cancel'.
* # Cancel is 7-th argument of BeforeNavigate,
* # so you can use 6 as key of hash instead of 'Cancel'.
@@ -1075,7 +1075,7 @@ ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg)
* {:Cancel => true} # or {'Cancel' => true} or {6 => true}
* }
*
- * ev.on_event(...) {|*args|
+ * ev.on_event(event_name) {|*args|
* {:return => 1, :xxx => yyy}
* }
*/
@@ -1087,14 +1087,14 @@ fev_on_event(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * WIN32OLE_EVENT#on_event_with_outargs([event]){...}
+ * on_event_with_outargs([event]){...}
*
* Defines the callback of event.
* If you want modify argument in callback,
- * you could use this method instead of WIN32OLE_EVENT#on_event.
+ * you could use this method instead of WIN32OLE::Event#on_event.
*
* ie = WIN32OLE.new('InternetExplorer.Application')
- * ev = WIN32OLE_EVENT.new(ie)
+ * ev = WIN32OLE::Event.new(ie)
* ev.on_event_with_outargs('BeforeNavigate2') {|*args|
* args.last[6] = true
* }
@@ -1107,18 +1107,18 @@ fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * WIN32OLE_EVENT#off_event([event])
+ * off_event([event])
*
* removes the callback of event.
*
* ie = WIN32OLE.new('InternetExplorer.Application')
- * ev = WIN32OLE_EVENT.new(ie)
+ * ev = WIN32OLE::Event.new(ie)
* ev.on_event('BeforeNavigate2') {|*args|
* args.last[6] = true
* }
- * ...
+ * # ...
* ev.off_event('BeforeNavigate2')
- * ...
+ * # ...
*/
static VALUE
fev_off_event(int argc, VALUE *argv, VALUE self)
@@ -1145,16 +1145,16 @@ fev_off_event(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * WIN32OLE_EVENT#unadvise -> nil
+ * unadvise -> nil
*
- * disconnects OLE server. If this method called, then the WIN32OLE_EVENT object
+ * disconnects OLE server. If this method called, then the WIN32OLE::Event object
* does not receive the OLE server event any more.
* This method is trial implementation.
*
* ie = WIN32OLE.new('InternetExplorer.Application')
- * ev = WIN32OLE_EVENT.new(ie)
- * ev.on_event() {...}
- * ...
+ * ev = WIN32OLE::Event.new(ie)
+ * ev.on_event() { something }
+ * # ...
* ev.unadvise
*
*/
@@ -1201,7 +1201,7 @@ evs_length(void)
/*
* call-seq:
- * WIN32OLE_EVENT#handler=
+ * handler=
*
* sets event handler object. If handler object has onXXX
* method according to XXX event, then onXXX method is called
@@ -1212,7 +1212,7 @@ evs_length(void)
* called and 1-st argument is event name.
*
* If handler object has onXXX method and there is block
- * defined by WIN32OLE_EVENT#on_event('XXX'){},
+ * defined by <code>on_event('XXX'){}</code>,
* then block is executed but handler object method is not called
* when XXX event occurs.
*
@@ -1230,7 +1230,7 @@ evs_length(void)
*
* handler = Handler.new
* ie = WIN32OLE.new('InternetExplorer.Application')
- * ev = WIN32OLE_EVENT.new(ie)
+ * ev = WIN32OLE::Event.new(ie)
* ev.on_event("StatusTextChange") {|*args|
* puts "this block executed."
* puts "handler.onStatusTextChange method is not called."
@@ -1246,7 +1246,7 @@ fev_set_handler(VALUE self, VALUE val)
/*
* call-seq:
- * WIN32OLE_EVENT#handler
+ * handler
*
* returns handler object.
*
@@ -1265,6 +1265,7 @@ Init_win32ole_event(void)
rb_gc_register_mark_object(ary_ole_event);
id_events = rb_intern("events");
cWIN32OLE_EVENT = rb_define_class_under(cWIN32OLE, "Event", rb_cObject);
+ /* Alias of WIN32OLE::Event, for the backward compatibility */
rb_define_const(rb_cObject, "WIN32OLE_EVENT", cWIN32OLE_EVENT);
rb_define_singleton_method(cWIN32OLE_EVENT, "message_loop", fev_s_msg_loop, 0);
rb_define_alloc_func(cWIN32OLE_EVENT, fev_s_allocate);
diff --git a/ext/win32ole/win32ole_method.c b/ext/win32ole/win32ole_method.c
index 646fdaf60c..a0278729f0 100644
--- a/ext/win32ole/win32ole_method.c
+++ b/ext/win32ole/win32ole_method.c
@@ -216,9 +216,9 @@ create_win32ole_method(ITypeInfo *pTypeInfo, VALUE name)
}
/*
- * Document-class: WIN32OLE_METHOD
+ * Document-class: WIN32OLE::Method
*
- * <code>WIN32OLE_METHOD</code> objects represent OLE method information.
+ * +WIN32OLE::Method+ objects represent OLE method information.
*/
static VALUE
@@ -251,16 +251,16 @@ folemethod_s_allocate(VALUE klass)
/*
* call-seq:
- * WIN32OLE_METHOD.new(ole_type, method) -> WIN32OLE_METHOD object
+ * WIN32OLE::Method.new(ole_type, method) -> WIN32OLE::Method object
*
- * Returns a new WIN32OLE_METHOD object which represents the information
+ * Returns a new WIN32OLE::Method object which represents the information
* about OLE method.
- * The first argument <i>ole_type</i> specifies WIN32OLE_TYPE object.
+ * The first argument <i>ole_type</i> specifies WIN32OLE::Type object.
* The second argument <i>method</i> specifies OLE method name defined OLE class
- * which represents WIN32OLE_TYPE object.
+ * which represents WIN32OLE::Type object.
*
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
- * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook')
+ * method = WIN32OLE::Method.new(tobj, 'SaveAs')
*/
static VALUE
folemethod_initialize(VALUE self, VALUE oletype, VALUE method)
@@ -277,19 +277,19 @@ folemethod_initialize(VALUE self, VALUE oletype, VALUE method)
}
}
else {
- rb_raise(rb_eTypeError, "1st argument should be WIN32OLE_TYPE object");
+ rb_raise(rb_eTypeError, "1st argument should be WIN32OLE::Type object");
}
return obj;
}
/*
* call-seq:
- * WIN32OLE_METHOD#name
+ * name
*
* Returns the name of the method.
*
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
- * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook')
+ * method = WIN32OLE::Method.new(tobj, 'SaveAs')
* puts method.name # => SaveAs
*
*/
@@ -317,11 +317,11 @@ ole_method_return_type(ITypeInfo *pTypeInfo, UINT method_index)
/*
* call-seq:
- * WIN32OLE_METHOD#return_type
+ * return_type
*
* Returns string of return value type of method.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
- * method = WIN32OLE_METHOD.new(tobj, 'Add')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
+ * method = WIN32OLE::Method.new(tobj, 'Add')
* puts method.return_type # => Workbook
*
*/
@@ -351,11 +351,11 @@ ole_method_return_vtype(ITypeInfo *pTypeInfo, UINT method_index)
/*
* call-seq:
- * WIN32OLE_METHOD#return_vtype
+ * return_vtype
*
* Returns number of return value type of method.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
- * method = WIN32OLE_METHOD.new(tobj, 'Add')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
+ * method = WIN32OLE::Method.new(tobj, 'Add')
* puts method.return_vtype # => 26
*
*/
@@ -385,12 +385,12 @@ ole_method_return_type_detail(ITypeInfo *pTypeInfo, UINT method_index)
/*
* call-seq:
- * WIN32OLE_METHOD#return_type_detail
+ * return_type_detail
*
* Returns detail information of return value type of method.
* The information is array.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
- * method = WIN32OLE_METHOD.new(tobj, 'Add')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
+ * method = WIN32OLE::Method.new(tobj, 'Add')
* p method.return_type_detail # => ["PTR", "USERDEFINED", "Workbook"]
*/
static VALUE
@@ -437,11 +437,11 @@ ole_method_invoke_kind(ITypeInfo *pTypeInfo, UINT method_index)
/*
* call-seq:
- * WIN32OLE_METHOD#invkind
+ * invkind
*
* Returns the method invoke kind.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
- * method = WIN32OLE_METHOD.new(tobj, 'Add')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
+ * method = WIN32OLE::Method.new(tobj, 'Add')
* puts method.invkind # => 1
*
*/
@@ -455,13 +455,13 @@ folemethod_invkind(VALUE self)
/*
* call-seq:
- * WIN32OLE_METHOD#invoke_kind
+ * invoke_kind
*
* Returns the method kind string. The string is "UNKNOWN" or "PROPERTY"
* or "PROPERTY" or "PROPERTYGET" or "PROPERTYPUT" or "PROPERTYPPUTREF"
* or "FUNC".
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
- * method = WIN32OLE_METHOD.new(tobj, 'Add')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
+ * method = WIN32OLE::Method.new(tobj, 'Add')
* puts method.invoke_kind # => "FUNC"
*/
static VALUE
@@ -494,11 +494,11 @@ ole_method_visible(ITypeInfo *pTypeInfo, UINT method_index)
/*
* call-seq:
- * WIN32OLE_METHOD#visible?
+ * visible?
*
* Returns true if the method is public.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
- * method = WIN32OLE_METHOD.new(tobj, 'Add')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
+ * method = WIN32OLE::Method.new(tobj, 'Add')
* puts method.visible? # => true
*/
static VALUE
@@ -575,11 +575,11 @@ ole_method_event(ITypeInfo *pTypeInfo, UINT method_index, VALUE method_name)
/*
* call-seq:
- * WIN32OLE_METHOD#event?
+ * event?
*
* Returns true if the method is event.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
- * method = WIN32OLE_METHOD.new(tobj, 'SheetActivate')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook')
+ * method = WIN32OLE::Method.new(tobj, 'SheetActivate')
* puts method.event? # => true
*
*/
@@ -597,11 +597,11 @@ folemethod_event(VALUE self)
/*
* call-seq:
- * WIN32OLE_METHOD#event_interface
+ * event_interface
*
* Returns event interface name if the method is event.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
- * method = WIN32OLE_METHOD.new(tobj, 'SheetActivate')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook')
+ * method = WIN32OLE::Method.new(tobj, 'SheetActivate')
* puts method.event_interface # => WorkbookEvents
*/
static VALUE
@@ -655,12 +655,12 @@ ole_method_helpstring(ITypeInfo *pTypeInfo, UINT method_index)
/*
* call-seq:
- * WIN32OLE_METHOD#helpstring
+ * helpstring
*
* Returns help string of OLE method. If the help string is not found,
* then the method returns nil.
- * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'IWebBrowser')
- * method = WIN32OLE_METHOD.new(tobj, 'Navigate')
+ * tobj = WIN32OLE::Type.new('Microsoft Internet Controls', 'IWebBrowser')
+ * method = WIN32OLE::Method.new(tobj, 'Navigate')
* puts method.helpstring # => Navigates to a URL or file.
*
*/
@@ -686,12 +686,12 @@ ole_method_helpfile(ITypeInfo *pTypeInfo, UINT method_index)
/*
* call-seq:
- * WIN32OLE_METHOD#helpfile
+ * helpfile
*
* Returns help file. If help file is not found, then
* the method returns nil.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
- * method = WIN32OLE_METHOD.new(tobj, 'Add')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
+ * method = WIN32OLE::Method.new(tobj, 'Add')
* puts method.helpfile # => C:\...\VBAXL9.CHM
*/
static VALUE
@@ -717,11 +717,11 @@ ole_method_helpcontext(ITypeInfo *pTypeInfo, UINT method_index)
/*
* call-seq:
- * WIN32OLE_METHOD#helpcontext
+ * helpcontext
*
* Returns help context.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
- * method = WIN32OLE_METHOD.new(tobj, 'Add')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
+ * method = WIN32OLE::Method.new(tobj, 'Add')
* puts method.helpcontext # => 65717
*/
static VALUE
@@ -748,11 +748,11 @@ ole_method_dispid(ITypeInfo *pTypeInfo, UINT method_index)
/*
* call-seq:
- * WIN32OLE_METHOD#dispid
+ * dispid
*
* Returns dispatch ID.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
- * method = WIN32OLE_METHOD.new(tobj, 'Add')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
+ * method = WIN32OLE::Method.new(tobj, 'Add')
* puts method.dispid # => 181
*/
static VALUE
@@ -779,11 +779,11 @@ ole_method_offset_vtbl(ITypeInfo *pTypeInfo, UINT method_index)
/*
* call-seq:
- * WIN32OLE_METHOD#offset_vtbl
+ * offset_vtbl
*
* Returns the offset ov VTBL.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
- * method = WIN32OLE_METHOD.new(tobj, 'Add')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
+ * method = WIN32OLE::Method.new(tobj, 'Add')
* puts method.offset_vtbl # => 40
*/
static VALUE
@@ -810,11 +810,11 @@ ole_method_size_params(ITypeInfo *pTypeInfo, UINT method_index)
/*
* call-seq:
- * WIN32OLE_METHOD#size_params
+ * size_params
*
* Returns the size of arguments of the method.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
- * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook')
+ * method = WIN32OLE::Method.new(tobj, 'SaveAs')
* puts method.size_params # => 11
*
*/
@@ -842,11 +842,11 @@ ole_method_size_opt_params(ITypeInfo *pTypeInfo, UINT method_index)
/*
* call-seq:
- * WIN32OLE_METHOD#size_opt_params
+ * size_opt_params
*
* Returns the size of optional parameters.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
- * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook')
+ * method = WIN32OLE::Method.new(tobj, 'SaveAs')
* puts method.size_opt_params # => 4
*/
static VALUE
@@ -892,11 +892,11 @@ ole_method_params(ITypeInfo *pTypeInfo, UINT method_index)
/*
* call-seq:
- * WIN32OLE_METHOD#params
+ * params
*
- * returns array of WIN32OLE_PARAM object corresponding with method parameters.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
- * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
+ * returns array of WIN32OLE::Param object corresponding with method parameters.
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook')
+ * method = WIN32OLE::Method.new(tobj, 'SaveAs')
* p method.params # => [Filename, FileFormat, Password, WriteResPassword,
* ReadOnlyRecommended, CreateBackup, AccessMode,
* ConflictResolution, AddToMru, TextCodepage,
@@ -912,7 +912,7 @@ folemethod_params(VALUE self)
/*
* call-seq:
- * WIN32OLE_METHOD#inspect -> String
+ * inspect -> String
*
* Returns the method name with class name.
*
@@ -920,7 +920,7 @@ folemethod_params(VALUE self)
static VALUE
folemethod_inspect(VALUE self)
{
- return default_inspect(self, "WIN32OLE_METHOD");
+ return default_inspect(self, "WIN32OLE::Method");
}
VALUE cWIN32OLE_METHOD;
@@ -928,6 +928,7 @@ VALUE cWIN32OLE_METHOD;
void Init_win32ole_method(void)
{
cWIN32OLE_METHOD = rb_define_class_under(cWIN32OLE, "Method", rb_cObject);
+ /* Alias of WIN32OLE::Method, for the backward compatibility */
rb_define_const(rb_cObject, "WIN32OLE_METHOD", cWIN32OLE_METHOD);
rb_define_alloc_func(cWIN32OLE_METHOD, folemethod_s_allocate);
rb_define_method(cWIN32OLE_METHOD, "initialize", folemethod_initialize, 2);
diff --git a/ext/win32ole/win32ole_param.c b/ext/win32ole/win32ole_param.c
index b654aaa845..0c4b185921 100644
--- a/ext/win32ole/win32ole_param.c
+++ b/ext/win32ole/win32ole_param.c
@@ -64,9 +64,9 @@ create_win32ole_param(ITypeInfo *pTypeInfo, UINT method_index, UINT index, VALUE
}
/*
- * Document-class: WIN32OLE_PARAM
+ * Document-class: WIN32OLE::Param
*
- * <code>WIN32OLE_PARAM</code> objects represent param information of
+ * +WIN32OLE::Param+ objects represent param information of
* the OLE method.
*/
static VALUE
@@ -131,15 +131,15 @@ oleparam_ole_param(VALUE self, VALUE olemethod, int n)
/*
* call-seq:
- * WIN32OLE_PARAM.new(method, n) -> WIN32OLE_PARAM object
+ * new(method, n) -> WIN32OLE::Param object
*
- * Returns WIN32OLE_PARAM object which represents OLE parameter information.
- * 1st argument should be WIN32OLE_METHOD object.
+ * Returns WIN32OLE::Param object which represents OLE parameter information.
+ * 1st argument should be WIN32OLE::Method object.
* 2nd argument `n' is n-th parameter of the method specified by 1st argument.
*
- * tobj = WIN32OLE_TYPE.new('Microsoft Scripting Runtime', 'IFileSystem')
- * method = WIN32OLE_METHOD.new(tobj, 'CreateTextFile')
- * param = WIN32OLE_PARAM.new(method, 2) # => #<WIN32OLE_PARAM:Overwrite=true>
+ * tobj = WIN32OLE::Type.new('Microsoft Scripting Runtime', 'IFileSystem')
+ * method = WIN32OLE::Method.new(tobj, 'CreateTextFile')
+ * param = WIN32OLE::Param.new(method, 2) # => #<WIN32OLE::Param:Overwrite=true>
*
*/
static VALUE
@@ -147,7 +147,7 @@ foleparam_initialize(VALUE self, VALUE olemethod, VALUE n)
{
int idx;
if (!rb_obj_is_kind_of(olemethod, cWIN32OLE_METHOD)) {
- rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE_METHOD object");
+ rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE::Method object");
}
idx = RB_FIX2INT(n);
return oleparam_ole_param(self, olemethod, idx);
@@ -155,11 +155,11 @@ foleparam_initialize(VALUE self, VALUE olemethod, VALUE n)
/*
* call-seq:
- * WIN32OLE_PARAM#name
+ * name
*
* Returns name.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
- * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook')
+ * method = WIN32OLE::Method.new(tobj, 'SaveAs')
* param1 = method.params[0]
* puts param1.name # => Filename
*/
@@ -186,11 +186,11 @@ ole_param_ole_type(ITypeInfo *pTypeInfo, UINT method_index, UINT index)
/*
* call-seq:
- * WIN32OLE_PARAM#ole_type
+ * ole_type
*
- * Returns OLE type of WIN32OLE_PARAM object(parameter of OLE method).
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
- * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
+ * Returns OLE type of WIN32OLE::Param object(parameter of OLE method).
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook')
+ * method = WIN32OLE::Method.new(tobj, 'SaveAs')
* param1 = method.params[0]
* puts param1.ole_type # => VARIANT
*/
@@ -220,11 +220,11 @@ ole_param_ole_type_detail(ITypeInfo *pTypeInfo, UINT method_index, UINT index)
/*
* call-seq:
- * WIN32OLE_PARAM#ole_type_detail
+ * ole_type_detail
*
* Returns detail information of type of argument.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'IWorksheetFunction')
- * method = WIN32OLE_METHOD.new(tobj, 'SumIf')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'IWorksheetFunction')
+ * method = WIN32OLE::Method.new(tobj, 'SumIf')
* param1 = method.params[0]
* p param1.ole_type_detail # => ["PTR", "USERDEFINED", "Range"]
*/
@@ -254,11 +254,11 @@ ole_param_flag_mask(ITypeInfo *pTypeInfo, UINT method_index, UINT index, USHORT
/*
* call-seq:
- * WIN32OLE_PARAM#input?
+ * input?
*
* Returns true if the parameter is input.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
- * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook')
+ * method = WIN32OLE::Method.new(tobj, 'SaveAs')
* param1 = method.params[0]
* puts param1.input? # => true
*/
@@ -273,22 +273,22 @@ foleparam_input(VALUE self)
/*
* call-seq:
- * WIN32OLE#output?
+ * output?
*
* Returns true if argument is output.
- * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'DWebBrowserEvents')
- * method = WIN32OLE_METHOD.new(tobj, 'NewWindow')
+ * tobj = WIN32OLE::Type.new('Microsoft Internet Controls', 'DWebBrowserEvents')
+ * method = WIN32OLE::Method.new(tobj, 'NewWindow')
* method.params.each do |param|
* puts "#{param.name} #{param.output?}"
* end
*
- * The result of above script is following:
- * URL false
- * Flags false
- * TargetFrameName false
- * PostData false
- * Headers false
- * Processed true
+ * The result of above script is following:
+ * URL false
+ * Flags false
+ * TargetFrameName false
+ * PostData false
+ * Headers false
+ * Processed true
*/
static VALUE
foleparam_output(VALUE self)
@@ -301,11 +301,11 @@ foleparam_output(VALUE self)
/*
* call-seq:
- * WIN32OLE_PARAM#optional?
+ * optional?
*
* Returns true if argument is optional.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
- * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook')
+ * method = WIN32OLE::Method.new(tobj, 'SaveAs')
* param1 = method.params[0]
* puts "#{param1.name} #{param1.optional?}" # => Filename true
*/
@@ -320,12 +320,12 @@ foleparam_optional(VALUE self)
/*
* call-seq:
- * WIN32OLE_PARAM#retval?
+ * retval?
*
* Returns true if argument is return value.
- * tobj = WIN32OLE_TYPE.new('DirectX 7 for Visual Basic Type Library',
- * 'DirectPlayLobbyConnection')
- * method = WIN32OLE_METHOD.new(tobj, 'GetPlayerShortName')
+ * tobj = WIN32OLE::Type.new('DirectX 7 for Visual Basic Type Library',
+ * 'DirectPlayLobbyConnection')
+ * method = WIN32OLE::Method.new(tobj, 'GetPlayerShortName')
* param = method.params[0]
* puts "#{param.name} #{param.retval?}" # => name true
*/
@@ -363,12 +363,12 @@ ole_param_default(ITypeInfo *pTypeInfo, UINT method_index, UINT index)
/*
* call-seq:
- * WIN32OLE_PARAM#default
+ * default
*
* Returns default value. If the default value does not exist,
* this method returns nil.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
- * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook')
+ * method = WIN32OLE::Method.new(tobj, 'SaveAs')
* method.params.each do |param|
* if param.default
* puts "#{param.name} (= #{param.default})"
@@ -377,18 +377,18 @@ ole_param_default(ITypeInfo *pTypeInfo, UINT method_index, UINT index)
* end
* end
*
- * The above script result is following:
- * Filename
- * FileFormat
- * Password
- * WriteResPassword
- * ReadOnlyRecommended
- * CreateBackup
- * AccessMode (= 1)
- * ConflictResolution
- * AddToMru
- * TextCodepage
- * TextVisualLayout
+ * The above script result is following:
+ * Filename
+ * FileFormat
+ * Password
+ * WriteResPassword
+ * ReadOnlyRecommended
+ * CreateBackup
+ * AccessMode (= 1)
+ * ConflictResolution
+ * AddToMru
+ * TextCodepage
+ * TextVisualLayout
*/
static VALUE
foleparam_default(VALUE self)
@@ -401,7 +401,7 @@ foleparam_default(VALUE self)
/*
* call-seq:
- * WIN32OLE_PARAM#inspect -> String
+ * inspect -> String
*
* Returns the parameter name with class name. If the parameter has default value,
* then returns name=value string with class name.
@@ -416,13 +416,14 @@ foleparam_inspect(VALUE self)
rb_str_cat2(detail, "=");
rb_str_concat(detail, rb_inspect(defval));
}
- return make_inspect("WIN32OLE_PARAM", detail);
+ return make_inspect("WIN32OLE::Param", detail);
}
void
Init_win32ole_param(void)
{
cWIN32OLE_PARAM = rb_define_class_under(cWIN32OLE, "Param", rb_cObject);
+ /* Alias of WIN32OLE::Param, for the backward compatibility */
rb_define_const(rb_cObject, "WIN32OLE_PARAM", cWIN32OLE_PARAM);
rb_define_alloc_func(cWIN32OLE_PARAM, foleparam_s_allocate);
rb_define_method(cWIN32OLE_PARAM, "initialize", foleparam_initialize, 2);
diff --git a/ext/win32ole/win32ole_record.c b/ext/win32ole/win32ole_record.c
index 9e18653db9..02f05a3fa7 100644
--- a/ext/win32ole/win32ole_record.c
+++ b/ext/win32ole/win32ole_record.c
@@ -177,10 +177,10 @@ create_win32ole_record(IRecordInfo *pri, void *prec)
}
/*
- * Document-class: WIN32OLE_RECORD
+ * Document-class: WIN32OLE::Record
*
- * <code>WIN32OLE_RECORD</code> objects represents VT_RECORD OLE variant.
- * Win32OLE returns WIN32OLE_RECORD object if the result value of invoking
+ * +WIN32OLE::Record+ objects represents VT_RECORD OLE variant.
+ * Win32OLE returns WIN32OLE::Record object if the result value of invoking
* OLE methods.
*
* If COM server in VB.NET ComServer project is the following:
@@ -206,7 +206,7 @@ create_win32ole_record(IRecordInfo *pri, void *prec)
* require 'win32ole'
* obj = WIN32OLE.new('ComServer.ComClass')
* book = obj.getBook
- * book.class # => WIN32OLE_RECORD
+ * book.class # => WIN32OLE::Record
* book.title # => "The Ruby Book"
* book.cost # => 20
*
@@ -253,11 +253,11 @@ folerecord_s_allocate(VALUE klass) {
/*
* call-seq:
- * WIN32OLE_RECORD.new(typename, obj) -> WIN32OLE_RECORD object
+ * new(typename, obj) -> WIN32OLE::Record object
*
- * Returns WIN32OLE_RECORD object. The first argument is struct name (String
+ * Returns WIN32OLE::Record object. The first argument is struct name (String
* or Symbol).
- * The second parameter obj should be WIN32OLE object or WIN32OLE_TYPELIB object.
+ * The second parameter obj should be WIN32OLE object or WIN32OLE::TypeLib object.
* If COM server in VB.NET ComServer project is the following:
*
* Imports System.Runtime.InteropServices
@@ -269,13 +269,13 @@ folerecord_s_allocate(VALUE klass) {
* End Structure
* End Class
*
- * then, you can create WIN32OLE_RECORD object is as following:
+ * then, you can create WIN32OLE::Record object is as following:
*
* require 'win32ole'
* obj = WIN32OLE.new('ComServer.ComClass')
- * book1 = WIN32OLE_RECORD.new('Book', obj) # => WIN32OLE_RECORD object
+ * book1 = WIN32OLE::Record.new('Book', obj) # => WIN32OLE::Record object
* tlib = obj.ole_typelib
- * book2 = WIN32OLE_RECORD.new('Book', tlib) # => WIN32OLE_RECORD object
+ * book2 = WIN32OLE::Record.new('Book', tlib) # => WIN32OLE::Record object
*
*/
static VALUE
@@ -303,7 +303,7 @@ folerecord_initialize(VALUE self, VALUE typename, VALUE oleobj) {
hr = E_FAIL;
}
} else {
- rb_raise(rb_eArgError, "2nd argument should be WIN32OLE object or WIN32OLE_TYPELIB object");
+ rb_raise(rb_eArgError, "2nd argument should be WIN32OLE object or WIN32OLE::TypeLib object");
}
if (FAILED(hr)) {
@@ -323,7 +323,7 @@ folerecord_initialize(VALUE self, VALUE typename, VALUE oleobj) {
/*
* call-seq:
- * WIN32OLE_RECORD#to_h #=> Ruby Hash object.
+ * WIN32OLE::Record#to_h #=> Ruby Hash object.
*
* Returns Ruby Hash object which represents VT_RECORD variable.
* The keys of Hash object are member names of VT_RECORD OLE variable and
@@ -346,7 +346,7 @@ folerecord_initialize(VALUE self, VALUE typename, VALUE oleobj) {
* End Function
* End Class
*
- * then, the result of WIN32OLE_RECORD#to_h is the following:
+ * then, the result of WIN32OLE::Record#to_h is the following:
*
* require 'win32ole'
* obj = WIN32OLE.new('ComServer.ComClass')
@@ -362,7 +362,7 @@ folerecord_to_h(VALUE self)
/*
* call-seq:
- * WIN32OLE_RECORD#typename #=> String object
+ * typename #=> String object
*
* Returns the type name of VT_RECORD OLE variable.
*
@@ -383,7 +383,7 @@ folerecord_to_h(VALUE self)
* End Function
* End Class
*
- * then, the result of WIN32OLE_RECORD#typename is the following:
+ * then, the result of WIN32OLE::Record#typename is the following:
*
* require 'win32ole'
* obj = WIN32OLE.new('ComServer.ComClass')
@@ -423,7 +423,7 @@ olerecord_ivar_set(VALUE self, VALUE name, VALUE val)
/*
* call-seq:
- * WIN32OLE_RECORD#method_missing(name)
+ * method_missing(name)
*
* Returns value specified by the member name of VT_RECORD OLE variable.
* Or sets value specified by the member name of VT_RECORD OLE variable.
@@ -443,7 +443,7 @@ olerecord_ivar_set(VALUE self, VALUE name, VALUE val)
* Then getting/setting value from Ruby is as the following:
*
* obj = WIN32OLE.new('ComServer.ComClass')
- * book = WIN32OLE_RECORD.new('Book', obj)
+ * book = WIN32OLE::Record.new('Book', obj)
* book.title # => nil ( book.method_missing(:title) is invoked. )
* book.title = "Ruby" # ( book.method_missing(:title=, "Ruby") is invoked. )
*/
@@ -473,7 +473,7 @@ folerecord_method_missing(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * WIN32OLE_RECORD#ole_instance_variable_get(name)
+ * ole_instance_variable_get(name)
*
* Returns value specified by the member name of VT_RECORD OLE object.
* If the member name is not correct, KeyError exception is raised.
@@ -494,7 +494,7 @@ folerecord_method_missing(int argc, VALUE *argv, VALUE self)
* then accessing object_id of ComObject from Ruby is as the following:
*
* srver = WIN32OLE.new('ComServer.ComClass')
- * obj = WIN32OLE_RECORD.new('ComObject', server)
+ * obj = WIN32OLE::Record.new('ComObject', server)
* # obj.object_id returns Ruby Object#object_id
* obj.ole_instance_variable_get(:object_id) # => nil
*
@@ -515,7 +515,7 @@ folerecord_ole_instance_variable_get(VALUE self, VALUE name)
/*
* call-seq:
- * WIN32OLE_RECORD#ole_instance_variable_set(name, val)
+ * ole_instance_variable_set(name, val)
*
* Sets value specified by the member name of VT_RECORD OLE object.
* If the member name is not correct, KeyError exception is raised.
@@ -534,7 +534,7 @@ folerecord_ole_instance_variable_get(VALUE self, VALUE name)
* then setting value of the `title' member is as following:
*
* srver = WIN32OLE.new('ComServer.ComClass')
- * obj = WIN32OLE_RECORD.new('Book', server)
+ * obj = WIN32OLE::Record.new('Book', server)
* obj.ole_instance_variable_set(:title, "The Ruby Book")
*
*/
@@ -554,7 +554,7 @@ folerecord_ole_instance_variable_set(VALUE self, VALUE name, VALUE val)
/*
* call-seq:
- * WIN32OLE_RECORD#inspect -> String
+ * inspect -> String
*
* Returns the OLE struct name and member name and the value of member
*
@@ -570,8 +570,8 @@ folerecord_ole_instance_variable_set(VALUE self, VALUE name, VALUE val)
* then
*
* srver = WIN32OLE.new('ComServer.ComClass')
- * obj = WIN32OLE_RECORD.new('Book', server)
- * obj.inspect # => <WIN32OLE_RECORD(ComClass) {"title" => nil, "cost" => nil}>
+ * obj = WIN32OLE::Record.new('Book', server)
+ * obj.inspect # => <WIN32OLE::Record(ComClass) {"title" => nil, "cost" => nil}>
*
*/
static VALUE
@@ -584,7 +584,7 @@ folerecord_inspect(VALUE self)
tname = rb_inspect(tname);
}
field = rb_inspect(folerecord_to_h(self));
- return rb_sprintf("#<WIN32OLE_RECORD(%"PRIsVALUE") %"PRIsVALUE">",
+ return rb_sprintf("#<WIN32OLE::Record(%"PRIsVALUE") %"PRIsVALUE">",
tname,
field);
}
@@ -595,6 +595,7 @@ void
Init_win32ole_record(void)
{
cWIN32OLE_RECORD = rb_define_class_under(cWIN32OLE, "Record", rb_cObject);
+ /* Alias of WIN32OLE::Record, for the backward compatibility */
rb_define_const(rb_cObject, "WIN32OLE_RECORD", cWIN32OLE_RECORD);
rb_define_alloc_func(cWIN32OLE_RECORD, folerecord_s_allocate);
rb_define_method(cWIN32OLE_RECORD, "initialize", folerecord_initialize, 2);
diff --git a/ext/win32ole/win32ole_type.c b/ext/win32ole/win32ole_type.c
index 1b96aea858..45b16d6722 100644
--- a/ext/win32ole/win32ole_type.c
+++ b/ext/win32ole/win32ole_type.c
@@ -54,9 +54,9 @@ static const rb_data_type_t oletype_datatype = {
};
/*
- * Document-class: WIN32OLE_TYPE
+ * Document-class: WIN32OLE::Type
*
- * <code>WIN32OLE_TYPE</code> objects represent OLE type library information.
+ * +WIN32OLE::Type+ objects represent OLE type library information.
*/
static void
@@ -106,10 +106,12 @@ ole_type_from_itypeinfo(ITypeInfo *pTypeInfo)
/*
* call-seq:
- * WIN32OLE_TYPE.ole_classes(typelib)
+ * ole_classes(typelib)
*
- * Returns array of WIN32OLE_TYPE objects defined by the <i>typelib</i> type library.
- * This method will be OBSOLETE. Use WIN32OLE_TYPELIB.new(typelib).ole_classes instead.
+ * Returns array of WIN32OLE::Type objects defined by the <i>typelib</i> type library.
+ *
+ * This method will be OBSOLETE.
+ * Use <code>WIN32OLE::TypeLib.new(typelib).ole_classes</code> instead.
*/
static VALUE
foletype_s_ole_classes(VALUE self, VALUE typelib)
@@ -118,8 +120,8 @@ foletype_s_ole_classes(VALUE self, VALUE typelib)
/*
rb_warn("%s is obsolete; use %s instead.",
- "WIN32OLE_TYPE.ole_classes",
- "WIN32OLE_TYPELIB.new(typelib).ole_types");
+ "WIN32OLE::Type.ole_classes",
+ "WIN32OLE::TypeLib.new(typelib).ole_types");
*/
obj = rb_funcall(cWIN32OLE_TYPELIB, rb_intern("new"), 1, typelib);
return rb_funcall(obj, rb_intern("ole_types"), 0);
@@ -127,10 +129,12 @@ foletype_s_ole_classes(VALUE self, VALUE typelib)
/*
* call-seq:
- * WIN32OLE_TYPE.typelibs
+ * typelibs
*
* Returns array of type libraries.
- * This method will be OBSOLETE. Use WIN32OLE_TYPELIB.typelibs.collect{|t| t.name} instead.
+ *
+ * This method will be OBSOLETE.
+ * Use <code>WIN32OLE::TypeLib.typelibs.collect{|t| t.name}</code> instead.
*
*/
static VALUE
@@ -138,15 +142,15 @@ foletype_s_typelibs(VALUE self)
{
/*
rb_warn("%s is obsolete. use %s instead.",
- "WIN32OLE_TYPE.typelibs",
- "WIN32OLE_TYPELIB.typelibs.collect{t|t.name}");
+ "WIN32OLE::Type.typelibs",
+ "WIN32OLE::TypeLib.typelibs.collect{t|t.name}");
*/
- return rb_eval_string("WIN32OLE_TYPELIB.typelibs.collect{|t|t.name}");
+ return rb_eval_string("WIN32OLE::TypeLib.typelibs.collect{|t|t.name}");
}
/*
* call-seq:
- * WIN32OLE_TYPE.progids
+ * progids
*
* Returns array of ProgID.
*/
@@ -214,7 +218,6 @@ create_win32ole_type(ITypeInfo *pTypeInfo, VALUE name)
static VALUE
oleclass_from_typelib(VALUE self, ITypeLib *pTypeLib, VALUE oleclass)
{
-
long count;
int i;
HRESULT hr;
@@ -245,14 +248,14 @@ oleclass_from_typelib(VALUE self, ITypeLib *pTypeLib, VALUE oleclass)
/*
* call-seq:
- * WIN32OLE_TYPE.new(typelib, ole_class) -> WIN32OLE_TYPE object
+ * new(typelib, ole_class) -> WIN32OLE::Type object
*
- * Returns a new WIN32OLE_TYPE object.
+ * Returns a new WIN32OLE::Type object.
* The first argument <i>typelib</i> specifies OLE type library name.
* The second argument specifies OLE class name.
*
- * WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application')
- * # => WIN32OLE_TYPE object of Application class of Excel.
+ * WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Application')
+ * # => WIN32OLE::Type object of Application class of Excel.
*/
static VALUE
foletype_initialize(VALUE self, VALUE typelib, VALUE oleclass)
@@ -284,10 +287,10 @@ foletype_initialize(VALUE self, VALUE typelib, VALUE oleclass)
/*
* call-seq:
- * WIN32OLE_TYPE#name #=> OLE type name
+ * name #=> OLE type name
*
* Returns OLE type name.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Application')
* puts tobj.name # => Application
*/
static VALUE
@@ -344,10 +347,10 @@ ole_ole_type(ITypeInfo *pTypeInfo)
/*
* call-seq:
- * WIN32OLE_TYPE#ole_type #=> OLE type string.
+ * ole_type #=> OLE type string.
*
* returns type of OLE class.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Application')
* puts tobj.ole_type # => Class
*/
static VALUE
@@ -378,10 +381,10 @@ ole_type_guid(ITypeInfo *pTypeInfo)
/*
* call-seq:
- * WIN32OLE_TYPE#guid #=> GUID
+ * guid #=> GUID
*
* Returns GUID.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Application')
* puts tobj.guid # => {00024500-0000-0000-C000-000000000046}
*/
static VALUE
@@ -412,10 +415,10 @@ ole_type_progid(ITypeInfo *pTypeInfo)
/*
* call-seq:
- * WIN32OLE_TYPE#progid #=> ProgID
+ * progid #=> ProgID
*
* Returns ProgID if it exists. If not found, then returns nil.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Application')
* puts tobj.progid # => Excel.Application.9
*/
static VALUE
@@ -446,10 +449,10 @@ ole_type_visible(ITypeInfo *pTypeInfo)
/*
* call-seq:
- * WIN32OLE_TYPE#visible? #=> true or false
+ * visible? #=> true or false
*
* Returns true if the OLE class is public.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Application')
* puts tobj.visible # => true
*/
static VALUE
@@ -475,10 +478,10 @@ ole_type_major_version(ITypeInfo *pTypeInfo)
/*
* call-seq:
- * WIN32OLE_TYPE#major_version
+ * major_version
*
* Returns major version.
- * tobj = WIN32OLE_TYPE.new('Microsoft Word 10.0 Object Library', 'Documents')
+ * tobj = WIN32OLE::Type.new('Microsoft Word 10.0 Object Library', 'Documents')
* puts tobj.major_version # => 8
*/
static VALUE
@@ -504,10 +507,10 @@ ole_type_minor_version(ITypeInfo *pTypeInfo)
/*
* call-seq:
- * WIN32OLE_TYPE#minor_version #=> OLE minor version
+ * minor_version #=> OLE minor version
*
* Returns minor version.
- * tobj = WIN32OLE_TYPE.new('Microsoft Word 10.0 Object Library', 'Documents')
+ * tobj = WIN32OLE::Type.new('Microsoft Word 10.0 Object Library', 'Documents')
* puts tobj.minor_version # => 2
*/
static VALUE
@@ -533,10 +536,10 @@ ole_type_typekind(ITypeInfo *pTypeInfo)
/*
* call-seq:
- * WIN32OLE_TYPE#typekind #=> number of type.
+ * typekind #=> number of type.
*
* Returns number which represents type.
- * tobj = WIN32OLE_TYPE.new('Microsoft Word 10.0 Object Library', 'Documents')
+ * tobj = WIN32OLE::Type.new('Microsoft Word 10.0 Object Library', 'Documents')
* puts tobj.typekind # => 4
*
*/
@@ -561,10 +564,10 @@ ole_type_helpstring(ITypeInfo *pTypeInfo)
/*
* call-seq:
- * WIN32OLE_TYPE#helpstring #=> help string.
+ * helpstring #=> help string.
*
* Returns help string.
- * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'IWebBrowser')
+ * tobj = WIN32OLE::Type.new('Microsoft Internet Controls', 'IWebBrowser')
* puts tobj.helpstring # => Web Browser interface
*/
static VALUE
@@ -594,10 +597,10 @@ ole_type_src_type(ITypeInfo *pTypeInfo)
/*
* call-seq:
- * WIN32OLE_TYPE#src_type #=> OLE source class
+ * src_type #=> OLE source class
*
* Returns source class when the OLE class is 'Alias'.
- * tobj = WIN32OLE_TYPE.new('Microsoft Office 9.0 Object Library', 'MsoRGBType')
+ * tobj = WIN32OLE::Type.new('Microsoft Office 9.0 Object Library', 'MsoRGBType')
* puts tobj.src_type # => I4
*
*/
@@ -622,10 +625,10 @@ ole_type_helpfile(ITypeInfo *pTypeInfo)
/*
* call-seq:
- * WIN32OLE_TYPE#helpfile
+ * helpfile
*
* Returns helpfile path. If helpfile is not found, then returns nil.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
* puts tobj.helpfile # => C:\...\VBAXL9.CHM
*
*/
@@ -650,10 +653,10 @@ ole_type_helpcontext(ITypeInfo *pTypeInfo)
/*
* call-seq:
- * WIN32OLE_TYPE#helpcontext
+ * helpcontext
*
* Returns helpcontext. If helpcontext is not found, then returns nil.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
* puts tobj.helpfile # => 131185
*/
static VALUE
@@ -701,11 +704,11 @@ ole_variables(ITypeInfo *pTypeInfo)
/*
* call-seq:
- * WIN32OLE_TYPE#variables
+ * variables
*
- * Returns array of WIN32OLE_VARIABLE objects which represent variables
+ * Returns array of WIN32OLE::Variable objects which represent variables
* defined in OLE class.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
* vars = tobj.variables
* vars.each do |v|
* puts "#{v.name} = #{v.value}"
@@ -728,11 +731,11 @@ foletype_variables(VALUE self)
/*
* call-seq:
- * WIN32OLE_TYPE#ole_methods # the array of WIN32OLE_METHOD objects.
+ * ole_methods # the array of WIN32OLE::Method objects.
*
- * Returns array of WIN32OLE_METHOD objects which represent OLE method defined in
+ * Returns array of WIN32OLE::Method objects which represent OLE method defined in
* OLE type library.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
* methods = tobj.ole_methods.collect{|m|
* m.name
* }
@@ -747,11 +750,11 @@ foletype_methods(VALUE self)
/*
* call-seq:
- * WIN32OLE_TYPE#ole_typelib
+ * ole_typelib
*
- * Returns the WIN32OLE_TYPELIB object which is including the WIN32OLE_TYPE
+ * Returns the WIN32OLE::TypeLib object which is including the WIN32OLE::Type
* object. If it is not found, then returns nil.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
* puts tobj.ole_typelib # => 'Microsoft Excel 9.0 Object Library'
*/
static VALUE
@@ -804,11 +807,11 @@ ole_type_impl_ole_types(ITypeInfo *pTypeInfo, int implflags)
/*
* call-seq:
- * WIN32OLE_TYPE#implemented_ole_types
+ * implemented_ole_types
*
- * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE
+ * Returns the array of WIN32OLE::Type object which is implemented by the WIN32OLE::Type
* object.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
* p tobj.implemented_ole_types # => [_Worksheet, DocEvents]
*/
static VALUE
@@ -820,13 +823,13 @@ foletype_impl_ole_types(VALUE self)
/*
* call-seq:
- * WIN32OLE_TYPE#source_ole_types
+ * source_ole_types
*
- * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE
+ * Returns the array of WIN32OLE::Type object which is implemented by the WIN32OLE::Type
* object and having IMPLTYPEFLAG_FSOURCE.
- * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer")
+ * tobj = WIN32OLE::Type.new('Microsoft Internet Controls', "InternetExplorer")
* p tobj.source_ole_types
- * # => [#<WIN32OLE_TYPE:DWebBrowserEvents2>, #<WIN32OLE_TYPE:DWebBrowserEvents>]
+ * # => [#<WIN32OLE::Type:DWebBrowserEvents2>, #<WIN32OLE::Type:DWebBrowserEvents>]
*/
static VALUE
foletype_source_ole_types(VALUE self)
@@ -837,12 +840,12 @@ foletype_source_ole_types(VALUE self)
/*
* call-seq:
- * WIN32OLE_TYPE#default_event_sources
+ * default_event_sources
*
- * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE
+ * Returns the array of WIN32OLE::Type object which is implemented by the WIN32OLE::Type
* object and having IMPLTYPEFLAG_FSOURCE and IMPLTYPEFLAG_FDEFAULT.
- * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer")
- * p tobj.default_event_sources # => [#<WIN32OLE_TYPE:DWebBrowserEvents2>]
+ * tobj = WIN32OLE::Type.new('Microsoft Internet Controls', "InternetExplorer")
+ * p tobj.default_event_sources # => [#<WIN32OLE::Type:DWebBrowserEvents2>]
*/
static VALUE
foletype_default_event_sources(VALUE self)
@@ -853,13 +856,13 @@ foletype_default_event_sources(VALUE self)
/*
* call-seq:
- * WIN32OLE_TYPE#default_ole_types
+ * default_ole_types
*
- * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE
+ * Returns the array of WIN32OLE::Type object which is implemented by the WIN32OLE::Type
* object and having IMPLTYPEFLAG_FDEFAULT.
- * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer")
+ * tobj = WIN32OLE::Type.new('Microsoft Internet Controls', "InternetExplorer")
* p tobj.default_ole_types
- * # => [#<WIN32OLE_TYPE:IWebBrowser2>, #<WIN32OLE_TYPE:DWebBrowserEvents2>]
+ * # => [#<WIN32OLE::Type:IWebBrowser2>, #<WIN32OLE::Type:DWebBrowserEvents2>]
*/
static VALUE
foletype_default_ole_types(VALUE self)
@@ -870,17 +873,17 @@ foletype_default_ole_types(VALUE self)
/*
* call-seq:
- * WIN32OLE_TYPE#inspect -> String
+ * inspect -> String
*
* Returns the type name with class name.
*
* ie = WIN32OLE.new('InternetExplorer.Application')
- * ie.ole_type.inspect => #<WIN32OLE_TYPE:IWebBrowser2>
+ * ie.ole_type.inspect => #<WIN32OLE::Type:IWebBrowser2>
*/
static VALUE
foletype_inspect(VALUE self)
{
- return default_inspect(self, "WIN32OLE_TYPE");
+ return default_inspect(self, "WIN32OLE::Type");
}
VALUE cWIN32OLE_TYPE;
@@ -888,6 +891,7 @@ VALUE cWIN32OLE_TYPE;
void Init_win32ole_type(void)
{
cWIN32OLE_TYPE = rb_define_class_under(cWIN32OLE, "Type", rb_cObject);
+ /* Alias of WIN32OLE::Type, for the backward compatibility */
rb_define_const(rb_cObject, "WIN32OLE_TYPE", cWIN32OLE_TYPE);
rb_define_singleton_method(cWIN32OLE_TYPE, "ole_classes", foletype_s_ole_classes, 1);
rb_define_singleton_method(cWIN32OLE_TYPE, "typelibs", foletype_s_typelibs, 0);
diff --git a/ext/win32ole/win32ole_typelib.c b/ext/win32ole/win32ole_typelib.c
index fb68bebda8..e5eda07e76 100644
--- a/ext/win32ole/win32ole_typelib.c
+++ b/ext/win32ole/win32ole_typelib.c
@@ -127,19 +127,19 @@ ole_typelib_from_itypeinfo(ITypeInfo *pTypeInfo)
}
/*
- * Document-class: WIN32OLE_TYPELIB
+ * Document-class: WIN32OLE::TypeLib
*
- * <code>WIN32OLE_TYPELIB</code> objects represent OLE tyblib information.
+ * +WIN32OLE::TypeLib+ objects represent OLE tyblib information.
*/
/*
* call-seq:
*
- * WIN32OLE_TYPELIB.typelibs
+ * typelibs
*
- * Returns the array of WIN32OLE_TYPELIB object.
+ * Returns the array of WIN32OLE::TypeLib object.
*
- * tlibs = WIN32OLE_TYPELIB.typelibs
+ * tlibs = WIN32OLE::TypeLib.typelibs
*
*/
static VALUE
@@ -364,9 +364,9 @@ oletypelib_search_registry2(VALUE self, VALUE args)
/*
* call-seq:
- * WIN32OLE_TYPELIB.new(typelib [, version1, version2]) -> WIN32OLE_TYPELIB object
+ * new(typelib [, version1, version2]) -> WIN32OLE::TypeLib object
*
- * Returns a new WIN32OLE_TYPELIB object.
+ * Returns a new WIN32OLE::TypeLib object.
*
* The first argument <i>typelib</i> specifies OLE type library name or GUID or
* OLE library file.
@@ -376,11 +376,11 @@ oletypelib_search_registry2(VALUE self, VALUE args)
* If the first argument is type library name, then the second and third argument
* are ignored.
*
- * tlib1 = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
- * tlib2 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}')
- * tlib3 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}', 1.3)
- * tlib4 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}', 1, 3)
- * tlib5 = WIN32OLE_TYPELIB.new("C:\\WINNT\\SYSTEM32\\SHELL32.DLL")
+ * tlib1 = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library')
+ * tlib2 = WIN32OLE::TypeLib.new('{00020813-0000-0000-C000-000000000046}')
+ * tlib3 = WIN32OLE::TypeLib.new('{00020813-0000-0000-C000-000000000046}', 1.3)
+ * tlib4 = WIN32OLE::TypeLib.new('{00020813-0000-0000-C000-000000000046}', 1, 3)
+ * tlib5 = WIN32OLE::TypeLib.new("C:\\WINNT\\SYSTEM32\\SHELL32.DLL")
* puts tlib1.name # -> 'Microsoft Excel 9.0 Object Library'
* puts tlib2.name # -> 'Microsoft Excel 9.0 Object Library'
* puts tlib3.name # -> 'Microsoft Excel 9.0 Object Library'
@@ -428,11 +428,11 @@ foletypelib_initialize(VALUE self, VALUE args)
/*
* call-seq:
- * WIN32OLE_TYPELIB#guid -> The guid string.
+ * guid -> The guid string.
*
* Returns guid string which specifies type library.
*
- * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
+ * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library')
* guid = tlib.guid # -> '{00020813-0000-0000-C000-000000000046}'
*/
static VALUE
@@ -456,11 +456,11 @@ foletypelib_guid(VALUE self)
/*
* call-seq:
- * WIN32OLE_TYPELIB#name -> The type library name
+ * name -> The type library name
*
* Returns the type library name.
*
- * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
+ * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library')
* name = tlib.name # -> 'Microsoft Excel 9.0 Object Library'
*/
static VALUE
@@ -500,11 +500,11 @@ make_version_str(VALUE major, VALUE minor)
/*
* call-seq:
- * WIN32OLE_TYPELIB#version -> The type library version String object.
+ * version -> The type library version String object.
*
* Returns the type library version.
*
- * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
+ * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library')
* puts tlib.version #-> "1.3"
*/
static VALUE
@@ -523,11 +523,11 @@ foletypelib_version(VALUE self)
/*
* call-seq:
- * WIN32OLE_TYPELIB#major_version -> The type library major version.
+ * major_version -> The type library major version.
*
* Returns the type library major version.
*
- * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
+ * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library')
* puts tlib.major_version # -> 1
*/
static VALUE
@@ -546,11 +546,11 @@ foletypelib_major_version(VALUE self)
/*
* call-seq:
- * WIN32OLE_TYPELIB#minor_version -> The type library minor version.
+ * minor_version -> The type library minor version.
*
* Returns the type library minor version.
*
- * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
+ * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library')
* puts tlib.minor_version # -> 3
*/
static VALUE
@@ -568,11 +568,11 @@ foletypelib_minor_version(VALUE self)
/*
* call-seq:
- * WIN32OLE_TYPELIB#path -> The type library file path.
+ * path -> The type library file path.
*
* Returns the type library file path.
*
- * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
+ * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library')
* puts tlib.path #-> 'C:\...\EXCEL9.OLB'
*/
static VALUE
@@ -604,15 +604,15 @@ foletypelib_path(VALUE self)
/*
* call-seq:
- * WIN32OLE_TYPELIB#visible?
+ * visible?
*
* Returns true if the type library information is not hidden.
* If wLibFlags of TLIBATTR is 0 or LIBFLAG_FRESTRICTED or LIBFLAG_FHIDDEN,
* the method returns false, otherwise, returns true.
* If the method fails to access the TLIBATTR information, then
- * WIN32OLERuntimeError is raised.
+ * WIN32OLE::RuntimeError is raised.
*
- * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
+ * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library')
* tlib.visible? # => true
*/
static VALUE
@@ -636,12 +636,12 @@ foletypelib_visible(VALUE self)
/*
* call-seq:
- * WIN32OLE_TYPELIB#library_name
+ * library_name
*
* Returns library name.
- * If the method fails to access library name, WIN32OLERuntimeError is raised.
+ * If the method fails to access library name, WIN32OLE::RuntimeError is raised.
*
- * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
+ * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library')
* tlib.library_name # => Excel
*/
static VALUE
@@ -790,11 +790,11 @@ typelib_file(VALUE ole)
/*
* call-seq:
- * WIN32OLE_TYPELIB#ole_types -> The array of WIN32OLE_TYPE object included the type library.
+ * ole_types -> The array of WIN32OLE::Type object included the type library.
*
* Returns the type library file path.
*
- * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
+ * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library')
* classes = tlib.ole_types.collect{|k| k.name} # -> ['AddIn', 'AddIns' ...]
*/
static VALUE
@@ -809,17 +809,17 @@ foletypelib_ole_types(VALUE self)
/*
* call-seq:
- * WIN32OLE_TYPELIB#inspect -> String
+ * inspect -> String
*
* Returns the type library name with class name.
*
- * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library')
- * tlib.inspect # => "<#WIN32OLE_TYPELIB:Microsoft Excel 9.0 Object Library>"
+ * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library')
+ * tlib.inspect # => "<#WIN32OLE::TypeLib:Microsoft Excel 9.0 Object Library>"
*/
static VALUE
foletypelib_inspect(VALUE self)
{
- return default_inspect(self, "WIN32OLE_TYPELIB");
+ return default_inspect(self, "WIN32OLE::TypeLib");
}
VALUE cWIN32OLE_TYPELIB;
@@ -827,7 +827,8 @@ VALUE cWIN32OLE_TYPELIB;
void
Init_win32ole_typelib(void)
{
- cWIN32OLE_TYPELIB = rb_define_class_under(cWIN32OLE, "Typelib", rb_cObject);
+ cWIN32OLE_TYPELIB = rb_define_class_under(cWIN32OLE, "TypeLib", rb_cObject);
+ /* Alias of WIN32OLE::TypeLib, for the backward compatibility */
rb_define_const(rb_cObject, "WIN32OLE_TYPELIB", cWIN32OLE_TYPELIB);
rb_define_singleton_method(cWIN32OLE_TYPELIB, "typelibs", foletypelib_s_typelibs, 0);
rb_define_alloc_func(cWIN32OLE_TYPELIB, foletypelib_s_allocate);
diff --git a/ext/win32ole/win32ole_variable.c b/ext/win32ole/win32ole_variable.c
index e7f58c891e..34435301d4 100644
--- a/ext/win32ole/win32ole_variable.c
+++ b/ext/win32ole/win32ole_variable.c
@@ -43,9 +43,9 @@ olevariable_size(const void *ptr)
}
/*
- * Document-class: WIN32OLE_VARIABLE
+ * Document-class: WIN32OLE::Variable
*
- * <code>WIN32OLE_VARIABLE</code> objects represent OLE variable information.
+ * +WIN32OLE::Variable+ objects represent OLE variable information.
*/
VALUE
@@ -63,11 +63,11 @@ create_win32ole_variable(ITypeInfo *pTypeInfo, UINT index, VALUE name)
/*
* call-seq:
- * WIN32OLE_VARIABLE#name
+ * name
*
* Returns the name of variable.
*
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
* variables = tobj.variables
* variables.each do |variable|
* puts "#{variable.name}"
@@ -103,11 +103,11 @@ ole_variable_ole_type(ITypeInfo *pTypeInfo, UINT var_index)
/*
* call-seq:
- * WIN32OLE_VARIABLE#ole_type
+ * ole_type
*
* Returns OLE type string.
*
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
* variables = tobj.variables
* variables.each do |variable|
* puts "#{variable.ole_type} #{variable.name}"
@@ -145,11 +145,11 @@ ole_variable_ole_type_detail(ITypeInfo *pTypeInfo, UINT var_index)
/*
* call-seq:
- * WIN32OLE_VARIABLE#ole_type_detail
+ * ole_type_detail
*
* Returns detail information of type. The information is array of type.
*
- * tobj = WIN32OLE_TYPE.new('DirectX 7 for Visual Basic Type Library', 'D3DCLIPSTATUS')
+ * tobj = WIN32OLE::Type.new('DirectX 7 for Visual Basic Type Library', 'D3DCLIPSTATUS')
* variable = tobj.variables.find {|variable| variable.name == 'lFlags'}
* tdetail = variable.ole_type_detail
* p tdetail # => ["USERDEFINED", "CONST_D3DCLIPSTATUSFLAGS"]
@@ -180,12 +180,12 @@ ole_variable_value(ITypeInfo *pTypeInfo, UINT var_index)
/*
* call-seq:
- * WIN32OLE_VARIABLE#value
+ * value
*
* Returns value if value is exists. If the value does not exist,
* this method returns nil.
*
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
* variables = tobj.variables
* variables.each do |variable|
* puts "#{variable.name} #{variable.value}"
@@ -227,11 +227,11 @@ ole_variable_visible(ITypeInfo *pTypeInfo, UINT var_index)
/*
* call-seq:
- * WIN32OLE_VARIABLE#visible?
+ * visible?
*
* Returns true if the variable is public.
*
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
* variables = tobj.variables
* variables.each do |variable|
* puts "#{variable.name} #{variable.visible?}"
@@ -284,11 +284,11 @@ ole_variable_kind(ITypeInfo *pTypeInfo, UINT var_index)
/*
* call-seq:
- * WIN32OLE_VARIABLE#variable_kind
+ * variable_kind
*
* Returns variable kind string.
*
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
* variables = tobj.variables
* variables.each do |variable|
* puts "#{variable.name} #{variable.variable_kind}"
@@ -325,10 +325,10 @@ ole_variable_varkind(ITypeInfo *pTypeInfo, UINT var_index)
/*
* call-seq:
- * WIN32OLE_VARIABLE#varkind
+ * varkind
*
* Returns the number which represents variable kind.
- * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
+ * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
* variables = tobj.variables
* variables.each do |variable|
* puts "#{variable.name} #{variable.varkind}"
@@ -351,7 +351,7 @@ folevariable_varkind(VALUE self)
/*
* call-seq:
- * WIN32OLE_VARIABLE#inspect -> String
+ * inspect -> String
*
* Returns the OLE variable name and the value with class name.
*
@@ -362,7 +362,7 @@ folevariable_inspect(VALUE self)
VALUE v = rb_inspect(folevariable_value(self));
VALUE n = folevariable_name(self);
VALUE detail = rb_sprintf("%"PRIsVALUE"=%"PRIsVALUE, n, v);
- return make_inspect("WIN32OLE_VARIABLE", detail);
+ return make_inspect("WIN32OLE::Variable", detail);
}
VALUE cWIN32OLE_VARIABLE;
@@ -370,6 +370,7 @@ VALUE cWIN32OLE_VARIABLE;
void Init_win32ole_variable(void)
{
cWIN32OLE_VARIABLE = rb_define_class_under(cWIN32OLE, "Variable", rb_cObject);
+ /* Alias of WIN32OLE::Variable, for the backward compatibility */
rb_define_const(rb_cObject, "WIN32OLE_VARIABLE", cWIN32OLE_VARIABLE);
rb_undef_alloc_func(cWIN32OLE_VARIABLE);
rb_define_method(cWIN32OLE_VARIABLE, "name", folevariable_name, 0);
diff --git a/ext/win32ole/win32ole_variant.c b/ext/win32ole/win32ole_variant.c
index f1d83ed2e1..45c70b1dc3 100644
--- a/ext/win32ole/win32ole_variant.c
+++ b/ext/win32ole/win32ole_variant.c
@@ -267,7 +267,7 @@ folevariant_s_allocate(VALUE klass)
/*
* call-seq:
- * WIN32OLE_VARIANT.array(ary, vt)
+ * array(ary, vt)
*
* Returns Ruby object wrapping OLE variant whose variant type is VT_ARRAY.
* The first argument should be Array object which specifies dimensions
@@ -277,7 +277,7 @@ folevariant_s_allocate(VALUE klass)
* The following create 2 dimensions OLE array. The first dimensions size
* is 3, and the second is 4.
*
- * ole_ary = WIN32OLE_VARIANT.array([3,4], VT_I4)
+ * ole_ary = WIN32OLE::Variant.array([3,4], VT_I4)
* ruby_ary = ole_ary.value # => [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
*
*/
@@ -357,44 +357,44 @@ check_type_val2variant(VALUE val)
case T_NIL:
break;
default:
- rb_raise(rb_eTypeError, "can not convert WIN32OLE_VARIANT from type %s",
+ rb_raise(rb_eTypeError, "can not convert WIN32OLE::Variant from type %s",
rb_obj_classname(val));
}
}
}
/*
- * Document-class: WIN32OLE_VARIANT
+ * Document-class: WIN32OLE::Variant
*
- * <code>WIN32OLE_VARIANT</code> objects represents OLE variant.
+ * +WIN32OLE::Variant+ objects represents OLE variant.
*
* Win32OLE converts Ruby object into OLE variant automatically when
* invoking OLE methods. If OLE method requires the argument which is
* different from the variant by automatic conversion of Win32OLE, you
- * can convert the specified variant type by using WIN32OLE_VARIANT class.
+ * can convert the specified variant type by using WIN32OLE::Variant class.
*
- * param = WIN32OLE_VARIANT.new(10, WIN32OLE::VARIANT::VT_R4)
+ * param = WIN32OLE::Variant.new(10, WIN32OLE::VARIANT::VT_R4)
* oleobj.method(param)
*
- * WIN32OLE_VARIANT does not support VT_RECORD variant. Use WIN32OLE_RECORD
- * class instead of WIN32OLE_VARIANT if the VT_RECORD variant is needed.
+ * WIN32OLE::Variant does not support VT_RECORD variant. Use WIN32OLE::Record
+ * class instead of WIN32OLE::Variant if the VT_RECORD variant is needed.
*/
/*
* call-seq:
- * WIN32OLE_VARIANT.new(val, vartype) #=> WIN32OLE_VARIANT object.
+ * new(val, vartype) #=> WIN32OLE::Variant object.
*
* Returns Ruby object wrapping OLE variant.
* The first argument specifies Ruby object to convert OLE variant variable.
* The second argument specifies VARIANT type.
- * In some situation, you need the WIN32OLE_VARIANT object to pass OLE method
+ * In some situation, you need the WIN32OLE::Variant object to pass OLE method
*
* shell = WIN32OLE.new("Shell.Application")
* folder = shell.NameSpace("C:\\Windows")
* item = folder.ParseName("tmp.txt")
* # You can't use Ruby String object to call FolderItem.InvokeVerb.
- * # Instead, you have to use WIN32OLE_VARIANT object to call the method.
- * shortcut = WIN32OLE_VARIANT.new("Create Shortcut(\&S)")
+ * # Instead, you have to use WIN32OLE::Variant object to call the method.
+ * shortcut = WIN32OLE::Variant.new("Create Shortcut(\&S)")
* item.invokeVerb(shortcut)
*
*/
@@ -422,7 +422,7 @@ folevariant_initialize(VALUE self, VALUE args)
vvt = rb_ary_entry(args, 1);
vt = RB_NUM2INT(vvt);
if ((vt & VT_TYPEMASK) == VT_RECORD) {
- rb_raise(rb_eArgError, "not supported VT_RECORD WIN32OLE_VARIANT object");
+ rb_raise(rb_eArgError, "not supported VT_RECORD WIN32OLE::Variant object");
}
ole_val2olevariantdata(val, vt, pvar);
}
@@ -482,22 +482,22 @@ unlock_safe_array(SAFEARRAY *psa)
/*
* call-seq:
- * WIN32OLE_VARIANT[i,j,...] #=> element of OLE array.
+ * variant[i,j,...] #=> element of OLE array.
*
- * Returns the element of WIN32OLE_VARIANT object(OLE array).
+ * Returns the element of WIN32OLE::Variant object(OLE array).
* This method is available only when the variant type of
- * WIN32OLE_VARIANT object is VT_ARRAY.
+ * WIN32OLE::Variant object is VT_ARRAY.
*
* REMARK:
* The all indices should be 0 or natural number and
* lower than or equal to max indices.
* (This point is different with Ruby Array indices.)
*
- * obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]])
+ * obj = WIN32OLE::Variant.new([[1,2,3],[4,5,6]])
* p obj[0,0] # => 1
* p obj[1,0] # => 4
- * p obj[2,0] # => WIN32OLERuntimeError
- * p obj[0, -1] # => WIN32OLERuntimeError
+ * p obj[2,0] # => WIN32OLE::RuntimeError
+ * p obj[0, -1] # => WIN32OLE::RuntimeError
*
*/
static VALUE
@@ -537,23 +537,23 @@ folevariant_ary_aref(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * WIN32OLE_VARIANT[i,j,...] = val #=> set the element of OLE array
+ * variant[i,j,...] = val #=> set the element of OLE array
*
- * Set the element of WIN32OLE_VARIANT object(OLE array) to val.
+ * Set the element of WIN32OLE::Variant object(OLE array) to val.
* This method is available only when the variant type of
- * WIN32OLE_VARIANT object is VT_ARRAY.
+ * WIN32OLE::Variant object is VT_ARRAY.
*
* REMARK:
* The all indices should be 0 or natural number and
* lower than or equal to max indices.
* (This point is different with Ruby Array indices.)
*
- * obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]])
+ * obj = WIN32OLE::Variant.new([[1,2,3],[4,5,6]])
* obj[0,0] = 7
* obj[1,0] = 8
* p obj.value # => [[7,2,3], [8,5,6]]
- * obj[2,0] = 9 # => WIN32OLERuntimeError
- * obj[0, -1] = 9 # => WIN32OLERuntimeError
+ * obj[2,0] = 9 # => WIN32OLE::RuntimeError
+ * obj[0, -1] = 9 # => WIN32OLE::RuntimeError
*
*/
static VALUE
@@ -598,10 +598,10 @@ folevariant_ary_aset(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * WIN32OLE_VARIANT.value #=> Ruby object.
+ * value #=> Ruby object.
*
* Returns Ruby object value from OLE variant.
- * obj = WIN32OLE_VARIANT.new(1, WIN32OLE::VARIANT::VT_BSTR)
+ * obj = WIN32OLE::Variant.new(1, WIN32OLE::VARIANT::VT_BSTR)
* obj.value # => "1" (not Integer object, but String object "1")
*
*/
@@ -637,10 +637,10 @@ folevariant_value(VALUE self)
/*
* call-seq:
- * WIN32OLE_VARIANT.vartype #=> OLE variant type.
+ * vartype #=> OLE variant type.
*
* Returns OLE variant type.
- * obj = WIN32OLE_VARIANT.new("string")
+ * obj = WIN32OLE::Variant.new("string")
* obj.vartype # => WIN32OLE::VARIANT::VT_BSTR
*
*/
@@ -654,7 +654,7 @@ folevariant_vartype(VALUE self)
/*
* call-seq:
- * WIN32OLE_VARIANT.value = val #=> set WIN32OLE_VARIANT value to val.
+ * variant.value = val #=> set WIN32OLE::Variant value to val.
*
* Sets variant value to val. If the val type does not match variant value
* type(vartype), then val is changed to match variant value type(vartype)
@@ -662,7 +662,7 @@ folevariant_vartype(VALUE self)
* This method is not available when vartype is VT_ARRAY(except VT_UI1|VT_ARRAY).
* If the vartype is VT_UI1|VT_ARRAY, the val should be String object.
*
- * obj = WIN32OLE_VARIANT.new(1) # obj.vartype is WIN32OLE::VARIANT::VT_I4
+ * obj = WIN32OLE::Variant.new(1) # obj.vartype is WIN32OLE::VARIANT::VT_I4
* obj.value = 3.2 # 3.2 is changed to 3 when setting value.
* p obj.value # => 3
*/
@@ -696,6 +696,7 @@ Init_win32ole_variant(void)
{
#undef rb_intern
cWIN32OLE_VARIANT = rb_define_class_under(cWIN32OLE, "Variant", rb_cObject);
+ /* Alias of WIN32OLE::Variant, for the backward compatibility */
rb_define_const(rb_cObject, "WIN32OLE_VARIANT", cWIN32OLE_VARIANT);
rb_define_alloc_func(cWIN32OLE_VARIANT, folevariant_s_allocate);
rb_define_singleton_method(cWIN32OLE_VARIANT, "array", folevariant_s_array, 2);
@@ -729,7 +730,7 @@ Init_win32ole_variant(void)
* This constants is used for not specified parameter.
*
* fso = WIN32OLE.new("Scripting.FileSystemObject")
- * fso.openTextFile(filename, WIN32OLE_VARIANT::NoParam, false)
+ * fso.openTextFile(filename, WIN32OLE::Variant::NoParam, false)
*/
rb_define_const(cWIN32OLE_VARIANT, "NoParam",
rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, INT2NUM(DISP_E_PARAMNOTFOUND), RB_INT2FIX(VT_ERROR)));
diff --git a/ext/win32ole/win32ole_variant_m.c b/ext/win32ole/win32ole_variant_m.c
index c285a00177..d879506be3 100644
--- a/ext/win32ole/win32ole_variant_m.c
+++ b/ext/win32ole/win32ole_variant_m.c
@@ -5,16 +5,18 @@ VALUE mWIN32OLE_VARIANT;
void Init_win32ole_variant_m(void)
{
/*
- * Document-module: WIN32OLE::VARIANT
+ * Document-module: WIN32OLE::VariantType
*
- * The WIN32OLE::VARIANT module includes constants of VARIANT type constants.
- * The constants is used when creating WIN32OLE_VARIANT object.
+ * The +WIN32OLE::VariantType+ module includes constants of VARIANT type constants.
+ * The constants is used when creating WIN32OLE::Variant object.
*
- * obj = WIN32OLE_VARIANT.new("2e3", WIN32OLE::VARIANT::VT_R4)
+ * obj = WIN32OLE::Variant.new("2e3", WIN32OLE::VARIANT::VT_R4)
* obj.value # => 2000.0
*
*/
- mWIN32OLE_VARIANT = rb_define_module_under(cWIN32OLE, "VARIANT");
+ mWIN32OLE_VARIANT = rb_define_module_under(cWIN32OLE, "VariantType");
+ /* Alias of WIN32OLE::VariantType, for the backward compatibility */
+ rb_define_const(cWIN32OLE, "VARIANT", mWIN32OLE_VARIANT);
/*
* represents VT_EMPTY type constant.
diff --git a/ext/zlib/depend b/ext/zlib/depend
index bdcf6a93e8..bdce420264 100644
--- a/ext/zlib/depend
+++ b/ext/zlib/depend
@@ -157,6 +157,7 @@ zlib.o: $(hdrdir)/ruby/internal/special_consts.h
zlib.o: $(hdrdir)/ruby/internal/static_assert.h
zlib.o: $(hdrdir)/ruby/internal/stdalign.h
zlib.o: $(hdrdir)/ruby/internal/stdbool.h
+zlib.o: $(hdrdir)/ruby/internal/stdckdint.h
zlib.o: $(hdrdir)/ruby/internal/symbol.h
zlib.o: $(hdrdir)/ruby/internal/value.h
zlib.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
index dc608ee460..aad9f8d28a 100644
--- a/ext/zlib/zlib.c
+++ b/ext/zlib/zlib.c
@@ -90,7 +90,7 @@ static void zstream_expand_buffer_into(struct zstream*, unsigned long);
static int zstream_expand_buffer_non_stream(struct zstream *z);
static void zstream_append_buffer(struct zstream*, const Bytef*, long);
static VALUE zstream_detach_buffer(struct zstream*);
-static VALUE zstream_shift_buffer(struct zstream*, long);
+static VALUE zstream_shift_buffer(struct zstream*, long, VALUE);
static void zstream_buffer_ungets(struct zstream*, const Bytef*, unsigned long);
static void zstream_buffer_ungetbyte(struct zstream*, int);
static void zstream_append_input(struct zstream*, const Bytef*, long);
@@ -170,8 +170,8 @@ static void gzfile_check_footer(struct gzfile*, VALUE outbuf);
static void gzfile_write(struct gzfile*, Bytef*, long);
static long gzfile_read_more(struct gzfile*, VALUE outbuf);
static void gzfile_calc_crc(struct gzfile*, VALUE);
-static VALUE gzfile_read(struct gzfile*, long);
-static VALUE gzfile_read_all(struct gzfile*);
+static VALUE gzfile_read(struct gzfile*, long, VALUE);
+static VALUE gzfile_read_all(struct gzfile*, VALUE);
static void gzfile_ungets(struct gzfile*, const Bytef*, long);
static void gzfile_ungetbyte(struct gzfile*, int);
static VALUE gzfile_writer_end_run(VALUE);
@@ -820,19 +820,31 @@ zstream_detach_buffer(struct zstream *z)
}
static VALUE
-zstream_shift_buffer(struct zstream *z, long len)
+zstream_shift_buffer(struct zstream *z, long len, VALUE dst)
{
- VALUE dst;
char *bufptr;
long buflen = ZSTREAM_BUF_FILLED(z);
if (buflen <= len) {
- return zstream_detach_buffer(z);
+ if (NIL_P(dst) || (!ZSTREAM_IS_FINISHED(z) && !ZSTREAM_IS_GZFILE(z) &&
+ rb_block_given_p())) {
+ return zstream_detach_buffer(z);
+ } else {
+ bufptr = RSTRING_PTR(z->buf);
+ rb_str_resize(dst, buflen);
+ memcpy(RSTRING_PTR(dst), bufptr, buflen);
+ }
+ buflen = 0;
+ } else {
+ bufptr = RSTRING_PTR(z->buf);
+ if (NIL_P(dst)) {
+ dst = rb_str_new(bufptr, len);
+ } else {
+ rb_str_resize(dst, len);
+ memcpy(RSTRING_PTR(dst), bufptr, len);
+ }
+ buflen -= len;
}
-
- bufptr = RSTRING_PTR(z->buf);
- dst = rb_str_new(bufptr, len);
- buflen -= len;
memmove(bufptr, bufptr + len, buflen);
rb_str_set_len(z->buf, buflen);
z->stream.next_out = (Bytef*)RSTRING_END(z->buf);
@@ -2874,18 +2886,18 @@ gzfile_newstr(struct gzfile *gz, VALUE str)
}
static long
-gzfile_fill(struct gzfile *gz, long len)
+gzfile_fill(struct gzfile *gz, long len, VALUE outbuf)
{
if (len < 0)
rb_raise(rb_eArgError, "negative length %ld given", len);
if (len == 0)
return 0;
while (!ZSTREAM_IS_FINISHED(&gz->z) && ZSTREAM_BUF_FILLED(&gz->z) < len) {
- gzfile_read_more(gz, Qnil);
+ gzfile_read_more(gz, outbuf);
}
if (GZFILE_IS_FINISHED(gz)) {
if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
- gzfile_check_footer(gz, Qnil);
+ gzfile_check_footer(gz, outbuf);
}
return -1;
}
@@ -2893,14 +2905,27 @@ gzfile_fill(struct gzfile *gz, long len)
}
static VALUE
-gzfile_read(struct gzfile *gz, long len)
+gzfile_read(struct gzfile *gz, long len, VALUE outbuf)
{
VALUE dst;
- len = gzfile_fill(gz, len);
- if (len == 0) return rb_str_new(0, 0);
- if (len < 0) return Qnil;
- dst = zstream_shift_buffer(&gz->z, len);
+ len = gzfile_fill(gz, len, outbuf);
+
+ if (len < 0) {
+ if (!NIL_P(outbuf))
+ rb_str_resize(outbuf, 0);
+ return Qnil;
+ }
+ if (len == 0) {
+ if (NIL_P(outbuf))
+ return rb_str_new(0, 0);
+ else {
+ rb_str_resize(outbuf, 0);
+ return outbuf;
+ }
+ }
+
+ dst = zstream_shift_buffer(&gz->z, len, outbuf);
if (!NIL_P(dst)) gzfile_calc_crc(gz, dst);
return dst;
}
@@ -2933,29 +2958,26 @@ gzfile_readpartial(struct gzfile *gz, long len, VALUE outbuf)
rb_raise(rb_eEOFError, "end of file reached");
}
- dst = zstream_shift_buffer(&gz->z, len);
+ dst = zstream_shift_buffer(&gz->z, len, outbuf);
gzfile_calc_crc(gz, dst);
- if (!NIL_P(outbuf)) {
- rb_str_resize(outbuf, RSTRING_LEN(dst));
- memcpy(RSTRING_PTR(outbuf), RSTRING_PTR(dst), RSTRING_LEN(dst));
- dst = outbuf;
- }
return dst;
}
static VALUE
-gzfile_read_all(struct gzfile *gz)
+gzfile_read_all(struct gzfile *gz, VALUE dst)
{
- VALUE dst;
-
while (!ZSTREAM_IS_FINISHED(&gz->z)) {
- gzfile_read_more(gz, Qnil);
+ gzfile_read_more(gz, dst);
}
if (GZFILE_IS_FINISHED(gz)) {
if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
- gzfile_check_footer(gz, Qnil);
+ gzfile_check_footer(gz, dst);
}
+ if (!NIL_P(dst)) {
+ rb_str_resize(dst, 0);
+ return dst;
+ }
return rb_str_new(0, 0);
}
@@ -2993,7 +3015,7 @@ gzfile_getc(struct gzfile *gz)
de = (unsigned char *)ds + GZFILE_CBUF_CAPA;
(void)rb_econv_convert(gz->ec, &sp, se, &dp, de, ECONV_PARTIAL_INPUT|ECONV_AFTER_OUTPUT);
rb_econv_check_error(gz->ec);
- dst = zstream_shift_buffer(&gz->z, sp - ss);
+ dst = zstream_shift_buffer(&gz->z, sp - ss, Qnil);
gzfile_calc_crc(gz, dst);
rb_str_resize(cbuf, dp - ds);
return cbuf;
@@ -3001,7 +3023,7 @@ gzfile_getc(struct gzfile *gz)
else {
buf = gz->z.buf;
len = rb_enc_mbclen(RSTRING_PTR(buf), RSTRING_END(buf), gz->enc);
- dst = gzfile_read(gz, len);
+ dst = gzfile_read(gz, len, Qnil);
if (NIL_P(dst)) return dst;
return gzfile_newstr(gz, dst);
}
@@ -3500,6 +3522,9 @@ static VALUE
rb_gzfile_eof_p(VALUE obj)
{
struct gzfile *gz = get_gzfile(obj);
+ while (!ZSTREAM_IS_FINISHED(&gz->z) && ZSTREAM_BUF_FILLED(&gz->z) == 0) {
+ gzfile_read_more(gz, Qnil);
+ }
return GZFILE_IS_FINISHED(gz) ? Qtrue : Qfalse;
}
@@ -3906,7 +3931,7 @@ rb_gzreader_s_zcat(int argc, VALUE *argv, VALUE klass)
if (!buf) {
buf = rb_str_new(0, 0);
}
- tmpbuf = gzfile_read_all(get_gzfile(obj));
+ tmpbuf = gzfile_read_all(get_gzfile(obj), Qnil);
rb_str_cat(buf, RSTRING_PTR(tmpbuf), RSTRING_LEN(tmpbuf));
}
@@ -4008,19 +4033,19 @@ static VALUE
rb_gzreader_read(int argc, VALUE *argv, VALUE obj)
{
struct gzfile *gz = get_gzfile(obj);
- VALUE vlen;
+ VALUE vlen, outbuf;
long len;
- rb_scan_args(argc, argv, "01", &vlen);
+ rb_scan_args(argc, argv, "02", &vlen, &outbuf);
if (NIL_P(vlen)) {
- return gzfile_read_all(gz);
+ return gzfile_read_all(gz, outbuf);
}
len = NUM2INT(vlen);
if (len < 0) {
rb_raise(rb_eArgError, "negative length %ld given", len);
}
- return gzfile_read(gz, len);
+ return gzfile_read(gz, len, outbuf);
}
/*
@@ -4093,7 +4118,7 @@ rb_gzreader_getbyte(VALUE obj)
struct gzfile *gz = get_gzfile(obj);
VALUE dst;
- dst = gzfile_read(gz, 1);
+ dst = gzfile_read(gz, 1, Qnil);
if (!NIL_P(dst)) {
dst = INT2FIX((unsigned int)(RSTRING_PTR(dst)[0]) & 0xff);
}
@@ -4214,7 +4239,7 @@ gzreader_skip_linebreaks(struct gzfile *gz)
}
}
- str = zstream_shift_buffer(&gz->z, n - 1);
+ str = zstream_shift_buffer(&gz->z, n - 1, Qnil);
gzfile_calc_crc(gz, str);
}
@@ -4235,7 +4260,7 @@ gzreader_charboundary(struct gzfile *gz, long n)
if (l < n) {
int n_bytes = rb_enc_precise_mbclen(p, e, gz->enc);
if (MBCLEN_NEEDMORE_P(n_bytes)) {
- if ((l = gzfile_fill(gz, n + MBCLEN_NEEDMORE_LEN(n_bytes))) > 0) {
+ if ((l = gzfile_fill(gz, n + MBCLEN_NEEDMORE_LEN(n_bytes), Qnil)) > 0) {
return l;
}
}
@@ -4287,10 +4312,10 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj)
if (NIL_P(rs)) {
if (limit < 0) {
- dst = gzfile_read_all(gz);
+ dst = gzfile_read_all(gz, Qnil);
if (RSTRING_LEN(dst) == 0) return Qnil;
}
- else if ((n = gzfile_fill(gz, limit)) <= 0) {
+ else if ((n = gzfile_fill(gz, limit, Qnil)) <= 0) {
return Qnil;
}
else {
@@ -4300,7 +4325,7 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj)
else {
n = limit;
}
- dst = zstream_shift_buffer(&gz->z, n);
+ dst = zstream_shift_buffer(&gz->z, n, Qnil);
if (NIL_P(dst)) return dst;
gzfile_calc_crc(gz, dst);
dst = gzfile_newstr(gz, dst);
@@ -4327,7 +4352,7 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj)
while (ZSTREAM_BUF_FILLED(&gz->z) < rslen) {
if (ZSTREAM_IS_FINISHED(&gz->z)) {
if (ZSTREAM_BUF_FILLED(&gz->z) > 0) gz->lineno++;
- return gzfile_read(gz, rslen);
+ return gzfile_read(gz, rslen, Qnil);
}
gzfile_read_more(gz, Qnil);
}
@@ -4364,7 +4389,7 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj)
}
gz->lineno++;
- dst = gzfile_read(gz, n);
+ dst = gzfile_read(gz, n, Qnil);
if (NIL_P(dst)) return dst;
if (rspara) {
gzreader_skip_linebreaks(gz);
diff --git a/ext/zlib/zlib.gemspec b/ext/zlib/zlib.gemspec
index bb67ea156c..345dc5f225 100644
--- a/ext/zlib/zlib.gemspec
+++ b/ext/zlib/zlib.gemspec
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
spec.homepage = "https://github.com/ruby/zlib"
spec.licenses = ["Ruby", "BSD-2-Clause"]
- spec.files = ["LICENSE.txt", "README.md", "ext/zlib/extconf.rb", "ext/zlib/zlib.c", "zlib.gemspec"]
+ spec.files = ["COPYING", "BSDL", "README.md", "ext/zlib/extconf.rb", "ext/zlib/zlib.c", "zlib.gemspec"]
spec.bindir = "exe"
spec.executables = []
spec.require_paths = ["lib"]
diff --git a/file.c b/file.c
index 1b52621928..835f19e541 100644
--- a/file.c
+++ b/file.c
@@ -468,7 +468,7 @@ apply2files(int (*func)(const char *, void *), int argc, VALUE *argv, void *arg)
aa->fn[aa->i].path = path;
}
- rb_thread_call_without_gvl(no_gvl_apply2files, aa, RUBY_UBF_IO, 0);
+ IO_WITHOUT_GVL(no_gvl_apply2files, aa);
if (aa->errnum) {
#ifdef UTIME_EINVAL
if (func == utime_internal) {
@@ -483,28 +483,29 @@ apply2files(int (*func)(const char *, void *), int argc, VALUE *argv, void *arg)
return LONG2FIX(argc);
}
-static size_t
-stat_memsize(const void *p)
-{
- return sizeof(struct stat);
-}
-
static const rb_data_type_t stat_data_type = {
"stat",
- {NULL, RUBY_TYPED_DEFAULT_FREE, stat_memsize,},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
+ {
+ NULL,
+ RUBY_TYPED_DEFAULT_FREE,
+ NULL, // No external memory to report
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
+};
+
+struct rb_stat {
+ struct stat stat;
+ bool initialized;
};
static VALUE
stat_new_0(VALUE klass, const struct stat *st)
{
- struct stat *nst = 0;
- VALUE obj = TypedData_Wrap_Struct(klass, &stat_data_type, 0);
-
+ struct rb_stat *rb_st;
+ VALUE obj = TypedData_Make_Struct(klass, struct rb_stat, &stat_data_type, rb_st);
if (st) {
- nst = ALLOC(struct stat);
- *nst = *st;
- RTYPEDDATA_DATA(obj) = nst;
+ rb_st->stat = *st;
+ rb_st->initialized = true;
}
return obj;
}
@@ -518,10 +519,10 @@ rb_stat_new(const struct stat *st)
static struct stat*
get_stat(VALUE self)
{
- struct stat* st;
- TypedData_Get_Struct(self, struct stat, &stat_data_type, st);
- if (!st) rb_raise(rb_eTypeError, "uninitialized File::Stat");
- return st;
+ struct rb_stat* rb_st;
+ TypedData_Get_Struct(self, struct rb_stat, &stat_data_type, rb_st);
+ if (!rb_st->initialized) rb_raise(rb_eTypeError, "uninitialized File::Stat");
+ return &rb_st->stat;
}
static struct timespec stat_mtimespec(const struct stat *st);
@@ -1092,9 +1093,9 @@ rb_stat_inspect(VALUE self)
#endif
};
- struct stat* st;
- TypedData_Get_Struct(self, struct stat, &stat_data_type, st);
- if (!st) {
+ struct rb_stat* rb_st;
+ TypedData_Get_Struct(self, struct rb_stat, &stat_data_type, rb_st);
+ if (!rb_st->initialized) {
return rb_sprintf("#<%s: uninitialized>", rb_obj_classname(self));
}
@@ -1167,8 +1168,7 @@ stat_without_gvl(const char *path, struct stat *st)
data.file.path = path;
data.st = st;
- return (int)(VALUE)rb_thread_call_without_gvl(no_gvl_stat, &data,
- RUBY_UBF_IO, NULL);
+ return IO_WITHOUT_GVL_INT(no_gvl_stat, &data);
}
#if !defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC) && \
@@ -1218,8 +1218,7 @@ statx_without_gvl(const char *path, struct statx *stx, unsigned int mask)
no_gvl_statx_data data = {stx, AT_FDCWD, path, 0, mask};
/* call statx(2) with pathname */
- return (int)(VALUE)rb_thread_call_without_gvl(no_gvl_statx, &data,
- RUBY_UBF_IO, NULL);
+ return IO_WITHOUT_GVL_INT(no_gvl_statx, &data);
}
static int
@@ -1381,8 +1380,7 @@ lstat_without_gvl(const char *path, struct stat *st)
data.file.path = path;
data.st = st;
- return (int)(VALUE)rb_thread_call_without_gvl(no_gvl_lstat, &data,
- RUBY_UBF_IO, NULL);
+ return IO_WITHOUT_GVL_INT(no_gvl_lstat, &data);
}
#endif /* HAVE_LSTAT */
@@ -1556,8 +1554,7 @@ rb_eaccess(VALUE fname, int mode)
aa.path = StringValueCStr(fname);
aa.mode = mode;
- return (int)(VALUE)rb_thread_call_without_gvl(nogvl_eaccess, &aa,
- RUBY_UBF_IO, 0);
+ return IO_WITHOUT_GVL_INT(nogvl_eaccess, &aa);
}
static void *
@@ -1578,8 +1575,7 @@ rb_access(VALUE fname, int mode)
aa.path = StringValueCStr(fname);
aa.mode = mode;
- return (int)(VALUE)rb_thread_call_without_gvl(nogvl_access, &aa,
- RUBY_UBF_IO, 0);
+ return IO_WITHOUT_GVL_INT(nogvl_access, &aa);
}
/*
@@ -1593,8 +1589,6 @@ rb_access(VALUE fname, int mode)
*/
/*
- * Document-method: directory?
- *
* call-seq:
* File.directory?(path) -> true or false
*
@@ -2454,6 +2448,7 @@ rb_file_ctime(VALUE obj)
return stat_ctime(&st);
}
+#if defined(HAVE_STAT_BIRTHTIME)
/*
* call-seq:
* File.birthtime(file_name) -> time
@@ -2468,8 +2463,7 @@ rb_file_ctime(VALUE obj)
*
*/
-#if defined(HAVE_STAT_BIRTHTIME)
-RUBY_FUNC_EXPORTED VALUE
+VALUE
rb_file_s_birthtime(VALUE klass, VALUE fname)
{
statx_data st;
@@ -2514,16 +2508,6 @@ rb_file_birthtime(VALUE obj)
# define rb_file_birthtime rb_f_notimplement
#endif
-/*
- * call-seq:
- * file.size -> integer
- *
- * Returns the size of <i>file</i> in bytes.
- *
- * File.new("testfile").size #=> 66
- *
- */
-
rb_off_t
rb_file_size(VALUE file)
{
@@ -2547,12 +2531,45 @@ rb_file_size(VALUE file)
}
}
+/*
+ * call-seq:
+ * file.size -> integer
+ *
+ * Returns the size of <i>file</i> in bytes.
+ *
+ * File.new("testfile").size #=> 66
+ *
+ */
+
static VALUE
file_size(VALUE self)
{
return OFFT2NUM(rb_file_size(self));
}
+struct nogvl_chmod_data {
+ const char *path;
+ mode_t mode;
+};
+
+static void *
+nogvl_chmod(void *ptr)
+{
+ struct nogvl_chmod_data *data = ptr;
+ int ret = chmod(data->path, data->mode);
+ return (void *)(VALUE)ret;
+}
+
+static int
+rb_chmod(const char *path, mode_t mode)
+{
+ struct nogvl_chmod_data data = {
+ .path = path,
+ .mode = mode,
+ };
+ return IO_WITHOUT_GVL_INT(nogvl_chmod, &data);
+}
+
static int
chmod_internal(const char *path, void *mode)
{
@@ -2583,6 +2600,29 @@ rb_file_s_chmod(int argc, VALUE *argv, VALUE _)
return apply2files(chmod_internal, argc, argv, &mode);
}
+#ifdef HAVE_FCHMOD
+struct nogvl_fchmod_data {
+ int fd;
+ mode_t mode;
+};
+
+static VALUE
+io_blocking_fchmod(void *ptr)
+{
+ struct nogvl_fchmod_data *data = ptr;
+ int ret = fchmod(data->fd, data->mode);
+ return (VALUE)ret;
+}
+
+static int
+rb_fchmod(int fd, mode_t mode)
+{
+ (void)rb_chmod; /* suppress unused-function warning when HAVE_FCHMOD */
+ struct nogvl_fchmod_data data = {.fd = fd, .mode = mode};
+ return (int)rb_thread_io_blocking_region(io_blocking_fchmod, &data, fd);
+}
+#endif
+
/*
* call-seq:
* file.chmod(mode_int) -> 0
@@ -2609,7 +2649,7 @@ rb_file_chmod(VALUE obj, VALUE vmode)
GetOpenFile(obj, fptr);
#ifdef HAVE_FCHMOD
- if (fchmod(fptr->fd, mode) == -1) {
+ if (rb_fchmod(fptr->fd, mode) == -1) {
if (HAVE_FCHMOD || errno != ENOSYS)
rb_sys_fail_path(fptr->pathv);
}
@@ -2620,7 +2660,7 @@ rb_file_chmod(VALUE obj, VALUE vmode)
#if !defined HAVE_FCHMOD || !HAVE_FCHMOD
if (NIL_P(fptr->pathv)) return Qnil;
path = rb_str_encode_ospath(fptr->pathv);
- if (chmod(RSTRING_PTR(path), mode) == -1)
+ if (rb_chmod(RSTRING_PTR(path), mode) == -1)
rb_sys_fail_path(fptr->pathv);
#endif
@@ -2715,6 +2755,51 @@ rb_file_s_chown(int argc, VALUE *argv, VALUE _)
return apply2files(chown_internal, argc, argv, &arg);
}
+struct nogvl_chown_data {
+ union {
+ const char *path;
+ int fd;
+ } as;
+ struct chown_args new;
+};
+
+static void *
+nogvl_chown(void *ptr)
+{
+ struct nogvl_chown_data *data = ptr;
+ return (void *)(VALUE)chown(data->as.path, data->new.owner, data->new.group);
+}
+
+static int
+rb_chown(const char *path, rb_uid_t owner, rb_gid_t group)
+{
+ struct nogvl_chown_data data = {
+ .as = {.path = path},
+ .new = {.owner = owner, .group = group},
+ };
+ return IO_WITHOUT_GVL_INT(nogvl_chown, &data);
+}
+
+#ifdef HAVE_FCHOWN
+static void *
+nogvl_fchown(void *ptr)
+{
+ struct nogvl_chown_data *data = ptr;
+ return (void *)(VALUE)fchown(data->as.fd, data->new.owner, data->new.group);
+}
+
+static int
+rb_fchown(int fd, rb_uid_t owner, rb_gid_t group)
+{
+ (void)rb_chown; /* suppress unused-function warning when HAVE_FCHMOD */
+ struct nogvl_chown_data data = {
+ .as = {.fd = fd},
+ .new = {.owner = owner, .group = group},
+ };
+ return IO_WITHOUT_GVL_INT(nogvl_fchown, &data);
+}
+#endif
+
/*
* call-seq:
* file.chown(owner_int, group_int ) -> 0
@@ -2746,10 +2831,10 @@ rb_file_chown(VALUE obj, VALUE owner, VALUE group)
#ifndef HAVE_FCHOWN
if (NIL_P(fptr->pathv)) return Qnil;
path = rb_str_encode_ospath(fptr->pathv);
- if (chown(RSTRING_PTR(path), o, g) == -1)
+ if (rb_chown(RSTRING_PTR(path), o, g) == -1)
rb_sys_fail_path(fptr->pathv);
#else
- if (fchown(fptr->fd, o, g) == -1)
+ if (rb_fchown(fptr->fd, o, g) == -1)
rb_sys_fail_path(fptr->pathv);
#endif
@@ -3141,8 +3226,7 @@ readlink_without_gvl(VALUE path, VALUE buf, size_t size)
ra.buf = RSTRING_PTR(buf);
ra.size = size;
- return (ssize_t)rb_thread_call_without_gvl(nogvl_readlink, &ra,
- RUBY_UBF_IO, 0);
+ return (ssize_t)IO_WITHOUT_GVL(nogvl_readlink, &ra);
}
VALUE
@@ -3243,8 +3327,7 @@ rb_file_s_rename(VALUE klass, VALUE from, VALUE to)
#if defined __CYGWIN__
errno = 0;
#endif
- if ((int)(VALUE)rb_thread_call_without_gvl(no_gvl_rename, &ra,
- RUBY_UBF_IO, 0) < 0) {
+ if (IO_WITHOUT_GVL_INT(no_gvl_rename, &ra) < 0) {
int e = errno;
#if defined DOSISH
switch (e) {
@@ -3674,7 +3757,7 @@ rb_default_home_dir(VALUE result)
* lookup by getuid() has a chance of succeeding.
*/
if (NIL_P(login_name)) {
- rb_raise(rb_eArgError, "couldn't find login name -- expanding `~'");
+ rb_raise(rb_eArgError, "couldn't find login name -- expanding '~'");
}
# endif /* !defined(HAVE_GETPWUID_R) && !defined(HAVE_GETPWUID) */
@@ -3682,7 +3765,7 @@ rb_default_home_dir(VALUE result)
if (NIL_P(pw_dir)) {
pw_dir = rb_getpwdiruid();
if (NIL_P(pw_dir)) {
- rb_raise(rb_eArgError, "couldn't find home for uid `%ld'", (long)getuid());
+ rb_raise(rb_eArgError, "couldn't find home for uid '%ld'", (long)getuid());
}
}
@@ -3693,7 +3776,7 @@ rb_default_home_dir(VALUE result)
}
#endif /* defined HAVE_PWD_H */
if (!dir) {
- rb_raise(rb_eArgError, "couldn't find HOME environment -- expanding `~'");
+ rb_raise(rb_eArgError, "couldn't find HOME environment -- expanding '~'");
}
return copy_home_path(result, dir);
}
@@ -3718,7 +3801,15 @@ append_fspath(VALUE result, VALUE fname, char *dir, rb_encoding **enc, rb_encodi
size_t dirlen = strlen(dir), buflen = rb_str_capacity(result);
if (NORMALIZE_UTF8PATH || *enc != fsenc) {
- rb_encoding *direnc = fs_enc_check(fname, dirname = ospath_new(dir, dirlen, fsenc));
+ dirname = ospath_new(dir, dirlen, fsenc);
+ if (!rb_enc_compatible(fname, dirname)) {
+ xfree(dir);
+ /* rb_enc_check must raise because the two encodings are not
+ * compatible. */
+ rb_enc_check(fname, dirname);
+ rb_bug("unreachable");
+ }
+ rb_encoding *direnc = fs_enc_check(fname, dirname);
if (direnc != fsenc) {
dirname = rb_str_conv_enc(dirname, fsenc, direnc);
RSTRING_GETMEM(dirname, cwdp, dirlen);
@@ -5129,8 +5220,7 @@ rb_file_s_truncate(VALUE klass, VALUE path, VALUE len)
path = rb_str_encode_ospath(path);
ta.path = StringValueCStr(path);
- r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_truncate, &ta,
- RUBY_UBF_IO, NULL);
+ r = IO_WITHOUT_GVL_INT(nogvl_truncate, &ta);
if (r < 0)
rb_sys_fail_path(path);
return INT2FIX(0);
@@ -5223,47 +5313,50 @@ rb_thread_flock(void *data)
return (VALUE)ret;
}
-/*
+/* :markup: markdown
+ *
* call-seq:
- * file.flock(locking_constant) -> 0 or false
- *
- * Locks or unlocks a file according to <i>locking_constant</i> (a
- * logical <em>or</em> of the values in the table below).
- * Returns <code>false</code> if File::LOCK_NB is specified and the
- * operation would otherwise have blocked. Not available on all
- * platforms.
- *
- * Locking constants (in class File):
- *
- * LOCK_EX | Exclusive lock. Only one process may hold an
- * | exclusive lock for a given file at a time.
- * ----------+------------------------------------------------
- * LOCK_NB | Don't block when locking. May be combined
- * | with other lock options using logical or.
- * ----------+------------------------------------------------
- * LOCK_SH | Shared lock. Multiple processes may each hold a
- * | shared lock for a given file at the same time.
- * ----------+------------------------------------------------
- * LOCK_UN | Unlock.
+ * flock(locking_constant) -> 0 or false
+ *
+ * Locks or unlocks file +self+ according to the given `locking_constant`,
+ * a bitwise OR of the values in the table below.
+ *
+ * Not available on all platforms.
+ *
+ * Returns `false` if `File::LOCK_NB` is specified and the operation would have blocked;
+ * otherwise returns `0`.
+ *
+ * <br>
+ *
+ * | Constant | Lock | Effect
+ * |-----------------|--------------|-------------------------------------------------------------------
+ * | +File::LOCK_EX+ | Exclusive | Only one process may hold an exclusive lock for +self+ at a time.
+ * | +File::LOCK_NB+ | Non-blocking | No blocking; may be combined with +File::LOCK_SH+ or +File::LOCK_EX+ using the bitwise OR operator <tt>\|</tt>.
+ * | +File::LOCK_SH+ | Shared | Multiple processes may each hold a shared lock for +self+ at the same time.
+ * | +File::LOCK_UN+ | Unlock | Remove an existing lock held by this process.
+ *
+ * <br>
*
* Example:
*
- * # update a counter using write lock
- * # don't use "w" because it truncates the file before lock.
- * File.open("counter", File::RDWR|File::CREAT, 0644) {|f|
- * f.flock(File::LOCK_EX)
- * value = f.read.to_i + 1
- * f.rewind
- * f.write("#{value}\n")
- * f.flush
- * f.truncate(f.pos)
- * }
- *
- * # read the counter using read lock
- * File.open("counter", "r") {|f|
- * f.flock(File::LOCK_SH)
- * p f.read
- * }
+ * ```ruby
+ * # Update a counter using an exclusive lock.
+ * # Don't use File::WRONLY because it truncates the file.
+ * File.open('counter', File::RDWR | File::CREAT, 0644) do |f|
+ * f.flock(File::LOCK_EX)
+ * value = f.read.to_i + 1
+ * f.rewind
+ * f.write("#{value}\n")
+ * f.flush
+ * f.truncate(f.pos)
+ * end
+ *
+ * # Read the counter using a shared lock.
+ * File.open('counter', 'r') do |f|
+ * f.flock(File::LOCK_SH)
+ * f.read
+ * end
+ * ```
*
*/
@@ -5327,60 +5420,83 @@ test_check(int n, int argc, VALUE *argv)
#define CHECK(n) test_check((n), argc, argv)
/*
+ * :markup: markdown
+ *
* call-seq:
- * test(cmd, file1 [, file2] ) -> obj
- *
- * Uses the character +cmd+ to perform various tests on +file1+ (first
- * table below) or on +file1+ and +file2+ (second table).
- *
- * File tests on a single file:
- *
- * Cmd Returns Meaning
- * "A" | Time | Last access time for file1
- * "b" | boolean | True if file1 is a block device
- * "c" | boolean | True if file1 is a character device
- * "C" | Time | Last change time for file1
- * "d" | boolean | True if file1 exists and is a directory
- * "e" | boolean | True if file1 exists
- * "f" | boolean | True if file1 exists and is a regular file
- * "g" | boolean | True if file1 has the setgid bit set
- * "G" | boolean | True if file1 exists and has a group
- * | | ownership equal to the caller's group
- * "k" | boolean | True if file1 exists and has the sticky bit set
- * "l" | boolean | True if file1 exists and is a symbolic link
- * "M" | Time | Last modification time for file1
- * "o" | boolean | True if file1 exists and is owned by
- * | | the caller's effective uid
- * "O" | boolean | True if file1 exists and is owned by
- * | | the caller's real uid
- * "p" | boolean | True if file1 exists and is a fifo
- * "r" | boolean | True if file1 is readable by the effective
- * | | uid/gid of the caller
- * "R" | boolean | True if file is readable by the real
- * | | uid/gid of the caller
- * "s" | int/nil | If file1 has nonzero size, return the size,
- * | | otherwise return nil
- * "S" | boolean | True if file1 exists and is a socket
- * "u" | boolean | True if file1 has the setuid bit set
- * "w" | boolean | True if file1 exists and is writable by
- * | | the effective uid/gid
- * "W" | boolean | True if file1 exists and is writable by
- * | | the real uid/gid
- * "x" | boolean | True if file1 exists and is executable by
- * | | the effective uid/gid
- * "X" | boolean | True if file1 exists and is executable by
- * | | the real uid/gid
- * "z" | boolean | True if file1 exists and has a zero length
- *
- * Tests that take two files:
- *
- * "-" | boolean | True if file1 and file2 are identical
- * "=" | boolean | True if the modification times of file1
- * | | and file2 are equal
- * "<" | boolean | True if the modification time of file1
- * | | is prior to that of file2
- * ">" | boolean | True if the modification time of file1
- * | | is after that of file2
+ * test(char, path0, path1 = nil) -> object
+ *
+ * Performs a test on one or both of the <i>filesystem entities</i> at the given paths
+ * `path0` and `path1`:
+ *
+ * - Each path `path0` or `path1` points to a file, directory, device, pipe, etc.
+ * - Character `char` selects a specific test.
+ *
+ * The tests:
+ *
+ * - Each of these tests operates only on the entity at `path0`,
+ * and returns `true` or `false`;
+ * for a non-existent entity, returns `false` (does not raise exception):
+ *
+ * | Character | Test |
+ * |:------------:|:--------------------------------------------------------------------------|
+ * | <tt>'b'</tt> | Whether the entity is a block device. |
+ * | <tt>'c'</tt> | Whether the entity is a character device. |
+ * | <tt>'d'</tt> | Whether the entity is a directory. |
+ * | <tt>'e'</tt> | Whether the entity is an existing entity. |
+ * | <tt>'f'</tt> | Whether the entity is an existing regular file. |
+ * | <tt>'g'</tt> | Whether the entity's setgid bit is set. |
+ * | <tt>'G'</tt> | Whether the entity's group ownership is equal to the caller's. |
+ * | <tt>'k'</tt> | Whether the entity's sticky bit is set. |
+ * | <tt>'l'</tt> | Whether the entity is a symbolic link. |
+ * | <tt>'o'</tt> | Whether the entity is owned by the caller's effective uid. |
+ * | <tt>'O'</tt> | Like <tt>'o'</tt>, but uses the real uid (not the effective uid). |
+ * | <tt>'p'</tt> | Whether the entity is a FIFO device (named pipe). |
+ * | <tt>'r'</tt> | Whether the entity is readable by the caller's effecive uid/gid. |
+ * | <tt>'R'</tt> | Like <tt>'r'</tt>, but uses the real uid/gid (not the effective uid/gid). |
+ * | <tt>'S'</tt> | Whether the entity is a socket. |
+ * | <tt>'u'</tt> | Whether the entity's setuid bit is set. |
+ * | <tt>'w'</tt> | Whether the entity is writable by the caller's effective uid/gid. |
+ * | <tt>'W'</tt> | Like <tt>'w'</tt>, but uses the real uid/gid (not the effective uid/gid). |
+ * | <tt>'x'</tt> | Whether the entity is executable by the caller's effective uid/gid. |
+ * | <tt>'X'</tt> | Like <tt>'x'</tt>, but uses the real uid/gid (not the effecive uid/git). |
+ * | <tt>'z'</tt> | Whether the entity exists and is of length zero. |
+ *
+ * - This test operates only on the entity at `path0`,
+ * and returns an integer size or +nil+:
+ *
+ * | Character | Test |
+ * |:------------:|:---------------------------------------------------------------------------------------------|
+ * | <tt>'s'</tt> | Returns positive integer size if the entity exists and has non-zero length, +nil+ otherwise. |
+ *
+ * - Each of these tests operates only on the entity at `path0`,
+ * and returns a Time object;
+ * raises an exception if the entity does not exist:
+ *
+ * | Character | Test |
+ * |:------------:|:---------------------------------------|
+ * | <tt>'A'</tt> | Last access time for the entity. |
+ * | <tt>'C'</tt> | Last change time for the entity. |
+ * | <tt>'M'</tt> | Last modification time for the entity. |
+ *
+ * - Each of these tests operates on the modification time (`mtime`)
+ * of each of the entities at `path0` and `path1`,
+ * and returns a `true` or `false`;
+ * returns `false` if either entity does not exist:
+ *
+ * | Character | Test |
+ * |:------------:|:----------------------------------------------------------------|
+ * | <tt>'<'</tt> | Whether the `mtime` at `path0` is less than that at `path1`. |
+ * | <tt>'='</tt> | Whether the `mtime` at `path0` is equal to that at `path1`. |
+ * | <tt>'>'</tt> | Whether the `mtime` at `path0` is greater than that at `path1`. |
+ *
+ * - This test operates on the content of each of the entities at `path0` and `path1`,
+ * and returns a `true` or `false`;
+ * returns `false` if either entity does not exist:
+ *
+ * | Character | Test |
+ * |:------------:|:----------------------------------------------|
+ * | <tt>'-'</tt> | Whether the entities exist and are identical. |
+ *
*/
static VALUE
@@ -5559,7 +5675,7 @@ rb_stat_s_alloc(VALUE klass)
static VALUE
rb_stat_init(VALUE obj, VALUE fname)
{
- struct stat st, *nst;
+ struct stat st;
FilePathValue(fname);
fname = rb_str_encode_ospath(fname);
@@ -5567,13 +5683,11 @@ rb_stat_init(VALUE obj, VALUE fname)
rb_sys_fail_path(fname);
}
- if (DATA_PTR(obj)) {
- xfree(DATA_PTR(obj));
- DATA_PTR(obj) = NULL;
- }
- nst = ALLOC(struct stat);
- *nst = st;
- DATA_PTR(obj) = nst;
+ struct rb_stat *rb_st;
+ TypedData_Get_Struct(obj, struct rb_stat, &stat_data_type, rb_st);
+
+ rb_st->stat = st;
+ rb_st->initialized = true;
return Qnil;
}
@@ -5582,19 +5696,15 @@ rb_stat_init(VALUE obj, VALUE fname)
static VALUE
rb_stat_init_copy(VALUE copy, VALUE orig)
{
- struct stat *nst;
-
if (!OBJ_INIT_COPY(copy, orig)) return copy;
- if (DATA_PTR(copy)) {
- xfree(DATA_PTR(copy));
- DATA_PTR(copy) = 0;
- }
- if (DATA_PTR(orig)) {
- nst = ALLOC(struct stat);
- *nst = *(struct stat*)DATA_PTR(orig);
- DATA_PTR(copy) = nst;
- }
+ struct rb_stat *orig_rb_st;
+ TypedData_Get_Struct(orig, struct rb_stat, &stat_data_type, orig_rb_st);
+
+ struct rb_stat *copy_rb_st;
+ TypedData_Get_Struct(copy, struct rb_stat, &stat_data_type, copy_rb_st);
+
+ *copy_rb_st = *orig_rb_st;
return copy;
}
@@ -6205,7 +6315,7 @@ rb_file_s_mkfifo(int argc, VALUE *argv, VALUE _)
FilePathValue(path);
path = rb_str_encode_ospath(path);
ma.path = RSTRING_PTR(path);
- if (rb_thread_call_without_gvl(nogvl_mkfifo, &ma, RUBY_UBF_IO, 0)) {
+ if (IO_WITHOUT_GVL(nogvl_mkfifo, &ma)) {
rb_sys_fail_path(path);
}
return INT2FIX(0);
@@ -6612,7 +6722,7 @@ const char ruby_null_device[] =
*
* - <tt>'r'</tt>:
*
- * - File is not initially truncated:
+ * - \File is not initially truncated:
*
* f = File.new('t.txt') # => #<File:t.txt>
* f.size == 0 # => false
@@ -6621,7 +6731,7 @@ const char ruby_null_device[] =
*
* f.pos # => 0
*
- * - File may be read anywhere; see IO#rewind, IO#pos=, IO#seek:
+ * - \File may be read anywhere; see IO#rewind, IO#pos=, IO#seek:
*
* f.readline # => "First line\n"
* f.readline # => "Second line\n"
@@ -6641,7 +6751,7 @@ const char ruby_null_device[] =
*
* - <tt>'w'</tt>:
*
- * - File is initially truncated:
+ * - \File is initially truncated:
*
* path = 't.tmp'
* File.write(path, text)
@@ -6652,7 +6762,7 @@ const char ruby_null_device[] =
*
* f.pos # => 0
*
- * - File may be written anywhere (even past end-of-file);
+ * - \File may be written anywhere (even past end-of-file);
* see IO#rewind, IO#pos=, IO#seek:
*
* f.write('foo')
@@ -6695,7 +6805,7 @@ const char ruby_null_device[] =
*
* - <tt>'a'</tt>:
*
- * - File is not initially truncated:
+ * - \File is not initially truncated:
*
* path = 't.tmp'
* File.write(path, 'foo')
@@ -6706,7 +6816,7 @@ const char ruby_null_device[] =
*
* f.pos # => 0
*
- * - File may be written only at end-of-file;
+ * - \File may be written only at end-of-file;
* IO#rewind, IO#pos=, IO#seek do not affect writing:
*
* f.write('bar')
@@ -6727,7 +6837,7 @@ const char ruby_null_device[] =
*
* - <tt>'r+'</tt>:
*
- * - File is not initially truncated:
+ * - \File is not initially truncated:
*
* path = 't.tmp'
* File.write(path, text)
@@ -6738,7 +6848,7 @@ const char ruby_null_device[] =
*
* f.pos # => 0
*
- * - File may be read or written anywhere (even past end-of-file);
+ * - \File may be read or written anywhere (even past end-of-file);
* see IO#rewind, IO#pos=, IO#seek:
*
* f.readline # => "First line\n"
@@ -6783,7 +6893,7 @@ const char ruby_null_device[] =
*
* - <tt>'a+'</tt>:
*
- * - File is not initially truncated:
+ * - \File is not initially truncated:
*
* path = 't.tmp'
* File.write(path, 'foo')
@@ -6794,7 +6904,7 @@ const char ruby_null_device[] =
*
* f.pos # => 0
*
- * - File may be written only at end-of-file;
+ * - \File may be written only at end-of-file;
* IO#rewind, IO#pos=, IO#seek do not affect writing:
*
* f.write('bar')
@@ -6809,7 +6919,7 @@ const char ruby_null_device[] =
* f.flush
* File.read(path) # => "foobarbazbat"
*
- * - File may be read anywhere; see IO#rewind, IO#pos=, IO#seek:
+ * - \File may be read anywhere; see IO#rewind, IO#pos=, IO#seek:
*
* f.rewind
* f.read # => "foobarbazbat"
@@ -6834,7 +6944,7 @@ const char ruby_null_device[] =
* f = File.new(path, 'w')
* f.pos # => 0
*
- * - File may be written anywhere (even past end-of-file);
+ * - \File may be written anywhere (even past end-of-file);
* see IO#rewind, IO#pos=, IO#seek:
*
* f.write('foo')
@@ -6911,7 +7021,7 @@ const char ruby_null_device[] =
* f = File.new(path, 'w+')
* f.pos # => 0
*
- * - File may be written anywhere (even past end-of-file);
+ * - \File may be written anywhere (even past end-of-file);
* see IO#rewind, IO#pos=, IO#seek:
*
* f.write('foo')
@@ -6948,7 +7058,7 @@ const char ruby_null_device[] =
* File.read(path) # => "bazbam\u0000\u0000bah"
* f.pos # => 11
*
- * - File may be read anywhere (even past end-of-file);
+ * - \File may be read anywhere (even past end-of-file);
* see IO#rewind, IO#pos=, IO#seek:
*
* f.rewind
@@ -6989,7 +7099,7 @@ const char ruby_null_device[] =
* f.flush
* File.read(path) # => "foobarbaz"
*
- * - File may be read anywhere (even past end-of-file);
+ * - \File may be read anywhere (even past end-of-file);
* see IO#rewind, IO#pos=, IO#seek:
*
* f.rewind
@@ -7472,7 +7582,7 @@ Init_File(void)
*
* ==== File::RDONLY
*
- * Flag File::RDONLY specifies the the stream should be opened for reading only:
+ * Flag File::RDONLY specifies the stream should be opened for reading only:
*
* filepath = '/tmp/t.tmp'
* f = File.new(filepath, File::RDONLY)
@@ -7646,11 +7756,13 @@ Init_File(void)
*
* Flag File::BINARY specifies that the stream is to be accessed in binary mode.
*
- * ==== File::SHARE_DELETE (Windows Only)
+ * ==== File::SHARE_DELETE
*
* Flag File::SHARE_DELETE enables other processes to open the stream
* with delete access.
*
+ * Windows only.
+ *
* If the stream is opened for (local) delete access without File::SHARE_DELETE,
* and another process attempts to open it with delete access,
* the attempt fails and the stream is not opened for that process.
@@ -7725,9 +7837,11 @@ Init_File(void)
* do not match the directory separator
* (the value of constant File::SEPARATOR).
*
- * ==== File::FNM_SHORTNAME (Windows Only)
+ * ==== File::FNM_SHORTNAME
+ *
+ * Flag File::FNM_SHORTNAME allows patterns to match short names if they exist.
*
- * Flag File::FNM_SHORTNAME Allows patterns to match short names if they exist.
+ * Windows only.
*
* ==== File::FNM_SYSCASE
*
@@ -7747,57 +7861,80 @@ Init_File(void)
*/
rb_mFConst = rb_define_module_under(rb_cFile, "Constants");
rb_include_module(rb_cIO, rb_mFConst);
+ /* {File::RDONLY}[rdoc-ref:File::Constants@File-3A-3ARDONLY] */
rb_define_const(rb_mFConst, "RDONLY", INT2FIX(O_RDONLY));
+ /* {File::WRONLY}[rdoc-ref:File::Constants@File-3A-3AWRONLY] */
rb_define_const(rb_mFConst, "WRONLY", INT2FIX(O_WRONLY));
+ /* {File::RDWR}[rdoc-ref:File::Constants@File-3A-3ARDWR] */
rb_define_const(rb_mFConst, "RDWR", INT2FIX(O_RDWR));
+ /* {File::APPEND}[rdoc-ref:File::Constants@File-3A-3AAPPEND] */
rb_define_const(rb_mFConst, "APPEND", INT2FIX(O_APPEND));
+ /* {File::CREAT}[rdoc-ref:File::Constants@File-3A-3ACREAT] */
rb_define_const(rb_mFConst, "CREAT", INT2FIX(O_CREAT));
+ /* {File::EXCL}[rdoc-ref:File::Constants@File-3A-3AEXCL] */
rb_define_const(rb_mFConst, "EXCL", INT2FIX(O_EXCL));
#if defined(O_NDELAY) || defined(O_NONBLOCK)
# ifndef O_NONBLOCK
# define O_NONBLOCK O_NDELAY
# endif
+ /* {File::NONBLOCK}[rdoc-ref:File::Constants@File-3A-3ANONBLOCK] */
rb_define_const(rb_mFConst, "NONBLOCK", INT2FIX(O_NONBLOCK));
#endif
+ /* {File::TRUNC}[rdoc-ref:File::Constants@File-3A-3ATRUNC] */
rb_define_const(rb_mFConst, "TRUNC", INT2FIX(O_TRUNC));
#ifdef O_NOCTTY
+ /* {File::NOCTTY}[rdoc-ref:File::Constants@File-3A-3ANOCTTY] */
rb_define_const(rb_mFConst, "NOCTTY", INT2FIX(O_NOCTTY));
#endif
#ifndef O_BINARY
# define O_BINARY 0
#endif
+ /* {File::BINARY}[rdoc-ref:File::Constants@File-3A-3ABINARY] */
rb_define_const(rb_mFConst, "BINARY", INT2FIX(O_BINARY));
#ifndef O_SHARE_DELETE
# define O_SHARE_DELETE 0
#endif
+ /* {File::SHARE_DELETE}[rdoc-ref:File::Constants@File-3A-3ASHARE_DELETE] */
rb_define_const(rb_mFConst, "SHARE_DELETE", INT2FIX(O_SHARE_DELETE));
#ifdef O_SYNC
+ /* {File::SYNC}[rdoc-ref:File::Constants@File-3A-3ASYNC-2C+File-3A-3ARSYNC-2C+and+File-3A-3ADSYNC] */
rb_define_const(rb_mFConst, "SYNC", INT2FIX(O_SYNC));
#endif
#ifdef O_DSYNC
+ /* {File::DSYNC}[rdoc-ref:File::Constants@File-3A-3ASYNC-2C+File-3A-3ARSYNC-2C+and+File-3A-3ADSYNC] */
rb_define_const(rb_mFConst, "DSYNC", INT2FIX(O_DSYNC));
#endif
#ifdef O_RSYNC
+ /* {File::RSYNC}[rdoc-ref:File::Constants@File-3A-3ASYNC-2C+File-3A-3ARSYNC-2C+and+File-3A-3ADSYNC] */
rb_define_const(rb_mFConst, "RSYNC", INT2FIX(O_RSYNC));
#endif
#ifdef O_NOFOLLOW
+ /* {File::NOFOLLOW}[rdoc-ref:File::Constants@File-3A-3ANOFOLLOW] */
rb_define_const(rb_mFConst, "NOFOLLOW", INT2FIX(O_NOFOLLOW)); /* FreeBSD, Linux */
#endif
#ifdef O_NOATIME
+ /* {File::NOATIME}[rdoc-ref:File::Constants@File-3A-3ANOATIME] */
rb_define_const(rb_mFConst, "NOATIME", INT2FIX(O_NOATIME)); /* Linux */
#endif
#ifdef O_DIRECT
+ /* {File::DIRECT}[rdoc-ref:File::Constants@File-3A-3ADIRECT] */
rb_define_const(rb_mFConst, "DIRECT", INT2FIX(O_DIRECT));
#endif
#ifdef O_TMPFILE
+ /* {File::TMPFILE}[rdoc-ref:File::Constants@File-3A-3ATMPFILE] */
rb_define_const(rb_mFConst, "TMPFILE", INT2FIX(O_TMPFILE));
#endif
+ /* {File::LOCK_SH}[rdoc-ref:File::Constants@File-3A-3ALOCK_SH] */
rb_define_const(rb_mFConst, "LOCK_SH", INT2FIX(LOCK_SH));
+ /* {File::LOCK_EX}[rdoc-ref:File::Constants@File-3A-3ALOCK_EX] */
rb_define_const(rb_mFConst, "LOCK_EX", INT2FIX(LOCK_EX));
+ /* {File::LOCK_UN}[rdoc-ref:File::Constants@File-3A-3ALOCK_UN] */
rb_define_const(rb_mFConst, "LOCK_UN", INT2FIX(LOCK_UN));
+ /* {File::LOCK_NB}[rdoc-ref:File::Constants@File-3A-3ALOCK_NB] */
rb_define_const(rb_mFConst, "LOCK_NB", INT2FIX(LOCK_NB));
+ /* {File::NULL}[rdoc-ref:File::Constants@File-3A-3ANULL] */
rb_define_const(rb_mFConst, "NULL", rb_fstring_cstr(ruby_null_device));
rb_define_global_function("test", rb_f_test, -1);
diff --git a/gc.c b/gc.c
index 7710fec7d4..f47f20fa57 100644
--- a/gc.c
+++ b/gc.c
@@ -21,8 +21,6 @@
#include <signal.h>
-#define sighandler_t ruby_sighandler_t
-
#ifndef _WIN32
#include <unistd.h>
#include <sys/mman.h>
@@ -226,6 +224,9 @@ size_add_overflow(size_t x, size_t y)
bool p;
#if 0
+#elif defined(ckd_add)
+ p = ckd_add(&z, x, y);
+
#elif __has_builtin(__builtin_add_overflow)
p = __builtin_add_overflow(x, y, &z);
@@ -418,7 +419,6 @@ rb_gc_guarded_ptr_val(volatile VALUE *ptr, VALUE val)
#endif
#define USE_TICK_T (PRINT_ENTER_EXIT_TICK || PRINT_MEASURE_LINE || PRINT_ROOT_TICKS)
-#define TICK_TYPE 1
typedef struct {
size_t size_pool_init_slots[SIZE_POOL_COUNT];
@@ -439,8 +439,6 @@ typedef struct {
size_t oldmalloc_limit_min;
size_t oldmalloc_limit_max;
double oldmalloc_limit_growth_factor;
-
- VALUE gc_stress;
} ruby_gc_params_t;
static ruby_gc_params_t gc_params = {
@@ -462,8 +460,6 @@ static ruby_gc_params_t gc_params = {
GC_OLDMALLOC_LIMIT_MIN,
GC_OLDMALLOC_LIMIT_MAX,
GC_OLDMALLOC_LIMIT_GROWTH_FACTOR,
-
- FALSE,
};
/* GC_DEBUG:
@@ -693,29 +689,33 @@ typedef struct RVALUE {
VALUE v3;
} values;
} as;
+} RVALUE;
- /* Start of RVALUE_OVERHEAD.
- * Do not directly read these members from the RVALUE as they're located
- * at the end of the slot (which may differ in size depending on the size
- * pool). */
-#if RACTOR_CHECK_MODE
+/* These members ae located at the end of the slot that the object is in. */
+#if RACTOR_CHECK_MODE || GC_DEBUG
+struct rvalue_overhead {
+# if RACTOR_CHECK_MODE
uint32_t _ractor_belonging_id;
-#endif
-#if GC_DEBUG
+# endif
+# if GC_DEBUG
const char *file;
int line;
-#endif
-} RVALUE;
+# endif
+};
-#if RACTOR_CHECK_MODE
-# define RVALUE_OVERHEAD (sizeof(RVALUE) - offsetof(RVALUE, _ractor_belonging_id))
-#elif GC_DEBUG
-# define RVALUE_OVERHEAD (sizeof(RVALUE) - offsetof(RVALUE, file))
+// Make sure that RVALUE_OVERHEAD aligns to sizeof(VALUE)
+# define RVALUE_OVERHEAD (sizeof(struct { \
+ union { \
+ struct rvalue_overhead overhead; \
+ VALUE value; \
+ }; \
+}))
+# define GET_RVALUE_OVERHEAD(obj) ((struct rvalue_overhead *)((uintptr_t)obj + rb_gc_obj_slot_size(obj)))
#else
# define RVALUE_OVERHEAD 0
#endif
-STATIC_ASSERT(sizeof_rvalue, sizeof(RVALUE) == (SIZEOF_VALUE * 5) + RVALUE_OVERHEAD);
+STATIC_ASSERT(sizeof_rvalue, sizeof(RVALUE) == (SIZEOF_VALUE * 5));
STATIC_ASSERT(alignof_rvalue, RUBY_ALIGNOF(RVALUE) == SIZEOF_VALUE);
typedef uintptr_t bits_t;
@@ -723,7 +723,6 @@ enum {
BITS_SIZE = sizeof(bits_t),
BITS_BITLENGTH = ( BITS_SIZE * CHAR_BIT )
};
-#define popcount_bits rb_popcount_intptr
struct heap_page_header {
struct heap_page *page;
@@ -735,11 +734,6 @@ struct heap_page_body {
/* RVALUE values[]; */
};
-struct gc_list {
- VALUE *varptr;
- struct gc_list *next;
-};
-
#define STACK_CHUNK_SIZE 500
typedef struct stack_chunk {
@@ -827,7 +821,7 @@ typedef struct rb_objspace {
} flags;
rb_event_flag_t hook_events;
- VALUE next_object_id;
+ unsigned long long next_object_id;
rb_size_pool_t size_pools[SIZE_POOL_COUNT];
@@ -904,7 +898,6 @@ typedef struct rb_objspace {
size_t weak_references_count;
size_t retained_weak_references_count;
} profile;
- struct gc_list *global_list;
VALUE gc_stress_mode;
@@ -952,6 +945,12 @@ typedef struct rb_objspace {
#endif
rb_darray(VALUE *) weak_references;
+ rb_postponed_job_handle_t finalize_deferred_pjob;
+
+#ifdef RUBY_ASAN_ENABLED
+ const rb_execution_context_t *marking_machine_context_ec;
+#endif
+
} rb_objspace_t;
@@ -960,7 +959,7 @@ typedef struct rb_objspace {
#define HEAP_PAGE_ALIGN_LOG 16
#endif
-#define BASE_SLOT_SIZE sizeof(RVALUE)
+#define BASE_SLOT_SIZE (sizeof(RVALUE) + RVALUE_OVERHEAD)
#define CEILDIV(i, mod) roomof(i, mod)
enum {
@@ -1135,10 +1134,6 @@ RVALUE_AGE_SET(VALUE obj, int age)
if (unless_objspace_vm) objspace = unless_objspace_vm->objspace; \
else /* return; or objspace will be warned uninitialized */
-#define ruby_initial_gc_stress gc_params.gc_stress
-
-VALUE *ruby_initial_gc_stress_ptr = &ruby_initial_gc_stress;
-
#define malloc_limit objspace->malloc_params.limit
#define malloc_increase objspace->malloc_params.increase
#define malloc_allocated_size objspace->malloc_params.allocated_size
@@ -1154,7 +1149,6 @@ VALUE *ruby_initial_gc_stress_ptr = &ruby_initial_gc_stress;
#define during_gc objspace->flags.during_gc
#define finalizing objspace->atomic_flags.finalizing
#define finalizer_table objspace->finalizer_table
-#define global_list objspace->global_list
#define ruby_gc_stressful objspace->flags.gc_stressful
#define ruby_gc_stress_mode objspace->gc_stress_mode
#if GC_DEBUG_STRESS_TO_CLASS
@@ -1302,7 +1296,8 @@ total_freed_objects(rb_objspace_t *objspace)
}
#define gc_mode(objspace) gc_mode_verify((enum gc_mode)(objspace)->flags.mode)
-#define gc_mode_set(objspace, mode) ((objspace)->flags.mode = (unsigned int)gc_mode_verify(mode))
+#define gc_mode_set(objspace, m) ((objspace)->flags.mode = (unsigned int)gc_mode_verify(m))
+#define gc_needs_major_flags objspace->rgengc.need_major_gc
#define is_marking(objspace) (gc_mode(objspace) == gc_mode_marking)
#define is_sweeping(objspace) (gc_mode(objspace) == gc_mode_sweeping)
@@ -1341,10 +1336,10 @@ int ruby_gc_debug_indent = 0;
VALUE rb_mGC;
int ruby_disable_gc = 0;
int ruby_enable_autocompact = 0;
+#if RGENGC_CHECK_MODE
+gc_compact_compare_func ruby_autocompact_compare_func;
+#endif
-void rb_iseq_mark_and_move(rb_iseq_t *iseq, bool referece_updating);
-void rb_iseq_free(const rb_iseq_t *iseq);
-size_t rb_iseq_memsize(const rb_iseq_t *iseq);
void rb_vm_update_references(void *ptr);
void rb_gcdebug_print_obj_condition(VALUE obj);
@@ -1385,12 +1380,11 @@ static inline void gc_mark_and_pin(rb_objspace_t *objspace, VALUE ptr);
NO_SANITIZE("memory", static void gc_mark_maybe(rb_objspace_t *objspace, VALUE ptr));
static int gc_mark_stacked_objects_incremental(rb_objspace_t *, size_t count);
-NO_SANITIZE("memory", static inline int is_pointer_to_heap(rb_objspace_t *objspace, void *ptr));
+NO_SANITIZE("memory", static inline int is_pointer_to_heap(rb_objspace_t *objspace, const void *ptr));
static size_t obj_memsize_of(VALUE obj, int use_all_types);
static void gc_verify_internal_consistency(rb_objspace_t *objspace);
-static void gc_stress_set(rb_objspace_t *objspace, VALUE flag);
static VALUE gc_disable_no_rest(rb_objspace_t *);
static double getrusage_time(void);
@@ -1423,19 +1417,12 @@ static inline void gc_prof_set_heap_info(rb_objspace_t *);
#endif
PRINTF_ARGS(static void gc_report_body(int level, rb_objspace_t *objspace, const char *fmt, ...), 3, 4);
static const char *obj_info(VALUE obj);
+static const char *obj_info_basic(VALUE obj);
static const char *obj_type_name(VALUE obj);
-/*
- * 1 - TSC (H/W Time Stamp Counter)
- * 2 - getrusage
- */
-#ifndef TICK_TYPE
-#define TICK_TYPE 1
-#endif
+static void gc_finalize_deferred(void *dmy);
#if USE_TICK_T
-
-#if TICK_TYPE == 1
/* the following code is only for internal tuning. */
/* Source code to use RDTSC is quoted and modified from
@@ -1532,49 +1519,10 @@ tick(void)
return clock();
}
#endif /* TSC */
-
-#elif TICK_TYPE == 2
-typedef double tick_t;
-#define PRItick "4.9f"
-
-static inline tick_t
-tick(void)
-{
- return getrusage_time();
-}
-#else /* TICK_TYPE */
-#error "choose tick type"
-#endif /* TICK_TYPE */
-
-#define MEASURE_LINE(expr) do { \
- volatile tick_t start_time = tick(); \
- volatile tick_t end_time; \
- expr; \
- end_time = tick(); \
- fprintf(stderr, "0\t%"PRItick"\t%s\n", end_time - start_time, #expr); \
-} while (0)
-
#else /* USE_TICK_T */
#define MEASURE_LINE(expr) expr
#endif /* USE_TICK_T */
-static inline void *
-asan_unpoison_object_temporary(VALUE obj)
-{
- void *ptr = asan_poisoned_object_p(obj);
- asan_unpoison_object(obj, false);
- return ptr;
-}
-
-static inline void *
-asan_poison_object_restore(VALUE obj, void *ptr)
-{
- if (ptr) {
- asan_poison_object(obj);
- }
- return NULL;
-}
-
#define asan_unpoisoning_object(obj) \
for (void *poisoned = asan_unpoison_object_temporary(obj), \
*unpoisoning = &poisoned; /* flag to loop just once */ \
@@ -1900,29 +1848,68 @@ calloc1(size_t n)
return calloc(1, n);
}
-rb_objspace_t *
-rb_objspace_alloc(void)
+static VALUE initial_stress = Qfalse;
+
+void
+rb_gc_initial_stress_set(VALUE flag)
{
- rb_objspace_t *objspace = calloc1(sizeof(rb_objspace_t));
- objspace->flags.measure_gc = 1;
- malloc_limit = gc_params.malloc_limit_min;
+ initial_stress = flag;
+}
- for (int i = 0; i < SIZE_POOL_COUNT; i++) {
- rb_size_pool_t *size_pool = &size_pools[i];
+static void *rb_gc_impl_objspace_alloc(void);
- size_pool->slot_size = (1 << i) * BASE_SLOT_SIZE;
+#if USE_SHARED_GC
+# include "dln.h"
- ccan_list_head_init(&SIZE_POOL_EDEN_HEAP(size_pool)->pages);
- ccan_list_head_init(&SIZE_POOL_TOMB_HEAP(size_pool)->pages);
+# define RUBY_GC_LIBRARY_PATH "RUBY_GC_LIBRARY_PATH"
+
+void
+ruby_external_gc_init(void)
+{
+ char *gc_so_path = getenv(RUBY_GC_LIBRARY_PATH);
+ void *handle = NULL;
+ if (gc_so_path && dln_supported_p()) {
+ char error[1024];
+ handle = dln_open(gc_so_path, error, sizeof(error));
+ if (!handle) {
+ fprintf(stderr, "%s", error);
+ rb_bug("ruby_external_gc_init: Shared library %s cannot be opened", gc_so_path);
+ }
}
- rb_darray_make_without_gc(&objspace->weak_references, 0);
+# define load_external_gc_func(name) do { \
+ if (handle) { \
+ rb_gc_functions->name = dln_symbol(handle, "rb_gc_impl_" #name); \
+ if (!rb_gc_functions->name) { \
+ rb_bug("ruby_external_gc_init: " #name " func not exported by library %s", gc_so_path); \
+ } \
+ } \
+ else { \
+ rb_gc_functions->name = rb_gc_impl_##name; \
+ } \
+} while (0)
- dont_gc_on();
+ load_external_gc_func(objspace_alloc);
- return objspace;
+# undef load_external_gc_func
}
+# define rb_gc_impl_objspace_alloc rb_gc_functions->objspace_alloc
+#endif
+
+rb_objspace_t *
+rb_objspace_alloc(void)
+{
+#if USE_SHARED_GC
+ ruby_external_gc_init();
+#endif
+ return (rb_objspace_t *)rb_gc_impl_objspace_alloc();
+}
+
+#if USE_SHARED_GC
+# undef rb_gc_impl_objspace_alloc
+#endif
+
static void free_stack_chunks(mark_stack_t *);
static void mark_stack_free_cache(mark_stack_t *);
static void heap_page_free(rb_objspace_t *objspace, struct heap_page *page);
@@ -1936,13 +1923,6 @@ rb_objspace_free(rb_objspace_t *objspace)
free(objspace->profile.records);
objspace->profile.records = NULL;
- if (global_list) {
- struct gc_list *list, *next;
- for (list = global_list; list; list = next) {
- next = list->next;
- xfree(list);
- }
- }
if (heap_pages_sorted) {
size_t i;
size_t total_heap_pages = heap_allocated_pages;
@@ -1967,7 +1947,7 @@ rb_objspace_free(rb_objspace_t *objspace)
free_stack_chunks(&objspace->mark_stack);
mark_stack_free_cache(&objspace->mark_stack);
- rb_darray_free_without_gc(objspace->weak_references);
+ rb_darray_free(objspace->weak_references);
free(objspace);
}
@@ -2122,6 +2102,40 @@ heap_page_free(rb_objspace_t *objspace, struct heap_page *page)
free(page);
}
+static void *
+rb_aligned_malloc(size_t alignment, size_t size)
+{
+ /* alignment must be a power of 2 */
+ GC_ASSERT(((alignment - 1) & alignment) == 0);
+ GC_ASSERT(alignment % sizeof(void*) == 0);
+
+ void *res;
+
+#if defined __MINGW32__
+ res = __mingw_aligned_malloc(size, alignment);
+#elif defined _WIN32
+ void *_aligned_malloc(size_t, size_t);
+ res = _aligned_malloc(size, alignment);
+#elif defined(HAVE_POSIX_MEMALIGN)
+ if (posix_memalign(&res, alignment, size) != 0) {
+ return NULL;
+ }
+#elif defined(HAVE_MEMALIGN)
+ res = memalign(alignment, size);
+#else
+ char* aligned;
+ res = malloc(alignment + size + sizeof(void*));
+ aligned = (char*)res + alignment + sizeof(void*);
+ aligned -= ((VALUE)aligned & (alignment - 1));
+ ((void**)aligned)[-1] = res;
+ res = (void*)aligned;
+#endif
+
+ GC_ASSERT((uintptr_t)res % alignment == 0);
+
+ return res;
+}
+
static void
heap_pages_free_unused_pages(rb_objspace_t *objspace)
{
@@ -2515,7 +2529,7 @@ heap_prepare(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap
* sweeping and still don't have a free page, then
* gc_sweep_finish_size_pool should allow us to create a new page. */
if (heap->free_pages == NULL && !heap_increment(objspace, size_pool, heap)) {
- if (objspace->rgengc.need_major_gc == GPR_FLAG_NONE) {
+ if (gc_needs_major_flags == GPR_FLAG_NONE) {
rb_bug("cannot create a new page after GC");
}
else { // Major GC is required, which will allow us to create new page
@@ -2624,11 +2638,11 @@ newobj_init(VALUE klass, VALUE flags, int wb_protected, rb_objspace_t *objspace,
#endif
#if GC_DEBUG
- RANY(obj)->file = rb_source_location_cstr(&RANY(obj)->line);
+ GET_RVALUE_OVERHEAD(obj)->file = rb_source_location_cstr(&GET_RVALUE_OVERHEAD(obj)->line);
GC_ASSERT(!SPECIAL_CONST_P(obj)); /* check alignment */
#endif
- gc_report(5, objspace, "newobj: %s\n", obj_info(obj));
+ gc_report(5, objspace, "newobj: %s\n", obj_info_basic(obj));
// RUBY_DEBUG_LOG("obj:%p (%s)", (void *)obj, obj_type_name(obj));
return obj;
@@ -2657,18 +2671,50 @@ size_pool_slot_size(unsigned char pool_id)
return slot_size;
}
-size_t
-rb_size_pool_slot_size(unsigned char pool_id)
-{
- return size_pool_slot_size(pool_id);
-}
-
bool
rb_gc_size_allocatable_p(size_t size)
{
return size <= size_pool_slot_size(SIZE_POOL_COUNT - 1);
}
+static size_t size_pool_sizes[SIZE_POOL_COUNT + 1] = { 0 };
+
+size_t *
+rb_gc_size_pool_sizes(void)
+{
+ if (size_pool_sizes[0] == 0) {
+ for (unsigned char i = 0; i < SIZE_POOL_COUNT; i++) {
+ size_pool_sizes[i] = size_pool_slot_size(i);
+ }
+ }
+
+ return size_pool_sizes;
+}
+
+size_t
+rb_gc_size_pool_id_for_size(size_t size)
+{
+ size += RVALUE_OVERHEAD;
+
+ size_t slot_count = CEILDIV(size, BASE_SLOT_SIZE);
+
+ /* size_pool_idx is ceil(log2(slot_count)) */
+ size_t size_pool_idx = 64 - nlz_int64(slot_count - 1);
+
+ if (size_pool_idx >= SIZE_POOL_COUNT) {
+ rb_bug("rb_gc_size_pool_id_for_size: allocation size too large "
+ "(size=%"PRIuSIZE"u, size_pool_idx=%"PRIuSIZE"u)", size, size_pool_idx);
+ }
+
+#if RGENGC_CHECK_MODE
+ rb_objspace_t *objspace = &rb_objspace;
+ GC_ASSERT(size <= (size_t)size_pools[size_pool_idx].slot_size);
+ if (size_pool_idx > 0) GC_ASSERT(size > (size_t)size_pools[size_pool_idx - 1].slot_size);
+#endif
+
+ return size_pool_idx;
+}
+
static inline VALUE
ractor_cache_allocate_slot(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache,
size_t size_pool_idx)
@@ -2758,35 +2804,11 @@ newobj_fill(VALUE obj, VALUE v1, VALUE v2, VALUE v3)
return obj;
}
-static inline size_t
-size_pool_idx_for_size(size_t size)
-{
- size += RVALUE_OVERHEAD;
-
- size_t slot_count = CEILDIV(size, BASE_SLOT_SIZE);
-
- /* size_pool_idx is ceil(log2(slot_count)) */
- size_t size_pool_idx = 64 - nlz_int64(slot_count - 1);
-
- if (size_pool_idx >= SIZE_POOL_COUNT) {
- rb_bug("size_pool_idx_for_size: allocation size too large");
- }
-
-#if RGENGC_CHECK_MODE
- rb_objspace_t *objspace = &rb_objspace;
- GC_ASSERT(size <= (size_t)size_pools[size_pool_idx].slot_size);
- if (size_pool_idx > 0) GC_ASSERT(size > (size_t)size_pools[size_pool_idx - 1].slot_size);
-#endif
-
- return size_pool_idx;
-}
-
static VALUE
-newobj_alloc(rb_objspace_t *objspace, rb_ractor_t *cr, size_t size_pool_idx, bool vm_locked)
+newobj_alloc(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t size_pool_idx, bool vm_locked)
{
rb_size_pool_t *size_pool = &size_pools[size_pool_idx];
rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(size_pool);
- rb_ractor_newobj_cache_t *cache = &cr->newobj_cache;
VALUE obj = ractor_cache_allocate_slot(objspace, cache, size_pool_idx);
@@ -2795,7 +2817,7 @@ newobj_alloc(rb_objspace_t *objspace, rb_ractor_t *cr, size_t size_pool_idx, boo
bool unlock_vm = false;
if (!vm_locked) {
- RB_VM_LOCK_ENTER_CR_LEV(cr, &lev);
+ RB_VM_LOCK_ENTER_CR_LEV(GET_RACTOR(), &lev);
vm_locked = true;
unlock_vm = true;
}
@@ -2818,13 +2840,15 @@ newobj_alloc(rb_objspace_t *objspace, rb_ractor_t *cr, size_t size_pool_idx, boo
// Retry allocation after moving to new page
obj = ractor_cache_allocate_slot(objspace, cache, size_pool_idx);
-
- GC_ASSERT(obj != Qfalse);
}
}
if (unlock_vm) {
- RB_VM_LOCK_LEAVE_CR_LEV(cr, &lev);
+ RB_VM_LOCK_LEAVE_CR_LEV(GET_RACTOR(), &lev);
+ }
+
+ if (UNLIKELY(obj == Qfalse)) {
+ rb_memerror();
}
}
@@ -2839,15 +2863,15 @@ newobj_zero_slot(VALUE obj)
memset((char *)obj + sizeof(struct RBasic), 0, rb_gc_obj_slot_size(obj) - sizeof(struct RBasic));
}
-ALWAYS_INLINE(static VALUE newobj_slowpath(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_t *cr, int wb_protected, size_t size_pool_idx));
+ALWAYS_INLINE(static VALUE newobj_slowpath(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, int wb_protected, size_t size_pool_idx));
static inline VALUE
-newobj_slowpath(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_t *cr, int wb_protected, size_t size_pool_idx)
+newobj_slowpath(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, int wb_protected, size_t size_pool_idx)
{
VALUE obj;
unsigned int lev;
- RB_VM_LOCK_ENTER_CR_LEV(cr, &lev);
+ RB_VM_LOCK_ENTER_CR_LEV(GET_RACTOR(), &lev);
{
if (UNLIKELY(during_gc || ruby_gc_stressful)) {
if (during_gc) {
@@ -2863,35 +2887,35 @@ newobj_slowpath(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_t *
}
}
- obj = newobj_alloc(objspace, cr, size_pool_idx, true);
+ obj = newobj_alloc(objspace, cache, size_pool_idx, true);
newobj_init(klass, flags, wb_protected, objspace, obj);
gc_event_hook_prep(objspace, RUBY_INTERNAL_EVENT_NEWOBJ, obj, newobj_zero_slot(obj));
}
- RB_VM_LOCK_LEAVE_CR_LEV(cr, &lev);
+ RB_VM_LOCK_LEAVE_CR_LEV(GET_RACTOR(), &lev);
return obj;
}
NOINLINE(static VALUE newobj_slowpath_wb_protected(VALUE klass, VALUE flags,
- rb_objspace_t *objspace, rb_ractor_t *cr, size_t size_pool_idx));
+ rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t size_pool_idx));
NOINLINE(static VALUE newobj_slowpath_wb_unprotected(VALUE klass, VALUE flags,
- rb_objspace_t *objspace, rb_ractor_t *cr, size_t size_pool_idx));
+ rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t size_pool_idx));
static VALUE
-newobj_slowpath_wb_protected(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_t *cr, size_t size_pool_idx)
+newobj_slowpath_wb_protected(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t size_pool_idx)
{
- return newobj_slowpath(klass, flags, objspace, cr, TRUE, size_pool_idx);
+ return newobj_slowpath(klass, flags, objspace, cache, TRUE, size_pool_idx);
}
static VALUE
-newobj_slowpath_wb_unprotected(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_t *cr, size_t size_pool_idx)
+newobj_slowpath_wb_unprotected(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t size_pool_idx)
{
- return newobj_slowpath(klass, flags, objspace, cr, FALSE, size_pool_idx);
+ return newobj_slowpath(klass, flags, objspace, cache, FALSE, size_pool_idx);
}
static inline VALUE
-newobj_of0(VALUE klass, VALUE flags, int wb_protected, rb_ractor_t *cr, size_t alloc_size)
+newobj_of(rb_ractor_t *cr, VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, int wb_protected, size_t alloc_size)
{
VALUE obj;
rb_objspace_t *objspace = &rb_objspace;
@@ -2906,34 +2930,25 @@ newobj_of0(VALUE klass, VALUE flags, int wb_protected, rb_ractor_t *cr, size_t a
}
}
- size_t size_pool_idx = size_pool_idx_for_size(alloc_size);
+ size_t size_pool_idx = rb_gc_size_pool_id_for_size(alloc_size);
- if (SHAPE_IN_BASIC_FLAGS || (flags & RUBY_T_MASK) == T_OBJECT) {
- flags |= (VALUE)size_pool_idx << SHAPE_FLAG_SHIFT;
- }
+ rb_ractor_newobj_cache_t *cache = &cr->newobj_cache;
if (!UNLIKELY(during_gc ||
ruby_gc_stressful ||
gc_event_newobj_hook_needed_p(objspace)) &&
wb_protected) {
- obj = newobj_alloc(objspace, cr, size_pool_idx, false);
+ obj = newobj_alloc(objspace, cache, size_pool_idx, false);
newobj_init(klass, flags, wb_protected, objspace, obj);
}
else {
RB_DEBUG_COUNTER_INC(obj_newobj_slowpath);
obj = wb_protected ?
- newobj_slowpath_wb_protected(klass, flags, objspace, cr, size_pool_idx) :
- newobj_slowpath_wb_unprotected(klass, flags, objspace, cr, size_pool_idx);
+ newobj_slowpath_wb_protected(klass, flags, objspace, cache, size_pool_idx) :
+ newobj_slowpath_wb_unprotected(klass, flags, objspace, cache, size_pool_idx);
}
- return obj;
-}
-
-static inline VALUE
-newobj_of(rb_ractor_t *cr, VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, int wb_protected, size_t alloc_size)
-{
- VALUE obj = newobj_of0(klass, flags, wb_protected, cr, alloc_size);
return newobj_fill(obj, v1, v2, v3);
}
@@ -2951,172 +2966,10 @@ rb_wb_protected_newobj_of(rb_execution_context_t *ec, VALUE klass, VALUE flags,
return newobj_of(rb_ec_ractor_ptr(ec), klass, flags, 0, 0, 0, TRUE, size);
}
-/* for compatibility */
-
-VALUE
-rb_newobj(void)
-{
- return newobj_of(GET_RACTOR(), 0, T_NONE, 0, 0, 0, FALSE, RVALUE_SIZE);
-}
-
-static size_t
-rb_obj_embedded_size(uint32_t numiv)
-{
- return offsetof(struct RObject, as.ary) + (sizeof(VALUE) * numiv);
-}
-
-static VALUE
-rb_class_instance_allocate_internal(VALUE klass, VALUE flags, bool wb_protected)
-{
- GC_ASSERT((flags & RUBY_T_MASK) == T_OBJECT);
- GC_ASSERT(flags & ROBJECT_EMBED);
-
- size_t size;
- uint32_t index_tbl_num_entries = RCLASS_EXT(klass)->max_iv_count;
-
- size = rb_obj_embedded_size(index_tbl_num_entries);
- if (!rb_gc_size_allocatable_p(size)) {
- size = sizeof(struct RObject);
- }
-
- VALUE obj = newobj_of(GET_RACTOR(), klass, flags, 0, 0, 0, wb_protected, size);
- RUBY_ASSERT(rb_shape_get_shape(obj)->type == SHAPE_ROOT);
-
- // Set the shape to the specific T_OBJECT shape which is always
- // SIZE_POOL_COUNT away from the root shape.
- ROBJECT_SET_SHAPE_ID(obj, ROBJECT_SHAPE_ID(obj) + SIZE_POOL_COUNT);
-
-#if RUBY_DEBUG
- RUBY_ASSERT(!rb_shape_obj_too_complex(obj));
- VALUE *ptr = ROBJECT_IVPTR(obj);
- for (size_t i = 0; i < ROBJECT_IV_CAPACITY(obj); i++) {
- ptr[i] = Qundef;
- }
-#endif
-
- return obj;
-}
-
-VALUE
-rb_newobj_of(VALUE klass, VALUE flags)
-{
- if ((flags & RUBY_T_MASK) == T_OBJECT) {
- return rb_class_instance_allocate_internal(klass, (flags | ROBJECT_EMBED) & ~FL_WB_PROTECTED, flags & FL_WB_PROTECTED);
- }
- else {
- return newobj_of(GET_RACTOR(), klass, flags & ~FL_WB_PROTECTED, 0, 0, 0, flags & FL_WB_PROTECTED, RVALUE_SIZE);
- }
-}
-
#define UNEXPECTED_NODE(func) \
rb_bug(#func"(): GC does not handle T_NODE 0x%x(%p) 0x%"PRIxVALUE, \
BUILTIN_TYPE(obj), (void*)(obj), RBASIC(obj)->flags)
-const char *
-rb_imemo_name(enum imemo_type type)
-{
- // put no default case to get a warning if an imemo type is missing
- switch (type) {
-#define IMEMO_NAME(x) case imemo_##x: return #x;
- IMEMO_NAME(env);
- IMEMO_NAME(cref);
- IMEMO_NAME(svar);
- IMEMO_NAME(throw_data);
- IMEMO_NAME(ifunc);
- IMEMO_NAME(memo);
- IMEMO_NAME(ment);
- IMEMO_NAME(iseq);
- IMEMO_NAME(tmpbuf);
- IMEMO_NAME(ast);
- IMEMO_NAME(parser_strterm);
- IMEMO_NAME(callinfo);
- IMEMO_NAME(callcache);
- IMEMO_NAME(constcache);
-#undef IMEMO_NAME
- }
- return "unknown";
-}
-
-#undef rb_imemo_new
-
-VALUE
-rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0)
-{
- size_t size = RVALUE_SIZE;
- VALUE flags = T_IMEMO | (type << FL_USHIFT);
- return newobj_of(GET_RACTOR(), v0, flags, v1, v2, v3, TRUE, size);
-}
-
-static VALUE
-rb_imemo_tmpbuf_new(VALUE v1, VALUE v2, VALUE v3, VALUE v0)
-{
- size_t size = sizeof(struct rb_imemo_tmpbuf_struct);
- VALUE flags = T_IMEMO | (imemo_tmpbuf << FL_USHIFT);
- return newobj_of(GET_RACTOR(), v0, flags, v1, v2, v3, FALSE, size);
-}
-
-static VALUE
-rb_imemo_tmpbuf_auto_free_maybe_mark_buffer(void *buf, size_t cnt)
-{
- return rb_imemo_tmpbuf_new((VALUE)buf, 0, (VALUE)cnt, 0);
-}
-
-rb_imemo_tmpbuf_t *
-rb_imemo_tmpbuf_parser_heap(void *buf, rb_imemo_tmpbuf_t *old_heap, size_t cnt)
-{
- return (rb_imemo_tmpbuf_t *)rb_imemo_tmpbuf_new((VALUE)buf, (VALUE)old_heap, (VALUE)cnt, 0);
-}
-
-static size_t
-imemo_memsize(VALUE obj)
-{
- size_t size = 0;
- switch (imemo_type(obj)) {
- case imemo_ment:
- size += sizeof(RANY(obj)->as.imemo.ment.def);
- break;
- case imemo_iseq:
- size += rb_iseq_memsize((rb_iseq_t *)obj);
- break;
- case imemo_env:
- size += RANY(obj)->as.imemo.env.env_size * sizeof(VALUE);
- break;
- case imemo_tmpbuf:
- size += RANY(obj)->as.imemo.alloc.cnt * sizeof(VALUE);
- break;
- case imemo_ast:
- size += rb_ast_memsize(&RANY(obj)->as.imemo.ast);
- break;
- case imemo_cref:
- case imemo_svar:
- case imemo_throw_data:
- case imemo_ifunc:
- case imemo_memo:
- case imemo_parser_strterm:
- break;
- default:
- /* unreachable */
- break;
- }
- return size;
-}
-
-#if IMEMO_DEBUG
-VALUE
-rb_imemo_new_debug(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0, const char *file, int line)
-{
- VALUE memo = rb_imemo_new(type, v1, v2, v3, v0);
- fprintf(stderr, "memo %p (type: %d) @ %s:%d\n", (void *)memo, imemo_type(memo), file, line);
- return memo;
-}
-#endif
-
-VALUE
-rb_class_allocate_instance(VALUE klass)
-{
- return rb_class_instance_allocate_internal(klass, T_OBJECT | ROBJECT_EMBED, RGENGC_WB_PROTECTED_OBJECT);
-}
-
static inline void
rb_data_object_check(VALUE klass)
{
@@ -3182,7 +3035,7 @@ rb_data_typed_object_zalloc(VALUE klass, size_t size, const rb_data_type_t *type
return obj;
}
-size_t
+static size_t
rb_objspace_data_type_memsize(VALUE obj)
{
size_t size = 0;
@@ -3252,9 +3105,9 @@ heap_page_for_ptr(rb_objspace_t *objspace, uintptr_t ptr)
}
}
-PUREFUNC(static inline int is_pointer_to_heap(rb_objspace_t *objspace, void *ptr);)
+PUREFUNC(static inline int is_pointer_to_heap(rb_objspace_t *objspace, const void *ptr);)
static inline int
-is_pointer_to_heap(rb_objspace_t *objspace, void *ptr)
+is_pointer_to_heap(rb_objspace_t *objspace, const void *ptr)
{
register uintptr_t p = (uintptr_t)ptr;
register struct heap_page *page;
@@ -3285,151 +3138,19 @@ is_pointer_to_heap(rb_objspace_t *objspace, void *ptr)
}
static enum rb_id_table_iterator_result
-free_const_entry_i(VALUE value, void *data)
-{
- rb_const_entry_t *ce = (rb_const_entry_t *)value;
- xfree(ce);
- return ID_TABLE_CONTINUE;
-}
-
-void
-rb_free_const_table(struct rb_id_table *tbl)
-{
- rb_id_table_foreach_values(tbl, free_const_entry_i, 0);
- rb_id_table_free(tbl);
-}
-
-// alive: if false, target pointers can be freed already.
-// To check it, we need objspace parameter.
-static void
-vm_ccs_free(struct rb_class_cc_entries *ccs, int alive, rb_objspace_t *objspace, VALUE klass)
-{
- if (ccs->entries) {
- for (int i=0; i<ccs->len; i++) {
- const struct rb_callcache *cc = ccs->entries[i].cc;
- if (!alive) {
- void *ptr = asan_unpoison_object_temporary((VALUE)cc);
- // ccs can be free'ed.
- if (is_pointer_to_heap(objspace, (void *)cc) &&
- IMEMO_TYPE_P(cc, imemo_callcache) &&
- cc->klass == klass) {
- // OK. maybe target cc.
- }
- else {
- if (ptr) {
- asan_poison_object((VALUE)cc);
- }
- continue;
- }
- if (ptr) {
- asan_poison_object((VALUE)cc);
- }
- }
-
- VM_ASSERT(!vm_cc_super_p(cc) && !vm_cc_refinement_p(cc));
- vm_cc_invalidate(cc);
- }
- ruby_xfree(ccs->entries);
- }
- ruby_xfree(ccs);
-}
-
-void
-rb_vm_ccs_free(struct rb_class_cc_entries *ccs)
-{
- RB_DEBUG_COUNTER_INC(ccs_free);
- vm_ccs_free(ccs, TRUE, NULL, Qundef);
-}
-
-struct cc_tbl_i_data {
- rb_objspace_t *objspace;
- VALUE klass;
- bool alive;
-};
-
-static enum rb_id_table_iterator_result
-cc_table_mark_i(ID id, VALUE ccs_ptr, void *data_ptr)
-{
- struct cc_tbl_i_data *data = data_ptr;
- struct rb_class_cc_entries *ccs = (struct rb_class_cc_entries *)ccs_ptr;
- VM_ASSERT(vm_ccs_p(ccs));
- VM_ASSERT(id == ccs->cme->called_id);
-
- if (METHOD_ENTRY_INVALIDATED(ccs->cme)) {
- rb_vm_ccs_free(ccs);
- return ID_TABLE_DELETE;
- }
- else {
- gc_mark(data->objspace, (VALUE)ccs->cme);
-
- for (int i=0; i<ccs->len; i++) {
- VM_ASSERT(data->klass == ccs->entries[i].cc->klass);
- VM_ASSERT(vm_cc_check_cme(ccs->entries[i].cc, ccs->cme));
-
- gc_mark(data->objspace, (VALUE)ccs->entries[i].ci);
- gc_mark(data->objspace, (VALUE)ccs->entries[i].cc);
- }
- return ID_TABLE_CONTINUE;
- }
-}
-
-static void
-cc_table_mark(rb_objspace_t *objspace, VALUE klass)
-{
- struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass);
- if (cc_tbl) {
- struct cc_tbl_i_data data = {
- .objspace = objspace,
- .klass = klass,
- };
- rb_id_table_foreach(cc_tbl, cc_table_mark_i, &data);
- }
-}
-
-static enum rb_id_table_iterator_result
-cc_table_free_i(VALUE ccs_ptr, void *data_ptr)
+cvar_table_free_i(VALUE value, void *ctx)
{
- struct cc_tbl_i_data *data = data_ptr;
- struct rb_class_cc_entries *ccs = (struct rb_class_cc_entries *)ccs_ptr;
- VM_ASSERT(vm_ccs_p(ccs));
- vm_ccs_free(ccs, data->alive, data->objspace, data->klass);
- return ID_TABLE_CONTINUE;
-}
-
-static void
-cc_table_free(rb_objspace_t *objspace, VALUE klass, bool alive)
-{
- struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass);
-
- if (cc_tbl) {
- struct cc_tbl_i_data data = {
- .objspace = objspace,
- .klass = klass,
- .alive = alive,
- };
- rb_id_table_foreach_values(cc_tbl, cc_table_free_i, &data);
- rb_id_table_free(cc_tbl);
- }
-}
-
-static enum rb_id_table_iterator_result
-cvar_table_free_i(VALUE value, void * ctx)
-{
- xfree((void *) value);
+ xfree((void *)value);
return ID_TABLE_CONTINUE;
}
-void
-rb_cc_table_free(VALUE klass)
-{
- cc_table_free(&rb_objspace, klass, TRUE);
-}
+#define ZOMBIE_OBJ_KEPT_FLAGS (FL_SEEN_OBJ_ID | FL_FINALIZE)
static inline void
make_zombie(rb_objspace_t *objspace, VALUE obj, void (*dfree)(void *), void *data)
{
struct RZombie *zombie = RZOMBIE(obj);
- zombie->basic.flags = T_ZOMBIE | (zombie->basic.flags & FL_SEEN_OBJ_ID);
+ zombie->basic.flags = T_ZOMBIE | (zombie->basic.flags & ZOMBIE_OBJ_KEPT_FLAGS);
zombie->dfree = dfree;
zombie->data = data;
VALUE prev, next = heap_pages_deferred_final;
@@ -3569,11 +3290,11 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
case T_MODULE:
case T_CLASS:
rb_id_table_free(RCLASS_M_TBL(obj));
- cc_table_free(objspace, obj, FALSE);
+ rb_cc_table_free(obj);
if (rb_shape_obj_too_complex(obj)) {
st_free_table((st_table *)RCLASS_IVPTR(obj));
}
- else if (RCLASS_IVPTR(obj)) {
+ else {
xfree(RCLASS_IVPTR(obj));
}
@@ -3668,8 +3389,7 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
}
#endif
onig_region_free(&rm->regs, 0);
- if (rm->char_offset)
- xfree(rm->char_offset);
+ xfree(rm->char_offset);
RB_DEBUG_COUNTER_INC(obj_match_ptr);
}
@@ -3699,7 +3419,7 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
rb_id_table_free(RCLASS_CALLABLE_M_TBL(obj));
}
rb_class_remove_subclass_head(obj);
- cc_table_free(objspace, obj, FALSE);
+ rb_cc_table_free(obj);
rb_class_remove_from_module_subclasses(obj);
rb_class_remove_from_super_subclasses(obj);
@@ -3743,64 +3463,8 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
break;
case T_IMEMO:
- switch (imemo_type(obj)) {
- case imemo_ment:
- rb_free_method_entry(&RANY(obj)->as.imemo.ment);
- RB_DEBUG_COUNTER_INC(obj_imemo_ment);
- break;
- case imemo_iseq:
- rb_iseq_free(&RANY(obj)->as.imemo.iseq);
- RB_DEBUG_COUNTER_INC(obj_imemo_iseq);
- break;
- case imemo_env:
- GC_ASSERT(VM_ENV_ESCAPED_P(RANY(obj)->as.imemo.env.ep));
- xfree((VALUE *)RANY(obj)->as.imemo.env.env);
- RB_DEBUG_COUNTER_INC(obj_imemo_env);
- break;
- case imemo_tmpbuf:
- xfree(RANY(obj)->as.imemo.alloc.ptr);
- RB_DEBUG_COUNTER_INC(obj_imemo_tmpbuf);
- break;
- case imemo_ast:
- rb_ast_free(&RANY(obj)->as.imemo.ast);
- RB_DEBUG_COUNTER_INC(obj_imemo_ast);
- break;
- case imemo_cref:
- RB_DEBUG_COUNTER_INC(obj_imemo_cref);
- break;
- case imemo_svar:
- RB_DEBUG_COUNTER_INC(obj_imemo_svar);
- break;
- case imemo_throw_data:
- RB_DEBUG_COUNTER_INC(obj_imemo_throw_data);
- break;
- case imemo_ifunc:
- RB_DEBUG_COUNTER_INC(obj_imemo_ifunc);
- break;
- case imemo_memo:
- RB_DEBUG_COUNTER_INC(obj_imemo_memo);
- break;
- case imemo_parser_strterm:
- RB_DEBUG_COUNTER_INC(obj_imemo_parser_strterm);
- break;
- case imemo_callinfo:
- {
- const struct rb_callinfo * ci = ((const struct rb_callinfo *)obj);
- if (ci->kwarg) {
- ((struct rb_callinfo_kwarg *)ci->kwarg)->references--;
- if (ci->kwarg->references == 0) xfree((void *)ci->kwarg);
- }
- RB_DEBUG_COUNTER_INC(obj_imemo_callinfo);
- break;
- }
- case imemo_callcache:
- RB_DEBUG_COUNTER_INC(obj_imemo_callcache);
- break;
- case imemo_constcache:
- RB_DEBUG_COUNTER_INC(obj_imemo_constcache);
- break;
- }
- return TRUE;
+ rb_imemo_free((VALUE)obj);
+ break;
default:
rb_bug("gc_sweep(): unknown data type 0x%x(%p) 0x%"PRIxVALUE,
@@ -3812,13 +3476,14 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
return FALSE;
}
else {
+ RBASIC(obj)->flags = 0;
return TRUE;
}
}
-#define OBJ_ID_INCREMENT (sizeof(RVALUE) / 2)
-#define OBJ_ID_INITIAL (OBJ_ID_INCREMENT * 2)
+#define OBJ_ID_INCREMENT (BASE_SLOT_SIZE)
+#define OBJ_ID_INITIAL (OBJ_ID_INCREMENT)
static int
object_id_cmp(st_data_t x, st_data_t y)
@@ -3846,17 +3511,44 @@ static const struct st_hash_type object_id_hash_type = {
object_id_hash,
};
-void
-Init_heap(void)
+static void *
+rb_gc_impl_objspace_alloc(void)
{
- rb_objspace_t *objspace = &rb_objspace;
+ rb_objspace_t *objspace = calloc1(sizeof(rb_objspace_t));
+ ruby_current_vm_ptr->objspace = objspace;
+
+ objspace->flags.gc_stressful = RTEST(initial_stress);
+ objspace->gc_stress_mode = initial_stress;
+
+ objspace->flags.measure_gc = 1;
+ malloc_limit = gc_params.malloc_limit_min;
+ objspace->finalize_deferred_pjob = rb_postponed_job_preregister(0, gc_finalize_deferred, objspace);
+ if (objspace->finalize_deferred_pjob == POSTPONED_JOB_HANDLE_INVALID) {
+ rb_bug("Could not preregister postponed job for GC");
+ }
+
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+
+ size_pool->slot_size = (1 << i) * BASE_SLOT_SIZE;
+
+ ccan_list_head_init(&SIZE_POOL_EDEN_HEAP(size_pool)->pages);
+ ccan_list_head_init(&SIZE_POOL_TOMB_HEAP(size_pool)->pages);
+ }
+
+ rb_darray_make(&objspace->weak_references, 0);
+
+ // TODO: debug why on Windows Ruby crashes on boot when GC is on.
+#ifdef _WIN32
+ dont_gc_on();
+#endif
#if defined(INIT_HEAP_PAGE_ALLOC_USE_MMAP)
/* Need to determine if we can use mmap at runtime. */
heap_page_alloc_use_mmap = INIT_HEAP_PAGE_ALLOC_USE_MMAP;
#endif
- objspace->next_object_id = INT2FIX(OBJ_ID_INITIAL);
+ objspace->next_object_id = OBJ_ID_INITIAL;
objspace->id_to_obj_tbl = st_init_table(&object_id_hash_type);
objspace->obj_to_id_tbl = st_init_numtable();
@@ -3879,17 +3571,11 @@ Init_heap(void)
objspace->profile.invoke_time = getrusage_time();
finalizer_table = st_init_numtable();
-}
-
-void
-Init_gc_stress(void)
-{
- rb_objspace_t *objspace = &rb_objspace;
-
- gc_stress_set(objspace, ruby_initial_gc_stress);
+ return objspace;
}
typedef int each_obj_callback(void *, void *, size_t, void *);
+typedef int each_page_callback(struct heap_page *, void *);
static void objspace_each_objects(rb_objspace_t *objspace, each_obj_callback *callback, void *data, bool protected);
static void objspace_reachable_objects_from_root(rb_objspace_t *, void (func)(const char *, VALUE, void *), void *);
@@ -3898,7 +3584,8 @@ struct each_obj_data {
rb_objspace_t *objspace;
bool reenable_incremental;
- each_obj_callback *callback;
+ each_obj_callback *each_obj_callback;
+ each_page_callback *each_page_callback;
void *data;
struct heap_page **pages[SIZE_POOL_COUNT];
@@ -3972,8 +3659,12 @@ objspace_each_objects_try(VALUE arg)
uintptr_t pstart = (uintptr_t)page->start;
uintptr_t pend = pstart + (page->total_slots * size_pool->slot_size);
- if (!__asan_region_is_poisoned((void *)pstart, pend - pstart) &&
- (*data->callback)((void *)pstart, (void *)pend, size_pool->slot_size, data->data)) {
+ if (data->each_obj_callback &&
+ (*data->each_obj_callback)((void *)pstart, (void *)pend, size_pool->slot_size, data->data)) {
+ break;
+ }
+ if (data->each_page_callback &&
+ (*data->each_page_callback)(page, data->data)) {
break;
}
@@ -4029,9 +3720,10 @@ rb_objspace_each_objects(each_obj_callback *callback, void *data)
}
static void
-objspace_each_objects(rb_objspace_t *objspace, each_obj_callback *callback, void *data, bool protected)
+objspace_each_exec(bool protected, struct each_obj_data *each_obj_data)
{
/* Disable incremental GC */
+ rb_objspace_t *objspace = each_obj_data->objspace;
bool reenable_incremental = FALSE;
if (protected) {
reenable_incremental = !objspace->flags.dont_incremental;
@@ -4040,25 +3732,38 @@ objspace_each_objects(rb_objspace_t *objspace, each_obj_callback *callback, void
objspace->flags.dont_incremental = TRUE;
}
+ each_obj_data->reenable_incremental = reenable_incremental;
+ memset(&each_obj_data->pages, 0, sizeof(each_obj_data->pages));
+ memset(&each_obj_data->pages_counts, 0, sizeof(each_obj_data->pages_counts));
+ rb_ensure(objspace_each_objects_try, (VALUE)each_obj_data,
+ objspace_each_objects_ensure, (VALUE)each_obj_data);
+}
+
+static void
+objspace_each_objects(rb_objspace_t *objspace, each_obj_callback *callback, void *data, bool protected)
+{
struct each_obj_data each_obj_data = {
.objspace = objspace,
- .reenable_incremental = reenable_incremental,
-
- .callback = callback,
+ .each_obj_callback = callback,
+ .each_page_callback = NULL,
.data = data,
-
- .pages = {NULL},
- .pages_counts = {0},
};
- rb_ensure(objspace_each_objects_try, (VALUE)&each_obj_data,
- objspace_each_objects_ensure, (VALUE)&each_obj_data);
+ objspace_each_exec(protected, &each_obj_data);
}
-void
-rb_objspace_each_objects_without_setup(each_obj_callback *callback, void *data)
+#if GC_CAN_COMPILE_COMPACTION
+static void
+objspace_each_pages(rb_objspace_t *objspace, each_page_callback *callback, void *data, bool protected)
{
- objspace_each_objects(&rb_objspace, callback, data, FALSE);
+ struct each_obj_data each_obj_data = {
+ .objspace = objspace,
+ .each_obj_callback = NULL,
+ .each_page_callback = callback,
+ .data = data,
+ };
+ objspace_each_exec(protected, &each_obj_data);
}
+#endif
struct os_each_struct {
size_t num;
@@ -4085,7 +3790,7 @@ internal_object_p(VALUE obj)
break;
case T_CLASS:
if (!p->as.basic.klass) break;
- if (FL_TEST(obj, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON_P(obj)) {
return rb_singleton_class_internal_p(obj);
}
return 0;
@@ -4227,7 +3932,7 @@ should_be_finalizable(VALUE obj)
rb_check_frozen(obj);
}
-VALUE
+static VALUE
rb_define_finalizer_no_check(VALUE obj, VALUE block)
{
rb_objspace_t *objspace = &rb_objspace;
@@ -4365,11 +4070,15 @@ rb_gc_copy_finalizer(VALUE dest, VALUE obj)
st_data_t data;
if (!FL_TEST(obj, FL_FINALIZE)) return;
- if (st_lookup(finalizer_table, obj, &data)) {
+
+ if (RB_LIKELY(st_lookup(finalizer_table, obj, &data))) {
table = (VALUE)data;
st_insert(finalizer_table, dest, table);
+ FL_SET(dest, FL_FINALIZE);
+ }
+ else {
+ rb_bug("rb_gc_copy_finalizer: FL_FINALIZE set but not found in finalizer_table: %s", obj_info(obj));
}
- FL_SET(dest, FL_FINALIZE);
}
static VALUE
@@ -4398,16 +4107,20 @@ run_finalizer(rb_objspace_t *objspace, VALUE obj, VALUE table)
VALUE objid;
VALUE final;
rb_control_frame_t *cfp;
+ VALUE *sp;
long finished;
} saved;
+
rb_execution_context_t * volatile ec = GET_EC();
#define RESTORE_FINALIZER() (\
ec->cfp = saved.cfp, \
+ ec->cfp->sp = saved.sp, \
ec->errinfo = saved.errinfo)
saved.errinfo = ec->errinfo;
saved.objid = rb_obj_id(obj);
saved.cfp = ec->cfp;
+ saved.sp = ec->cfp->sp;
saved.finished = 0;
saved.final = Qundef;
@@ -4429,15 +4142,23 @@ run_finalizer(rb_objspace_t *objspace, VALUE obj, VALUE table)
static void
run_final(rb_objspace_t *objspace, VALUE zombie)
{
- st_data_t key, table;
-
if (RZOMBIE(zombie)->dfree) {
RZOMBIE(zombie)->dfree(RZOMBIE(zombie)->data);
}
- key = (st_data_t)zombie;
- if (st_delete(finalizer_table, &key, &table)) {
- run_finalizer(objspace, zombie, (VALUE)table);
+ st_data_t key = (st_data_t)zombie;
+ if (FL_TEST_RAW(zombie, FL_FINALIZE)) {
+ FL_UNSET(zombie, FL_FINALIZE);
+ st_data_t table;
+ if (st_delete(finalizer_table, &key, &table)) {
+ run_finalizer(objspace, zombie, (VALUE)table);
+ }
+ else {
+ rb_bug("FL_FINALIZE flag is set, but finalizers are not found");
+ }
+ }
+ else {
+ GC_ASSERT(!st_lookup(finalizer_table, key, NULL));
}
}
@@ -4506,9 +4227,44 @@ gc_finalize_deferred(void *dmy)
static void
gc_finalize_deferred_register(rb_objspace_t *objspace)
{
- if (rb_postponed_job_register_one(0, gc_finalize_deferred, objspace) == 0) {
- rb_bug("gc_finalize_deferred_register: can't register finalizer.");
+ /* will enqueue a call to gc_finalize_deferred */
+ rb_postponed_job_trigger(objspace->finalize_deferred_pjob);
+}
+
+static int pop_mark_stack(mark_stack_t *stack, VALUE *data);
+
+static void
+gc_abort(rb_objspace_t *objspace)
+{
+ if (is_incremental_marking(objspace)) {
+ /* Remove all objects from the mark stack. */
+ VALUE obj;
+ while (pop_mark_stack(&objspace->mark_stack, &obj));
+
+ objspace->flags.during_incremental_marking = FALSE;
+ }
+
+ if (is_lazy_sweeping(objspace)) {
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+ rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(size_pool);
+
+ heap->sweeping_page = NULL;
+ struct heap_page *page = NULL;
+
+ ccan_list_for_each(&heap->pages, page, page_node) {
+ page->flags.before_sweep = false;
+ }
+ }
}
+
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+ rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(size_pool);
+ rgengc_mark_and_rememberset_clear(objspace, heap);
+ }
+
+ gc_mode_set(objspace, gc_mode_none);
}
struct force_finalize_list {
@@ -4529,25 +4285,95 @@ force_chain_object(st_data_t key, st_data_t val, st_data_t arg)
return ST_CONTINUE;
}
+static void
+gc_each_object(rb_objspace_t *objspace, void (*func)(VALUE obj, void *data), void *data)
+{
+ for (size_t i = 0; i < heap_allocated_pages; i++) {
+ struct heap_page *page = heap_pages_sorted[i];
+ short stride = page->slot_size;
+
+ uintptr_t p = (uintptr_t)page->start;
+ uintptr_t pend = p + page->total_slots * stride;
+ for (; p < pend; p += stride) {
+ VALUE obj = (VALUE)p;
+
+ void *poisoned = asan_unpoison_object_temporary(obj);
+
+ func(obj, data);
+
+ if (poisoned) {
+ GC_ASSERT(BUILTIN_TYPE(obj) == T_NONE);
+ asan_poison_object(obj);
+ }
+ }
+ }
+}
+
bool rb_obj_is_main_ractor(VALUE gv);
+static void
+rb_objspace_free_objects_i(VALUE obj, void *data)
+{
+ rb_objspace_t *objspace = (rb_objspace_t *)data;
+
+ switch (BUILTIN_TYPE(obj)) {
+ case T_NONE:
+ case T_SYMBOL:
+ break;
+ default:
+ obj_free(objspace, obj);
+ break;
+ }
+}
+
void
-rb_objspace_call_finalizer(rb_objspace_t *objspace)
+rb_objspace_free_objects(rb_objspace_t *objspace)
{
- size_t i;
+ gc_each_object(objspace, rb_objspace_free_objects_i, objspace);
+}
+
+static void
+rb_objspace_call_finalizer_i(VALUE obj, void *data)
+{
+ rb_objspace_t *objspace = (rb_objspace_t *)data;
+
+ switch (BUILTIN_TYPE(obj)) {
+ case T_DATA:
+ if (!rb_free_at_exit && (!DATA_PTR(obj) || !RANY(obj)->as.data.dfree)) break;
+ if (rb_obj_is_thread(obj)) break;
+ if (rb_obj_is_mutex(obj)) break;
+ if (rb_obj_is_fiber(obj)) break;
+ if (rb_obj_is_main_ractor(obj)) break;
+ obj_free(objspace, obj);
+ break;
+ case T_FILE:
+ obj_free(objspace, obj);
+ break;
+ case T_SYMBOL:
+ case T_ARRAY:
+ case T_NONE:
+ break;
+ default:
+ if (rb_free_at_exit) {
+ obj_free(objspace, obj);
+ }
+ break;
+ }
+}
+
+void
+rb_objspace_call_finalizer(rb_objspace_t *objspace)
+{
#if RGENGC_CHECK_MODE >= 2
gc_verify_internal_consistency(objspace);
#endif
- gc_rest(objspace);
-
if (ATOMIC_EXCHANGE(finalizing, 1)) return;
/* run finalizers */
finalize_deferred(objspace);
GC_ASSERT(heap_pages_deferred_final == 0);
- gc_rest(objspace);
/* prohibit incremental GC */
objspace->flags.dont_incremental = 1;
@@ -4557,14 +4383,21 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace)
st_foreach(finalizer_table, force_chain_object, (st_data_t)&list);
while (list) {
struct force_finalize_list *curr = list;
+
st_data_t obj = (st_data_t)curr->obj;
- run_finalizer(objspace, curr->obj, curr->table);
st_delete(finalizer_table, &obj, 0);
+ FL_UNSET(curr->obj, FL_FINALIZE);
+
+ run_finalizer(objspace, curr->obj, curr->table);
+
list = curr->next;
xfree(curr);
}
}
+ /* Abort incremental marking and lazy sweeping to speed up shutdown. */
+ gc_abort(objspace);
+
/* prohibit GC because force T_DATA finalizers can break an object graph consistency */
dont_gc_on();
@@ -4572,40 +4405,7 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace)
unsigned int lock_lev;
gc_enter(objspace, gc_enter_event_finalizer, &lock_lev);
- /* run data/file object's finalizers */
- for (i = 0; i < heap_allocated_pages; i++) {
- struct heap_page *page = heap_pages_sorted[i];
- short stride = page->slot_size;
-
- uintptr_t p = (uintptr_t)page->start;
- uintptr_t pend = p + page->total_slots * stride;
- for (; p < pend; p += stride) {
- VALUE vp = (VALUE)p;
- void *poisoned = asan_unpoison_object_temporary(vp);
- switch (BUILTIN_TYPE(vp)) {
- case T_DATA:
- if (!DATA_PTR(p) || !RANY(p)->as.data.dfree) break;
- if (rb_obj_is_thread(vp)) break;
- if (rb_obj_is_mutex(vp)) break;
- if (rb_obj_is_fiber(vp)) break;
- if (rb_obj_is_main_ractor(vp)) break;
-
- rb_data_free(objspace, vp);
- break;
- case T_FILE:
- if (RANY(p)->as.file.fptr) {
- make_io_zombie(objspace, vp);
- }
- break;
- default:
- break;
- }
- if (poisoned) {
- GC_ASSERT(BUILTIN_TYPE(vp) == T_NONE);
- asan_poison_object(vp);
- }
- }
- }
+ gc_each_object(objspace, rb_objspace_call_finalizer_i, objspace);
gc_exit(objspace, gc_enter_event_finalizer, &lock_lev);
@@ -4616,29 +4416,15 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace)
ATOMIC_SET(finalizing, 0);
}
-static inline int
-is_swept_object(VALUE ptr)
-{
- struct heap_page *page = GET_HEAP_PAGE(ptr);
- return page->flags.before_sweep ? FALSE : TRUE;
-}
-
/* garbage objects will be collected soon. */
-static inline int
+static inline bool
is_garbage_object(rb_objspace_t *objspace, VALUE ptr)
{
- if (!is_lazy_sweeping(objspace) ||
- is_swept_object(ptr) ||
- MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(ptr), ptr)) {
-
- return FALSE;
- }
- else {
- return TRUE;
- }
+ return is_lazy_sweeping(objspace) && GET_HEAP_PAGE(ptr)->flags.before_sweep &&
+ !MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(ptr), ptr);
}
-static inline int
+static inline bool
is_live_object(rb_objspace_t *objspace, VALUE ptr)
{
switch (BUILTIN_TYPE(ptr)) {
@@ -4650,20 +4436,13 @@ is_live_object(rb_objspace_t *objspace, VALUE ptr)
break;
}
- if (!is_garbage_object(objspace, ptr)) {
- return TRUE;
- }
- else {
- return FALSE;
- }
+ return !is_garbage_object(objspace, ptr);
}
static inline int
is_markable_object(VALUE obj)
{
- if (rb_special_const_p(obj)) return FALSE; /* special const is not markable */
- check_rvalue_consistency(obj);
- return TRUE;
+ return !RB_SPECIAL_CONST_P(obj);
}
int
@@ -4681,26 +4460,12 @@ rb_objspace_garbage_object_p(VALUE obj)
}
bool
-rb_gc_is_ptr_to_obj(void *ptr)
+rb_gc_is_ptr_to_obj(const void *ptr)
{
rb_objspace_t *objspace = &rb_objspace;
return is_pointer_to_heap(objspace, ptr);
}
-VALUE
-rb_gc_id2ref_obj_tbl(VALUE objid)
-{
- rb_objspace_t *objspace = &rb_objspace;
-
- VALUE orig;
- if (st_lookup(objspace->id_to_obj_tbl, objid, &orig)) {
- return orig;
- }
- else {
- return Qundef;
- }
-}
-
/*
* call-seq:
* ObjectSpace._id2ref(object_id) -> an_object
@@ -4725,32 +4490,34 @@ id2ref(VALUE objid)
#define NUM2PTR(x) NUM2ULL(x)
#endif
rb_objspace_t *objspace = &rb_objspace;
- VALUE ptr;
- VALUE orig;
- void *p0;
objid = rb_to_int(objid);
if (FIXNUM_P(objid) || rb_big_size(objid) <= SIZEOF_VOIDP) {
- ptr = NUM2PTR(objid);
- if (ptr == Qtrue) return Qtrue;
- if (ptr == Qfalse) return Qfalse;
- if (NIL_P(ptr)) return Qnil;
- if (FIXNUM_P(ptr)) return (VALUE)ptr;
- if (FLONUM_P(ptr)) return (VALUE)ptr;
+ VALUE ptr = NUM2PTR(objid);
+ if (SPECIAL_CONST_P(ptr)) {
+ if (ptr == Qtrue) return Qtrue;
+ if (ptr == Qfalse) return Qfalse;
+ if (NIL_P(ptr)) return Qnil;
+ if (FIXNUM_P(ptr)) return ptr;
+ if (FLONUM_P(ptr)) return ptr;
+
+ if (SYMBOL_P(ptr)) {
+ // Check that the symbol is valid
+ if (rb_static_id_valid_p(SYM2ID(ptr))) {
+ return ptr;
+ }
+ else {
+ rb_raise(rb_eRangeError, "%p is not symbol id value", (void *)ptr);
+ }
+ }
- ptr = obj_id_to_ref(objid);
- if ((ptr % sizeof(RVALUE)) == (4 << 2)) {
- ID symid = ptr / sizeof(RVALUE);
- p0 = (void *)ptr;
- if (!rb_static_id_valid_p(symid))
- rb_raise(rb_eRangeError, "%p is not symbol id value", p0);
- return ID2SYM(symid);
+ rb_raise(rb_eRangeError, "%+"PRIsVALUE" is not id value", rb_int2str(objid, 10));
}
}
- if (!UNDEF_P(orig = rb_gc_id2ref_obj_tbl(objid)) &&
- is_live_object(objspace, orig)) {
-
+ VALUE orig;
+ if (st_lookup(objspace->id_to_obj_tbl, objid, &orig) &&
+ is_live_object(objspace, orig)) {
if (!rb_multi_ractor_p() || rb_ractor_shareable_p(orig)) {
return orig;
}
@@ -4759,7 +4526,7 @@ id2ref(VALUE objid)
}
}
- if (rb_int_ge(objid, objspace->next_object_id)) {
+ if (rb_int_ge(objid, ULL2NUM(objspace->next_object_id))) {
rb_raise(rb_eRangeError, "%+"PRIsVALUE" is not id value", rb_int2str(objid, 10));
}
else {
@@ -4777,19 +4544,13 @@ os_id2ref(VALUE os, VALUE objid)
static VALUE
rb_find_object_id(VALUE obj, VALUE (*get_heap_object_id)(VALUE))
{
- if (STATIC_SYM_P(obj)) {
- return (SYM2ID(obj) * sizeof(RVALUE) + (4 << 2)) | FIXNUM_FLAG;
- }
- else if (FLONUM_P(obj)) {
+ if (SPECIAL_CONST_P(obj)) {
#if SIZEOF_LONG == SIZEOF_VOIDP
return LONG2NUM((SIGNED_VALUE)obj);
#else
return LL2NUM((SIGNED_VALUE)obj);
#endif
}
- else if (SPECIAL_CONST_P(obj)) {
- return LONG2NUM((SIGNED_VALUE)obj);
- }
return get_heap_object_id(obj);
}
@@ -4807,8 +4568,8 @@ cached_object_id(VALUE obj)
else {
GC_ASSERT(!FL_TEST(obj, FL_SEEN_OBJ_ID));
- id = objspace->next_object_id;
- objspace->next_object_id = rb_int_plus(id, INT2FIX(OBJ_ID_INCREMENT));
+ id = ULL2NUM(objspace->next_object_id);
+ objspace->next_object_id += OBJ_ID_INCREMENT;
VALUE already_disabled = rb_gc_disable_no_rest();
st_insert(objspace->obj_to_id_tbl, (st_data_t)obj, (st_data_t)id);
@@ -5008,7 +4769,7 @@ obj_memsize_of(VALUE obj, int use_all_types)
case T_COMPLEX:
break;
case T_IMEMO:
- size += imemo_memsize(obj);
+ size += rb_imemo_memsize(obj);
break;
case T_FLOAT:
@@ -5096,6 +4857,27 @@ type_sym(size_t type)
}
}
+struct count_objects_data {
+ size_t counts[T_MASK+1];
+ size_t freed;
+ size_t total;
+};
+
+static void
+count_objects_i(VALUE obj, void *d)
+{
+ struct count_objects_data *data = (struct count_objects_data *)d;
+
+ if (RANY(obj)->as.basic.flags) {
+ data->counts[BUILTIN_TYPE(obj)]++;
+ }
+ else {
+ data->freed++;
+ }
+
+ data->total++;
+}
+
/*
* call-seq:
* ObjectSpace.count_objects([result_hash]) -> hash
@@ -5135,10 +4917,7 @@ static VALUE
count_objects(int argc, VALUE *argv, VALUE os)
{
rb_objspace_t *objspace = &rb_objspace;
- size_t counts[T_MASK+1];
- size_t freed = 0;
- size_t total = 0;
- size_t i;
+ struct count_objects_data data = { 0 };
VALUE hash = Qnil;
if (rb_check_arity(argc, 0, 1) == 1) {
@@ -5147,34 +4926,7 @@ count_objects(int argc, VALUE *argv, VALUE os)
rb_raise(rb_eTypeError, "non-hash given");
}
- for (i = 0; i <= T_MASK; i++) {
- counts[i] = 0;
- }
-
- for (i = 0; i < heap_allocated_pages; i++) {
- struct heap_page *page = heap_pages_sorted[i];
- short stride = page->slot_size;
-
- uintptr_t p = (uintptr_t)page->start;
- uintptr_t pend = p + page->total_slots * stride;
- for (;p < pend; p += stride) {
- VALUE vp = (VALUE)p;
- GC_ASSERT((NUM_IN_PAGE(vp) * BASE_SLOT_SIZE) % page->slot_size == 0);
-
- void *poisoned = asan_unpoison_object_temporary(vp);
- if (RANY(p)->as.basic.flags) {
- counts[BUILTIN_TYPE(vp)]++;
- }
- else {
- freed++;
- }
- if (poisoned) {
- GC_ASSERT(BUILTIN_TYPE(vp) == T_NONE);
- asan_poison_object(vp);
- }
- }
- total += page->total_slots;
- }
+ gc_each_object(objspace, count_objects_i, &data);
if (NIL_P(hash)) {
hash = rb_hash_new();
@@ -5182,13 +4934,13 @@ count_objects(int argc, VALUE *argv, VALUE os)
else if (!RHASH_EMPTY_P(hash)) {
rb_hash_stlike_foreach(hash, set_zero, hash);
}
- rb_hash_aset(hash, ID2SYM(rb_intern("TOTAL")), SIZET2NUM(total));
- rb_hash_aset(hash, ID2SYM(rb_intern("FREE")), SIZET2NUM(freed));
+ rb_hash_aset(hash, ID2SYM(rb_intern("TOTAL")), SIZET2NUM(data.total));
+ rb_hash_aset(hash, ID2SYM(rb_intern("FREE")), SIZET2NUM(data.freed));
- for (i = 0; i <= T_MASK; i++) {
+ for (size_t i = 0; i <= T_MASK; i++) {
VALUE type = type_sym(i);
- if (counts[i])
- rb_hash_aset(hash, type, SIZET2NUM(counts[i]));
+ if (data.counts[i])
+ rb_hash_aset(hash, type, SIZET2NUM(data.counts[i]));
}
return hash;
@@ -5294,7 +5046,9 @@ try_move(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *free_page,
* full */
return false;
}
+ asan_unlock_freelist(free_page);
free_page->freelist = RANY(dest)->as.free.next;
+ asan_lock_freelist(free_page);
GC_ASSERT(RB_BUILTIN_TYPE(dest) == T_NONE);
@@ -5563,46 +5317,46 @@ gc_sweep_plane(rb_objspace_t *objspace, rb_heap_t *heap, uintptr_t p, bits_t bit
asan_unpoison_object(vp, false);
if (bitset & 1) {
switch (BUILTIN_TYPE(vp)) {
- default: /* majority case */
- gc_report(2, objspace, "page_sweep: free %p\n", (void *)p);
+ default: /* majority case */
+ gc_report(2, objspace, "page_sweep: free %p\n", (void *)p);
#if RGENGC_CHECK_MODE
- if (!is_full_marking(objspace)) {
- if (RVALUE_OLD_P(vp)) rb_bug("page_sweep: %p - old while minor GC.", (void *)p);
- if (RVALUE_REMEMBERED(vp)) rb_bug("page_sweep: %p - remembered.", (void *)p);
- }
+ if (!is_full_marking(objspace)) {
+ if (RVALUE_OLD_P(vp)) rb_bug("page_sweep: %p - old while minor GC.", (void *)p);
+ if (RVALUE_REMEMBERED(vp)) rb_bug("page_sweep: %p - remembered.", (void *)p);
+ }
#endif
- if (obj_free(objspace, vp)) {
- // always add free slots back to the swept pages freelist,
- // so that if we're comapacting, we can re-use the slots
- (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, BASE_SLOT_SIZE);
- heap_page_add_freeobj(objspace, sweep_page, vp);
- gc_report(3, objspace, "page_sweep: %s is added to freelist\n", obj_info(vp));
- ctx->freed_slots++;
- }
- else {
- ctx->final_slots++;
- }
- break;
-
- case T_MOVED:
- if (objspace->flags.during_compacting) {
- /* The sweep cursor shouldn't have made it to any
- * T_MOVED slots while the compact flag is enabled.
- * The sweep cursor and compact cursor move in
- * opposite directions, and when they meet references will
- * get updated and "during_compacting" should get disabled */
- rb_bug("T_MOVED shouldn't be seen until compaction is finished");
- }
- gc_report(3, objspace, "page_sweep: %s is added to freelist\n", obj_info(vp));
- ctx->empty_slots++;
+ if (obj_free(objspace, vp)) {
+ // always add free slots back to the swept pages freelist,
+ // so that if we're comapacting, we can re-use the slots
+ (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, BASE_SLOT_SIZE);
heap_page_add_freeobj(objspace, sweep_page, vp);
- break;
- case T_ZOMBIE:
- /* already counted */
- break;
- case T_NONE:
- ctx->empty_slots++; /* already freed */
- break;
+ gc_report(3, objspace, "page_sweep: %s is added to freelist\n", obj_info(vp));
+ ctx->freed_slots++;
+ }
+ else {
+ ctx->final_slots++;
+ }
+ break;
+
+ case T_MOVED:
+ if (objspace->flags.during_compacting) {
+ /* The sweep cursor shouldn't have made it to any
+ * T_MOVED slots while the compact flag is enabled.
+ * The sweep cursor and compact cursor move in
+ * opposite directions, and when they meet references will
+ * get updated and "during_compacting" should get disabled */
+ rb_bug("T_MOVED shouldn't be seen until compaction is finished");
+ }
+ gc_report(3, objspace, "page_sweep: %s is added to freelist\n", obj_info(vp));
+ ctx->empty_slots++;
+ heap_page_add_freeobj(objspace, sweep_page, vp);
+ break;
+ case T_ZOMBIE:
+ /* already counted */
+ break;
+ case T_NONE:
+ ctx->empty_slots++; /* already freed */
+ break;
}
}
p += slot_size;
@@ -5681,10 +5435,7 @@ gc_sweep_page(rb_objspace_t *objspace, rb_heap_t *heap, struct gc_sweep_context
sweep_page->size_pool->total_freed_objects += ctx->freed_slots;
if (heap_pages_deferred_final && !finalizing) {
- rb_thread_t *th = GET_THREAD();
- if (th) {
- gc_finalize_deferred_register(objspace);
- }
+ gc_finalize_deferred_register(objspace);
}
#if RGENGC_CHECK_MODE
@@ -5856,7 +5607,7 @@ gc_sweep_finish_size_pool(rb_objspace_t *objspace, rb_size_pool_t *size_pool)
grow_heap = TRUE;
}
else if (is_growth_heap) { /* Only growth heaps are allowed to start a major GC. */
- objspace->rgengc.need_major_gc |= GPR_FLAG_MAJOR_BY_NOFREE;
+ gc_needs_major_flags |= GPR_FLAG_MAJOR_BY_NOFREE;
size_pool->force_major_gc_count++;
}
}
@@ -6286,9 +6037,8 @@ mark_stack_free_cache(mark_stack_t *stack)
}
static void
-push_mark_stack(mark_stack_t *stack, VALUE data)
+push_mark_stack(mark_stack_t *stack, VALUE obj)
{
- VALUE obj = data;
switch (BUILTIN_TYPE(obj)) {
case T_OBJECT:
case T_CLASS:
@@ -6313,7 +6063,7 @@ push_mark_stack(mark_stack_t *stack, VALUE data)
if (stack->index == stack->limit) {
push_mark_stack_chunk(stack);
}
- stack->chunk->data[stack->index++] = data;
+ stack->chunk->data[stack->index++] = obj;
return;
case T_NONE:
@@ -6332,8 +6082,8 @@ push_mark_stack(mark_stack_t *stack, VALUE data)
}
rb_bug("rb_gc_mark(): unknown data type 0x%x(%p) %s",
- BUILTIN_TYPE(obj), (void *)data,
- is_pointer_to_heap(&rb_objspace, (void *)data) ? "corrupted object" : "non object");
+ BUILTIN_TYPE(obj), (void *)obj,
+ is_pointer_to_heap(&rb_objspace, (void *)obj) ? "corrupted object" : "non object");
}
static int
@@ -6480,23 +6230,14 @@ rb_gc_mark_values(long n, const VALUE *values)
}
}
-static void
-gc_mark_stack_values(rb_objspace_t *objspace, long n, const VALUE *values)
-{
- long i;
-
- for (i=0; i<n; i++) {
- if (is_markable_object(values[i])) {
- gc_mark_and_pin(objspace, values[i]);
- }
- }
-}
-
void
rb_gc_mark_vm_stack_values(long n, const VALUE *values)
{
rb_objspace_t *objspace = &rb_objspace;
- gc_mark_stack_values(objspace, n, values);
+
+ for (long i = 0; i < n; i++) {
+ gc_mark_and_pin(objspace, values[i]);
+ }
}
static int
@@ -6621,52 +6362,6 @@ rb_mark_hash(st_table *tbl)
mark_st(&rb_objspace, tbl);
}
-static void
-mark_method_entry(rb_objspace_t *objspace, const rb_method_entry_t *me)
-{
- const rb_method_definition_t *def = me->def;
-
- gc_mark(objspace, me->owner);
- gc_mark(objspace, me->defined_class);
-
- if (def) {
- switch (def->type) {
- case VM_METHOD_TYPE_ISEQ:
- if (def->body.iseq.iseqptr) gc_mark(objspace, (VALUE)def->body.iseq.iseqptr);
- gc_mark(objspace, (VALUE)def->body.iseq.cref);
-
- if (def->iseq_overload && me->defined_class) {
- // it can be a key of "overloaded_cme" table
- // so it should be pinned.
- gc_mark_and_pin(objspace, (VALUE)me);
- }
- break;
- case VM_METHOD_TYPE_ATTRSET:
- case VM_METHOD_TYPE_IVAR:
- gc_mark(objspace, def->body.attr.location);
- break;
- case VM_METHOD_TYPE_BMETHOD:
- gc_mark(objspace, def->body.bmethod.proc);
- if (def->body.bmethod.hooks) rb_hook_list_mark(def->body.bmethod.hooks);
- break;
- case VM_METHOD_TYPE_ALIAS:
- gc_mark(objspace, (VALUE)def->body.alias.original_me);
- return;
- case VM_METHOD_TYPE_REFINED:
- gc_mark(objspace, (VALUE)def->body.refined.orig_me);
- gc_mark(objspace, (VALUE)def->body.refined.owner);
- break;
- case VM_METHOD_TYPE_CFUNC:
- case VM_METHOD_TYPE_ZSUPER:
- case VM_METHOD_TYPE_MISSING:
- case VM_METHOD_TYPE_OPTIMIZED:
- case VM_METHOD_TYPE_UNDEF:
- case VM_METHOD_TYPE_NOTIMPLEMENTED:
- break;
- }
- }
-}
-
static enum rb_id_table_iterator_result
mark_method_entry_i(VALUE me, void *data)
{
@@ -6715,6 +6410,26 @@ mark_const_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl)
static void each_stack_location(rb_objspace_t *objspace, const rb_execution_context_t *ec,
const VALUE *stack_start, const VALUE *stack_end, void (*cb)(rb_objspace_t *, VALUE));
+static void
+gc_mark_machine_stack_location_maybe(rb_objspace_t *objspace, VALUE obj)
+{
+ gc_mark_maybe(objspace, obj);
+
+#ifdef RUBY_ASAN_ENABLED
+ const rb_execution_context_t *ec = objspace->marking_machine_context_ec;
+ void *fake_frame_start;
+ void *fake_frame_end;
+ bool is_fake_frame = asan_get_fake_stack_extents(
+ ec->machine.asan_fake_stack_handle, obj,
+ ec->machine.stack_start, ec->machine.stack_end,
+ &fake_frame_start, &fake_frame_end
+ );
+ if (is_fake_frame) {
+ each_stack_location(objspace, ec, fake_frame_start, fake_frame_end, gc_mark_maybe);
+ }
+#endif
+}
+
#if defined(__wasm__)
@@ -6776,27 +6491,39 @@ mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec
SET_STACK_END;
GET_STACK_BOUNDS(stack_start, stack_end, 1);
- each_location(objspace, save_regs_gc_mark.v, numberof(save_regs_gc_mark.v), gc_mark_maybe);
+#ifdef RUBY_ASAN_ENABLED
+ objspace->marking_machine_context_ec = ec;
+#endif
+
+ each_location(objspace, save_regs_gc_mark.v, numberof(save_regs_gc_mark.v), gc_mark_machine_stack_location_maybe);
+ each_stack_location(objspace, ec, stack_start, stack_end, gc_mark_machine_stack_location_maybe);
- each_stack_location(objspace, ec, stack_start, stack_end, gc_mark_maybe);
+#ifdef RUBY_ASAN_ENABLED
+ objspace->marking_machine_context_ec = NULL;
+#endif
}
#endif
-static void
-each_machine_stack_value(const rb_execution_context_t *ec, void (*cb)(rb_objspace_t *, VALUE))
+void
+rb_gc_mark_machine_context(const rb_execution_context_t *ec)
{
rb_objspace_t *objspace = &rb_objspace;
+#ifdef RUBY_ASAN_ENABLED
+ objspace->marking_machine_context_ec = ec;
+#endif
+
VALUE *stack_start, *stack_end;
GET_STACK_BOUNDS(stack_start, stack_end, 0);
RUBY_DEBUG_LOG("ec->th:%u stack_start:%p stack_end:%p", rb_ec_thread_ptr(ec)->serial, stack_start, stack_end);
- each_stack_location(objspace, ec, stack_start, stack_end, cb);
-}
-void
-rb_gc_mark_machine_stack(const rb_execution_context_t *ec)
-{
- each_machine_stack_value(ec, gc_mark_maybe);
+ each_stack_location(objspace, ec, stack_start, stack_end, gc_mark_machine_stack_location_maybe);
+ int num_regs = sizeof(ec->machine.regs)/(sizeof(VALUE));
+ each_location(objspace, (VALUE*)&ec->machine.regs, num_regs, gc_mark_machine_stack_location_maybe);
+
+#ifdef RUBY_ASAN_ENABLED
+ objspace->marking_machine_context_ec = NULL;
+#endif
}
static void
@@ -6981,6 +6708,7 @@ gc_pin(rb_objspace_t *objspace, VALUE obj)
if (UNLIKELY(objspace->flags.during_compacting)) {
if (LIKELY(during_gc)) {
if (!MARKED_IN_BITMAP(GET_HEAP_PINNED_BITS(obj), obj)) {
+ GC_ASSERT(GET_HEAP_PAGE(obj)->pinned_slots <= GET_HEAP_PAGE(obj)->total_slots);
GET_HEAP_PAGE(obj)->pinned_slots++;
MARK_IN_BITMAP(GET_HEAP_PINNED_BITS(obj), obj);
}
@@ -7061,7 +6789,11 @@ rb_gc_mark_weak(VALUE *ptr)
rgengc_check_relation(objspace, obj);
- rb_darray_append_without_gc(&objspace->weak_references, ptr);
+ DURING_GC_COULD_MALLOC_REGION_START();
+ {
+ rb_darray_append(&objspace->weak_references, ptr);
+ }
+ DURING_GC_COULD_MALLOC_REGION_END();
objspace->profile.weak_references_count++;
}
@@ -7087,16 +6819,6 @@ rb_gc_remove_weak(VALUE parent_obj, VALUE *ptr)
}
}
-/* CAUTION: THIS FUNCTION ENABLE *ONLY BEFORE* SWEEPING.
- * This function is only for GC_END_MARK timing.
- */
-
-int
-rb_objspace_marked_object_p(VALUE obj)
-{
- return RVALUE_MARKED(obj) ? TRUE : FALSE;
-}
-
static inline void
gc_mark_set_parent(rb_objspace_t *objspace, VALUE obj)
{
@@ -7108,140 +6830,12 @@ gc_mark_set_parent(rb_objspace_t *objspace, VALUE obj)
}
}
-static void
-gc_mark_imemo(rb_objspace_t *objspace, VALUE obj)
-{
- switch (imemo_type(obj)) {
- case imemo_env:
- {
- const rb_env_t *env = (const rb_env_t *)obj;
-
- if (LIKELY(env->ep)) {
- // just after newobj() can be NULL here.
- GC_ASSERT(env->ep[VM_ENV_DATA_INDEX_ENV] == obj);
- GC_ASSERT(VM_ENV_ESCAPED_P(env->ep));
- rb_gc_mark_values((long)env->env_size, env->env);
- VM_ENV_FLAGS_SET(env->ep, VM_ENV_FLAG_WB_REQUIRED);
- gc_mark(objspace, (VALUE)rb_vm_env_prev_env(env));
- gc_mark(objspace, (VALUE)env->iseq);
- }
- }
- return;
- case imemo_cref:
- gc_mark(objspace, RANY(obj)->as.imemo.cref.klass_or_self);
- gc_mark(objspace, (VALUE)RANY(obj)->as.imemo.cref.next);
- gc_mark(objspace, RANY(obj)->as.imemo.cref.refinements);
- return;
- case imemo_svar:
- gc_mark(objspace, RANY(obj)->as.imemo.svar.cref_or_me);
- gc_mark(objspace, RANY(obj)->as.imemo.svar.lastline);
- gc_mark(objspace, RANY(obj)->as.imemo.svar.backref);
- gc_mark(objspace, RANY(obj)->as.imemo.svar.others);
- return;
- case imemo_throw_data:
- gc_mark(objspace, RANY(obj)->as.imemo.throw_data.throw_obj);
- return;
- case imemo_ifunc:
- gc_mark_maybe(objspace, (VALUE)RANY(obj)->as.imemo.ifunc.data);
- return;
- case imemo_memo:
- gc_mark(objspace, RANY(obj)->as.imemo.memo.v1);
- gc_mark(objspace, RANY(obj)->as.imemo.memo.v2);
- gc_mark_maybe(objspace, RANY(obj)->as.imemo.memo.u3.value);
- return;
- case imemo_ment:
- mark_method_entry(objspace, &RANY(obj)->as.imemo.ment);
- return;
- case imemo_iseq:
- rb_iseq_mark_and_move((rb_iseq_t *)obj, false);
- return;
- case imemo_tmpbuf:
- {
- const rb_imemo_tmpbuf_t *m = &RANY(obj)->as.imemo.alloc;
- do {
- rb_gc_mark_locations(m->ptr, m->ptr + m->cnt);
- } while ((m = m->next) != NULL);
- }
- return;
- case imemo_ast:
- rb_ast_mark(&RANY(obj)->as.imemo.ast);
- return;
- case imemo_parser_strterm:
- return;
- case imemo_callinfo:
- return;
- case imemo_callcache:
- /* cc is callcache.
- *
- * cc->klass (klass) should not be marked because if the klass is
- * free'ed, the cc->klass will be cleared by `vm_cc_invalidate()`.
- *
- * cc->cme (cme) should not be marked because if cc is invalidated
- * when cme is free'ed.
- * - klass marks cme if klass uses cme.
- * - caller classe's ccs->cme marks cc->cme.
- * - if cc is invalidated (klass doesn't refer the cc),
- * cc is invalidated by `vm_cc_invalidate()` and cc->cme is
- * not be accessed.
- * - On the multi-Ractors, cme will be collected with global GC
- * so that it is safe if GC is not interleaving while accessing
- * cc and cme.
- * - However, cc_type_super is not chained from cc so the cc->cme
- * should be marked.
- */
- {
- const struct rb_callcache *cc = (const struct rb_callcache *)obj;
- if (vm_cc_super_p(cc)) {
- gc_mark(objspace, (VALUE)cc->cme_);
- }
- }
- return;
- case imemo_constcache:
- {
- const struct iseq_inline_constant_cache_entry *ice = (struct iseq_inline_constant_cache_entry *)obj;
- gc_mark(objspace, ice->value);
- }
- return;
-#if VM_CHECK_MODE > 0
- default:
- VM_UNREACHABLE(gc_mark_imemo);
-#endif
- }
-}
-
static bool
gc_declarative_marking_p(const rb_data_type_t *type)
{
return (type->flags & RUBY_TYPED_DECL_MARKING) != 0;
}
-#define EDGE (VALUE *)((char *)data_struct + offset)
-
-static inline void
-gc_mark_from_offset(rb_objspace_t *objspace, VALUE obj)
-{
- // we are overloading the dmark callback to contain a list of offsets
- size_t *offset_list = (size_t *)RANY(obj)->as.typeddata.type->function.dmark;
- void *data_struct = RANY(obj)->as.typeddata.data;
-
- for (size_t offset = *offset_list; *offset_list != RUBY_REF_END; offset = *offset_list++) {
- rb_gc_mark_movable(*EDGE);
- }
-}
-
-static inline void
-gc_ref_update_from_offset(rb_objspace_t *objspace, VALUE obj)
-{
- // we are overloading the dmark callback to contain a list of offsets
- size_t *offset_list = (size_t *)RANY(obj)->as.typeddata.type->function.dmark;
- void *data_struct = RANY(obj)->as.typeddata.data;
-
- for (size_t offset = *offset_list; *offset_list != RUBY_REF_END; offset = *offset_list++) {
- if (SPECIAL_CONST_P(*EDGE)) continue;
- *EDGE = rb_gc_location(*EDGE);
- }
-}
-
static void mark_cvc_tbl(rb_objspace_t *objspace, VALUE klass);
static void
@@ -7251,15 +6845,17 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj)
gc_mark_set_parent(objspace, obj);
if (FL_TEST(obj, FL_EXIVAR)) {
- rb_mark_and_update_generic_ivar(obj);
+ rb_mark_generic_ivar(obj);
}
switch (BUILTIN_TYPE(obj)) {
case T_FLOAT:
case T_BIGNUM:
case T_SYMBOL:
- /* Not immediates, but does not have references and singleton
- * class */
+ /* Not immediates, but does not have references and singleton class.
+ *
+ * RSYMBOL(obj)->fstr intentionally not marked. See log for 96815f1e
+ * ("symbol.c: remove rb_gc_mark_symbols()") */
return;
case T_NIL:
@@ -7272,7 +6868,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj)
break;
case T_IMEMO:
- gc_mark_imemo(objspace, obj);
+ rb_imemo_mark_and_move(obj, false);
return;
default:
@@ -7294,9 +6890,9 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj)
mark_m_tbl(objspace, RCLASS_M_TBL(obj));
mark_cvc_tbl(objspace, obj);
- cc_table_mark(objspace, obj);
+ rb_cc_table_mark(obj);
if (rb_shape_obj_too_complex(obj)) {
- mark_tbl(objspace, (st_table *)RCLASS_IVPTR(obj));
+ mark_tbl_no_pin(objspace, (st_table *)RCLASS_IVPTR(obj));
}
else {
for (attr_index_t i = 0; i < RCLASS_IV_COUNT(obj); i++) {
@@ -7320,7 +6916,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj)
gc_mark(objspace, RCLASS_INCLUDER(obj));
}
mark_m_tbl(objspace, RCLASS_CALLABLE_M_TBL(obj));
- cc_table_mark(objspace, obj);
+ rb_cc_table_mark(obj);
break;
case T_ARRAY:
@@ -7343,7 +6939,16 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj)
case T_STRING:
if (STR_SHARED_P(obj)) {
- gc_mark(objspace, any->as.string.as.heap.aux.shared);
+ if (STR_EMBED_P(any->as.string.as.heap.aux.shared)) {
+ /* Embedded shared strings cannot be moved because this string
+ * points into the slot of the shared string. There may be code
+ * using the RSTRING_PTR on the stack, which would pin this
+ * string but not pin the shared string, causing it to move. */
+ gc_mark_and_pin(objspace, any->as.string.as.heap.aux.shared);
+ }
+ else {
+ gc_mark(objspace, any->as.string.as.heap.aux.shared);
+ }
}
break;
@@ -7353,7 +6958,11 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj)
if (ptr) {
if (RTYPEDDATA_P(obj) && gc_declarative_marking_p(any->as.typeddata.type)) {
- gc_mark_from_offset(objspace, obj);
+ size_t *offset_list = (size_t *)RANY(obj)->as.typeddata.type->function.dmark;
+
+ for (size_t offset = *offset_list; offset != RUBY_REF_END; offset = *offset_list++) {
+ rb_gc_mark_movable(*(VALUE *)((char *)ptr + offset));
+ }
}
else {
RUBY_DATA_FUNC mark_func = RTYPEDDATA_P(obj) ?
@@ -7535,7 +7144,6 @@ show_mark_ticks(void)
static void
gc_mark_roots(rb_objspace_t *objspace, const char **categoryp)
{
- struct gc_list *list;
rb_execution_context_t *ec = GET_EC();
rb_vm_t *vm = rb_ec_vm_ptr(ec);
@@ -7585,10 +7193,6 @@ gc_mark_roots(rb_objspace_t *objspace, const char **categoryp)
mark_current_machine_context(objspace, ec);
/* mark protected global variables */
- MARK_CHECKPOINT("global_list");
- for (list = global_list; list; list = list->next) {
- gc_mark_maybe(objspace, *list->varptr);
- }
MARK_CHECKPOINT("end_proc");
rb_mark_end_proc();
@@ -7597,7 +7201,6 @@ gc_mark_roots(rb_objspace_t *objspace, const char **categoryp)
rb_gc_mark_global_tbl();
MARK_CHECKPOINT("object_id");
- rb_gc_mark(objspace->next_object_id);
mark_tbl_no_pin(objspace, objspace->obj_to_id_tbl); /* Only mark ids */
if (stress_to_class) rb_gc_mark(stress_to_class);
@@ -7957,8 +7560,20 @@ verify_internal_consistency_i(void *page_start, void *page_end, size_t stride,
}
else {
if (BUILTIN_TYPE(obj) == T_ZOMBIE) {
- GC_ASSERT((RBASIC(obj)->flags & ~FL_SEEN_OBJ_ID) == T_ZOMBIE);
data->zombie_object_count++;
+
+ if ((RBASIC(obj)->flags & ~ZOMBIE_OBJ_KEPT_FLAGS) != T_ZOMBIE) {
+ fprintf(stderr, "verify_internal_consistency_i: T_ZOMBIE has extra flags set: %s\n",
+ obj_info(obj));
+ data->err_count++;
+ }
+
+ if (!!FL_TEST(obj, FL_FINALIZE) != !!st_is_member(finalizer_table, obj)) {
+ fprintf(stderr, "verify_internal_consistency_i: FL_FINALIZE %s but %s finalizer_table: %s\n",
+ FL_TEST(obj, FL_FINALIZE) ? "set" : "not set", st_is_member(finalizer_table, obj) ? "in" : "not in",
+ obj_info(obj));
+ data->err_count++;
+ }
}
}
if (poisoned) {
@@ -8248,6 +7863,14 @@ gc_marks_start(rb_objspace_t *objspace, int full_mark)
rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(size_pool);
rgengc_mark_and_rememberset_clear(objspace, heap);
heap_move_pooled_pages_to_free_pages(heap);
+
+ if (objspace->flags.during_compacting) {
+ struct heap_page *page = NULL;
+
+ ccan_list_for_each(&heap->pages, page, page_node) {
+ page->pinned_slots = 0;
+ }
+ }
}
}
else {
@@ -8334,7 +7957,12 @@ gc_update_weak_references(rb_objspace_t *objspace)
objspace->profile.retained_weak_references_count = retained_weak_references_count;
rb_darray_clear(objspace->weak_references);
- rb_darray_resize_capa_without_gc(&objspace->weak_references, retained_weak_references_count);
+
+ DURING_GC_COULD_MALLOC_REGION_START();
+ {
+ rb_darray_resize_capa(&objspace->weak_references, retained_weak_references_count);
+ }
+ DURING_GC_COULD_MALLOC_REGION_END();
}
static void
@@ -8418,7 +8046,7 @@ gc_marks_finish(rb_objspace_t *objspace)
}
else {
gc_report(1, objspace, "gc_marks_finish: next is full GC!!)\n");
- objspace->rgengc.need_major_gc |= GPR_FLAG_MAJOR_BY_NOFREE;
+ gc_needs_major_flags |= GPR_FLAG_MAJOR_BY_NOFREE;
}
}
}
@@ -8434,20 +8062,20 @@ gc_marks_finish(rb_objspace_t *objspace)
}
if (objspace->rgengc.uncollectible_wb_unprotected_objects > objspace->rgengc.uncollectible_wb_unprotected_objects_limit) {
- objspace->rgengc.need_major_gc |= GPR_FLAG_MAJOR_BY_SHADY;
+ gc_needs_major_flags |= GPR_FLAG_MAJOR_BY_SHADY;
}
if (objspace->rgengc.old_objects > objspace->rgengc.old_objects_limit) {
- objspace->rgengc.need_major_gc |= GPR_FLAG_MAJOR_BY_OLDGEN;
+ gc_needs_major_flags |= GPR_FLAG_MAJOR_BY_OLDGEN;
}
if (RGENGC_FORCE_MAJOR_GC) {
- objspace->rgengc.need_major_gc = GPR_FLAG_MAJOR_BY_FORCE;
+ gc_needs_major_flags = GPR_FLAG_MAJOR_BY_FORCE;
}
gc_report(1, objspace, "gc_marks_finish (marks %"PRIdSIZE" objects, "
"old %"PRIdSIZE" objects, total %"PRIdSIZE" slots, "
"sweep %"PRIdSIZE" slots, increment: %"PRIdSIZE", next GC: %s)\n",
objspace->marked_slots, objspace->rgengc.old_objects, heap_eden_total_slots(objspace), sweep_slots, heap_allocatable_pages(objspace),
- objspace->rgengc.need_major_gc ? "major" : "minor");
+ gc_needs_major_flags ? "major" : "minor");
}
rb_ractor_finish_marking();
@@ -8494,7 +8122,7 @@ gc_compact_destination_pool(rb_objspace_t *objspace, rb_size_pool_t *src_pool, V
}
if (rb_gc_size_allocatable_p(obj_size)){
- idx = size_pool_idx_for_size(obj_size);
+ idx = rb_gc_size_pool_id_for_size(obj_size);
}
return &size_pools[idx];
}
@@ -8517,7 +8145,7 @@ gc_compact_move(rb_objspace_t *objspace, rb_heap_t *heap, rb_size_pool_t *size_p
if (RB_TYPE_P(src, T_OBJECT)) {
orig_shape = rb_shape_get_shape(src);
if (dheap != heap && !rb_shape_obj_too_complex(src)) {
- rb_shape_t *initial_shape = rb_shape_get_shape_by_id((shape_id_t)((dest_pool - size_pools) + SIZE_POOL_COUNT));
+ rb_shape_t *initial_shape = rb_shape_get_shape_by_id((shape_id_t)((dest_pool - size_pools) + FIRST_T_OBJECT_SHAPE_ID));
new_shape = rb_shape_traverse_from_new_root(initial_shape, orig_shape);
if (!new_shape) {
@@ -8572,7 +8200,7 @@ gc_compact_plane(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *
do {
VALUE vp = (VALUE)p;
- GC_ASSERT(vp % sizeof(RVALUE) == 0);
+ GC_ASSERT(vp % BASE_SLOT_SIZE == 0);
if (bitset & 1) {
objspace->rcompactor.considered_count_table[BUILTIN_TYPE(vp)]++;
@@ -9098,35 +8726,12 @@ rb_gc_writebarrier_remember(VALUE obj)
}
void
-rb_copy_wb_protected_attribute(VALUE dest, VALUE obj)
+rb_gc_copy_attributes(VALUE dest, VALUE obj)
{
- rb_objspace_t *objspace = &rb_objspace;
-
- if (RVALUE_WB_UNPROTECTED(obj) && !RVALUE_WB_UNPROTECTED(dest)) {
- if (!RVALUE_OLD_P(dest)) {
- MARK_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(dest), dest);
- RVALUE_AGE_RESET(dest);
- }
- else {
- RVALUE_DEMOTE(objspace, dest);
- }
+ if (RVALUE_WB_UNPROTECTED(obj)) {
+ rb_gc_writebarrier_unprotect(dest);
}
-
- check_rvalue_consistency(dest);
-}
-
-/* RGENGC analysis information */
-
-VALUE
-rb_obj_rgengc_writebarrier_protected_p(VALUE obj)
-{
- return RBOOL(!RVALUE_WB_UNPROTECTED(obj));
-}
-
-VALUE
-rb_obj_rgengc_promoted_p(VALUE obj)
-{
- return RBOOL(OBJ_PROMOTED(obj));
+ rb_gc_copy_finalizer(dest, obj);
}
size_t
@@ -9178,48 +8783,25 @@ rb_gc_ractor_newobj_cache_clear(rb_ractor_newobj_cache_t *newobj_cache)
}
void
-rb_gc_force_recycle(VALUE obj)
-{
- /* no-op */
-}
-
-#ifndef MARK_OBJECT_ARY_BUCKET_SIZE
-#define MARK_OBJECT_ARY_BUCKET_SIZE 1024
-#endif
-
-void
rb_gc_register_mark_object(VALUE obj)
{
if (!is_pointer_to_heap(&rb_objspace, (void *)obj))
return;
- RB_VM_LOCK_ENTER();
- {
- VALUE ary_ary = GET_VM()->mark_object_ary;
- VALUE ary = rb_ary_last(0, 0, ary_ary);
-
- if (NIL_P(ary) || RARRAY_LEN(ary) >= MARK_OBJECT_ARY_BUCKET_SIZE) {
- ary = rb_ary_hidden_new(MARK_OBJECT_ARY_BUCKET_SIZE);
- rb_ary_push(ary_ary, ary);
- }
-
- rb_ary_push(ary, obj);
- }
- RB_VM_LOCK_LEAVE();
+ rb_vm_register_global_object(obj);
}
void
rb_gc_register_address(VALUE *addr)
{
- rb_objspace_t *objspace = &rb_objspace;
- struct gc_list *tmp;
+ rb_vm_t *vm = GET_VM();
VALUE obj = *addr;
- tmp = ALLOC(struct gc_list);
- tmp->next = global_list;
+ struct global_object_list *tmp = ALLOC(struct global_object_list);
+ tmp->next = vm->global_object_list;
tmp->varptr = addr;
- global_list = tmp;
+ vm->global_object_list = tmp;
/*
* Because some C extensions have assignment-then-register bugs,
@@ -9236,17 +8818,17 @@ rb_gc_register_address(VALUE *addr)
void
rb_gc_unregister_address(VALUE *addr)
{
- rb_objspace_t *objspace = &rb_objspace;
- struct gc_list *tmp = global_list;
+ rb_vm_t *vm = GET_VM();
+ struct global_object_list *tmp = vm->global_object_list;
if (tmp->varptr == addr) {
- global_list = tmp->next;
+ vm->global_object_list = tmp->next;
xfree(tmp);
return;
}
while (tmp->next) {
if (tmp->next->varptr == addr) {
- struct gc_list *t = tmp->next;
+ struct global_object_list *t = tmp->next;
tmp->next = tmp->next->next;
xfree(t);
@@ -9262,8 +8844,6 @@ rb_global_variable(VALUE *var)
rb_gc_register_address(var);
}
-#define GC_NOTIFY 0
-
enum {
gc_stress_no_major,
gc_stress_no_immediate_sweep,
@@ -9337,7 +8917,7 @@ gc_reset_malloc_info(rb_objspace_t *objspace, bool full_mark)
#if RGENGC_ESTIMATE_OLDMALLOC
if (!full_mark) {
if (objspace->rgengc.oldmalloc_increase > objspace->rgengc.oldmalloc_increase_limit) {
- objspace->rgengc.need_major_gc |= GPR_FLAG_MAJOR_BY_OLDMALLOC;
+ gc_needs_major_flags |= GPR_FLAG_MAJOR_BY_OLDMALLOC;
objspace->rgengc.oldmalloc_increase_limit =
(size_t)(objspace->rgengc.oldmalloc_increase_limit * gc_params.oldmalloc_limit_growth_factor);
@@ -9348,7 +8928,7 @@ gc_reset_malloc_info(rb_objspace_t *objspace, bool full_mark)
if (0) fprintf(stderr, "%"PRIdSIZE"\t%d\t%"PRIuSIZE"\t%"PRIuSIZE"\t%"PRIdSIZE"\n",
rb_gc_count(),
- objspace->rgengc.need_major_gc,
+ gc_needs_major_flags,
objspace->rgengc.oldmalloc_increase,
objspace->rgengc.oldmalloc_increase_limit,
gc_params.oldmalloc_limit_max);
@@ -9396,20 +8976,11 @@ static int
gc_start(rb_objspace_t *objspace, unsigned int reason)
{
unsigned int do_full_mark = !!(reason & GPR_FLAG_FULL_MARK);
- unsigned int immediate_mark = reason & GPR_FLAG_IMMEDIATE_MARK;
/* reason may be clobbered, later, so keep set immediate_sweep here */
objspace->flags.immediate_sweep = !!(reason & GPR_FLAG_IMMEDIATE_SWEEP);
- /* Explicitly enable compaction (GC.compact) */
- if (do_full_mark && ruby_enable_autocompact) {
- objspace->flags.during_compacting = TRUE;
- }
- else {
- objspace->flags.during_compacting = !!(reason & GPR_FLAG_COMPACT);
- }
-
- if (!heap_allocated_pages) return FALSE; /* heap is not ready */
+ if (!heap_allocated_pages) return TRUE; /* heap is not ready */
if (!(reason & GPR_FLAG_METHOD) && !ready_to_gc(objspace)) return TRUE; /* GC is not allowed */
GC_ASSERT(gc_mode(objspace) == gc_mode_none);
@@ -9432,30 +9003,42 @@ gc_start(rb_objspace_t *objspace, unsigned int reason)
objspace->flags.immediate_sweep = !(flag & (1<<gc_stress_no_immediate_sweep));
}
- else {
- if (objspace->rgengc.need_major_gc) {
- reason |= objspace->rgengc.need_major_gc;
- do_full_mark = TRUE;
- }
- else if (RGENGC_FORCE_MAJOR_GC) {
- reason = GPR_FLAG_MAJOR_BY_FORCE;
- do_full_mark = TRUE;
- }
- objspace->rgengc.need_major_gc = GPR_FLAG_NONE;
+ if (gc_needs_major_flags) {
+ reason |= gc_needs_major_flags;
+ do_full_mark = TRUE;
+ }
+ else if (RGENGC_FORCE_MAJOR_GC) {
+ reason = GPR_FLAG_MAJOR_BY_FORCE;
+ do_full_mark = TRUE;
}
+ gc_needs_major_flags = GPR_FLAG_NONE;
+
if (do_full_mark && (reason & GPR_FLAG_MAJOR_MASK) == 0) {
reason |= GPR_FLAG_MAJOR_BY_FORCE; /* GC by CAPI, METHOD, and so on. */
}
- if (objspace->flags.dont_incremental || immediate_mark) {
+ if (objspace->flags.dont_incremental ||
+ reason & GPR_FLAG_IMMEDIATE_MARK ||
+ ruby_gc_stressful) {
objspace->flags.during_incremental_marking = FALSE;
}
else {
objspace->flags.during_incremental_marking = do_full_mark;
}
+ /* Explicitly enable compaction (GC.compact) */
+ if (do_full_mark && ruby_enable_autocompact) {
+ objspace->flags.during_compacting = TRUE;
+#if RGENGC_CHECK_MODE
+ objspace->rcompactor.compare_func = ruby_autocompact_compare_func;
+#endif
+ }
+ else {
+ objspace->flags.during_compacting = !!(reason & GPR_FLAG_COMPACT);
+ }
+
if (!GC_ENABLE_LAZY_SWEEP || objspace->flags.dont_incremental) {
objspace->flags.immediate_sweep = TRUE;
}
@@ -9514,10 +9097,7 @@ gc_start(rb_objspace_t *objspace, unsigned int reason)
static void
gc_rest(rb_objspace_t *objspace)
{
- int marking = is_incremental_marking(objspace);
- int sweeping = is_lazy_sweeping(objspace);
-
- if (marking || sweeping) {
+ if (is_incremental_marking(objspace) || is_lazy_sweeping(objspace)) {
unsigned int lock_lev;
gc_enter(objspace, gc_enter_event_rest, &lock_lev);
@@ -9645,10 +9225,6 @@ gc_enter_count(enum gc_enter_event event)
}
}
-#ifndef MEASURE_GC
-#define MEASURE_GC (objspace->flags.measure_gc)
-#endif
-
static bool current_process_time(struct timespec *ts);
static void
@@ -9695,7 +9271,7 @@ gc_enter(rb_objspace_t *objspace, enum gc_enter_event event, unsigned int *lock_
gc_enter_count(event);
if (UNLIKELY(during_gc != 0)) rb_bug("during_gc != 0");
- if (RGENGC_CHECK_MODE >= 3) gc_verify_internal_consistency(objspace);
+ if (RGENGC_CHECK_MODE >= 3 && (dont_gc_val() == 0)) gc_verify_internal_consistency(objspace);
during_gc = TRUE;
RUBY_DEBUG_LOG("%s (%s)",gc_enter_event_cstr(event), gc_current_status(objspace));
@@ -9718,12 +9294,18 @@ gc_exit(rb_objspace_t *objspace, enum gc_enter_event event, unsigned int *lock_l
RB_VM_LOCK_LEAVE_LEV(lock_lev);
}
+#ifndef MEASURE_GC
+#define MEASURE_GC (objspace->flags.measure_gc)
+#endif
+
static void
gc_marking_enter(rb_objspace_t *objspace)
{
GC_ASSERT(during_gc != 0);
- gc_clock_start(&objspace->profile.marking_start_time);
+ if (MEASURE_GC) {
+ gc_clock_start(&objspace->profile.marking_start_time);
+ }
}
static void
@@ -9731,7 +9313,9 @@ gc_marking_exit(rb_objspace_t *objspace)
{
GC_ASSERT(during_gc != 0);
- objspace->profile.marking_time_ns += gc_clock_end(&objspace->profile.marking_start_time);
+ if (MEASURE_GC) {
+ objspace->profile.marking_time_ns += gc_clock_end(&objspace->profile.marking_start_time);
+ }
}
static void
@@ -9739,7 +9323,9 @@ gc_sweeping_enter(rb_objspace_t *objspace)
{
GC_ASSERT(during_gc != 0);
- gc_clock_start(&objspace->profile.sweeping_start_time);
+ if (MEASURE_GC) {
+ gc_clock_start(&objspace->profile.sweeping_start_time);
+ }
}
static void
@@ -9747,7 +9333,9 @@ gc_sweeping_exit(rb_objspace_t *objspace)
{
GC_ASSERT(during_gc != 0);
- objspace->profile.sweeping_time_ns += gc_clock_end(&objspace->profile.sweeping_start_time);
+ if (MEASURE_GC) {
+ objspace->profile.sweeping_time_ns += gc_clock_end(&objspace->profile.sweeping_start_time);
+ }
}
static void *
@@ -9785,18 +9373,20 @@ gc_set_candidate_object_i(void *vstart, void *vend, size_t stride, void *data)
rb_objspace_t *objspace = &rb_objspace;
VALUE v = (VALUE)vstart;
for (; v != (VALUE)vend; v += stride) {
- switch (BUILTIN_TYPE(v)) {
- case T_NONE:
- case T_ZOMBIE:
- break;
- case T_STRING:
- // precompute the string coderange. This both save time for when it will be
- // eventually needed, and avoid mutating heap pages after a potential fork.
- rb_enc_str_coderange(v);
- // fall through
- default:
- if (!RVALUE_OLD_P(v) && !RVALUE_WB_UNPROTECTED(v)) {
- RVALUE_AGE_SET_CANDIDATE(objspace, v);
+ asan_unpoisoning_object(v) {
+ switch (BUILTIN_TYPE(v)) {
+ case T_NONE:
+ case T_ZOMBIE:
+ break;
+ case T_STRING:
+ // precompute the string coderange. This both save time for when it will be
+ // eventually needed, and avoid mutating heap pages after a potential fork.
+ rb_enc_str_coderange(v);
+ // fall through
+ default:
+ if (!RVALUE_OLD_P(v) && !RVALUE_WB_UNPROTECTED(v)) {
+ RVALUE_AGE_SET_CANDIDATE(objspace, v);
+ }
}
}
}
@@ -9893,12 +9483,11 @@ gc_is_moveable_obj(rb_objspace_t *objspace, VALUE obj)
switch (BUILTIN_TYPE(obj)) {
case T_NONE:
- case T_NIL:
case T_MOVED:
case T_ZOMBIE:
return FALSE;
case T_SYMBOL:
- if (DYNAMIC_SYM_P(obj) && (RSYMBOL(obj)->id & ~ID_SCOPE_MASK)) {
+ if (RSYMBOL(obj)->id & ~ID_SCOPE_MASK) {
return FALSE;
}
/* fall through */
@@ -9961,7 +9550,7 @@ gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free, size_t src_slot_size, s
GC_ASSERT(!RVALUE_MARKING((VALUE)src));
/* Save off bits for current object. */
- marked = rb_objspace_marked_object_p((VALUE)src);
+ marked = RVALUE_MARKED((VALUE)src);
wb_unprotected = RVALUE_WB_UNPROTECTED((VALUE)src);
uncollectible = RVALUE_UNCOLLECTIBLE((VALUE)src);
bool remembered = RVALUE_REMEMBERED((VALUE)src);
@@ -9982,20 +9571,26 @@ gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free, size_t src_slot_size, s
DURING_GC_COULD_MALLOC_REGION_END();
}
- st_data_t srcid = (st_data_t)src, id;
+ if (FL_TEST((VALUE)src, FL_SEEN_OBJ_ID)) {
+ /* If the source object's object_id has been seen, we need to update
+ * the object to object id mapping. */
+ st_data_t srcid = (st_data_t)src, id;
- /* If the source object's object_id has been seen, we need to update
- * the object to object id mapping. */
- if (st_lookup(objspace->obj_to_id_tbl, srcid, &id)) {
gc_report(4, objspace, "Moving object with seen id: %p -> %p\n", (void *)src, (void *)dest);
/* Resizing the st table could cause a malloc */
DURING_GC_COULD_MALLOC_REGION_START();
{
- st_delete(objspace->obj_to_id_tbl, &srcid, 0);
+ if (!st_delete(objspace->obj_to_id_tbl, &srcid, &id)) {
+ rb_bug("gc_move: object ID seen, but not in mapping table: %s", obj_info((VALUE)src));
+ }
+
st_insert(objspace->obj_to_id_tbl, (st_data_t)dest, id);
}
DURING_GC_COULD_MALLOC_REGION_END();
}
+ else {
+ GC_ASSERT(!st_lookup(objspace->obj_to_id_tbl, (st_data_t)src, NULL));
+ }
/* Move the object */
memcpy(dest, src, MIN(src_slot_size, slot_size));
@@ -10146,13 +9741,15 @@ gc_ref_update_array(rb_objspace_t * objspace, VALUE v)
}
}
+static void gc_ref_update_table_values_only(rb_objspace_t *objspace, st_table *tbl);
+
static void
gc_ref_update_object(rb_objspace_t *objspace, VALUE v)
{
VALUE *ptr = ROBJECT_IVPTR(v);
if (rb_shape_obj_too_complex(v)) {
- rb_gc_update_tbl_refs(ROBJECT_IV_HASH(v));
+ gc_ref_update_table_values_only(objspace, ROBJECT_IV_HASH(v));
return;
}
@@ -10230,7 +9827,7 @@ hash_foreach_replace_value(st_data_t key, st_data_t value, st_data_t argp, int e
}
static void
-gc_update_tbl_refs(rb_objspace_t * objspace, st_table *tbl)
+gc_ref_update_table_values_only(rb_objspace_t *objspace, st_table *tbl)
{
if (!tbl || tbl->num_entries == 0) return;
@@ -10239,6 +9836,12 @@ gc_update_tbl_refs(rb_objspace_t * objspace, st_table *tbl)
}
}
+void
+rb_gc_ref_update_table_values_only(st_table *tbl)
+{
+ gc_ref_update_table_values_only(&rb_objspace, tbl);
+}
+
static void
gc_update_table_refs(rb_objspace_t * objspace, st_table *tbl)
{
@@ -10249,7 +9852,7 @@ gc_update_table_refs(rb_objspace_t * objspace, st_table *tbl)
}
}
-/* Update MOVED references in an st_table */
+/* Update MOVED references in a VALUE=>VALUE st_table */
void
rb_gc_update_tbl_refs(st_table *ptr)
{
@@ -10264,47 +9867,6 @@ gc_ref_update_hash(rb_objspace_t * objspace, VALUE v)
}
static void
-gc_ref_update_method_entry(rb_objspace_t *objspace, rb_method_entry_t *me)
-{
- rb_method_definition_t *def = me->def;
-
- UPDATE_IF_MOVED(objspace, me->owner);
- UPDATE_IF_MOVED(objspace, me->defined_class);
-
- if (def) {
- switch (def->type) {
- case VM_METHOD_TYPE_ISEQ:
- if (def->body.iseq.iseqptr) {
- TYPED_UPDATE_IF_MOVED(objspace, rb_iseq_t *, def->body.iseq.iseqptr);
- }
- TYPED_UPDATE_IF_MOVED(objspace, rb_cref_t *, def->body.iseq.cref);
- break;
- case VM_METHOD_TYPE_ATTRSET:
- case VM_METHOD_TYPE_IVAR:
- UPDATE_IF_MOVED(objspace, def->body.attr.location);
- break;
- case VM_METHOD_TYPE_BMETHOD:
- UPDATE_IF_MOVED(objspace, def->body.bmethod.proc);
- break;
- case VM_METHOD_TYPE_ALIAS:
- TYPED_UPDATE_IF_MOVED(objspace, struct rb_method_entry_struct *, def->body.alias.original_me);
- return;
- case VM_METHOD_TYPE_REFINED:
- TYPED_UPDATE_IF_MOVED(objspace, struct rb_method_entry_struct *, def->body.refined.orig_me);
- UPDATE_IF_MOVED(objspace, def->body.refined.owner);
- break;
- case VM_METHOD_TYPE_CFUNC:
- case VM_METHOD_TYPE_ZSUPER:
- case VM_METHOD_TYPE_MISSING:
- case VM_METHOD_TYPE_OPTIMIZED:
- case VM_METHOD_TYPE_UNDEF:
- case VM_METHOD_TYPE_NOTIMPLEMENTED:
- break;
- }
- }
-}
-
-static void
gc_update_values(rb_objspace_t *objspace, long n, VALUE *values)
{
long i;
@@ -10320,93 +9882,6 @@ rb_gc_update_values(long n, VALUE *values)
gc_update_values(&rb_objspace, n, values);
}
-static bool
-moved_or_living_object_strictly_p(rb_objspace_t *objspace, VALUE obj)
-{
- return obj &&
- is_pointer_to_heap(objspace, (void *)obj) &&
- (is_live_object(objspace, obj) || BUILTIN_TYPE(obj) == T_MOVED);
-}
-
-static void
-gc_ref_update_imemo(rb_objspace_t *objspace, VALUE obj)
-{
- switch (imemo_type(obj)) {
- case imemo_env:
- {
- rb_env_t *env = (rb_env_t *)obj;
- if (LIKELY(env->ep)) {
- // just after newobj() can be NULL here.
- TYPED_UPDATE_IF_MOVED(objspace, rb_iseq_t *, env->iseq);
- UPDATE_IF_MOVED(objspace, env->ep[VM_ENV_DATA_INDEX_ENV]);
- gc_update_values(objspace, (long)env->env_size, (VALUE *)env->env);
- }
- }
- break;
- case imemo_cref:
- UPDATE_IF_MOVED(objspace, RANY(obj)->as.imemo.cref.klass_or_self);
- TYPED_UPDATE_IF_MOVED(objspace, struct rb_cref_struct *, RANY(obj)->as.imemo.cref.next);
- UPDATE_IF_MOVED(objspace, RANY(obj)->as.imemo.cref.refinements);
- break;
- case imemo_svar:
- UPDATE_IF_MOVED(objspace, RANY(obj)->as.imemo.svar.cref_or_me);
- UPDATE_IF_MOVED(objspace, RANY(obj)->as.imemo.svar.lastline);
- UPDATE_IF_MOVED(objspace, RANY(obj)->as.imemo.svar.backref);
- UPDATE_IF_MOVED(objspace, RANY(obj)->as.imemo.svar.others);
- break;
- case imemo_throw_data:
- UPDATE_IF_MOVED(objspace, RANY(obj)->as.imemo.throw_data.throw_obj);
- break;
- case imemo_ifunc:
- break;
- case imemo_memo:
- UPDATE_IF_MOVED(objspace, RANY(obj)->as.imemo.memo.v1);
- UPDATE_IF_MOVED(objspace, RANY(obj)->as.imemo.memo.v2);
- break;
- case imemo_ment:
- gc_ref_update_method_entry(objspace, &RANY(obj)->as.imemo.ment);
- break;
- case imemo_iseq:
- rb_iseq_mark_and_move((rb_iseq_t *)obj, true);
- break;
- case imemo_ast:
- rb_ast_update_references((rb_ast_t *)obj);
- break;
- case imemo_callcache:
- {
- const struct rb_callcache *cc = (const struct rb_callcache *)obj;
-
- if (!cc->klass) {
- // already invalidated
- }
- else {
- if (moved_or_living_object_strictly_p(objspace, cc->klass) &&
- moved_or_living_object_strictly_p(objspace, (VALUE)cc->cme_)) {
- UPDATE_IF_MOVED(objspace, cc->klass);
- TYPED_UPDATE_IF_MOVED(objspace, struct rb_callable_method_entry_struct *, cc->cme_);
- }
- else {
- vm_cc_invalidate(cc);
- }
- }
- }
- break;
- case imemo_constcache:
- {
- const struct iseq_inline_constant_cache_entry *ice = (struct iseq_inline_constant_cache_entry *)obj;
- UPDATE_IF_MOVED(objspace, ice->value);
- }
- break;
- case imemo_parser_strterm:
- case imemo_tmpbuf:
- case imemo_callinfo:
- break;
- default:
- rb_bug("not reachable %d", imemo_type(obj));
- break;
- }
-}
-
static enum rb_id_table_iterator_result
check_id_table_move(VALUE value, void *data)
{
@@ -10483,9 +9958,6 @@ update_cc_tbl_i(VALUE ccs_ptr, void *data)
}
for (int i=0; i<ccs->len; i++) {
- if (gc_object_moved_p(objspace, (VALUE)ccs->entries[i].ci)) {
- ccs->entries[i].ci = (struct rb_callinfo *)rb_gc_location((VALUE)ccs->entries[i].ci);
- }
if (gc_object_moved_p(objspace, (VALUE)ccs->entries[i].cc)) {
ccs->entries[i].cc = (struct rb_callcache *)rb_gc_location((VALUE)ccs->entries[i].cc);
}
@@ -10613,7 +10085,7 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
gc_report(4, objspace, "update-refs: %p ->\n", (void *)obj);
if (FL_TEST(obj, FL_EXIVAR)) {
- rb_mark_and_update_generic_ivar(obj);
+ rb_ref_update_generic_ivar(obj);
}
switch (BUILTIN_TYPE(obj)) {
@@ -10631,8 +10103,13 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
update_cvc_tbl(objspace, obj);
update_superclasses(objspace, obj);
- for (attr_index_t i = 0; i < RCLASS_IV_COUNT(obj); i++) {
- UPDATE_IF_MOVED(objspace, RCLASS_IVPTR(obj)[i]);
+ if (rb_shape_obj_too_complex(obj)) {
+ gc_ref_update_table_values_only(objspace, RCLASS_IV_HASH(obj));
+ }
+ else {
+ for (attr_index_t i = 0; i < RCLASS_IV_COUNT(obj); i++) {
+ UPDATE_IF_MOVED(objspace, RCLASS_IVPTR(obj)[i]);
+ }
}
update_class_ext(objspace, RCLASS_EXT(obj));
@@ -10642,8 +10119,7 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
break;
case T_ICLASS:
- if (FL_TEST(obj, RICLASS_IS_ORIGIN) &&
- !FL_TEST(obj, RICLASS_ORIGIN_SHARED_MTBL)) {
+ if (RICLASS_OWNS_M_TBL_P(obj)) {
update_m_tbl(objspace, RCLASS_M_TBL(obj));
}
if (RCLASS_SUPER((VALUE)obj)) {
@@ -10655,7 +10131,7 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
break;
case T_IMEMO:
- gc_ref_update_imemo(objspace, obj);
+ rb_imemo_mark_and_move(obj, true);
return;
case T_NIL:
@@ -10678,10 +10154,7 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
case T_STRING:
{
if (STR_SHARED_P(obj)) {
- VALUE old_root = any->as.string.as.heap.aux.shared;
UPDATE_IF_MOVED(objspace, any->as.string.as.heap.aux.shared);
- VALUE new_root = any->as.string.as.heap.aux.shared;
- rb_str_update_shared_ary(obj, old_root, new_root);
}
/* If, after move the string is not embedded, and can fit in the
@@ -10700,7 +10173,13 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
void *const ptr = RTYPEDDATA_P(obj) ? RTYPEDDATA_GET_DATA(obj) : DATA_PTR(obj);
if (ptr) {
if (RTYPEDDATA_P(obj) && gc_declarative_marking_p(any->as.typeddata.type)) {
- gc_ref_update_from_offset(objspace, obj);
+ size_t *offset_list = (size_t *)RANY(obj)->as.typeddata.type->function.dmark;
+
+ for (size_t offset = *offset_list; offset != RUBY_REF_END; offset = *offset_list++) {
+ VALUE *ref = (VALUE *)((char *)ptr + offset);
+ if (SPECIAL_CONST_P(*ref)) continue;
+ *ref = rb_gc_location(*ref);
+ }
}
else if (RTYPEDDATA_P(obj)) {
RUBY_DATA_FUNC compact_func = any->as.typeddata.type->function.dcompact;
@@ -10730,9 +10209,7 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
break;
case T_SYMBOL:
- if (DYNAMIC_SYM_P((VALUE)any)) {
- UPDATE_IF_MOVED(objspace, RSYMBOL(any)->fstr);
- }
+ UPDATE_IF_MOVED(objspace, RSYMBOL(any)->fstr);
break;
case T_FLOAT:
@@ -10861,7 +10338,7 @@ gc_update_references(rb_objspace_t *objspace)
rb_gc_update_global_tbl();
global_symbols.ids = rb_gc_location(global_symbols.ids);
global_symbols.dsymbol_fstr_hash = rb_gc_location(global_symbols.dsymbol_fstr_hash);
- gc_update_tbl_refs(objspace, objspace->obj_to_id_tbl);
+ gc_ref_update_table_values_only(objspace, objspace->obj_to_id_tbl);
gc_update_table_refs(objspace, objspace->id_to_obj_tbl);
gc_update_table_refs(objspace, global_symbols.str_sym);
gc_update_table_refs(objspace, finalizer_table);
@@ -10876,11 +10353,23 @@ gc_update_references(rb_objspace_t *objspace)
*
* Returns information about object moved in the most recent \GC compaction.
*
- * The returned hash has two keys :considered and :moved. The hash for
- * :considered lists the number of objects that were considered for movement
- * by the compactor, and the :moved hash lists the number of objects that
- * were actually moved. Some objects can't be moved (maybe they were pinned)
- * so these numbers can be used to calculate compaction efficiency.
+ * The returned +hash+ contains the following keys:
+ *
+ * [considered]
+ * Hash containing the type of the object as the key and the number of
+ * objects of that type that were considered for movement.
+ * [moved]
+ * Hash containing the type of the object as the key and the number of
+ * objects of that type that were actually moved.
+ * [moved_up]
+ * Hash containing the type of the object as the key and the number of
+ * objects of that type that were increased in size.
+ * [moved_down]
+ * Hash containing the type of the object as the key and the number of
+ * objects of that type that were decreased in size.
+ *
+ * Some objects can't be moved (due to pinning) so these numbers can be used to
+ * calculate compaction efficiency.
*/
static VALUE
gc_compact_stats(VALUE self)
@@ -10926,7 +10415,9 @@ gc_compact_stats(VALUE self)
static void
root_obj_check_moved_i(const char *category, VALUE obj, void *data)
{
- if (gc_object_moved_p(&rb_objspace, obj)) {
+ rb_objspace_t *objspace = data;
+
+ if (gc_object_moved_p(objspace, obj)) {
rb_bug("ROOT %s points to MOVED: %p -> %s", category, (void *)obj, obj_info(rb_gc_location(obj)));
}
}
@@ -10943,9 +10434,11 @@ reachable_object_check_moved_i(VALUE ref, void *data)
static int
heap_check_moved_i(void *vstart, void *vend, size_t stride, void *data)
{
+ rb_objspace_t *objspace = data;
+
VALUE v = (VALUE)vstart;
for (; v != (VALUE)vend; v += stride) {
- if (gc_object_moved_p(&rb_objspace, v)) {
+ if (gc_object_moved_p(objspace, v)) {
/* Moved object still on the heap, something may have a reference. */
}
else {
@@ -10973,16 +10466,16 @@ heap_check_moved_i(void *vstart, void *vend, size_t stride, void *data)
/*
* call-seq:
- * GC.compact
+ * GC.compact -> hash
*
- * This function compacts objects together in Ruby's heap. It eliminates
+ * This function compacts objects together in Ruby's heap. It eliminates
* unused space (or fragmentation) in the heap by moving objects in to that
- * unused space. This function returns a hash which contains statistics about
- * which objects were moved. See <tt>GC.latest_gc_info</tt> for details about
- * compaction statistics.
+ * unused space.
+ *
+ * The returned +hash+ contains statistics about the objects that were moved;
+ * see GC.latest_compact_info.
*
- * This method is implementation specific and not expected to be implemented
- * in any implementation besides MRI.
+ * This method is only expected to work on CRuby.
*
* To test whether \GC compaction is supported, use the idiom:
*
@@ -11001,6 +10494,39 @@ gc_compact(VALUE self)
#endif
#if GC_CAN_COMPILE_COMPACTION
+
+struct desired_compaction_pages_i_data {
+ rb_objspace_t *objspace;
+ size_t required_slots[SIZE_POOL_COUNT];
+};
+
+static int
+desired_compaction_pages_i(struct heap_page *page, void *data)
+{
+ struct desired_compaction_pages_i_data *tdata = data;
+ rb_objspace_t *objspace = tdata->objspace;
+ VALUE vstart = (VALUE)page->start;
+ VALUE vend = vstart + (VALUE)(page->total_slots * page->size_pool->slot_size);
+
+
+ for (VALUE v = vstart; v != vend; v += page->size_pool->slot_size) {
+ /* skip T_NONEs; they won't be moved */
+ void *poisoned = asan_unpoison_object_temporary(v);
+ if (BUILTIN_TYPE(v) == T_NONE) {
+ if (poisoned) {
+ asan_poison_object(v);
+ }
+ continue;
+ }
+
+ rb_size_pool_t *dest_pool = gc_compact_destination_pool(objspace, page->size_pool, v);
+ size_t dest_pool_idx = dest_pool - size_pools;
+ tdata->required_slots[dest_pool_idx]++;
+ }
+
+ return 0;
+}
+
static VALUE
gc_verify_compaction_references(rb_execution_context_t *ec, VALUE self, VALUE double_heap, VALUE expand_heap, VALUE toward_empty)
{
@@ -11018,18 +10544,55 @@ gc_verify_compaction_references(rb_execution_context_t *ec, VALUE self, VALUE do
gc_rest(objspace);
/* if both double_heap and expand_heap are set, expand_heap takes precedence */
- if (RTEST(double_heap) || RTEST(expand_heap)) {
+ if (RTEST(expand_heap)) {
+ struct desired_compaction_pages_i_data desired_compaction = {
+ .objspace = objspace,
+ .required_slots = {0},
+ };
+ /* Work out how many objects want to be in each size pool, taking account of moves */
+ objspace_each_pages(objspace, desired_compaction_pages_i, &desired_compaction, TRUE);
+
+ /* Find out which pool has the most pages */
+ size_t max_existing_pages = 0;
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+ rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(size_pool);
+ max_existing_pages = MAX(max_existing_pages, heap->total_pages);
+ }
+ /* Add pages to each size pool so that compaction is guaranteed to move every object */
for (int i = 0; i < SIZE_POOL_COUNT; i++) {
rb_size_pool_t *size_pool = &size_pools[i];
rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(size_pool);
- size_t minimum_pages = 0;
- if (RTEST(expand_heap)) {
- minimum_pages = minimum_pages_for_size_pool(objspace, size_pool);
- }
-
- heap_add_pages(objspace, size_pool, heap, MAX(minimum_pages, heap->total_pages));
+ size_t pages_to_add = 0;
+ /*
+ * Step 1: Make sure every pool has the same number of pages, by adding empty pages
+ * to smaller pools. This is required to make sure the compact cursor can advance
+ * through all of the pools in `gc_sweep_compact` without hitting the "sweep &
+ * compact cursors met" condition on some pools before fully compacting others
+ */
+ pages_to_add += max_existing_pages - heap->total_pages;
+ /*
+ * Step 2: Now add additional free pages to each size pool sufficient to hold all objects
+ * that want to be in that size pool, whether moved into it or moved within it
+ */
+ pages_to_add += slots_to_pages_for_size_pool(objspace, size_pool, desired_compaction.required_slots[i]);
+ /*
+ * Step 3: Add two more pages so that the compact & sweep cursors will meet _after_ all objects
+ * have been moved, and not on the last iteration of the `gc_sweep_compact` loop
+ */
+ pages_to_add += 2;
+
+ heap_add_pages(objspace, size_pool, heap, pages_to_add);
+ }
+ }
+ else if (RTEST(double_heap)) {
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+ rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(size_pool);
+ heap_add_pages(objspace, size_pool, heap, heap->total_pages);
}
+
}
if (RTEST(toward_empty)) {
@@ -11040,8 +10603,8 @@ gc_verify_compaction_references(rb_execution_context_t *ec, VALUE self, VALUE do
gc_start_internal(NULL, self, Qtrue, Qtrue, Qtrue, Qtrue);
- objspace_reachable_objects_from_root(objspace, root_obj_check_moved_i, NULL);
- objspace_each_objects(objspace, heap_check_moved_i, NULL, TRUE);
+ objspace_reachable_objects_from_root(objspace, root_obj_check_moved_i, objspace);
+ objspace_each_objects(objspace, heap_check_moved_i, objspace, TRUE);
objspace->rcompactor.compare_func = NULL;
return gc_compact_stats(self);
@@ -11175,7 +10738,7 @@ gc_info_decode(rb_objspace_t *objspace, const VALUE hash_or_key, const unsigned
SET(major_by, major_by);
if (orig_flags == 0) { /* set need_major_by only if flags not set explicitly */
- unsigned int need_major_flags = objspace->rgengc.need_major_gc;
+ unsigned int need_major_flags = gc_needs_major_flags;
need_major_by =
(need_major_flags & GPR_FLAG_MAJOR_BY_NOFREE) ? sym_nofree :
(need_major_flags & GPR_FLAG_MAJOR_BY_OLDGEN) ? sym_oldgen :
@@ -11612,18 +11175,14 @@ gc_stress_get(rb_execution_context_t *ec, VALUE self)
return ruby_gc_stress_mode;
}
-static void
-gc_stress_set(rb_objspace_t *objspace, VALUE flag)
-{
- objspace->flags.gc_stressful = RTEST(flag);
- objspace->gc_stress_mode = flag;
-}
-
static VALUE
gc_stress_set_m(rb_execution_context_t *ec, VALUE self, VALUE flag)
{
rb_objspace_t *objspace = &rb_objspace;
- gc_stress_set(objspace, flag);
+
+ objspace->flags.gc_stressful = RTEST(flag);
+ objspace->gc_stress_mode = flag;
+
return flag;
}
@@ -11701,6 +11260,18 @@ gc_set_auto_compact(VALUE _, VALUE v)
GC_ASSERT(GC_COMPACTION_SUPPORTED);
ruby_enable_autocompact = RTEST(v);
+
+#if RGENGC_CHECK_MODE
+ ruby_autocompact_compare_func = NULL;
+
+ if (SYMBOL_P(v)) {
+ ID id = RB_SYM2ID(v);
+ if (id == rb_intern("empty")) {
+ ruby_autocompact_compare_func = compare_free_slots;
+ }
+ }
+#endif
+
return v;
}
#else
@@ -12117,40 +11688,6 @@ rb_memerror(void)
EC_JUMP_TAG(ec, TAG_RAISE);
}
-void *
-rb_aligned_malloc(size_t alignment, size_t size)
-{
- /* alignment must be a power of 2 */
- GC_ASSERT(((alignment - 1) & alignment) == 0);
- GC_ASSERT(alignment % sizeof(void*) == 0);
-
- void *res;
-
-#if defined __MINGW32__
- res = __mingw_aligned_malloc(size, alignment);
-#elif defined _WIN32
- void *_aligned_malloc(size_t, size_t);
- res = _aligned_malloc(size, alignment);
-#elif defined(HAVE_POSIX_MEMALIGN)
- if (posix_memalign(&res, alignment, size) != 0) {
- return NULL;
- }
-#elif defined(HAVE_MEMALIGN)
- res = memalign(alignment, size);
-#else
- char* aligned;
- res = malloc(alignment + size + sizeof(void*));
- aligned = (char*)res + alignment + sizeof(void*);
- aligned -= ((VALUE)aligned & (alignment - 1));
- ((void**)aligned)[-1] = res;
- res = (void*)aligned;
-#endif
-
- GC_ASSERT((uintptr_t)res % alignment == 0);
-
- return res;
-}
-
static void
rb_aligned_free(void *ptr, size_t size)
{
@@ -12330,7 +11867,7 @@ static inline void *
objspace_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size)
{
size = objspace_malloc_size(objspace, mem, size);
- objspace_malloc_increase(objspace, mem, size, 0, MEMOP_TYPE_MALLOC);
+ objspace_malloc_increase(objspace, mem, size, 0, MEMOP_TYPE_MALLOC) {}
#if CALC_EXACT_MALLOC_SIZE
{
@@ -12804,55 +12341,46 @@ ruby_mimmalloc(size_t size)
return mem;
}
-void
-ruby_mimfree(void *ptr)
+void *
+ruby_mimcalloc(size_t num, size_t size)
{
+ void *mem;
#if CALC_EXACT_MALLOC_SIZE
- struct malloc_obj_info *info = (struct malloc_obj_info *)ptr - 1;
- ptr = info;
+ struct rbimpl_size_mul_overflow_tag t = rbimpl_size_mul_overflow(num, size);
+ if (UNLIKELY(t.left)) {
+ return NULL;
+ }
+ size = t.right + sizeof(struct malloc_obj_info);
+ mem = calloc1(size);
+ if (!mem) {
+ return NULL;
+ }
+ else
+ /* set 0 for consistency of allocated_size/allocations */
+ {
+ struct malloc_obj_info *info = mem;
+ info->size = 0;
+#if USE_GC_MALLOC_OBJ_INFO_DETAILS
+ info->gen = 0;
+ info->file = NULL;
+ info->line = 0;
#endif
- free(ptr);
-}
-
-void *
-rb_alloc_tmp_buffer_with_count(volatile VALUE *store, size_t size, size_t cnt)
-{
- void *ptr;
- VALUE imemo;
- rb_imemo_tmpbuf_t *tmpbuf;
-
- /* Keep the order; allocate an empty imemo first then xmalloc, to
- * get rid of potential memory leak */
- imemo = rb_imemo_tmpbuf_auto_free_maybe_mark_buffer(NULL, 0);
- *store = imemo;
- ptr = ruby_xmalloc0(size);
- tmpbuf = (rb_imemo_tmpbuf_t *)imemo;
- tmpbuf->ptr = ptr;
- tmpbuf->cnt = cnt;
- return ptr;
-}
-
-void *
-rb_alloc_tmp_buffer(volatile VALUE *store, long len)
-{
- long cnt;
-
- if (len < 0 || (cnt = (long)roomof(len, sizeof(VALUE))) < 0) {
- rb_raise(rb_eArgError, "negative buffer size (or size too big)");
+ mem = info + 1;
}
-
- return rb_alloc_tmp_buffer_with_count(store, len, cnt);
+#else
+ mem = calloc(num, size);
+#endif
+ return mem;
}
void
-rb_free_tmp_buffer(volatile VALUE *store)
+ruby_mimfree(void *ptr)
{
- rb_imemo_tmpbuf_t *s = (rb_imemo_tmpbuf_t*)ATOMIC_VALUE_EXCHANGE(*store, 0);
- if (s) {
- void *ptr = ATOMIC_PTR_EXCHANGE(s->ptr, 0);
- s->cnt = 0;
- ruby_xfree(ptr);
- }
+#if CALC_EXACT_MALLOC_SIZE
+ struct malloc_obj_info *info = (struct malloc_obj_info *)ptr - 1;
+ ptr = info;
+#endif
+ free(ptr);
}
#if MALLOC_ALLOCATED_SIZE
@@ -13231,7 +12759,7 @@ gc_profile_record_get(VALUE _)
gc_profile_record *record = &objspace->profile.records[i];
prof = rb_hash_new();
- rb_hash_aset(prof, ID2SYM(rb_intern("GC_FLAGS")), gc_info_decode(0, rb_hash_new(), record->flags));
+ rb_hash_aset(prof, ID2SYM(rb_intern("GC_FLAGS")), gc_info_decode(objspace, rb_hash_new(), record->flags));
rb_hash_aset(prof, ID2SYM(rb_intern("GC_TIME")), DBL2NUM(record->gc_time));
rb_hash_aset(prof, ID2SYM(rb_intern("GC_INVOKE_TIME")), DBL2NUM(record->gc_invoke_time));
rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_USE_SIZE")), SIZET2NUM(record->heap_use_size));
@@ -13606,7 +13134,6 @@ str_len_no_raise(VALUE str)
memcpy(buff + pos, (s), rb_strlen_lit(s) + 1); \
} \
} while (0)
-#define TF(c) ((c) != 0 ? "true" : "false")
#define C(c, s) ((c) != 0 ? (s) : " ")
static size_t
@@ -13659,7 +13186,7 @@ rb_raw_obj_info_common(char *const buff, const size_t buff_size, const VALUE obj
}
#if GC_DEBUG
- APPEND_F("@%s:%d", RANY(obj)->file, RANY(obj)->line);
+ APPEND_F("@%s:%d", GET_RVALUE_OVERHEAD(obj)->file, GET_RVALUE_OVERHEAD(obj)->line);
#endif
}
end:
@@ -13752,14 +13279,20 @@ rb_raw_obj_info_buitin_type(char *const buff, const size_t buff_size, const VALU
}
case T_OBJECT:
{
- uint32_t len = ROBJECT_IV_CAPACITY(obj);
-
- if (RANY(obj)->as.basic.flags & ROBJECT_EMBED) {
- APPEND_F("(embed) len:%d", len);
+ if (rb_shape_obj_too_complex(obj)) {
+ size_t hash_len = rb_st_table_size(ROBJECT_IV_HASH(obj));
+ APPEND_F("(too_complex) len:%zu", hash_len);
}
else {
- VALUE *ptr = ROBJECT_IVPTR(obj);
- APPEND_F("len:%d ptr:%p", len, (void *)ptr);
+ uint32_t len = ROBJECT_IV_CAPACITY(obj);
+
+ if (RANY(obj)->as.basic.flags & ROBJECT_EMBED) {
+ APPEND_F("(embed) len:%d", len);
+ }
+ else {
+ VALUE *ptr = ROBJECT_IVPTR(obj);
+ APPEND_F("len:%d ptr:%p", len, (void *)ptr);
+ }
}
}
break;
@@ -13862,7 +13395,6 @@ rb_raw_obj_info_buitin_type(char *const buff, const size_t buff_size, const VALU
return pos;
}
-#undef TF
#undef C
const char *
@@ -13908,12 +13440,32 @@ obj_info(VALUE obj)
char *const buff = obj_info_buffers[index];
return rb_raw_obj_info(buff, OBJ_INFO_BUFFERS_SIZE, obj);
}
+
+static const char *
+obj_info_basic(VALUE obj)
+{
+ rb_atomic_t index = atomic_inc_wraparound(&obj_info_buffers_index, OBJ_INFO_BUFFERS_NUM);
+ char *const buff = obj_info_buffers[index];
+
+ asan_unpoisoning_object(obj) {
+ rb_raw_obj_info_common(buff, OBJ_INFO_BUFFERS_SIZE, obj);
+ }
+
+ return buff;
+}
#else
static const char *
obj_info(VALUE obj)
{
return obj_type_name(obj);
}
+
+static const char *
+obj_info_basic(VALUE obj)
+{
+ return obj_type_name(obj);
+}
+
#endif
const char *
@@ -13943,7 +13495,7 @@ rb_gcdebug_print_obj_condition(VALUE obj)
{
rb_objspace_t *objspace = &rb_objspace;
- fprintf(stderr, "created at: %s:%d\n", RANY(obj)->file, RANY(obj)->line);
+ fprintf(stderr, "created at: %s:%d\n", GET_RVALUE_OVERHEAD(obj)->file, GET_RVALUE_OVERHEAD(obj)->line);
if (BUILTIN_TYPE(obj) == T_MOVED) {
fprintf(stderr, "moved?: true\n");
@@ -13968,7 +13520,7 @@ rb_gcdebug_print_obj_condition(VALUE obj)
if (is_lazy_sweeping(objspace)) {
fprintf(stderr, "lazy sweeping?: true\n");
- fprintf(stderr, "swept?: %s\n", is_swept_object(obj) ? "done" : "not yet");
+ fprintf(stderr, "page swept?: %s\n", GET_HEAP_PAGE(obj)->flags.before_sweep ? "false" : "true");
}
else {
fprintf(stderr, "lazy sweeping?: false\n");
@@ -13990,7 +13542,8 @@ rb_gcdebug_sentinel(VALUE obj, const char *name)
#endif /* GC_DEBUG */
-/*
+/* :nodoc:
+ *
* call-seq:
* GC.add_stress_to_class(class[, ...])
*
@@ -14009,7 +13562,8 @@ rb_gcdebug_add_stress_to_class(int argc, VALUE *argv, VALUE self)
return self;
}
-/*
+/* :nodoc:
+ *
* call-seq:
* GC.remove_stress_to_class(class[, ...])
*
@@ -14042,10 +13596,9 @@ rb_gcdebug_remove_stress_to_class(int argc, VALUE *argv, VALUE self)
* traverse all living objects with an iterator.
*
* ObjectSpace also provides support for object finalizers, procs that will be
- * called when a specific object is about to be destroyed by garbage
- * collection. See the documentation for
- * <code>ObjectSpace.define_finalizer</code> for important information on
- * how to use this method correctly.
+ * called after a specific object was destroyed by garbage collection. See
+ * the documentation for +ObjectSpace.define_finalizer+ for important
+ * information on how to use this method correctly.
*
* a = "A"
* b = "B"
@@ -14085,6 +13638,12 @@ rb_gcdebug_remove_stress_to_class(int argc, VALUE *argv, VALUE self)
void
Init_GC(void)
{
+#if USE_SHARED_GC
+ if (getenv(RUBY_GC_LIBRARY_PATH) != NULL && !dln_supported_p()) {
+ rb_warn(RUBY_GC_LIBRARY_PATH " is ignored because this executable file can't load extension libraries");
+ }
+#endif
+
#undef rb_intern
malloc_offset = gc_compute_malloc_offset();
@@ -14098,7 +13657,7 @@ Init_GC(void)
rb_hash_aset(gc_constants, ID2SYM(rb_intern("DEBUG")), RBOOL(GC_DEBUG));
rb_hash_aset(gc_constants, ID2SYM(rb_intern("BASE_SLOT_SIZE")), SIZET2NUM(BASE_SLOT_SIZE - RVALUE_OVERHEAD));
rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVALUE_OVERHEAD")), SIZET2NUM(RVALUE_OVERHEAD));
- rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVALUE_SIZE")), SIZET2NUM(sizeof(RVALUE)));
+ rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVALUE_SIZE")), SIZET2NUM(BASE_SLOT_SIZE));
rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_PAGE_OBJ_LIMIT")), SIZET2NUM(HEAP_PAGE_OBJ_LIMIT));
rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_PAGE_BITMAP_SIZE")), SIZET2NUM(HEAP_PAGE_BITMAP_SIZE));
rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_PAGE_SIZE")), SIZET2NUM(HEAP_PAGE_SIZE));
diff --git a/gc.rb b/gc.rb
index c3b104454c..880aa46475 100644
--- a/gc.rb
+++ b/gc.rb
@@ -26,10 +26,10 @@ module GC
# then marking will always be immediate, regardless of the value of
# +immediate_mark+.
#
- # The +immedate_sweep+ keyword argument determines whether or not to defer
- # sweeping (using lazy sweep). When set to +true+, sweeping is performed in
+ # The +immediate_sweep+ keyword argument determines whether or not to defer
+ # sweeping (using lazy sweep). When set to +false+, sweeping is performed in
# steps that is interleaved with future Ruby code execution, so sweeping might
- # not be completed during this method call. When set to +false+, sweeping is
+ # not be completed during this method call. When set to +true+, sweeping is
# completed during the call to this method.
#
# Note: These keyword arguments are implementation and version dependent. They
@@ -39,6 +39,7 @@ module GC
Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false
end
+ # Alias of GC.start
def garbage_collect full_mark: true, immediate_mark: true, immediate_sweep: true
Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false
end
@@ -322,6 +323,7 @@ module GC
end
module ObjectSpace
+ # Alias of GC.start
def garbage_collect full_mark: true, immediate_mark: true, immediate_sweep: true
Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false
end
diff --git a/gems/bundled_gems b/gems/bundled_gems
index 25d897a884..38ddd97c89 100644
--- a/gems/bundled_gems
+++ b/gems/bundled_gems
@@ -5,19 +5,32 @@
# - repository-url: URL from where clone for test
# - revision: revision in repository-url to test
# if `revision` is not given, "v"+`version` or `version` will be used.
-minitest 5.20.0 https://github.com/minitest/minitest
-power_assert 2.0.3 https://github.com/ruby/power_assert
-rake 13.1.0 https://github.com/ruby/rake
-test-unit 3.6.1 https://github.com/test-unit/test-unit
-rexml 3.2.6 https://github.com/ruby/rexml
+
+minitest 5.23.1 https://github.com/minitest/minitest
+power_assert 2.0.3 https://github.com/ruby/power_assert 84e85124c5014a139af39161d484156cfe87a9ed
+rake 13.2.1 https://github.com/ruby/rake
+test-unit 3.6.2 https://github.com/test-unit/test-unit
+rexml 3.2.8 https://github.com/ruby/rexml
rss 0.3.0 https://github.com/ruby/rss
-net-ftp 0.2.0 https://github.com/ruby/net-ftp
-net-imap 0.4.4 https://github.com/ruby/net-imap
+net-ftp 0.3.5 https://github.com/ruby/net-ftp
+net-imap 0.4.12 https://github.com/ruby/net-imap
net-pop 0.1.2 https://github.com/ruby/net-pop
-net-smtp 0.4.0 https://github.com/ruby/net-smtp
+net-smtp 0.5.0 https://github.com/ruby/net-smtp
matrix 0.4.2 https://github.com/ruby/matrix
prime 0.1.2 https://github.com/ruby/prime
-rbs 3.2.2 https://github.com/ruby/rbs 33813a60752624d58dfe5ae770b39bfaf29fbaf1
-typeprof 0.21.8 https://github.com/ruby/typeprof
-debug 1.8.0 https://github.com/ruby/debug 927587afb6aac69b358b86a01f602d207053e8d2
-racc 1.7.3 https://github.com/ruby/racc
+rbs 3.5.1 https://github.com/ruby/rbs
+typeprof 0.21.11 https://github.com/ruby/typeprof b19a6416da3a05d57fadd6ffdadb382b6d236ca5
+debug 1.9.2 https://github.com/ruby/debug
+racc 1.8.0 https://github.com/ruby/racc
+mutex_m 0.2.0 https://github.com/ruby/mutex_m
+getoptlong 0.2.1 https://github.com/ruby/getoptlong
+base64 0.2.0 https://github.com/ruby/base64
+bigdecimal 3.1.8 https://github.com/ruby/bigdecimal
+observer 0.1.2 https://github.com/ruby/observer
+abbrev 0.1.2 https://github.com/ruby/abbrev
+resolv-replace 0.1.1 https://github.com/ruby/resolv-replace
+rinda 0.2.0 https://github.com/ruby/rinda
+drb 2.2.1 https://github.com/ruby/drb
+nkf 0.2.0 https://github.com/ruby/nkf
+syslog 0.1.2 https://github.com/ruby/syslog
+csv 3.3.0 https://github.com/ruby/csv
diff --git a/gems/lib/envutil.rb b/gems/lib/envutil.rb
new file mode 100644
index 0000000000..d684c22cf2
--- /dev/null
+++ b/gems/lib/envutil.rb
@@ -0,0 +1 @@
+require_relative "../../tool/lib/envutil.rb"
diff --git a/gems/lib/rake/extensiontask.rb b/gems/lib/rake/extensiontask.rb
index aa668935fc..fdbe8d8874 100644
--- a/gems/lib/rake/extensiontask.rb
+++ b/gems/lib/rake/extensiontask.rb
@@ -1,3 +1,5 @@
+require "rake/tasklib" unless defined?(Rake::TaskLib)
+
module Rake
class ExtensionTask < TaskLib
def initialize(...)
diff --git a/hash.c b/hash.c
index e8613339ba..f34f64065b 100644
--- a/hash.c
+++ b/hash.c
@@ -35,6 +35,7 @@
#include "internal/hash.h"
#include "internal/object.h"
#include "internal/proc.h"
+#include "internal/st.h"
#include "internal/symbol.h"
#include "internal/thread.h"
#include "internal/time.h"
@@ -209,10 +210,26 @@ any_hash(VALUE a, st_index_t (*other_func)(VALUE))
return (long)hnum;
}
+VALUE rb_obj_hash(VALUE obj);
+VALUE rb_vm_call0(rb_execution_context_t *ec, VALUE recv, ID id, int argc, const VALUE *argv, const rb_callable_method_entry_t *cme, int kw_splat);
+
static st_index_t
obj_any_hash(VALUE obj)
{
- VALUE hval = rb_check_funcall_basic_kw(obj, id_hash, rb_mKernel, 0, 0, 0);
+ VALUE hval = Qundef;
+ VALUE klass = CLASS_OF(obj);
+ if (klass) {
+ const rb_callable_method_entry_t *cme = rb_callable_method_entry(klass, id_hash);
+ if (cme && METHOD_ENTRY_BASIC(cme)) {
+ // Optimize away the frame push overhead if it's the default Kernel#hash
+ if (cme->def->type == VM_METHOD_TYPE_CFUNC && cme->def->body.cfunc.func == (rb_cfunc_t)rb_obj_hash) {
+ hval = rb_obj_hash(obj);
+ }
+ else if (RBASIC_CLASS(cme->defined_class) == rb_mKernel) {
+ hval = rb_vm_call0(GET_EC(), obj, id_hash, 0, 0, cme, 0);
+ }
+ }
+ }
if (UNDEF_P(hval)) {
hval = rb_exec_recursive_outer_mid(hash_recursive, obj, 0, id_hash);
@@ -377,6 +394,9 @@ const struct st_hash_type rb_hashtype_ident = {
rb_ident_hash,
};
+#define RHASH_IDENTHASH_P(hash) (RHASH_TYPE(hash) == &identhash)
+#define RHASH_STRING_KEY_P(hash, key) (!RHASH_IDENTHASH_P(hash) && (rb_obj_class(key) == rb_cString))
+
typedef st_index_t st_hash_t;
/*
@@ -694,61 +714,75 @@ hash_ar_free_and_clear_table(VALUE hash)
HASH_ASSERT(RHASH_AR_TABLE_BOUND(hash) == 0);
}
-static void
-ar_try_convert_table(VALUE hash)
-{
- if (!RHASH_AR_TABLE_P(hash)) return;
-
- const unsigned size = RHASH_AR_TABLE_SIZE(hash);
-
- if (size < RHASH_AR_TABLE_MAX_SIZE) {
- return;
- }
+void rb_st_add_direct_with_hash(st_table *tab, st_data_t key, st_data_t value, st_hash_t hash); // st.c
- st_table tab;
- st_table *new_tab = &tab;
- rb_st_init_existing_table_with_size(new_tab, &objhash, size * 2);
+enum ar_each_key_type {
+ ar_each_key_copy,
+ ar_each_key_cmp,
+ ar_each_key_insert,
+};
- for (st_index_t i = 0; i < RHASH_AR_TABLE_MAX_BOUND; i++) {
- ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, i);
- st_add_direct(new_tab, pair->key, pair->val);
+static inline int
+ar_each_key(ar_table *ar, int max, enum ar_each_key_type type, st_data_t *dst_keys, st_table *new_tab, st_hash_t *hashes)
+{
+ for (int i = 0; i < max; i++) {
+ ar_table_pair *pair = &ar->pairs[i];
+
+ switch (type) {
+ case ar_each_key_copy:
+ dst_keys[i] = pair->key;
+ break;
+ case ar_each_key_cmp:
+ if (dst_keys[i] != pair->key) return 1;
+ break;
+ case ar_each_key_insert:
+ if (UNDEF_P(pair->key)) continue; // deleted entry
+ rb_st_add_direct_with_hash(new_tab, pair->key, pair->val, hashes[i]);
+ break;
+ }
}
- hash_ar_free_and_clear_table(hash);
- RHASH_ST_TABLE_SET(hash, new_tab);
+ return 0;
}
static st_table *
ar_force_convert_table(VALUE hash, const char *file, int line)
{
- st_table *new_tab;
- st_table tab;
- new_tab = &tab;
-
if (RHASH_ST_TABLE_P(hash)) {
return RHASH_ST_TABLE(hash);
}
+ else {
+ ar_table *ar = RHASH_AR_TABLE(hash);
+ st_hash_t hashes[RHASH_AR_TABLE_MAX_SIZE];
+ unsigned int bound, size;
+
+ // prepare hash values
+ do {
+ st_data_t keys[RHASH_AR_TABLE_MAX_SIZE];
+ bound = RHASH_AR_TABLE_BOUND(hash);
+ size = RHASH_AR_TABLE_SIZE(hash);
+ ar_each_key(ar, bound, ar_each_key_copy, keys, NULL, NULL);
+
+ for (unsigned int i = 0; i < bound; i++) {
+ // do_hash calls #hash method and it can modify hash object
+ hashes[i] = UNDEF_P(keys[i]) ? 0 : ar_do_hash(keys[i]);
+ }
- RUBY_ASSERT(RHASH_AR_TABLE(hash));
- {
- unsigned i, bound = RHASH_AR_TABLE_BOUND(hash);
-
- rb_st_init_existing_table_with_size(new_tab, &objhash, RHASH_AR_TABLE_SIZE(hash));
-
- for (i = 0; i < bound; i++) {
- if (ar_cleared_entry(hash, i)) continue;
-
- ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, i);
- st_add_direct(new_tab, pair->key, pair->val);
- }
+ // check if modified
+ if (UNLIKELY(!RHASH_AR_TABLE_P(hash))) return RHASH_ST_TABLE(hash);
+ if (UNLIKELY(RHASH_AR_TABLE_BOUND(hash) != bound)) continue;
+ if (UNLIKELY(ar_each_key(ar, bound, ar_each_key_cmp, keys, NULL, NULL))) continue;
+ } while (0);
+
+ // make st
+ st_table tab;
+ st_table *new_tab = &tab;
+ st_init_existing_table_with_size(new_tab, &objhash, size);
+ ar_each_key(ar, bound, ar_each_key_insert, NULL, new_tab, hashes);
hash_ar_free_and_clear_table(hash);
+ RHASH_ST_TABLE_SET(hash, new_tab);
+ return RHASH_ST_TABLE(hash);
}
-
- RHASH_ST_TABLE_SET(hash, new_tab);
-
- new_tab = RHASH_ST_TABLE(hash);
-
- return new_tab;
}
static int
@@ -811,6 +845,14 @@ ar_add_direct_with_hash(VALUE hash, st_data_t key, st_data_t val, st_hash_t hash
}
}
+static void
+ensure_ar_table(VALUE hash)
+{
+ if (!RHASH_AR_TABLE_P(hash)) {
+ rb_raise(rb_eRuntimeError, "hash representation was changed during iteration");
+ }
+}
+
static int
ar_general_foreach(VALUE hash, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg)
{
@@ -821,7 +863,10 @@ ar_general_foreach(VALUE hash, st_foreach_check_callback_func *func, st_update_c
if (ar_cleared_entry(hash, i)) continue;
ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, i);
- enum st_retval retval = (*func)(pair->key, pair->val, arg, 0);
+ st_data_t key = (st_data_t)pair->key;
+ st_data_t val = (st_data_t)pair->val;
+ enum st_retval retval = (*func)(key, val, arg, 0);
+ ensure_ar_table(hash);
/* pair may be not valid here because of theap */
switch (retval) {
@@ -832,14 +877,12 @@ ar_general_foreach(VALUE hash, st_foreach_check_callback_func *func, st_update_c
return 0;
case ST_REPLACE:
if (replace) {
- VALUE key = pair->key;
- VALUE val = pair->val;
retval = (*replace)(&key, &val, arg, TRUE);
// TODO: pair should be same as pair before.
- ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, i);
- pair->key = key;
- pair->val = val;
+ pair = RHASH_AR_TABLE_REF(hash, i);
+ pair->key = (VALUE)key;
+ pair->val = (VALUE)val;
}
break;
case ST_DELETE:
@@ -896,6 +939,7 @@ ar_foreach_check(VALUE hash, st_foreach_check_callback_func *func, st_data_t arg
hint = ar_hint(hash, i);
retval = (*func)(key, pair->val, arg, 0);
+ ensure_ar_table(hash);
hash_verify(hash);
switch (retval) {
@@ -956,6 +1000,7 @@ ar_update(VALUE hash, st_data_t key,
old_key = key;
retval = (*func)(&key, &value, arg, existing);
/* pair can be invalid here because of theap */
+ ensure_ar_table(hash);
switch (retval) {
case ST_CONTINUE:
@@ -1166,8 +1211,8 @@ hash_st_free(VALUE hash)
st_table *tab = RHASH_ST_TABLE(hash);
- free(tab->bins);
- free(tab->entries);
+ xfree(tab->bins);
+ xfree(tab->entries);
}
static void
@@ -1505,7 +1550,7 @@ hash_copy(VALUE ret, VALUE hash)
}
else {
st_table *tab = RHASH_ST_TABLE(ret);
- rb_st_init_existing_table_with_size(tab, &objhash, RHASH_AR_TABLE_SIZE(hash));
+ st_init_existing_table_with_size(tab, &objhash, RHASH_AR_TABLE_SIZE(hash));
int bound = RHASH_AR_TABLE_BOUND(hash);
for (int i = 0; i < bound; i++) {
@@ -1532,7 +1577,15 @@ hash_copy(VALUE ret, VALUE hash)
static VALUE
hash_dup_with_compare_by_id(VALUE hash)
{
- return hash_copy(copy_compare_by_id(rb_hash_new(), hash), hash);
+ VALUE dup = hash_alloc_flags(rb_cHash, 0, Qnil, RHASH_ST_TABLE_P(hash));
+ if (RHASH_ST_TABLE_P(hash)) {
+ RHASH_SET_ST_FLAG(dup);
+ }
+ else {
+ RHASH_UNSET_ST_FLAG(dup);
+ }
+
+ return hash_copy(dup, hash);
}
static VALUE
@@ -1566,7 +1619,7 @@ rb_hash_modify_check(VALUE hash)
rb_check_frozen(hash);
}
-RUBY_FUNC_EXPORTED struct st_table *
+struct st_table *
rb_hash_tbl_raw(VALUE hash, const char *file, int line)
{
return ar_force_convert_table(hash, file, line);
@@ -1627,7 +1680,7 @@ rb_hash_stlike_update(VALUE hash, st_data_t key, st_update_callback_func *func,
if (RHASH_AR_TABLE_P(hash)) {
int result = ar_update(hash, key, func, arg);
if (result == -1) {
- ar_try_convert_table(hash);
+ ar_force_convert_table(hash, __FILE__, __LINE__);
}
else {
return result;
@@ -1714,7 +1767,7 @@ set_proc_default(VALUE hash, VALUE proc)
* Hash.new(default_value = nil) -> new_hash
* Hash.new {|hash, key| ... } -> new_hash
*
- * Returns a new empty \Hash object.
+ * Returns a new empty +Hash+ object.
*
* The initial default value and initial default proc for the new hash
* depend on which form above was used. See {Default Values}[rdoc-ref:Hash@Default+Values].
@@ -1773,26 +1826,26 @@ static VALUE rb_hash_to_a(VALUE hash);
* Hash[ [*2_element_arrays] ] -> new_hash
* Hash[*objects] -> new_hash
*
- * Returns a new \Hash object populated with the given objects, if any.
+ * Returns a new +Hash+ object populated with the given objects, if any.
* See Hash::new.
*
- * With no argument, returns a new empty \Hash.
+ * With no argument, returns a new empty +Hash+.
*
- * When the single given argument is a \Hash, returns a new \Hash
- * populated with the entries from the given \Hash, excluding the
+ * When the single given argument is a +Hash+, returns a new +Hash+
+ * populated with the entries from the given +Hash+, excluding the
* default value or proc.
*
* h = {foo: 0, bar: 1, baz: 2}
* Hash[h] # => {:foo=>0, :bar=>1, :baz=>2}
*
* When the single given argument is an Array of 2-element Arrays,
- * returns a new \Hash object wherein each 2-element array forms a
+ * returns a new +Hash+ object wherein each 2-element array forms a
* key-value entry:
*
* Hash[ [ [:foo, 0], [:bar, 1] ] ] # => {:foo=>0, :bar=>1}
*
* When the argument count is an even number;
- * returns a new \Hash object wherein each successive pair of arguments
+ * returns a new +Hash+ object wherein each successive pair of arguments
* has become a key-value entry:
*
* Hash[:foo, 0, :bar, 1] # => {:foo=>0, :bar=>1}
@@ -1880,14 +1933,14 @@ rb_check_hash_type(VALUE hash)
* call-seq:
* Hash.try_convert(obj) -> obj, new_hash, or nil
*
- * If +obj+ is a \Hash object, returns +obj+.
+ * If +obj+ is a +Hash+ object, returns +obj+.
*
* Otherwise if +obj+ responds to <tt>:to_hash</tt>,
* calls <tt>obj.to_hash</tt> and returns the result.
*
* Returns +nil+ if +obj+ does not respond to <tt>:to_hash</tt>
*
- * Raises an exception unless <tt>obj.to_hash</tt> returns a \Hash object.
+ * Raises an exception unless <tt>obj.to_hash</tt> returns a +Hash+ object.
*/
static VALUE
rb_hash_s_try_convert(VALUE dummy, VALUE hash)
@@ -2256,7 +2309,7 @@ rb_hash_default_proc(VALUE hash)
* call-seq:
* hash.default_proc = proc -> proc
*
- * Sets the default proc for +self+ to +proc+:
+ * Sets the default proc for +self+ to +proc+
* (see {Default Values}[rdoc-ref:Hash@Default+Values]):
* h = {}
* h.default_proc # => nil
@@ -2571,7 +2624,7 @@ rb_hash_reject_bang(VALUE hash)
* hash.reject {|key, value| ... } -> new_hash
* hash.reject -> new_enumerator
*
- * Returns a new \Hash object whose entries are all those
+ * Returns a new +Hash+ object whose entries are all those
* from +self+ for which the block returns +false+ or +nil+:
* h = {foo: 0, bar: 1, baz: 2}
* h1 = h.reject {|key, value| key.start_with?('b') }
@@ -2602,7 +2655,7 @@ rb_hash_reject(VALUE hash)
* call-seq:
* hash.slice(*keys) -> new_hash
*
- * Returns a new \Hash object containing the entries for the given +keys+:
+ * Returns a new +Hash+ object containing the entries for the given +keys+:
* h = {foo: 0, bar: 1, baz: 2}
* h.slice(:baz, :foo) # => {:baz=>2, :foo=>0}
*
@@ -2634,7 +2687,7 @@ rb_hash_slice(int argc, VALUE *argv, VALUE hash)
* call-seq:
* hsh.except(*keys) -> a_hash
*
- * Returns a new \Hash excluding entries for the given +keys+:
+ * Returns a new +Hash+ excluding entries for the given +keys+:
* h = { a: 100, b: 200, c: 300 }
* h.except(:a) #=> {:b=>200, :c=>300}
*
@@ -2730,7 +2783,7 @@ keep_if_i(VALUE key, VALUE value, VALUE hash)
* hash.select {|key, value| ... } -> new_hash
* hash.select -> new_enumerator
*
- * Returns a new \Hash object whose entries are those for which the block returns a truthy value:
+ * Returns a new +Hash+ object whose entries are those for which the block returns a truthy value:
* h = {foo: 0, bar: 1, baz: 2}
* h.select {|key, value| value < 2 } # => {:foo=>0, :bar=>1}
*
@@ -2906,7 +2959,7 @@ rb_hash_aset(VALUE hash, VALUE key, VALUE val)
rb_hash_modify(hash);
- if (RHASH_TYPE(hash) == &identhash || rb_obj_class(key) != rb_cString) {
+ if (!RHASH_STRING_KEY_P(hash, key)) {
RHASH_UPDATE_ITER(hash, iter_p, key, hash_aset, val);
}
else {
@@ -2981,7 +3034,7 @@ rb_hash_size_num(VALUE hash)
* {foo: 0, bar: 1, baz: 2}.empty? # => false
*/
-static VALUE
+VALUE
rb_hash_empty_p(VALUE hash)
{
return RBOOL(RHASH_EMPTY_P(hash));
@@ -3155,7 +3208,7 @@ transform_keys_i(VALUE key, VALUE value, VALUE result)
* hash.transform_keys(hash2) {|other_key| ...} -> new_hash
* hash.transform_keys -> new_enumerator
*
- * Returns a new \Hash object; each entry has:
+ * Returns a new +Hash+ object; each entry has:
* * A key provided by the block.
* * The value from +self+.
*
@@ -3295,7 +3348,7 @@ transform_values_foreach_replace(st_data_t *key, st_data_t *value, st_data_t arg
* hash.transform_values {|value| ... } -> new_hash
* hash.transform_values -> new_enumerator
*
- * Returns a new \Hash object; each entry has:
+ * Returns a new +Hash+ object; each entry has:
* * A key from +self+.
* * A value provided by the block.
*
@@ -3485,12 +3538,12 @@ rb_hash_to_h_block(VALUE hash)
* hash.to_h -> self or new_hash
* hash.to_h {|key, value| ... } -> new_hash
*
- * For an instance of \Hash, returns +self+.
+ * For an instance of +Hash+, returns +self+.
*
- * For a subclass of \Hash, returns a new \Hash
+ * For a subclass of +Hash+, returns a new +Hash+
* containing the content of +self+.
*
- * When a block is given, returns a new \Hash object
+ * When a block is given, returns a new +Hash+ object
* whose content is based on the block;
* the block should return a 2-element Array object
* specifying the key-value pair to be included in the returned Array:
@@ -3738,7 +3791,7 @@ hash_equal(VALUE hash1, VALUE hash2, int eql)
* hash == object -> true or false
*
* Returns +true+ if all of the following are true:
- * * +object+ is a \Hash object.
+ * * +object+ is a +Hash+ object.
* * +hash+ and +object+ have the same keys (regardless of order).
* * For each key +key+, <tt>hash[key] == object[key]</tt>.
*
@@ -3760,16 +3813,15 @@ rb_hash_equal(VALUE hash1, VALUE hash2)
/*
* call-seq:
- * hash.eql? object -> true or false
+ * hash.eql?(object) -> true or false
*
* Returns +true+ if all of the following are true:
- * * +object+ is a \Hash object.
+ * * +object+ is a +Hash+ object.
* * +hash+ and +object+ have the same keys (regardless of order).
- * * For each key +key+, <tt>h[key] eql? object[key]</tt>.
+ * * For each key +key+, <tt>h[key].eql?(object[key])</tt>.
*
* Otherwise, returns +false+.
*
- * Equal:
* h1 = {foo: 0, bar: 1, baz: 2}
* h2 = {foo: 0, bar: 1, baz: 2}
* h1.eql? h2 # => true
@@ -3801,7 +3853,7 @@ hash_i(VALUE key, VALUE val, VALUE arg)
*
* Returns the Integer hash-code for the hash.
*
- * Two \Hash objects have the same hash-code if their content is the same
+ * Two +Hash+ objects have the same hash-code if their content is the same
* (regardless of order):
* h1 = {foo: 0, bar: 1, baz: 2}
* h2 = {baz: 2, bar: 1, foo: 0}
@@ -3833,7 +3885,7 @@ rb_hash_invert_i(VALUE key, VALUE value, VALUE hash)
* call-seq:
* hash.invert -> new_hash
*
- * Returns a new \Hash object with the each key-value pair inverted:
+ * Returns a new +Hash+ object with the each key-value pair inverted:
* h = {foo: 0, bar: 1, baz: 2}
* h1 = h.invert
* h1 # => {0=>:foo, 1=>:bar, 2=>:baz}
@@ -3854,18 +3906,9 @@ rb_hash_invert(VALUE hash)
}
static int
-rb_hash_update_callback(st_data_t *key, st_data_t *value, struct update_arg *arg, int existing)
-{
- *value = arg->arg;
- return ST_CONTINUE;
-}
-
-NOINSERT_UPDATE_CALLBACK(rb_hash_update_callback)
-
-static int
rb_hash_update_i(VALUE key, VALUE value, VALUE hash)
{
- RHASH_UPDATE(hash, key, rb_hash_update_callback, value);
+ rb_hash_aset(hash, key, value);
return ST_CONTINUE;
}
@@ -3877,6 +3920,9 @@ rb_hash_update_block_callback(st_data_t *key, st_data_t *value, struct update_ar
if (existing) {
newvalue = (st_data_t)rb_yield_values(3, (VALUE)*key, (VALUE)*value, (VALUE)newvalue);
}
+ else if (RHASH_STRING_KEY_P(arg->hash, *key) && !RB_OBJ_FROZEN(*key)) {
+ *key = rb_hash_key_str(*key);
+ }
*value = newvalue;
return ST_CONTINUE;
}
@@ -3898,7 +3944,7 @@ rb_hash_update_block_i(VALUE key, VALUE value, VALUE hash)
*
* Merges each of +other_hashes+ into +self+; returns +self+.
*
- * Each argument in +other_hashes+ must be a \Hash.
+ * Each argument in +other_hashes+ must be a +Hash+.
*
* With arguments and no block:
* * Returns +self+, after the given hashes are merged into it.
@@ -4012,16 +4058,16 @@ rb_hash_update_by(VALUE hash1, VALUE hash2, rb_hash_update_func *func)
* hash.merge(*other_hashes) -> new_hash
* hash.merge(*other_hashes) { |key, old_value, new_value| ... } -> new_hash
*
- * Returns the new \Hash formed by merging each of +other_hashes+
+ * Returns the new +Hash+ formed by merging each of +other_hashes+
* into a copy of +self+.
*
- * Each argument in +other_hashes+ must be a \Hash.
+ * Each argument in +other_hashes+ must be a +Hash+.
*
* ---
*
* With arguments and no block:
- * * Returns the new \Hash object formed by merging each successive
- * \Hash in +other_hashes+ into +self+.
+ * * Returns the new +Hash+ object formed by merging each successive
+ * +Hash+ in +other_hashes+ into +self+.
* * Each new-key entry is added at the end.
* * Each duplicate-key entry's value overwrites the previous value.
*
@@ -4032,7 +4078,7 @@ rb_hash_update_by(VALUE hash1, VALUE hash2, rb_hash_update_func *func)
* h.merge(h1, h2) # => {:foo=>0, :bar=>4, :baz=>2, :bat=>6, :bam=>5}
*
* With arguments and a block:
- * * Returns a new \Hash object that is the merge of +self+ and each given hash.
+ * * Returns a new +Hash+ object that is the merge of +self+ and each given hash.
* * The given hashes are merged left to right.
* * Each new-key entry is added at the end.
* * For each duplicate key:
@@ -4069,24 +4115,17 @@ assoc_cmp(VALUE a, VALUE b)
return !RTEST(rb_equal(a, b));
}
-static VALUE
-lookup2_call(VALUE arg)
-{
- VALUE *args = (VALUE *)arg;
- return rb_hash_lookup2(args[0], args[1], Qundef);
-}
-
-struct reset_hash_type_arg {
- VALUE hash;
- const struct st_hash_type *orighash;
+struct assoc_arg {
+ st_table *tbl;
+ st_data_t key;
};
static VALUE
-reset_hash_type(VALUE arg)
+assoc_lookup(VALUE arg)
{
- struct reset_hash_type_arg *p = (struct reset_hash_type_arg *)arg;
- HASH_ASSERT(RHASH_ST_TABLE_P(p->hash));
- RHASH_ST_TABLE(p->hash)->type = p->orighash;
+ struct assoc_arg *p = (struct assoc_arg*)arg;
+ st_data_t data;
+ if (st_lookup(p->tbl, p->key, &data)) return (VALUE)data;
return Qundef;
}
@@ -4116,30 +4155,30 @@ assoc_i(VALUE key, VALUE val, VALUE arg)
static VALUE
rb_hash_assoc(VALUE hash, VALUE key)
{
- st_table *table;
- const struct st_hash_type *orighash;
VALUE args[2];
if (RHASH_EMPTY_P(hash)) return Qnil;
- ar_force_convert_table(hash, __FILE__, __LINE__);
- HASH_ASSERT(RHASH_ST_TABLE_P(hash));
- table = RHASH_ST_TABLE(hash);
- orighash = table->type;
-
- if (orighash != &identhash) {
- VALUE value;
- struct reset_hash_type_arg ensure_arg;
- struct st_hash_type assochash;
-
- assochash.compare = assoc_cmp;
- assochash.hash = orighash->hash;
- table->type = &assochash;
- args[0] = hash;
- args[1] = key;
- ensure_arg.hash = hash;
- ensure_arg.orighash = orighash;
- value = rb_ensure(lookup2_call, (VALUE)&args, reset_hash_type, (VALUE)&ensure_arg);
+ if (RHASH_ST_TABLE_P(hash) && !RHASH_IDENTHASH_P(hash)) {
+ VALUE value = Qundef;
+ st_table assoctable = *RHASH_ST_TABLE(hash);
+ assoctable.type = &(struct st_hash_type){
+ .compare = assoc_cmp,
+ .hash = assoctable.type->hash,
+ };
+ VALUE arg = (VALUE)&(struct assoc_arg){
+ .tbl = &assoctable,
+ .key = (st_data_t)key,
+ };
+
+ if (RB_OBJ_FROZEN(hash)) {
+ value = assoc_lookup(arg);
+ }
+ else {
+ hash_iter_lev_inc(hash);
+ value = rb_ensure(assoc_lookup, arg, hash_foreach_ensure, hash);
+ }
+ hash_verify(hash);
if (!UNDEF_P(value)) return rb_assoc_new(key, value);
}
@@ -4356,17 +4395,33 @@ rb_hash_compare_by_id(VALUE hash)
if (rb_hash_compare_by_id_p(hash)) return hash;
rb_hash_modify_check(hash);
- ar_force_convert_table(hash, __FILE__, __LINE__);
- HASH_ASSERT(RHASH_ST_TABLE_P(hash));
+ if (hash_iterating_p(hash)) {
+ rb_raise(rb_eRuntimeError, "compare_by_identity during iteration");
+ }
+
+ if (RHASH_TABLE_EMPTY_P(hash)) {
+ // Fast path: There's nothing to rehash, so we don't need a `tmp` table.
+ // We're most likely an AR table, so this will need an allocation.
+ ar_force_convert_table(hash, __FILE__, __LINE__);
+ HASH_ASSERT(RHASH_ST_TABLE_P(hash));
- tmp = hash_alloc(0);
- hash_st_table_init(tmp, &identhash, RHASH_SIZE(hash));
- identtable = RHASH_ST_TABLE(tmp);
+ RHASH_ST_TABLE(hash)->type = &identhash;
+ }
+ else {
+ // Slow path: Need to rehash the members of `self` into a new
+ // `tmp` table using the new `identhash` compare/hash functions.
+ tmp = hash_alloc(0);
+ hash_st_table_init(tmp, &identhash, RHASH_SIZE(hash));
+ identtable = RHASH_ST_TABLE(tmp);
- rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tmp);
+ rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tmp);
+ rb_hash_free(hash);
- RHASH_ST_TABLE_SET(hash, identtable);
- RHASH_ST_CLEAR(tmp);
+ // We know for sure `identtable` is an st table,
+ // so we can skip `ar_force_convert_table` here.
+ RHASH_ST_TABLE_SET(hash, identtable);
+ RHASH_ST_CLEAR(tmp);
+ }
return hash;
}
@@ -4381,7 +4436,7 @@ rb_hash_compare_by_id(VALUE hash)
VALUE
rb_hash_compare_by_id_p(VALUE hash)
{
- return RBOOL(RHASH_ST_TABLE_P(hash) && RHASH_ST_TABLE(hash)->type == &identhash);
+ return RBOOL(RHASH_IDENTHASH_P(hash));
}
VALUE
@@ -4662,6 +4717,7 @@ rb_hash_to_proc(VALUE hash)
return rb_func_lambda_new(hash_proc_call, hash, 1, 1);
}
+/* :nodoc: */
static VALUE
rb_hash_deconstruct_keys(VALUE hash, VALUE keys)
{
@@ -4696,8 +4752,9 @@ rb_hash_add_new_element(VALUE hash, VALUE key, VALUE val)
if (ret != -1) {
return ret;
}
- ar_try_convert_table(hash);
+ ar_force_convert_table(hash, __FILE__, __LINE__);
}
+
tbl = RHASH_TBL_RAW(hash);
return st_update(tbl, (st_data_t)key, add_new_i, (st_data_t)args);
@@ -4854,7 +4911,7 @@ static inline const char *
env_name(volatile VALUE *s)
{
const char *name;
- SafeStringValue(*s);
+ StringValue(*s);
get_env_ptr(name, *s);
return name;
}
@@ -5331,8 +5388,8 @@ env_aset(VALUE nm, VALUE val)
env_delete(nm);
return Qnil;
}
- SafeStringValue(nm);
- SafeStringValue(val);
+ StringValue(nm);
+ StringValue(val);
/* nm can be modified in `val.to_str`, don't get `name` before
* check for `val` */
get_env_ptr(name, nm);
@@ -6195,7 +6252,7 @@ env_rassoc(VALUE dmy, VALUE obj)
static VALUE
env_key(VALUE dmy, VALUE value)
{
- SafeStringValue(value);
+ StringValue(value);
VALUE str = Qnil;
ENV_LOCK();
@@ -6602,20 +6659,20 @@ static const rb_data_type_t env_data_type = {
};
/*
- * A \Hash maps each of its unique keys to a specific value.
+ * A +Hash+ maps each of its unique keys to a specific value.
*
- * A \Hash has certain similarities to an Array, but:
+ * A +Hash+ has certain similarities to an Array, but:
* - An Array index is always an Integer.
- * - A \Hash key can be (almost) any object.
+ * - A +Hash+ key can be (almost) any object.
*
- * === \Hash \Data Syntax
+ * === +Hash+ \Data Syntax
*
- * The older syntax for \Hash data uses the "hash rocket," <tt>=></tt>:
+ * The older syntax for +Hash+ data uses the "hash rocket," <tt>=></tt>:
*
* h = {:foo => 0, :bar => 1, :baz => 2}
* h # => {:foo=>0, :bar=>1, :baz=>2}
*
- * Alternatively, but only for a \Hash key that's a Symbol,
+ * Alternatively, but only for a +Hash+ key that's a Symbol,
* you can use a newer JSON-style syntax,
* where each bareword becomes a Symbol:
*
@@ -6638,7 +6695,7 @@ static const rb_data_type_t env_data_type = {
* # Raises SyntaxError (syntax error, unexpected ':', expecting =>):
* h = {0: 'zero'}
*
- * Hash value can be omitted, meaning that value will be fetched from the context
+ * +Hash+ value can be omitted, meaning that value will be fetched from the context
* by the name of the key:
*
* x = 0
@@ -6648,24 +6705,24 @@ static const rb_data_type_t env_data_type = {
*
* === Common Uses
*
- * You can use a \Hash to give names to objects:
+ * You can use a +Hash+ to give names to objects:
*
* person = {name: 'Matz', language: 'Ruby'}
* person # => {:name=>"Matz", :language=>"Ruby"}
*
- * You can use a \Hash to give names to method arguments:
+ * You can use a +Hash+ to give names to method arguments:
*
* def some_method(hash)
* p hash
* end
* some_method({foo: 0, bar: 1, baz: 2}) # => {:foo=>0, :bar=>1, :baz=>2}
*
- * Note: when the last argument in a method call is a \Hash,
+ * Note: when the last argument in a method call is a +Hash+,
* the curly braces may be omitted:
*
* some_method(foo: 0, bar: 1, baz: 2) # => {:foo=>0, :bar=>1, :baz=>2}
*
- * You can use a \Hash to initialize an object:
+ * You can use a +Hash+ to initialize an object:
*
* class Dev
* attr_accessor :name, :language
@@ -6677,9 +6734,9 @@ static const rb_data_type_t env_data_type = {
* matz = Dev.new(name: 'Matz', language: 'Ruby')
* matz # => #<Dev: @name="Matz", @language="Ruby">
*
- * === Creating a \Hash
+ * === Creating a +Hash+
*
- * You can create a \Hash object explicitly with:
+ * You can create a +Hash+ object explicitly with:
*
* - A {hash literal}[rdoc-ref:syntax/literals.rdoc@Hash+Literals].
*
@@ -6687,47 +6744,47 @@ static const rb_data_type_t env_data_type = {
*
* - \Method #Hash.
*
- * You can create a \Hash by calling method Hash.new.
+ * You can create a +Hash+ by calling method Hash.new.
*
- * Create an empty Hash:
+ * Create an empty +Hash+:
*
* h = Hash.new
* h # => {}
* h.class # => Hash
*
- * You can create a \Hash by calling method Hash.[].
+ * You can create a +Hash+ by calling method Hash.[].
*
- * Create an empty Hash:
+ * Create an empty +Hash+:
*
* h = Hash[]
* h # => {}
*
- * Create a \Hash with initial entries:
+ * Create a +Hash+ with initial entries:
*
* h = Hash[foo: 0, bar: 1, baz: 2]
* h # => {:foo=>0, :bar=>1, :baz=>2}
*
- * You can create a \Hash by using its literal form (curly braces).
+ * You can create a +Hash+ by using its literal form (curly braces).
*
- * Create an empty \Hash:
+ * Create an empty +Hash+:
*
* h = {}
* h # => {}
*
- * Create a \Hash with initial entries:
+ * Create a +Hash+ with initial entries:
*
* h = {foo: 0, bar: 1, baz: 2}
* h # => {:foo=>0, :bar=>1, :baz=>2}
*
*
- * === \Hash Value Basics
+ * === +Hash+ Value Basics
*
- * The simplest way to retrieve a \Hash value (instance method #[]):
+ * The simplest way to retrieve a +Hash+ value (instance method #[]):
*
* h = {foo: 0, bar: 1, baz: 2}
* h[:foo] # => 0
*
- * The simplest way to create or update a \Hash value (instance method #[]=):
+ * The simplest way to create or update a +Hash+ value (instance method #[]=):
*
* h = {foo: 0, bar: 1, baz: 2}
* h[:bat] = 3 # => 3
@@ -6735,7 +6792,7 @@ static const rb_data_type_t env_data_type = {
* h[:foo] = 4 # => 4
* h # => {:foo=>4, :bar=>1, :baz=>2, :bat=>3}
*
- * The simplest way to delete a \Hash entry (instance method #delete):
+ * The simplest way to delete a +Hash+ entry (instance method #delete):
*
* h = {foo: 0, bar: 1, baz: 2}
* h.delete(:bar) # => 1
@@ -6743,13 +6800,13 @@ static const rb_data_type_t env_data_type = {
*
* === Entry Order
*
- * A \Hash object presents its entries in the order of their creation. This is seen in:
+ * A +Hash+ object presents its entries in the order of their creation. This is seen in:
*
* - Iterative methods such as <tt>each</tt>, <tt>each_key</tt>, <tt>each_pair</tt>, <tt>each_value</tt>.
* - Other order-sensitive methods such as <tt>shift</tt>, <tt>keys</tt>, <tt>values</tt>.
* - The String returned by method <tt>inspect</tt>.
*
- * A new \Hash has its initial ordering per the given entries:
+ * A new +Hash+ has its initial ordering per the given entries:
*
* h = Hash[foo: 0, bar: 1]
* h # => {:foo=>0, :bar=>1}
@@ -6770,18 +6827,18 @@ static const rb_data_type_t env_data_type = {
* h[:foo] = 5
* h # => {:bar=>1, :baz=>3, :foo=>5}
*
- * === \Hash Keys
+ * === +Hash+ Keys
*
- * ==== \Hash Key Equivalence
+ * ==== +Hash+ Key Equivalence
*
* Two objects are treated as the same \hash key when their <code>hash</code> value
* is identical and the two objects are <code>eql?</code> to each other.
*
- * ==== Modifying an Active \Hash Key
+ * ==== Modifying an Active +Hash+ Key
*
- * Modifying a \Hash key while it is in use damages the hash's index.
+ * Modifying a +Hash+ key while it is in use damages the hash's index.
*
- * This \Hash has keys that are Arrays:
+ * This +Hash+ has keys that are Arrays:
*
* a0 = [ :foo, :bar ]
* a1 = [ :baz, :bat ]
@@ -6795,7 +6852,7 @@ static const rb_data_type_t env_data_type = {
* a0[0] = :bam
* a0.hash # => 1069447059
*
- * And damages the \Hash index:
+ * And damages the +Hash+ index:
*
* h.include?(a0) # => false
* h[a0] # => nil
@@ -6816,10 +6873,10 @@ static const rb_data_type_t env_data_type = {
* first_key = h.keys.first
* first_key.frozen? # => true
*
- * ==== User-Defined \Hash Keys
+ * ==== User-Defined +Hash+ Keys
*
- * To be useable as a \Hash key, objects must implement the methods <code>hash</code> and <code>eql?</code>.
- * Note: this requirement does not apply if the \Hash uses #compare_by_identity since comparison will then
+ * To be useable as a +Hash+ key, objects must implement the methods <code>hash</code> and <code>eql?</code>.
+ * Note: this requirement does not apply if the +Hash+ uses #compare_by_identity since comparison will then
* rely on the keys' object id instead of <code>hash</code> and <code>eql?</code>.
*
* Object defines basic implementation for <code>hash</code> and <code>eq?</code> that makes each object
@@ -6907,7 +6964,7 @@ static const rb_data_type_t env_data_type = {
*
* ==== Default Proc
*
- * When the default proc for a \Hash is set (i.e., not +nil+),
+ * When the default proc for a +Hash+ is set (i.e., not +nil+),
* the default value returned by method #[] is determined by the default proc alone.
*
* You can retrieve the default proc with method #default_proc:
@@ -6925,7 +6982,7 @@ static const rb_data_type_t env_data_type = {
*
* When the default proc is set (i.e., not +nil+)
* and method #[] is called with with a non-existent key,
- * #[] calls the default proc with both the \Hash object itself and the missing key,
+ * #[] calls the default proc with both the +Hash+ object itself and the missing key,
* then returns the proc's return value:
*
* h = Hash.new { |hash, key| "Default value for #{key}" }
@@ -6951,13 +7008,13 @@ static const rb_data_type_t env_data_type = {
*
* === What's Here
*
- * First, what's elsewhere. \Class \Hash:
+ * First, what's elsewhere. \Class +Hash+:
*
* - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
* - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
* which provides dozens of additional methods.
*
- * Here, class \Hash provides methods that are useful for:
+ * Here, class +Hash+ provides methods that are useful for:
*
* - {Creating a Hash}[rdoc-ref:Hash@Methods+for+Creating+a+Hash]
* - {Setting Hash State}[rdoc-ref:Hash@Methods+for+Setting+Hash+State]
@@ -6971,15 +7028,15 @@ static const rb_data_type_t env_data_type = {
* - {Transforming Keys and Values}[rdoc-ref:Hash@Methods+for+Transforming+Keys+and+Values]
* - {And more....}[rdoc-ref:Hash@Other+Methods]
*
- * \Class \Hash also includes methods from module Enumerable.
+ * \Class +Hash+ also includes methods from module Enumerable.
*
- * ==== Methods for Creating a \Hash
+ * ==== Methods for Creating a +Hash+
*
* - ::[]: Returns a new hash populated with given objects.
* - ::new: Returns a new empty hash.
* - ::try_convert: Returns a new hash created from a given object.
*
- * ==== Methods for Setting \Hash State
+ * ==== Methods for Setting +Hash+ State
*
* - #compare_by_identity: Sets +self+ to consider only identity in comparing keys.
* - #default=: Sets the default to a given value.
@@ -7061,8 +7118,8 @@ static const rb_data_type_t env_data_type = {
* - #inspect, #to_s: Returns a new String containing the hash entries.
* - #to_a: Returns a new array of 2-element arrays;
* each nested array contains a key-value pair from +self+.
- * - #to_h: Returns +self+ if a \Hash;
- * if a subclass of \Hash, returns a \Hash containing the entries from +self+.
+ * - #to_h: Returns +self+ if a +Hash+;
+ * if a subclass of +Hash+, returns a +Hash+ containing the entries from +self+.
* - #to_hash: Returns +self+.
* - #to_proc: Returns a proc that maps a given key to its value.
*
@@ -7184,15 +7241,15 @@ Init_Hash(void)
/* Document-class: ENV
*
- * \ENV is a hash-like accessor for environment variables.
+ * +ENV+ is a hash-like accessor for environment variables.
*
* === Interaction with the Operating System
*
- * The \ENV object interacts with the operating system's environment variables:
+ * The +ENV+ object interacts with the operating system's environment variables:
*
- * - When you get the value for a name in \ENV, the value is retrieved from among the current environment variables.
- * - When you create or set a name-value pair in \ENV, the name and value are immediately set in the environment variables.
- * - When you delete a name-value pair in \ENV, it is immediately deleted from the environment variables.
+ * - When you get the value for a name in +ENV+, the value is retrieved from among the current environment variables.
+ * - When you create or set a name-value pair in +ENV+, the name and value are immediately set in the environment variables.
+ * - When you delete a name-value pair in +ENV+, it is immediately deleted from the environment variables.
*
* === Names and Values
*
@@ -7242,33 +7299,33 @@ Init_Hash(void)
*
* === About Ordering
*
- * \ENV enumerates its name/value pairs in the order found
+ * +ENV+ enumerates its name/value pairs in the order found
* in the operating system's environment variables.
- * Therefore the ordering of \ENV content is OS-dependent, and may be indeterminate.
+ * Therefore the ordering of +ENV+ content is OS-dependent, and may be indeterminate.
*
* This will be seen in:
- * - A Hash returned by an \ENV method.
- * - An Enumerator returned by an \ENV method.
+ * - A Hash returned by an +ENV+ method.
+ * - An Enumerator returned by an +ENV+ method.
* - An Array returned by ENV.keys, ENV.values, or ENV.to_a.
* - The String returned by ENV.inspect.
* - The Array returned by ENV.shift.
* - The name returned by ENV.key.
*
* === About the Examples
- * Some methods in \ENV return \ENV itself. Typically, there are many environment variables.
- * It's not useful to display a large \ENV in the examples here,
- * so most example snippets begin by resetting the contents of \ENV:
- * - ENV.replace replaces \ENV with a new collection of entries.
- * - ENV.clear empties \ENV.
+ * Some methods in +ENV+ return +ENV+ itself. Typically, there are many environment variables.
+ * It's not useful to display a large +ENV+ in the examples here,
+ * so most example snippets begin by resetting the contents of +ENV+:
+ * - ENV.replace replaces +ENV+ with a new collection of entries.
+ * - ENV.clear empties +ENV+.
*
- * == What's Here
+ * === What's Here
*
- * First, what's elsewhere. \Class \ENV:
+ * First, what's elsewhere. \Class +ENV+:
*
* - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
* - Extends {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
*
- * Here, class \ENV provides methods that are useful for:
+ * Here, class +ENV+ provides methods that are useful for:
*
* - {Querying}[rdoc-ref:ENV@Methods+for+Querying]
* - {Assigning}[rdoc-ref:ENV@Methods+for+Assigning]
@@ -7277,26 +7334,26 @@ Init_Hash(void)
* - {Converting}[rdoc-ref:ENV@Methods+for+Converting]
* - {And more ....}[rdoc-ref:ENV@More+Methods]
*
- * === Methods for Querying
+ * ==== Methods for Querying
*
* - ::[]: Returns the value for the given environment variable name if it exists:
- * - ::empty?: Returns whether \ENV is empty.
- * - ::has_value?, ::value?: Returns whether the given value is in \ENV.
+ * - ::empty?: Returns whether +ENV+ is empty.
+ * - ::has_value?, ::value?: Returns whether the given value is in +ENV+.
* - ::include?, ::has_key?, ::key?, ::member?: Returns whether the given name
- is in \ENV.
+ is in +ENV+.
* - ::key: Returns the name of the first entry with the given value.
* - ::size, ::length: Returns the number of entries.
* - ::value?: Returns whether any entry has the given value.
*
- * === Methods for Assigning
+ * ==== Methods for Assigning
*
* - ::[]=, ::store: Creates, updates, or deletes the named environment variable.
- * - ::clear: Removes every environment variable; returns \ENV:
- * - ::update, ::merge!: Adds to \ENV each key/value pair in the given hash.
- * - ::replace: Replaces the entire content of the \ENV
+ * - ::clear: Removes every environment variable; returns +ENV+:
+ * - ::update, ::merge!: Adds to +ENV+ each key/value pair in the given hash.
+ * - ::replace: Replaces the entire content of the +ENV+
* with the name/value pairs in the given hash.
*
- * === Methods for Deleting
+ * ==== Methods for Deleting
*
* - ::delete: Deletes the named environment variable name if it exists.
* - ::delete_if: Deletes entries selected by the block.
@@ -7305,22 +7362,22 @@ Init_Hash(void)
* - ::select!, ::filter!: Deletes entries selected by the block.
* - ::shift: Removes and returns the first entry.
*
- * === Methods for Iterating
+ * ==== Methods for Iterating
*
* - ::each, ::each_pair: Calls the block with each name/value pair.
* - ::each_key: Calls the block with each name.
* - ::each_value: Calls the block with each value.
*
- * === Methods for Converting
+ * ==== Methods for Converting
*
* - ::assoc: Returns a 2-element array containing the name and value
* of the named environment variable if it exists:
- * - ::clone: Returns \ENV (and issues a warning).
+ * - ::clone: Returns +ENV+ (and issues a warning).
* - ::except: Returns a hash of all name/value pairs except those given.
* - ::fetch: Returns the value for the given name.
- * - ::inspect: Returns the contents of \ENV as a string.
- * - ::invert: Returns a hash whose keys are the \ENV values,
- and whose values are the corresponding \ENV names.
+ * - ::inspect: Returns the contents of +ENV+ as a string.
+ * - ::invert: Returns a hash whose keys are the +ENV+ values,
+ and whose values are the corresponding +ENV+ names.
* - ::keys: Returns an array of all names.
* - ::rassoc: Returns the name and value of the first found entry
* that has the given value.
@@ -7334,11 +7391,11 @@ Init_Hash(void)
* - ::values: Returns all values as an array.
* - ::values_at: Returns an array of the values for the given name.
*
- * === More Methods
+ * ==== More Methods
*
* - ::dup: Raises an exception.
* - ::freeze: Raises an exception.
- * - ::rehash: Returns +nil+, without modifying \ENV.
+ * - ::rehash: Returns +nil+, without modifying +ENV+.
*
*/
@@ -7409,7 +7466,7 @@ Init_Hash(void)
rb_undef_method(envtbl_class, "initialize_dup");
/*
- * \ENV is a Hash-like accessor for environment variables.
+ * +ENV+ is a Hash-like accessor for environment variables.
*
* See ENV (the class) for more details.
*/
diff --git a/hrtime.h b/hrtime.h
index 7ed4e6b04c..2ca7b0c088 100644
--- a/hrtime.h
+++ b/hrtime.h
@@ -6,6 +6,8 @@
# include <sys/time.h>
#endif
+#include "internal/compilers.h"
+
/*
* Hi-res monotonic clock. It is currently nsec resolution, which has over
* 500 years of range (with an unsigned 64-bit integer). Developers
@@ -61,7 +63,11 @@ rb_hrtime_mul(rb_hrtime_t a, rb_hrtime_t b)
{
rb_hrtime_t c;
-#ifdef HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW
+#ifdef ckd_mul
+ if (ckd_mul(&c, a, b))
+ return RB_HRTIME_MAX;
+
+#elif __has_builtin(__builtin_mul_overflow)
if (__builtin_mul_overflow(a, b, &c))
return RB_HRTIME_MAX;
#else
@@ -81,7 +87,11 @@ rb_hrtime_add(rb_hrtime_t a, rb_hrtime_t b)
{
rb_hrtime_t c;
-#ifdef HAVE_BUILTIN___BUILTIN_ADD_OVERFLOW
+#ifdef ckd_add
+ if (ckd_add(&c, a, b))
+ return RB_HRTIME_MAX;
+
+#elif __has_builtin(__builtin_add_overflow)
if (__builtin_add_overflow(a, b, &c))
return RB_HRTIME_MAX;
#else
diff --git a/id_table.c b/id_table.c
index 650721c670..6bb067d09a 100644
--- a/id_table.c
+++ b/id_table.c
@@ -150,7 +150,7 @@ hash_table_raw_insert(struct rb_id_table *tbl, id_key_t key, VALUE val)
int mask = tbl->capa - 1;
int ix = key & mask;
int d = 1;
- assert(key != 0);
+ RUBY_ASSERT(key != 0);
while (ITEM_KEY_ISSET(tbl, ix)) {
ITEM_SET_COLLIDED(tbl, ix);
ix = (ix + d) & mask;
@@ -276,7 +276,7 @@ rb_id_table_foreach(struct rb_id_table *tbl, rb_id_table_foreach_func_t *func, v
if (ITEM_KEY_ISSET(tbl, i)) {
const id_key_t key = ITEM_GET_KEY(tbl, i);
enum rb_id_table_iterator_result ret = (*func)(key2id(key), tbl->items[i].val, data);
- assert(key != 0);
+ RUBY_ASSERT(key != 0);
if (ret == ID_TABLE_DELETE)
hash_delete_index(tbl, i);
diff --git a/imemo.c b/imemo.c
new file mode 100644
index 0000000000..23a9a7531f
--- /dev/null
+++ b/imemo.c
@@ -0,0 +1,590 @@
+
+#include "constant.h"
+#include "id_table.h"
+#include "internal.h"
+#include "internal/imemo.h"
+#include "vm_callinfo.h"
+
+size_t rb_iseq_memsize(const rb_iseq_t *iseq);
+void rb_iseq_mark_and_move(rb_iseq_t *iseq, bool reference_updating);
+void rb_iseq_free(const rb_iseq_t *iseq);
+
+const char *
+rb_imemo_name(enum imemo_type type)
+{
+ // put no default case to get a warning if an imemo type is missing
+ switch (type) {
+#define IMEMO_NAME(x) case imemo_##x: return #x;
+ IMEMO_NAME(ast);
+ IMEMO_NAME(callcache);
+ IMEMO_NAME(callinfo);
+ IMEMO_NAME(constcache);
+ IMEMO_NAME(cref);
+ IMEMO_NAME(env);
+ IMEMO_NAME(ifunc);
+ IMEMO_NAME(iseq);
+ IMEMO_NAME(memo);
+ IMEMO_NAME(ment);
+ IMEMO_NAME(parser_strterm);
+ IMEMO_NAME(svar);
+ IMEMO_NAME(throw_data);
+ IMEMO_NAME(tmpbuf);
+#undef IMEMO_NAME
+ default:
+ rb_bug("unreachable");
+ }
+}
+
+/* =========================================================================
+ * allocation
+ * ========================================================================= */
+
+VALUE
+rb_imemo_new(enum imemo_type type, VALUE v0)
+{
+ size_t size = RVALUE_SIZE;
+ VALUE flags = T_IMEMO | FL_WB_PROTECTED | (type << FL_USHIFT);
+ NEWOBJ_OF(obj, void, v0, flags, size, 0);
+
+ return (VALUE)obj;
+}
+
+static rb_imemo_tmpbuf_t *
+rb_imemo_tmpbuf_new(void)
+{
+ size_t size = sizeof(struct rb_imemo_tmpbuf_struct);
+ VALUE flags = T_IMEMO | (imemo_tmpbuf << FL_USHIFT);
+ NEWOBJ_OF(obj, struct rb_imemo_tmpbuf_struct, 0, flags, size, 0);
+
+ return obj;
+}
+
+void *
+rb_alloc_tmp_buffer_with_count(volatile VALUE *store, size_t size, size_t cnt)
+{
+ void *ptr;
+ rb_imemo_tmpbuf_t *tmpbuf;
+
+ /* Keep the order; allocate an empty imemo first then xmalloc, to
+ * get rid of potential memory leak */
+ tmpbuf = rb_imemo_tmpbuf_new();
+ *store = (VALUE)tmpbuf;
+ ptr = ruby_xmalloc(size);
+ tmpbuf->ptr = ptr;
+ tmpbuf->cnt = cnt;
+
+ return ptr;
+}
+
+void *
+rb_alloc_tmp_buffer(volatile VALUE *store, long len)
+{
+ long cnt;
+
+ if (len < 0 || (cnt = (long)roomof(len, sizeof(VALUE))) < 0) {
+ rb_raise(rb_eArgError, "negative buffer size (or size too big)");
+ }
+
+ return rb_alloc_tmp_buffer_with_count(store, len, cnt);
+}
+
+void
+rb_free_tmp_buffer(volatile VALUE *store)
+{
+ rb_imemo_tmpbuf_t *s = (rb_imemo_tmpbuf_t*)ATOMIC_VALUE_EXCHANGE(*store, 0);
+ if (s) {
+ void *ptr = ATOMIC_PTR_EXCHANGE(s->ptr, 0);
+ s->cnt = 0;
+ ruby_xfree(ptr);
+ }
+}
+
+rb_imemo_tmpbuf_t *
+rb_imemo_tmpbuf_parser_heap(void *buf, rb_imemo_tmpbuf_t *old_heap, size_t cnt)
+{
+ rb_imemo_tmpbuf_t *tmpbuf = rb_imemo_tmpbuf_new();
+ tmpbuf->ptr = buf;
+ tmpbuf->next = old_heap;
+ tmpbuf->cnt = cnt;
+
+ return tmpbuf;
+}
+
+#if IMEMO_DEBUG
+VALUE
+rb_imemo_new_debug(enum imemo_type type, VALUE v0, const char *file, int line)
+{
+ VALUE memo = rb_imemo_new(type, v0);
+ fprintf(stderr, "memo %p (type: %d) @ %s:%d\n", (void *)memo, imemo_type(memo), file, line);
+ return memo;
+}
+#endif
+
+/* =========================================================================
+ * memsize
+ * ========================================================================= */
+
+size_t
+rb_imemo_memsize(VALUE obj)
+{
+ size_t size = 0;
+ switch (imemo_type(obj)) {
+ case imemo_ast:
+ rb_bug("imemo_ast is obsolete");
+
+ break;
+ case imemo_callcache:
+ break;
+ case imemo_callinfo:
+ break;
+ case imemo_constcache:
+ break;
+ case imemo_cref:
+ break;
+ case imemo_env:
+ size += ((rb_env_t *)obj)->env_size * sizeof(VALUE);
+
+ break;
+ case imemo_ifunc:
+ break;
+ case imemo_iseq:
+ size += rb_iseq_memsize((rb_iseq_t *)obj);
+
+ break;
+ case imemo_memo:
+ break;
+ case imemo_ment:
+ size += sizeof(((rb_method_entry_t *)obj)->def);
+
+ break;
+ case imemo_parser_strterm:
+ break;
+ case imemo_svar:
+ break;
+ case imemo_throw_data:
+ break;
+ case imemo_tmpbuf:
+ size += ((rb_imemo_tmpbuf_t *)obj)->cnt * sizeof(VALUE);
+
+ break;
+ default:
+ rb_bug("unreachable");
+ }
+
+ return size;
+}
+
+/* =========================================================================
+ * mark
+ * ========================================================================= */
+
+static enum rb_id_table_iterator_result
+cc_table_mark_i(ID id, VALUE ccs_ptr, void *data)
+{
+ struct rb_class_cc_entries *ccs = (struct rb_class_cc_entries *)ccs_ptr;
+ VM_ASSERT(vm_ccs_p(ccs));
+ VM_ASSERT(id == ccs->cme->called_id);
+
+ if (METHOD_ENTRY_INVALIDATED(ccs->cme)) {
+ rb_vm_ccs_free(ccs);
+ return ID_TABLE_DELETE;
+ }
+ else {
+ rb_gc_mark_movable((VALUE)ccs->cme);
+
+ for (int i=0; i<ccs->len; i++) {
+ VM_ASSERT((VALUE)data == ccs->entries[i].cc->klass);
+ VM_ASSERT(vm_cc_check_cme(ccs->entries[i].cc, ccs->cme));
+
+ rb_gc_mark_movable((VALUE)ccs->entries[i].cc);
+ }
+ return ID_TABLE_CONTINUE;
+ }
+}
+
+void
+rb_cc_table_mark(VALUE klass)
+{
+ struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass);
+ if (cc_tbl) {
+ rb_id_table_foreach(cc_tbl, cc_table_mark_i, (void *)klass);
+ }
+}
+
+static bool
+moved_or_living_object_strictly_p(VALUE obj)
+{
+ return obj && (rb_objspace_markable_object_p(obj) || BUILTIN_TYPE(obj) == T_MOVED);
+}
+
+static void
+mark_and_move_method_entry(rb_method_entry_t *ment, bool reference_updating)
+{
+ rb_method_definition_t *def = ment->def;
+
+ rb_gc_mark_and_move(&ment->owner);
+ rb_gc_mark_and_move(&ment->defined_class);
+
+ if (def) {
+ switch (def->type) {
+ case VM_METHOD_TYPE_ISEQ:
+ if (def->body.iseq.iseqptr) {
+ rb_gc_mark_and_move_ptr(&def->body.iseq.iseqptr);
+ }
+ rb_gc_mark_and_move_ptr(&def->body.iseq.cref);
+
+ if (!reference_updating) {
+ if (def->iseq_overload && ment->defined_class) {
+ // it can be a key of "overloaded_cme" table
+ // so it should be pinned.
+ rb_gc_mark((VALUE)ment);
+ }
+ }
+ break;
+ case VM_METHOD_TYPE_ATTRSET:
+ case VM_METHOD_TYPE_IVAR:
+ rb_gc_mark_and_move(&def->body.attr.location);
+ break;
+ case VM_METHOD_TYPE_BMETHOD:
+ rb_gc_mark_and_move(&def->body.bmethod.proc);
+ if (!reference_updating) {
+ if (def->body.bmethod.hooks) rb_hook_list_mark(def->body.bmethod.hooks);
+ }
+ break;
+ case VM_METHOD_TYPE_ALIAS:
+ rb_gc_mark_and_move_ptr(&def->body.alias.original_me);
+ return;
+ case VM_METHOD_TYPE_REFINED:
+ rb_gc_mark_and_move_ptr(&def->body.refined.orig_me);
+ break;
+ case VM_METHOD_TYPE_CFUNC:
+ case VM_METHOD_TYPE_ZSUPER:
+ case VM_METHOD_TYPE_MISSING:
+ case VM_METHOD_TYPE_OPTIMIZED:
+ case VM_METHOD_TYPE_UNDEF:
+ case VM_METHOD_TYPE_NOTIMPLEMENTED:
+ break;
+ }
+ }
+}
+
+void
+rb_imemo_mark_and_move(VALUE obj, bool reference_updating)
+{
+ switch (imemo_type(obj)) {
+ case imemo_ast:
+ rb_bug("imemo_ast is obsolete");
+
+ break;
+ case imemo_callcache: {
+ /* cc is callcache.
+ *
+ * cc->klass (klass) should not be marked because if the klass is
+ * free'ed, the cc->klass will be cleared by `vm_cc_invalidate()`.
+ *
+ * cc->cme (cme) should not be marked because if cc is invalidated
+ * when cme is free'ed.
+ * - klass marks cme if klass uses cme.
+ * - caller classe's ccs->cme marks cc->cme.
+ * - if cc is invalidated (klass doesn't refer the cc),
+ * cc is invalidated by `vm_cc_invalidate()` and cc->cme is
+ * not be accessed.
+ * - On the multi-Ractors, cme will be collected with global GC
+ * so that it is safe if GC is not interleaving while accessing
+ * cc and cme.
+ * - However, cc_type_super and cc_type_refinement are not chained
+ * from ccs so cc->cme should be marked; the cme might be
+ * reachable only through cc in these cases.
+ */
+ struct rb_callcache *cc = (struct rb_callcache *)obj;
+ if (reference_updating) {
+ if (!cc->klass) {
+ // already invalidated
+ }
+ else {
+ if (moved_or_living_object_strictly_p(cc->klass) &&
+ moved_or_living_object_strictly_p((VALUE)cc->cme_)) {
+ *((VALUE *)&cc->klass) = rb_gc_location(cc->klass);
+ *((struct rb_callable_method_entry_struct **)&cc->cme_) =
+ (struct rb_callable_method_entry_struct *)rb_gc_location((VALUE)cc->cme_);
+ }
+ else {
+ vm_cc_invalidate(cc);
+ }
+ }
+ }
+ else {
+ if (vm_cc_super_p(cc) || vm_cc_refinement_p(cc)) {
+ rb_gc_mark_movable((VALUE)cc->cme_);
+ }
+ }
+
+ break;
+ }
+ case imemo_callinfo:
+ break;
+ case imemo_constcache: {
+ struct iseq_inline_constant_cache_entry *ice = (struct iseq_inline_constant_cache_entry *)obj;
+
+ rb_gc_mark_and_move(&ice->value);
+
+ break;
+ }
+ case imemo_cref: {
+ rb_cref_t *cref = (rb_cref_t *)obj;
+
+ rb_gc_mark_and_move(&cref->klass_or_self);
+ rb_gc_mark_and_move_ptr(&cref->next);
+ rb_gc_mark_and_move(&cref->refinements);
+
+ break;
+ }
+ case imemo_env: {
+ rb_env_t *env = (rb_env_t *)obj;
+
+ if (LIKELY(env->ep)) {
+ // just after newobj() can be NULL here.
+ RUBY_ASSERT(rb_gc_location(env->ep[VM_ENV_DATA_INDEX_ENV]) == rb_gc_location(obj));
+ RUBY_ASSERT(reference_updating || VM_ENV_ESCAPED_P(env->ep));
+
+ for (unsigned int i = 0; i < env->env_size; i++) {
+ rb_gc_mark_and_move((VALUE *)&env->env[i]);
+ }
+
+ rb_gc_mark_and_move_ptr(&env->iseq);
+
+ if (reference_updating) {
+ ((VALUE *)env->ep)[VM_ENV_DATA_INDEX_ENV] = rb_gc_location(env->ep[VM_ENV_DATA_INDEX_ENV]);
+ }
+ else {
+ if (!VM_ENV_FLAGS(env->ep, VM_ENV_FLAG_WB_REQUIRED)) {
+ VM_ENV_FLAGS_SET(env->ep, VM_ENV_FLAG_WB_REQUIRED);
+ }
+ rb_gc_mark_movable( (VALUE)rb_vm_env_prev_env(env));
+ }
+ }
+
+ break;
+ }
+ case imemo_ifunc: {
+ struct vm_ifunc *ifunc = (struct vm_ifunc *)obj;
+
+ if (!reference_updating) {
+ rb_gc_mark_maybe((VALUE)ifunc->data);
+ }
+
+ break;
+ }
+ case imemo_iseq:
+ rb_iseq_mark_and_move((rb_iseq_t *)obj, reference_updating);
+ break;
+ case imemo_memo: {
+ struct MEMO *memo = (struct MEMO *)obj;
+
+ rb_gc_mark_and_move((VALUE *)&memo->v1);
+ rb_gc_mark_and_move((VALUE *)&memo->v2);
+ if (!reference_updating) {
+ rb_gc_mark_maybe(memo->u3.value);
+ }
+
+ break;
+ }
+ case imemo_ment:
+ mark_and_move_method_entry((rb_method_entry_t *)obj, reference_updating);
+ break;
+ case imemo_parser_strterm:
+ break;
+ case imemo_svar: {
+ struct vm_svar *svar = (struct vm_svar *)obj;
+
+ rb_gc_mark_and_move((VALUE *)&svar->cref_or_me);
+ rb_gc_mark_and_move((VALUE *)&svar->lastline);
+ rb_gc_mark_and_move((VALUE *)&svar->backref);
+ rb_gc_mark_and_move((VALUE *)&svar->others);
+
+ break;
+ }
+ case imemo_throw_data: {
+ struct vm_throw_data *throw_data = (struct vm_throw_data *)obj;
+
+ rb_gc_mark_and_move((VALUE *)&throw_data->throw_obj);
+
+ break;
+ }
+ case imemo_tmpbuf: {
+ const rb_imemo_tmpbuf_t *m = (const rb_imemo_tmpbuf_t *)obj;
+
+ if (!reference_updating) {
+ do {
+ rb_gc_mark_locations(m->ptr, m->ptr + m->cnt);
+ } while ((m = m->next) != NULL);
+ }
+
+ break;
+ }
+ default:
+ rb_bug("unreachable");
+ }
+}
+
+/* =========================================================================
+ * free
+ * ========================================================================= */
+
+static enum rb_id_table_iterator_result
+free_const_entry_i(VALUE value, void *data)
+{
+ rb_const_entry_t *ce = (rb_const_entry_t *)value;
+ xfree(ce);
+ return ID_TABLE_CONTINUE;
+}
+
+void
+rb_free_const_table(struct rb_id_table *tbl)
+{
+ rb_id_table_foreach_values(tbl, free_const_entry_i, 0);
+ rb_id_table_free(tbl);
+}
+
+// alive: if false, target pointers can be freed already.
+static void
+vm_ccs_free(struct rb_class_cc_entries *ccs, int alive, VALUE klass)
+{
+ if (ccs->entries) {
+ for (int i=0; i<ccs->len; i++) {
+ const struct rb_callcache *cc = ccs->entries[i].cc;
+ if (!alive) {
+ void *ptr = asan_unpoison_object_temporary((VALUE)cc);
+ // ccs can be free'ed.
+ if (rb_objspace_markable_object_p((VALUE)cc) &&
+ IMEMO_TYPE_P(cc, imemo_callcache) &&
+ cc->klass == klass) {
+ // OK. maybe target cc.
+ }
+ else {
+ if (ptr) {
+ asan_poison_object((VALUE)cc);
+ }
+ continue;
+ }
+ if (ptr) {
+ asan_poison_object((VALUE)cc);
+ }
+ }
+
+ VM_ASSERT(!vm_cc_super_p(cc) && !vm_cc_refinement_p(cc));
+ vm_cc_invalidate(cc);
+ }
+ ruby_xfree(ccs->entries);
+ }
+ ruby_xfree(ccs);
+}
+
+void
+rb_vm_ccs_free(struct rb_class_cc_entries *ccs)
+{
+ RB_DEBUG_COUNTER_INC(ccs_free);
+ vm_ccs_free(ccs, true, Qundef);
+}
+
+static enum rb_id_table_iterator_result
+cc_table_free_i(VALUE ccs_ptr, void *data)
+{
+ struct rb_class_cc_entries *ccs = (struct rb_class_cc_entries *)ccs_ptr;
+ VALUE klass = (VALUE)data;
+ VM_ASSERT(vm_ccs_p(ccs));
+
+ vm_ccs_free(ccs, false, klass);
+
+ return ID_TABLE_CONTINUE;
+}
+
+void
+rb_cc_table_free(VALUE klass)
+{
+ struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass);
+
+ if (cc_tbl) {
+ rb_id_table_foreach_values(cc_tbl, cc_table_free_i, (void *)klass);
+ rb_id_table_free(cc_tbl);
+ }
+}
+
+void
+rb_imemo_free(VALUE obj)
+{
+ switch (imemo_type(obj)) {
+ case imemo_ast:
+ rb_bug("imemo_ast is obsolete");
+
+ break;
+ case imemo_callcache:
+ RB_DEBUG_COUNTER_INC(obj_imemo_callcache);
+
+ break;
+ case imemo_callinfo:{
+ const struct rb_callinfo *ci = ((const struct rb_callinfo *)obj);
+
+ rb_vm_ci_free(ci);
+ if (ci->kwarg) {
+ ((struct rb_callinfo_kwarg *)ci->kwarg)->references--;
+ if (ci->kwarg->references == 0) xfree((void *)ci->kwarg);
+ }
+ RB_DEBUG_COUNTER_INC(obj_imemo_callinfo);
+
+ break;
+ }
+ case imemo_constcache:
+ RB_DEBUG_COUNTER_INC(obj_imemo_constcache);
+
+ break;
+ case imemo_cref:
+ RB_DEBUG_COUNTER_INC(obj_imemo_cref);
+
+ break;
+ case imemo_env: {
+ rb_env_t *env = (rb_env_t *)obj;
+
+ RUBY_ASSERT(VM_ENV_ESCAPED_P(env->ep));
+ xfree((VALUE *)env->env);
+ RB_DEBUG_COUNTER_INC(obj_imemo_env);
+
+ break;
+ }
+ case imemo_ifunc:
+ RB_DEBUG_COUNTER_INC(obj_imemo_ifunc);
+ break;
+ case imemo_iseq:
+ rb_iseq_free((rb_iseq_t *)obj);
+ RB_DEBUG_COUNTER_INC(obj_imemo_iseq);
+
+ break;
+ case imemo_memo:
+ RB_DEBUG_COUNTER_INC(obj_imemo_memo);
+
+ break;
+ case imemo_ment:
+ rb_free_method_entry((rb_method_entry_t *)obj);
+ RB_DEBUG_COUNTER_INC(obj_imemo_ment);
+
+ break;
+ case imemo_parser_strterm:
+ RB_DEBUG_COUNTER_INC(obj_imemo_parser_strterm);
+
+ break;
+ case imemo_svar:
+ RB_DEBUG_COUNTER_INC(obj_imemo_svar);
+ break;
+ case imemo_throw_data:
+ RB_DEBUG_COUNTER_INC(obj_imemo_throw_data);
+
+ break;
+ case imemo_tmpbuf:
+ xfree(((rb_imemo_tmpbuf_t *)obj)->ptr);
+ RB_DEBUG_COUNTER_INC(obj_imemo_tmpbuf);
+
+ break;
+ default:
+ rb_bug("unreachable");
+ }
+}
diff --git a/include/ruby/assert.h b/include/ruby/assert.h
index 0c052363bc..e9edd9e640 100644
--- a/include/ruby/assert.h
+++ b/include/ruby/assert.h
@@ -22,6 +22,7 @@
*/
#include "ruby/internal/assume.h"
#include "ruby/internal/attr/cold.h"
+#include "ruby/internal/attr/format.h"
#include "ruby/internal/attr/noreturn.h"
#include "ruby/internal/cast.h"
#include "ruby/internal/dllexport.h"
@@ -132,6 +133,11 @@ RBIMPL_SYMBOL_EXPORT_BEGIN()
RBIMPL_ATTR_NORETURN()
RBIMPL_ATTR_COLD()
void rb_assert_failure(const char *file, int line, const char *name, const char *expr);
+
+RBIMPL_ATTR_NORETURN()
+RBIMPL_ATTR_COLD()
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 5, 6)
+void rb_assert_failure_detail(const char *file, int line, const char *name, const char *expr, const char *fmt, ...);
RBIMPL_SYMBOL_EXPORT_END()
#ifdef RUBY_FUNCTION_NAME_STRING
@@ -147,8 +153,28 @@ RBIMPL_SYMBOL_EXPORT_END()
*
* @param mesg The message to display.
*/
-#define RUBY_ASSERT_FAIL(mesg) \
+#if defined(HAVE___VA_OPT__)
+# if RBIMPL_HAS_WARNING("-Wgnu-zero-variadic-macro-arguments")
+/* __VA_OPT__ is to be used for the zero variadic macro arguments
+ * cases. */
+RBIMPL_WARNING_IGNORED(-Wgnu-zero-variadic-macro-arguments)
+# endif
+# define RBIMPL_VA_OPT_ARGS(...) __VA_OPT__(,) __VA_ARGS__
+
+# define RUBY_ASSERT_FAIL(mesg, ...) \
+ rb_assert_failure##__VA_OPT__(_detail)( \
+ __FILE__, __LINE__, RBIMPL_ASSERT_FUNC, mesg RBIMPL_VA_OPT_ARGS(__VA_ARGS__))
+#elif !defined(__cplusplus)
+# define RBIMPL_VA_OPT_ARGS(...)
+
+# define RUBY_ASSERT_FAIL(mesg, ...) \
+ rb_assert_failure(__FILE__, __LINE__, RBIMPL_ASSERT_FUNC, mesg)
+#else
+# undef RBIMPL_VA_OPT_ARGS
+
+# define RUBY_ASSERT_FAIL(mesg) \
rb_assert_failure(__FILE__, __LINE__, RBIMPL_ASSERT_FUNC, mesg)
+#endif
/**
* Asserts that the expression is truthy. If not aborts with the message.
@@ -156,15 +182,25 @@ RBIMPL_SYMBOL_EXPORT_END()
* @param expr What supposedly evaluates to true.
* @param mesg The message to display on failure.
*/
-#define RUBY_ASSERT_MESG(expr, mesg) \
+#if defined(RBIMPL_VA_OPT_ARGS)
+# define RUBY_ASSERT_MESG(expr, ...) \
+ (RB_LIKELY(expr) ? RBIMPL_ASSERT_NOTHING : RUBY_ASSERT_FAIL(__VA_ARGS__))
+#else
+# define RUBY_ASSERT_MESG(expr, mesg) \
(RB_LIKELY(expr) ? RBIMPL_ASSERT_NOTHING : RUBY_ASSERT_FAIL(mesg))
+#endif
/**
* A variant of #RUBY_ASSERT that does not interface with #RUBY_DEBUG.
*
* @copydetails #RUBY_ASSERT
*/
-#define RUBY_ASSERT_ALWAYS(expr) RUBY_ASSERT_MESG((expr), #expr)
+#if defined(RBIMPL_VA_OPT_ARGS)
+# define RUBY_ASSERT_ALWAYS(expr, ...) \
+ RUBY_ASSERT_MESG(expr, #expr RBIMPL_VA_OPT_ARGS(__VA_ARGS__))
+#else
+# define RUBY_ASSERT_ALWAYS(expr) RUBY_ASSERT_MESG((expr), #expr)
+#endif
/**
* Asserts that the given expression is truthy if and only if #RUBY_DEBUG is truthy.
@@ -172,9 +208,18 @@ RBIMPL_SYMBOL_EXPORT_END()
* @param expr What supposedly evaluates to true.
*/
#if RUBY_DEBUG
-# define RUBY_ASSERT(expr) RUBY_ASSERT_MESG((expr), #expr)
+# if defined(RBIMPL_VA_OPT_ARGS)
+# define RUBY_ASSERT(expr, ...) \
+ RUBY_ASSERT_MESG((expr), #expr RBIMPL_VA_OPT_ARGS(__VA_ARGS__))
+# else
+# define RUBY_ASSERT(expr) RUBY_ASSERT_MESG((expr), #expr)
+# endif
#else
-# define RUBY_ASSERT(expr) RBIMPL_ASSERT_NOTHING
+# if defined(RBIMPL_VA_OPT_ARGS)
+# define RUBY_ASSERT(/* expr, */...) RBIMPL_ASSERT_NOTHING
+# else
+# define RUBY_ASSERT(expr) RBIMPL_ASSERT_NOTHING
+# endif
#endif
/**
@@ -187,9 +232,18 @@ RBIMPL_SYMBOL_EXPORT_END()
/* Currently `RUBY_DEBUG == ! defined(NDEBUG)` is always true. There is no
* difference any longer between this one and `RUBY_ASSERT`. */
#if defined(NDEBUG)
-# define RUBY_ASSERT_NDEBUG(expr) RBIMPL_ASSERT_NOTHING
+# if defined(RBIMPL_VA_OPT_ARGS)
+# define RUBY_ASSERT_NDEBUG(/* expr, */...) RBIMPL_ASSERT_NOTHING
+# else
+# define RUBY_ASSERT_NDEBUG(expr) RBIMPL_ASSERT_NOTHING
+# endif
#else
-# define RUBY_ASSERT_NDEBUG(expr) RUBY_ASSERT_MESG((expr), #expr)
+# if defined(RBIMPL_VA_OPT_ARGS)
+# define RUBY_ASSERT_NDEBUG(expr, ...) \
+ RUBY_ASSERT_MESG((expr), #expr RBIMPL_VA_OPT_ARGS(__VA_ARGS__))
+# else
+# define RUBY_ASSERT_NDEBUG(expr) RUBY_ASSERT_MESG((expr), #expr)
+# endif
#endif
/**
@@ -197,10 +251,20 @@ RBIMPL_SYMBOL_EXPORT_END()
* @param mesg The message to display on failure.
*/
#if RUBY_DEBUG
-# define RUBY_ASSERT_MESG_WHEN(cond, expr, mesg) RUBY_ASSERT_MESG((expr), (mesg))
+# if defined(RBIMPL_VA_OPT_ARGS)
+# define RUBY_ASSERT_MESG_WHEN(cond, /* expr, */...) \
+ RUBY_ASSERT_MESG(__VA_ARGS__)
+# else
+# define RUBY_ASSERT_MESG_WHEN(cond, expr, mesg) RUBY_ASSERT_MESG((expr), (mesg))
+# endif
#else
-# define RUBY_ASSERT_MESG_WHEN(cond, expr, mesg) \
+# if defined(RBIMPL_VA_OPT_ARGS)
+# define RUBY_ASSERT_MESG_WHEN(cond, expr, ...) \
+ ((cond) ? RUBY_ASSERT_MESG((expr), __VA_ARGS__) : RBIMPL_ASSERT_NOTHING)
+# else
+# define RUBY_ASSERT_MESG_WHEN(cond, expr, mesg) \
((cond) ? RUBY_ASSERT_MESG((expr), (mesg)) : RBIMPL_ASSERT_NOTHING)
+# endif
#endif
/**
@@ -210,7 +274,23 @@ RBIMPL_SYMBOL_EXPORT_END()
* @param cond Extra condition that shall hold for assertion to take effect.
* @param expr What supposedly evaluates to true.
*/
-#define RUBY_ASSERT_WHEN(cond, expr) RUBY_ASSERT_MESG_WHEN((cond), (expr), #expr)
+#if defined(RBIMPL_VA_OPT_ARGS)
+# define RUBY_ASSERT_WHEN(cond, expr, ...) \
+ RUBY_ASSERT_MESG_WHEN(cond, expr, #expr RBIMPL_VA_OPT_ARGS(__VA_ARGS__))
+#else
+# define RUBY_ASSERT_WHEN(cond, expr) RUBY_ASSERT_MESG_WHEN((cond), (expr), #expr)
+#endif
+
+/**
+ * A variant of #RUBY_ASSERT that asserts when either #RUBY_DEBUG or built-in
+ * type of `obj` is `type`.
+ *
+ * @param obj Object to check its built-in typue.
+ * @param type Built-in type constant, T_ARRAY, T_STRING, etc.
+ */
+#define RUBY_ASSERT_BUILTIN_TYPE(obj, type) \
+ RUBY_ASSERT(RB_TYPE_P(obj, type), \
+ "Actual type is %s", rb_builtin_type_name(BUILTIN_TYPE(obj)))
/**
* This is either #RUBY_ASSERT or #RBIMPL_ASSUME, depending on #RUBY_DEBUG.
diff --git a/include/ruby/atomic.h b/include/ruby/atomic.h
index 3eb80fbf7d..d786df20c9 100644
--- a/include/ruby/atomic.h
+++ b/include/ruby/atomic.h
@@ -139,6 +139,15 @@ typedef unsigned int rb_atomic_t;
rbimpl_atomic_cas(&(var), (oldval), (newval))
/**
+ * Atomic load. This loads `var` with an atomic intrinsic and returns
+ * its value.
+ *
+ * @param var A variable of ::rb_atomic_t
+ * @return What was stored in `var`j
+ */
+#define RUBY_ATOMIC_LOAD(var) rbimpl_atomic_load(&(var))
+
+/**
* Identical to #RUBY_ATOMIC_EXCHANGE, except for the return type.
*
* @param var A variable of ::rb_atomic_t.
@@ -280,6 +289,17 @@ typedef unsigned int rb_atomic_t;
RBIMPL_CAST(rbimpl_atomic_ptr_exchange((void **)&(var), (void *)val))
/**
+ * Identical to #RUBY_ATOMIC_LOAD, except it expects its arguments are `void*`.
+ * There are cases where ::rb_atomic_t is 32bit while `void*` is 64bit. This
+ * should be used for size related operations to support such platforms.
+ *
+ * @param var A variable of `void*`
+ * @return The value of `var` (without tearing)
+ */
+#define RUBY_ATOMIC_PTR_LOAD(var) \
+ RBIMPL_CAST(rbimpl_atomic_ptr_load((void **)&var))
+
+/**
* Identical to #RUBY_ATOMIC_CAS, except it expects its arguments are `void*`.
* There are cases where ::rb_atomic_t is 32bit while `void*` is 64bit. This
* should be used for size related operations to support such platforms.
@@ -291,7 +311,7 @@ typedef unsigned int rb_atomic_t;
* @retval otherwise Something else is at `var`; not updated.
*/
#define RUBY_ATOMIC_PTR_CAS(var, oldval, newval) \
- RBIMPL_CAST(rbimpl_atomic_ptr_cas((void **)&(var), (oldval), (newval)))
+ RBIMPL_CAST(rbimpl_atomic_ptr_cas((void **)&(var), (void *)(oldval), (void *)(newval)))
/**
* Identical to #RUBY_ATOMIC_EXCHANGE, except it expects its arguments are
@@ -404,7 +424,7 @@ rbimpl_atomic_size_add(volatile size_t *ptr, size_t val)
#elif defined(HAVE_GCC_SYNC_BUILTINS)
__sync_add_and_fetch(ptr, val);
-#elif defined(_WIN32) && defined(_M_AMD64)
+#elif defined(_WIN64)
/* Ditto for `InterlockeExchangedAdd`. */
InterlockedExchangeAdd64(ptr, val);
@@ -456,13 +476,15 @@ rbimpl_atomic_size_inc(volatile size_t *ptr)
#elif defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS)
rbimpl_atomic_size_add(ptr, 1);
-#elif defined(_WIN32) && defined(_M_AMD64)
+#elif defined(_WIN64)
InterlockedIncrement64(ptr);
#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx))
atomic_inc_ulong(ptr);
#else
+ RBIMPL_STATIC_ASSERT(size_of_size_t, sizeof *ptr == sizeof(rb_atomic_t));
+
rbimpl_atomic_size_add(ptr, 1);
#endif
@@ -538,7 +560,7 @@ rbimpl_atomic_size_sub(volatile size_t *ptr, size_t val)
#elif defined(HAVE_GCC_SYNC_BUILTINS)
__sync_sub_and_fetch(ptr, val);
-#elif defined(_WIN32) && defined(_M_AMD64)
+#elif defined(_WIN64)
const ssize_t neg = -1;
InterlockedExchangeAdd64(ptr, neg * val);
@@ -590,13 +612,15 @@ rbimpl_atomic_size_dec(volatile size_t *ptr)
#elif defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS)
rbimpl_atomic_size_sub(ptr, 1);
-#elif defined(_WIN32) && defined(_M_AMD64)
+#elif defined(_WIN64)
InterlockedDecrement64(ptr);
#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx))
atomic_dec_ulong(ptr);
#else
+ RBIMPL_STATIC_ASSERT(size_of_size_t, sizeof *ptr == sizeof(rb_atomic_t));
+
rbimpl_atomic_size_sub(ptr, 1);
#endif
@@ -688,7 +712,7 @@ rbimpl_atomic_size_exchange(volatile size_t *ptr, size_t val)
#elif defined(HAVE_GCC_SYNC_BUILTINS)
return __sync_lock_test_and_set(ptr, val);
-#elif defined(_WIN32) && defined(_M_AMD64)
+#elif defined(_WIN64)
return InterlockedExchange64(ptr, val);
#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx))
@@ -749,6 +773,21 @@ rbimpl_atomic_value_exchange(volatile VALUE *ptr, VALUE val)
RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
+static inline rb_atomic_t
+rbimpl_atomic_load(volatile rb_atomic_t *ptr)
+{
+#if 0
+
+#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
+ return __atomic_load_n(ptr, __ATOMIC_SEQ_CST);
+#else
+ return rbimpl_atomic_fetch_add(ptr, 0);
+#endif
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
static inline void
rbimpl_atomic_set(volatile rb_atomic_t *ptr, rb_atomic_t val)
{
@@ -823,7 +862,7 @@ rbimpl_atomic_size_cas(volatile size_t *ptr, size_t oldval, size_t newval)
#elif defined(HAVE_GCC_SYNC_BUILTINS)
return __sync_val_compare_and_swap(ptr, oldval, newval);
-#elif defined(_WIN32) && defined(_M_AMD64)
+#elif defined(_WIN64)
return InterlockedCompareExchange64(ptr, newval, oldval);
#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx))
@@ -875,6 +914,22 @@ rbimpl_atomic_ptr_cas(void **ptr, const void *oldval, const void *newval)
RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
+static inline void *
+rbimpl_atomic_ptr_load(void **ptr)
+{
+#if 0
+
+#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
+ return __atomic_load_n(ptr, __ATOMIC_SEQ_CST);
+#else
+ void *val = *ptr;
+ return rbimpl_atomic_ptr_cas(ptr, val, val);
+#endif
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
static inline VALUE
rbimpl_atomic_value_cas(volatile VALUE *ptr, VALUE oldval, VALUE newval)
{
diff --git a/include/ruby/debug.h b/include/ruby/debug.h
index e173f16e25..f7c8e6ca8d 100644
--- a/include/ruby/debug.h
+++ b/include/ruby/debug.h
@@ -10,6 +10,7 @@
* modify this file, provided that the conditions mentioned in the
* file COPYING are met. Consult the file for details.
*/
+#include "ruby/internal/attr/deprecated.h"
#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/attr/returns_nonnull.h"
#include "ruby/internal/dllexport.h"
@@ -615,48 +616,157 @@ VALUE rb_tracearg_object(rb_trace_arg_t *trace_arg);
/*
* Postponed Job API
- * rb_postponed_job_register and rb_postponed_job_register_one are
- * async-signal-safe and used via SIGPROF by the "stackprof" RubyGem
+ *
+ * This API is designed to be called from contexts where it is not safe to run Ruby
+ * code (e.g. because they do not hold the GVL or because GC is in progress), and
+ * defer a callback to run in a context where it _is_ safe. The primary intended
+ * users of this API is for sampling profilers like the "stackprof" gem; these work
+ * by scheduling the periodic delivery of a SIGPROF signal, and inside the C-level
+ * signal handler, deferring a job to collect a Ruby backtrace when it is next safe
+ * to do so.
+ *
+ * Ruby maintains a small, fixed-size postponed job table. An extension using this
+ * API should first call `rb_postponed_job_preregister` to register a callback
+ * function in this table and obtain a handle of type `rb_postponed_job_handle_t`
+ * to it. Subsequently, the callback can be triggered by calling
+ * `rb_postponed_job_trigger` with that handle, or the `data` associated with the
+ * callback function can be changed by calling `rb_postponed_job_preregister` again.
+ *
+ * Because the postponed job table is quite small (it only has 32 entries on most
+ * common systems), extensions should generally only preregister one or two `func`
+ * values.
+ *
+ * Historically, this API provided two functions `rb_postponed_job_register` and
+ * `rb_postponed_job_register_one`, which claimed to be fully async-signal-safe and
+ * would call back the provided `func` and `data` at an appropriate time. However,
+ * these functions were subject to race conditions which could cause crashes when
+ * racing with Ruby's internal use of them. These two functions are still present,
+ * but are marked as deprecated and have slightly changed semantics:
+ *
+ * * rb_postponed_job_register now works like rb_postponed_job_register_one i.e.
+ * `func` will only be executed at most one time each time Ruby checks for
+ * interrupts, no matter how many times it is registered
+ * * They are also called with the last `data` to be registered, not the first
+ * (which is how rb_postponed_job_register_one previously worked)
*/
+
/**
* Type of postponed jobs.
*
- * @param[in,out] arg What was passed to rb_postponed_job_register().
+ * @param[in,out] arg What was passed to `rb_postponed_job_preregister`
*/
typedef void (*rb_postponed_job_func_t)(void *arg);
/**
- * Registers a postponed job.
+ * The type of a handle returned from `rb_postponed_job_preregister` and
+ * passed to `rb_postponed_job_trigger`
+ */
+typedef unsigned int rb_postponed_job_handle_t;
+#define POSTPONED_JOB_HANDLE_INVALID ((rb_postponed_job_handle_t)UINT_MAX)
+
+/**
+ * Pre-registers a func in Ruby's postponed job preregistration table,
+ * returning an opaque handle which can be used to trigger the job later. Generally,
+ * this function will be called during the initialization routine of an extension.
+ *
+ * The returned handle can be used later to call `rb_postponed_job_trigger`. This will
+ * cause Ruby to call back into the registered `func` with `data` at a later time, in
+ * a context where the GVL is held and it is safe to perform Ruby allocations.
+ *
+ * If the given `func` was already pre-registered, this function will overwrite the
+ * stored data with the newly passed data, and return the same handle instance as
+ * was previously returned.
+ *
+ * If this function is called concurrently with the same `func`, then the stored data
+ * could be the value from either call (but will definitely be one of them).
*
- * There are situations when running a ruby program is not possible. For
- * instance when a program is in a signal handler; for another instance when
- * the GC is busy. On such situations however, there might be needs to do
- * something. We cannot but defer such operations until we are 100% sure it is
- * safe to execute them. This mechanism is called postponed jobs. This
- * function registers a new one. The registered job would eventually gets
- * executed.
+ * If this function is called to update the data concurrently with a call to
+ * `rb_postponed_job_trigger` on the same handle, it's undefined whether `func` will
+ * be called with the old data or the new data.
*
- * @param[in] flags (Unused) reserved for future extensions.
+ * Although the current implementation of this function is in fact async-signal-safe and
+ * has defined semantics when called concurrently on the same `func`, a future Ruby
+ * version might require that this method be called under the GVL; thus, programs which
+ * aim to be forward-compatible should call this method whilst holding the GVL.
+ *
+ * @param[in] flags Unused and ignored
+ * @param[in] func The function to be pre-registered
+ * @param[in] data The data to be pre-registered
+ * @retval POSTPONED_JOB_HANDLE_INVALID The job table is full; this registration
+ * did not succeed and no further registration will do so for
+ * the lifetime of the program.
+ * @retval otherwise A handle which can be passed to `rb_postponed_job_trigger`
+ */
+rb_postponed_job_handle_t rb_postponed_job_preregister(unsigned int flags, rb_postponed_job_func_t func, void *data);
+
+/**
+ * Triggers a pre-registered job registered with rb_postponed_job_preregister,
+ * scheduling it for execution the next time the Ruby VM checks for interrupts.
+ * The context in which the job is called in holds the GVL and is safe to perform
+ * Ruby allocations within (i.e. it is not during GC).
+ *
+ * This method is async-signal-safe and can be called from any thread, at any
+ * time, including in signal handlers.
+ *
+ * If this method is called multiple times, Ruby will coalesce this into only
+ * one call to the job the next time it checks for interrupts.
+ *
+ * @params[in] h A handle returned from rb_postponed_job_preregister
+ */
+void rb_postponed_job_trigger(rb_postponed_job_handle_t h);
+
+/**
+ * Schedules the given `func` to be called with `data` when Ruby next checks for
+ * interrupts. If this function is called multiple times in between Ruby checking
+ * for interrupts, then `func` will be called only once with the `data` value from
+ * the first call to this function.
+ *
+ * Like `rb_postponed_job_trigger`, the context in which the job is called
+ * holds the GVL and can allocate Ruby objects.
+ *
+ * This method essentially has the same semantics as:
+ *
+ * ```
+ * rb_postponed_job_trigger(rb_postponed_job_preregister(func, data));
+ * ```
+ *
+ * @note Previous versions of Ruby promised that the (`func`, `data`) pairs would
+ * be executed as many times as they were registered with this function; in
+ * reality this was always subject to race conditions and this function no
+ * longer provides this guarantee. Instead, multiple calls to this function
+ * can be coalesced into a single execution of the passed `func`, with the
+ * most recent `data` registered at that time passed in.
+ *
+ * @deprecated This interface implies that arbitrarily many `func`'s can be enqueued
+ * over the lifetime of the program, whilst in reality the registration
+ * slots for postponed jobs are a finite resource. This is made clearer
+ * by the `rb_postponed_job_preregister` and `rb_postponed_job_trigger`
+ * functions, and a future version of Ruby might delete this function.
+ *
+ * @param[in] flags Unused and ignored.
* @param[in] func Job body.
* @param[in,out] data Passed as-is to `func`.
- * @retval 0 Postponed job buffer is full. Failed.
- * @retval otherwise Opaque return value.
- * @post The passed job is postponed.
+ * @retval 0 Postponed job registration table is full. Failed.
+ * @retval 1 Registration succeeded.
+ * @post The passed job will run on the next interrupt check.
*/
+ RBIMPL_ATTR_DEPRECATED(("use rb_postponed_job_preregister and rb_postponed_job_trigger"))
int rb_postponed_job_register(unsigned int flags, rb_postponed_job_func_t func, void *data);
/**
- * Identical to rb_postponed_job_register(), except it additionally checks for
- * duplicated registration. In case the passed job is already in the postponed
- * job buffer this function does nothing.
+ * Identical to `rb_postponed_job_register`
+ *
+ * @deprecated This is deprecated for the same reason as `rb_postponed_job_register`
*
- * @param[in] flags (Unused) reserved for future extensions.
+ * @param[in] flags Unused and ignored.
* @param[in] func Job body.
* @param[in,out] data Passed as-is to `func`.
- * @retval 0 Postponed job buffer is full. Failed.
- * @retval otherwise Opaque return value.
+ * @retval 0 Postponed job registration table is full. Failed.
+ * @retval 1 Registration succeeded.
+ * @post The passed job will run on the next interrupt check.
*/
+ RBIMPL_ATTR_DEPRECATED(("use rb_postponed_job_preregister and rb_postponed_job_trigger"))
int rb_postponed_job_register_one(unsigned int flags, rb_postponed_job_func_t func, void *data);
/** @} */
diff --git a/include/ruby/fiber/scheduler.h b/include/ruby/fiber/scheduler.h
index ad3d2d7483..8f3d383330 100644
--- a/include/ruby/fiber/scheduler.h
+++ b/include/ruby/fiber/scheduler.h
@@ -97,7 +97,7 @@ VALUE rb_fiber_scheduler_get(void);
* current thread will call scheduler's `#close` method on finalisation
* (allowing the scheduler to properly manage all non-finished fibers).
* `scheduler` can be an object of any class corresponding to
- * `Fiber::SchedulerInterface`. Its implementation is up to the user.
+ * `Fiber::Scheduler` interface. Its implementation is up to the user.
*
* @param[in] scheduler The scheduler to set.
* @exception rb_eArgError `scheduler` does not conform the interface.
diff --git a/include/ruby/internal/abi.h b/include/ruby/internal/abi.h
index 8e1bbf3951..e735a67564 100644
--- a/include/ruby/internal/abi.h
+++ b/include/ruby/internal/abi.h
@@ -33,7 +33,7 @@
#endif
#endif /* RUBY_ABI_VERSION */
-#ifdef RUBY_DLN_CHECK_ABI
+#if defined(RUBY_DLN_CHECK_ABI) && !defined(RUBY_EXPORT)
# ifdef __cplusplus
extern "C" {
diff --git a/include/ruby/internal/arithmetic/long.h b/include/ruby/internal/arithmetic/long.h
index 6b8fd8ffc3..6c00dbceb7 100644
--- a/include/ruby/internal/arithmetic/long.h
+++ b/include/ruby/internal/arithmetic/long.h
@@ -114,11 +114,11 @@ RB_INT2FIX(long i)
/* :NOTE: VALUE can be wider than long. As j being unsigned, 2j+1 is fully
* defined. Also it can be compiled into a single LEA instruction. */
- const unsigned long j = i;
+ const unsigned long j = RBIMPL_CAST((unsigned long)i);
const unsigned long k = (j << 1) + RUBY_FIXNUM_FLAG;
- const long l = k;
+ const long l = RBIMPL_CAST((long)k);
const SIGNED_VALUE m = l; /* Sign extend */
- const VALUE n = m;
+ const VALUE n = RBIMPL_CAST((VALUE)m);
RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(n));
return n;
@@ -166,7 +166,7 @@ rbimpl_fix2long_by_idiv(VALUE x)
/* :NOTE: VALUE can be wider than long. (x-1)/2 never overflows because
* RB_FIXNUM_P(x) holds. Also it has no portability issue like y>>1
* below. */
- const SIGNED_VALUE y = x - RUBY_FIXNUM_FLAG;
+ const SIGNED_VALUE y = RBIMPL_CAST((SIGNED_VALUE)(x - RUBY_FIXNUM_FLAG));
const SIGNED_VALUE z = y / 2;
const long w = RBIMPL_CAST((long)z);
@@ -193,7 +193,7 @@ rbimpl_fix2long_by_shift(VALUE x)
/* :NOTE: VALUE can be wider than long. If right shift is arithmetic, this
* is noticeably faster than above. */
- const SIGNED_VALUE y = x;
+ const SIGNED_VALUE y = RBIMPL_CAST((SIGNED_VALUE)x);
const SIGNED_VALUE z = y >> 1;
const long w = RBIMPL_CAST((long)z);
@@ -252,7 +252,7 @@ static inline unsigned long
rb_fix2ulong(VALUE x)
{
RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(x));
- return rb_fix2long(x);
+ return RBIMPL_CAST((unsigned long)rb_fix2long(x));
}
/**
@@ -323,7 +323,7 @@ static inline VALUE
rb_ulong2num_inline(unsigned long v)
{
if (RB_POSFIXABLE(v))
- return RB_LONG2FIX(v);
+ return RB_LONG2FIX(RBIMPL_CAST((long)v));
else
return rb_uint2big(v);
}
diff --git a/include/ruby/internal/arithmetic/long_long.h b/include/ruby/internal/arithmetic/long_long.h
index 65dec8729d..aab455c830 100644
--- a/include/ruby/internal/arithmetic/long_long.h
+++ b/include/ruby/internal/arithmetic/long_long.h
@@ -127,7 +127,7 @@ static inline unsigned LONG_LONG
rb_num2ull_inline(VALUE x)
{
if (RB_FIXNUM_P(x))
- return RB_FIX2LONG(x);
+ return RBIMPL_CAST((unsigned LONG_LONG)RB_FIX2LONG(x));
else
return rb_num2ull(x);
}
diff --git a/include/ruby/internal/arithmetic/st_data_t.h b/include/ruby/internal/arithmetic/st_data_t.h
index 3bff4ffc0b..91776b3fce 100644
--- a/include/ruby/internal/arithmetic/st_data_t.h
+++ b/include/ruby/internal/arithmetic/st_data_t.h
@@ -58,7 +58,7 @@ RBIMPL_ATTR_ARTIFICIAL()
static inline VALUE
RB_ST2FIX(st_data_t i)
{
- SIGNED_VALUE x = i;
+ SIGNED_VALUE x = RBIMPL_CAST((SIGNED_VALUE)i);
if (x >= 0) {
x &= RUBY_FIXNUM_MAX;
@@ -69,7 +69,7 @@ RB_ST2FIX(st_data_t i)
RBIMPL_ASSERT_OR_ASSUME(RB_FIXABLE(x));
unsigned long y = RBIMPL_CAST((unsigned long)x);
- return RB_LONG2FIX(y);
+ return RB_LONG2FIX(RBIMPL_CAST((long)y));
}
#endif /* RBIMPL_ARITHMETIC_ST_DATA_T_H */
diff --git a/include/ruby/internal/attr/noexcept.h b/include/ruby/internal/attr/noexcept.h
index ea3001df2a..7c3f92f1e7 100644
--- a/include/ruby/internal/attr/noexcept.h
+++ b/include/ruby/internal/attr/noexcept.h
@@ -54,7 +54,7 @@
* get smarter and smarter. Today they can infer if it actually throws
* or not without any annotations by humans (correct me if I'm wrong).
*
- * - When an inline function attributed `noexcepr` actually _does_ throw an
+ * - When an inline function attributed `noexcept` actually _does_ throw an
* exception: they have to call `std::terminate` then (C++ standard
* mandates so). This means exception handling routines are actually
* enforced, not omitted. This doesn't impact runtime performance (The
diff --git a/include/ruby/internal/core/rbasic.h b/include/ruby/internal/core/rbasic.h
index 4617f743a7..a1477e2600 100644
--- a/include/ruby/internal/core/rbasic.h
+++ b/include/ruby/internal/core/rbasic.h
@@ -56,22 +56,20 @@ enum ruby_rvalue_flags {
};
/**
- * Ruby's object's, base components. Every single ruby objects have them in
- * common.
+ * Ruby object's base components. All Ruby objects have them in common.
*/
struct
RUBY_ALIGNAS(SIZEOF_VALUE)
RBasic {
/**
- * Per-object flags. Each ruby objects have their own characteristics
- * apart from their classes. For instance whether an object is frozen or
- * not is not controlled by its class. This is where such properties are
- * stored.
+ * Per-object flags. Each Ruby object has its own characteristics apart
+ * from its class. For instance, whether an object is frozen or not is not
+ * controlled by its class. This is where such properties are stored.
*
* @see enum ::ruby_fl_type
*
- * @note This is ::VALUE rather than an enum for alignment purpose. Back
+ * @note This is ::VALUE rather than an enum for alignment purposes. Back
* in the 1990s there were no such thing like `_Alignas` in C.
*/
VALUE flags;
@@ -79,10 +77,10 @@ RBasic {
/**
* Class of an object. Every object has its class. Also, everything is an
* object in Ruby. This means classes are also objects. Classes have
- * their own classes, classes of classes have their classes, too ... and
- * it recursively continues forever.
+ * their own classes, classes of classes have their classes too, and it
+ * recursively continues forever.
*
- * Also note the `const` qualifier. In ruby an object cannot "change" its
+ * Also note the `const` qualifier. In Ruby, an object cannot "change" its
* class.
*/
const VALUE klass;
diff --git a/include/ruby/internal/core/rdata.h b/include/ruby/internal/core/rdata.h
index 43ab3c01e7..e4c146a716 100644
--- a/include/ruby/internal/core/rdata.h
+++ b/include/ruby/internal/core/rdata.h
@@ -37,12 +37,8 @@
#include "ruby/defines.h"
/** @cond INTERNAL_MACRO */
-#ifdef RUBY_UNTYPED_DATA_WARNING
-# /* Take that. */
-#elif defined(RUBY_EXPORT)
-# define RUBY_UNTYPED_DATA_WARNING 1
-#else
-# define RUBY_UNTYPED_DATA_WARNING 0
+#ifndef RUBY_UNTYPED_DATA_WARNING
+#define RUBY_UNTYPED_DATA_WARNING 1
#endif
#define RBIMPL_DATA_FUNC(f) RBIMPL_CAST((void (*)(void *))(f))
@@ -331,15 +327,6 @@ rb_data_object_get_warning(VALUE obj)
return rb_data_object_get(obj);
}
-#if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P)
-# define rb_data_object_wrap_warning(klass, ptr, mark, free) \
- RB_GNUC_EXTENSION( \
- __builtin_choose_expr( \
- __builtin_constant_p(klass) && !(klass), \
- rb_data_object_wrap(klass, ptr, mark, free), \
- (rb_data_object_wrap_warning)(klass, ptr, mark, free)))
-#endif
-
/**
* This is an implementation detail of #Data_Make_Struct. People don't use it
* directly.
diff --git a/include/ruby/internal/encoding/encoding.h b/include/ruby/internal/encoding/encoding.h
index dc3e0151f0..a58f9f2b15 100644
--- a/include/ruby/internal/encoding/encoding.h
+++ b/include/ruby/internal/encoding/encoding.h
@@ -28,6 +28,7 @@
#include "ruby/internal/attr/pure.h"
#include "ruby/internal/attr/returns_nonnull.h"
#include "ruby/internal/dllexport.h"
+#include "ruby/internal/encoding/coderange.h"
#include "ruby/internal/value.h"
#include "ruby/internal/core/rbasic.h"
#include "ruby/internal/fl_type.h"
@@ -79,7 +80,7 @@ enum ruby_encoding_consts {
static inline void
RB_ENCODING_SET_INLINED(VALUE obj, int encindex)
{
- VALUE f = /* upcast */ encindex;
+ VALUE f = /* upcast */ RBIMPL_CAST((VALUE)encindex);
f <<= RUBY_ENCODING_SHIFT;
RB_FL_UNSET_RAW(obj, RUBY_ENCODING_MASK);
diff --git a/include/ruby/internal/fl_type.h b/include/ruby/internal/fl_type.h
index f7f5abdd9b..0a05166784 100644
--- a/include/ruby/internal/fl_type.h
+++ b/include/ruby/internal/fl_type.h
@@ -395,7 +395,7 @@ ruby_fl_type {
* 3rd parties. It must be an implementation detail that they should never
* know. Might better be hidden.
*/
- RUBY_FL_SINGLETON = RUBY_FL_USER0,
+ RUBY_FL_SINGLETON = RUBY_FL_USER1,
};
enum {
@@ -457,7 +457,7 @@ RB_FL_ABLE(VALUE obj)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
/**
- * This is an implenentation detail of RB_FL_TEST(). 3rd parties need not use
+ * This is an implementation detail of RB_FL_TEST(). 3rd parties need not use
* this. Just always use RB_FL_TEST().
*
* @param[in] obj Object in question.
@@ -505,7 +505,7 @@ RB_FL_TEST(VALUE obj, VALUE flags)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
/**
- * This is an implenentation detail of RB_FL_ANY(). 3rd parties need not use
+ * This is an implementation detail of RB_FL_ANY(). 3rd parties need not use
* this. Just always use RB_FL_ANY().
*
* @param[in] obj Object in question.
@@ -539,7 +539,7 @@ RB_FL_ANY(VALUE obj, VALUE flags)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
/**
- * This is an implenentation detail of RB_FL_ALL(). 3rd parties need not use
+ * This is an implementation detail of RB_FL_ALL(). 3rd parties need not use
* this. Just always use RB_FL_ALL().
*
* @param[in] obj Object in question.
@@ -575,7 +575,7 @@ RBIMPL_ATTR_ARTIFICIAL()
/**
* @private
*
- * This is an implenentation detail of RB_FL_SET(). 3rd parties need not use
+ * This is an implementation detail of RB_FL_SET(). 3rd parties need not use
* this. Just always use RB_FL_SET().
*
* @param[out] obj Object in question.
@@ -595,7 +595,7 @@ rbimpl_fl_set_raw_raw(struct RBasic *obj, VALUE flags)
RBIMPL_ATTR_ARTIFICIAL()
/**
- * This is an implenentation detail of RB_FL_SET(). 3rd parties need not use
+ * This is an implementation detail of RB_FL_SET(). 3rd parties need not use
* this. Just always use RB_FL_SET().
*
* @param[out] obj Object in question.
@@ -635,7 +635,7 @@ RBIMPL_ATTR_ARTIFICIAL()
/**
* @private
*
- * This is an implenentation detail of RB_FL_UNSET(). 3rd parties need not use
+ * This is an implementation detail of RB_FL_UNSET(). 3rd parties need not use
* this. Just always use RB_FL_UNSET().
*
* @param[out] obj Object in question.
@@ -655,7 +655,7 @@ rbimpl_fl_unset_raw_raw(struct RBasic *obj, VALUE flags)
RBIMPL_ATTR_ARTIFICIAL()
/**
- * This is an implenentation detail of RB_FL_UNSET(). 3rd parties need not use
+ * This is an implementation detail of RB_FL_UNSET(). 3rd parties need not use
* this. Just always use RB_FL_UNSET().
*
* @param[out] obj Object in question.
@@ -690,7 +690,7 @@ RBIMPL_ATTR_ARTIFICIAL()
/**
* @private
*
- * This is an implenentation detail of RB_FL_REVERSE(). 3rd parties need not
+ * This is an implementation detail of RB_FL_REVERSE(). 3rd parties need not
* use this. Just always use RB_FL_REVERSE().
*
* @param[out] obj Object in question.
@@ -710,7 +710,7 @@ rbimpl_fl_reverse_raw_raw(struct RBasic *obj, VALUE flags)
RBIMPL_ATTR_ARTIFICIAL()
/**
- * This is an implenentation detail of RB_FL_REVERSE(). 3rd parties need not
+ * This is an implementation detail of RB_FL_REVERSE(). 3rd parties need not
* use this. Just always use RB_FL_REVERSE().
*
* @param[out] obj Object in question.
@@ -866,7 +866,7 @@ RB_OBJ_INFECT(VALUE dst, VALUE src)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
/**
- * This is an implenentation detail of RB_OBJ_FROZEN(). 3rd parties need not
+ * This is an implementation detail of RB_OBJ_FROZEN(). 3rd parties need not
* use this. Just always use RB_OBJ_FROZEN().
*
* @param[in] obj Object in question.
@@ -905,9 +905,13 @@ RB_OBJ_FROZEN(VALUE obj)
}
}
+RUBY_SYMBOL_EXPORT_BEGIN
+void rb_obj_freeze_inline(VALUE obj);
+RUBY_SYMBOL_EXPORT_END
+
RBIMPL_ATTR_ARTIFICIAL()
/**
- * This is an implenentation detail of RB_OBJ_FREEZE(). 3rd parties need not
+ * This is an implementation detail of RB_OBJ_FREEZE(). 3rd parties need not
* use this. Just always use RB_OBJ_FREEZE().
*
* @param[out] obj Object in question.
@@ -915,11 +919,7 @@ RBIMPL_ATTR_ARTIFICIAL()
static inline void
RB_OBJ_FREEZE_RAW(VALUE obj)
{
- RB_FL_SET_RAW(obj, RUBY_FL_FREEZE);
+ rb_obj_freeze_inline(obj);
}
-RUBY_SYMBOL_EXPORT_BEGIN
-void rb_obj_freeze_inline(VALUE obj);
-RUBY_SYMBOL_EXPORT_END
-
#endif /* RBIMPL_FL_TYPE_H */
diff --git a/include/ruby/internal/gc.h b/include/ruby/internal/gc.h
index 2a5180671c..462f416af2 100644
--- a/include/ruby/internal/gc.h
+++ b/include/ruby/internal/gc.h
@@ -44,10 +44,11 @@
RBIMPL_SYMBOL_EXPORT_BEGIN()
-#define REF_EDGE(s, p) (offsetof(struct s, p))
-#define REFS_LIST_PTR(l) ((RUBY_DATA_FUNC)l)
+#define RUBY_REF_EDGE(s, p) offsetof(s, p)
+#define RUBY_REFS_LIST_PTR(l) (RUBY_DATA_FUNC)(l)
#define RUBY_REF_END SIZE_MAX
-#define RUBY_REFERENCES_START(t) static size_t t[] = {
+#define RUBY_REFERENCES(t) static const size_t t[]
+#define RUBY_REFERENCES_START(t) RUBY_REFERENCES(t) = {
#define RUBY_REFERENCES_END RUBY_REF_END, };
/* gc.c */
@@ -209,22 +210,6 @@ void rb_gc_mark_movable(VALUE obj);
VALUE rb_gc_location(VALUE obj);
/**
- * Asserts that the passed object is no longer needed. Such objects are
- * reclaimed sooner or later so this function is not mandatory. But sometimes
- * you can know from your application knowledge that an object is surely dead
- * at some point. Calling this as a hint can be a polite way.
- *
- * @param[out] obj Object, dead.
- * @pre `obj` have never been passed to this function before.
- * @post `obj` could be invalidated.
- * @warning It is a failure to pass an object multiple times to this
- * function.
- * @deprecated This is now a no-op function.
- */
-RBIMPL_ATTR_DEPRECATED(("this is now a no-op function"))
-void rb_gc_force_recycle(VALUE obj);
-
-/**
* Triggers a GC process. This was the only GC entry point that we had at the
* beginning. Over time our GC evolved. Now what this function does is just a
* very simplified variation of the entire GC algorithms. A series of
@@ -838,4 +823,7 @@ rb_obj_write(
return a;
}
+RBIMPL_ATTR_DEPRECATED(("Will be removed soon"))
+static inline void rb_gc_force_recycle(VALUE obj){}
+
#endif /* RBIMPL_GC_H */
diff --git a/include/ruby/internal/globals.h b/include/ruby/internal/globals.h
index 5a414fc472..60d8e5309a 100644
--- a/include/ruby/internal/globals.h
+++ b/include/ruby/internal/globals.h
@@ -94,7 +94,7 @@ RUBY_EXTERN VALUE rb_cRegexp; /**< `Regexp` class. */
RUBY_EXTERN VALUE rb_cStat; /**< `File::Stat` class. */
RUBY_EXTERN VALUE rb_cString; /**< `String` class. */
RUBY_EXTERN VALUE rb_cStruct; /**< `Struct` class. */
-RUBY_EXTERN VALUE rb_cSymbol; /**< `Sumbol` class. */
+RUBY_EXTERN VALUE rb_cSymbol; /**< `Symbol` class. */
RUBY_EXTERN VALUE rb_cThread; /**< `Thread` class. */
RUBY_EXTERN VALUE rb_cTime; /**< `Time` class. */
RUBY_EXTERN VALUE rb_cTrueClass; /**< `TrueClass` class. */
diff --git a/include/ruby/internal/intern/array.h b/include/ruby/internal/intern/array.h
index 2262c6f0c6..1909fdf17b 100644
--- a/include/ruby/internal/intern/array.h
+++ b/include/ruby/internal/intern/array.h
@@ -187,7 +187,7 @@ VALUE rb_ary_shared_with_p(VALUE lhs, VALUE rhs);
* : (int i) -> T?
* | (int beg, int len) -> ::Array[T]?
* | (Range[int] r) -> ::Array[T]?
- * | (ArithmeticSequence as) -> ::Array[T]? # This also raises RagneError.
+ * | (ArithmeticSequence as) -> ::Array[T]? # This also raises RangeError.
* end
* ```
*/
diff --git a/include/ruby/internal/intern/bignum.h b/include/ruby/internal/intern/bignum.h
index 4ba48264fa..c27f77a1fb 100644
--- a/include/ruby/internal/intern/bignum.h
+++ b/include/ruby/internal/intern/bignum.h
@@ -51,7 +51,7 @@ RBIMPL_SYMBOL_EXPORT_BEGIN()
VALUE rb_big_new(size_t len, int sign);
/**
- * Queries if the passed bignum instance is a "bigzro". What is a bigzero?
+ * Queries if the passed bignum instance is a "bigzero". What is a bigzero?
* Well, bignums are for very big integers, but can also represent tiny ones
* like -1, 0, 1. Bigzero are instances of bignums whose values are zero.
* Knowing if a bignum is bigzero can be handy on occasions, like for instance
diff --git a/include/ruby/internal/intern/class.h b/include/ruby/internal/intern/class.h
index 0fb2d001bc..357af5d176 100644
--- a/include/ruby/internal/intern/class.h
+++ b/include/ruby/internal/intern/class.h
@@ -88,8 +88,8 @@ VALUE rb_define_class_id(ID id, VALUE super);
* @post `outer::id` refers the returned class.
* @note If a class named `id` is already defined and its superclass is
* `super`, the function just returns the defined class.
- * @note The compaction GC does not move classes returned by this
- * function.
+ * @note The GC does not collect nor move classes returned by this
+ * function. They are immortal.
*/
VALUE rb_define_class_id_under(VALUE outer, ID id, VALUE super);
@@ -127,8 +127,8 @@ VALUE rb_define_module_id(ID id);
* constant is not a module.
* @return The created module.
* @post `outer::id` refers the returned module.
- * @note The compaction GC does not move classes returned by this
- * function.
+ * @note The GC does not collect nor move classes returned by this
+ * function. They are immortal.
*/
VALUE rb_define_module_id_under(VALUE outer, ID id);
diff --git a/include/ruby/internal/intern/error.h b/include/ruby/internal/intern/error.h
index bf8daadd3e..2ca51d0111 100644
--- a/include/ruby/internal/intern/error.h
+++ b/include/ruby/internal/intern/error.h
@@ -244,24 +244,10 @@ RBIMPL_SYMBOL_EXPORT_END()
*
* Does anyone use this? Remain not deleted for compatibility.
*/
-#define rb_check_frozen_internal(obj) do { \
- VALUE frozen_obj = (obj); \
- if (RB_UNLIKELY(RB_OBJ_FROZEN(frozen_obj))) { \
- rb_error_frozen_object(frozen_obj); \
- } \
- } while (0)
+#define rb_check_frozen_internal rb_check_frozen
/** @alias{rb_check_frozen} */
-static inline void
-rb_check_frozen_inline(VALUE obj)
-{
- if (RB_UNLIKELY(RB_OBJ_FROZEN(obj))) {
- rb_error_frozen_object(obj);
- }
-}
-
-/** @alias{rb_check_frozen} */
-#define rb_check_frozen rb_check_frozen_inline
+#define rb_check_frozen_inline rb_check_frozen
/**
* Ensures that the passed integer is in the passed range. When you can use
diff --git a/include/ruby/internal/intern/load.h b/include/ruby/internal/intern/load.h
index 288a16c2ec..9ceb98c2e4 100644
--- a/include/ruby/internal/intern/load.h
+++ b/include/ruby/internal/intern/load.h
@@ -177,6 +177,43 @@ VALUE rb_f_require(VALUE self, VALUE feature);
VALUE rb_require_string(VALUE feature);
/**
+ * Resolves and returns a symbol of a function in the native extension
+ * specified by the feature and symbol names. Extensions will use this function
+ * to access the symbols provided by other native extensions.
+ *
+ * @param[in] feature Name of a feature, e.g. `"json"`.
+ * @param[in] symbol Name of a symbol defined by the feature.
+ * @return The resolved symbol of a function, defined and externed by the
+ * specified feature. It may be NULL if the feature is not loaded,
+ * the feature is not extension, or the symbol is not found.
+ */
+void *rb_ext_resolve_symbol(const char *feature, const char *symbol);
+
+/**
+ * This macro is to provide backwards compatibility. It provides a way to
+ * define function prototypes and resolving function symbols in a safe way.
+ *
+ * ```CXX
+ * // prototypes
+ * #ifdef HAVE_RB_EXT_RESOLVE_SYMBOL
+ * VALUE *(*other_extension_func)(VALUE,VALUE);
+ * #else
+ * VALUE other_extension_func(VALUE);
+ * #endif
+ *
+ * // in Init_xxx()
+ * #ifdef HAVE_RB_EXT_RESOLVE_SYMBOL
+ * other_extension_func = \
+ * (VALUE(*)(VALUE,VALUE))rb_ext_resolve_symbol(fname, sym_name);
+ * if (other_extension_func == NULL) {
+ * // raise your own error
+ * }
+ * #endif
+ * ```
+ */
+#define HAVE_RB_EXT_RESOLVE_SYMBOL 1
+
+/**
* @name extension configuration
* @{
*/
diff --git a/include/ruby/internal/intern/object.h b/include/ruby/internal/intern/object.h
index b9ffa57c06..9daad7d046 100644
--- a/include/ruby/internal/intern/object.h
+++ b/include/ruby/internal/intern/object.h
@@ -151,13 +151,12 @@ VALUE rb_obj_is_kind_of(VALUE obj, VALUE klass);
* @return An allocated, not yet initialised instance of `klass`.
* @note It calls the allocator defined by rb_define_alloc_func(). You
* cannot use this function to define an allocator. Use
- * rb_newobj_of(), #TypedData_Make_Struct or others, instead.
+ * TypedData_Make_Struct or others, instead.
* @note Usually prefer rb_class_new_instance() to rb_obj_alloc() and
* rb_obj_call_init().
* @see rb_class_new_instance()
* @see rb_obj_call_init()
* @see rb_define_alloc_func()
- * @see rb_newobj_of()
* @see #TypedData_Make_Struct
*/
VALUE rb_obj_alloc(VALUE klass);
diff --git a/include/ruby/internal/intern/process.h b/include/ruby/internal/intern/process.h
index 5dcf85e80c..cfa5e13162 100644
--- a/include/ruby/internal/intern/process.h
+++ b/include/ruby/internal/intern/process.h
@@ -256,7 +256,7 @@ rb_pid_t rb_spawn_err(int argc, const VALUE *argv, char *errbuf, size_t buflen);
*
* @internal
*
- * This function might or might not exist depending on `./confiugre` result.
+ * This function might or might not exist depending on `./configure` result.
* It must be a portability hell. Better not use.
*/
VALUE rb_proc_times(VALUE _);
diff --git a/include/ruby/internal/intern/select.h b/include/ruby/internal/intern/select.h
index fabc287cd1..6ba84c6e63 100644
--- a/include/ruby/internal/intern/select.h
+++ b/include/ruby/internal/intern/select.h
@@ -76,7 +76,7 @@ struct timeval;
*
* Although any file descriptors are possible here, it makes completely no
* sense to pass a descriptor that is not `O_NONBLOCK`. If you want to know
- * the reason for this limitatuon in detail, you might find this thread super
+ * the reason for this limitation in detail, you might find this thread super
* interesting: https://lkml.org/lkml/2004/10/6/117
*/
int rb_thread_fd_select(int nfds, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout);
diff --git a/include/ruby/internal/intern/signal.h b/include/ruby/internal/intern/signal.h
index e5b6d6c3d5..4773788651 100644
--- a/include/ruby/internal/intern/signal.h
+++ b/include/ruby/internal/intern/signal.h
@@ -97,7 +97,7 @@ RBIMPL_ATTR_NONNULL(())
* - Case #11: When signo and PID are both negative, the behaviour of this
* function depends on how `killpg(3)` works. On Linux, it seems such
* attempt is strictly prohibited and `Errno::EINVAL` is raised. But on
- * macOS, it seems it tries to to send the signal actually to the process
+ * macOS, it seems it tries to send the signal actually to the process
* group.
*
* @note Above description is in fact different from how `kill(2)` works.
diff --git a/include/ruby/internal/intern/string.h b/include/ruby/internal/intern/string.h
index 3083125e56..37dee45527 100644
--- a/include/ruby/internal/intern/string.h
+++ b/include/ruby/internal/intern/string.h
@@ -412,7 +412,7 @@ VALUE rb_utf8_str_new_static(const char *ptr, long len);
/**
* Identical to rb_interned_str(), except it takes a Ruby's string instead of
- * C's. It can also be seen as a routine identical to to rb_str_new_shared(),
+ * C's. It can also be seen as a routine identical to rb_str_new_shared(),
* except it returns an infamous "f"string.
*
* @param[in] str An object of ::RString.
@@ -454,7 +454,7 @@ VALUE rb_interned_str(const char *ptr, long len);
RBIMPL_ATTR_NONNULL(())
/**
* Identical to rb_interned_str(), except it assumes the passed pointer is a
- * pointer to a C's string. It can also be seen as a routine identical to to
+ * pointer to a C's string. It can also be seen as a routine identical to
* rb_str_to_interned_str(), except it takes a C's string instead of Ruby's.
* Or it can also be seen as a routine identical to rb_str_new_cstr(), except
* it returns an infamous "f"string.
diff --git a/include/ruby/internal/intern/struct.h b/include/ruby/internal/intern/struct.h
index 4510508d77..16b3fad4e0 100644
--- a/include/ruby/internal/intern/struct.h
+++ b/include/ruby/internal/intern/struct.h
@@ -54,6 +54,8 @@ VALUE rb_struct_new(VALUE klass, ...);
* @post Global toplevel constant `name` is defined.
* @note `name` is allowed to be a null pointer. This function creates
* an anonymous struct class then.
+ * @note The GC does not collect nor move classes returned by this
+ * function. They are immortal.
*
* @internal
*
@@ -78,6 +80,8 @@ RBIMPL_ATTR_NONNULL((2))
* @post `name` is a constant under `space`.
* @note In contrast to rb_struct_define(), it doesn't make any sense to
* pass a null pointer to this function.
+ * @note The GC does not collect nor move classes returned by this
+ * function. They are immortal.
*/
VALUE rb_struct_define_under(VALUE space, const char *name, ...);
@@ -195,6 +199,8 @@ RBIMPL_ATTR_NONNULL((2))
* @post `class_name` is a constant under `outer`.
* @note In contrast to rb_struct_define_without_accessor(), it doesn't
* make any sense to pass a null name.
+ * @note The GC does not collect nor move classes returned by this
+ * function. They are immortal.
*/
VALUE rb_struct_define_without_accessor_under(VALUE outer, const char *class_name, VALUE super, rb_alloc_func_t alloc, ...);
@@ -209,6 +215,8 @@ VALUE rb_struct_define_without_accessor_under(VALUE outer, const char *class_nam
* NULL. Each of which are the name of fields.
* @exception rb_eArgError Duplicated field name.
* @return The defined class.
+ * @note The GC does not collect nor move classes returned by this
+ * function. They are immortal.
*/
VALUE rb_data_define(VALUE super, ...);
diff --git a/include/ruby/internal/intern/vm.h b/include/ruby/internal/intern/vm.h
index 76af796b54..29e0c7f534 100644
--- a/include/ruby/internal/intern/vm.h
+++ b/include/ruby/internal/intern/vm.h
@@ -229,8 +229,7 @@ void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func);
* restrict creation of an instance of a class. For example it rarely makes
* sense for a DB adaptor class to allow programmers creating DB row objects
* without querying the DB itself. You can kill sporadic creation of such
- * objects then, by nullifying the allocator function using this API. Your
- * object shall be allocated using #RB_NEWOBJ_OF() directly.
+ * objects then, by nullifying the allocator function using this API.
*
* @param[out] klass The class to modify.
* @pre `klass` must be an instance of Class.
diff --git a/include/ruby/internal/interpreter.h b/include/ruby/internal/interpreter.h
index 662d39c0ec..a10e7ad2d8 100644
--- a/include/ruby/internal/interpreter.h
+++ b/include/ruby/internal/interpreter.h
@@ -141,7 +141,7 @@ void ruby_show_copyright(void);
*
* @param[in] addr A pointer somewhere on the stack, near its bottom.
*/
-void ruby_init_stack(volatile VALUE *addr);
+void ruby_init_stack(void *addr);
/**
* Initializes the VM and builtin libraries.
diff --git a/include/ruby/internal/memory.h b/include/ruby/internal/memory.h
index 6884db195d..64e850c65e 100644
--- a/include/ruby/internal/memory.h
+++ b/include/ruby/internal/memory.h
@@ -38,7 +38,7 @@
# include <alloca.h>
#endif
-#if defined(_MSC_VER) && defined(_WIN64)
+#if defined(_MSC_VER) && defined(_M_AMD64)
# include <intrin.h>
# pragma intrinsic(_umul128)
#endif
@@ -56,13 +56,14 @@
#include "ruby/internal/has/builtin.h"
#include "ruby/internal/stdalign.h"
#include "ruby/internal/stdbool.h"
+#include "ruby/internal/stdckdint.h"
#include "ruby/internal/xmalloc.h"
#include "ruby/backward/2/limits.h"
#include "ruby/backward/2/long_long.h"
#include "ruby/backward/2/assume.h"
#include "ruby/defines.h"
-/** @cond INTENAL_MACRO */
+/** @cond INTERNAL_MACRO */
/* Make alloca work the best possible way. */
#if defined(alloca)
@@ -567,7 +568,10 @@ rbimpl_size_mul_overflow(size_t x, size_t y)
{
struct rbimpl_size_mul_overflow_tag ret = { false, 0, };
-#if RBIMPL_HAS_BUILTIN(__builtin_mul_overflow)
+#if defined(ckd_mul)
+ ret.left = ckd_mul(&ret.right, x, y);
+
+#elif RBIMPL_HAS_BUILTIN(__builtin_mul_overflow)
ret.left = __builtin_mul_overflow(x, y, &ret.right);
#elif defined(DSIZE_T)
@@ -639,7 +643,7 @@ rbimpl_size_mul_or_raise(size_t x, size_t y)
static inline void *
rb_alloc_tmp_buffer2(volatile VALUE *store, long count, size_t elsize)
{
- const size_t total_size = rbimpl_size_mul_or_raise(count, elsize);
+ const size_t total_size = rbimpl_size_mul_or_raise(RBIMPL_CAST((size_t)count), elsize);
const size_t cnt = (total_size + sizeof(VALUE) - 1) / sizeof(VALUE);
return rb_alloc_tmp_buffer_with_count(store, total_size, cnt);
}
diff --git a/include/ruby/internal/module.h b/include/ruby/internal/module.h
index d678dd2102..97b0b2b8b0 100644
--- a/include/ruby/internal/module.h
+++ b/include/ruby/internal/module.h
@@ -56,8 +56,8 @@ RBIMPL_ATTR_NONNULL(())
* @post Top-level constant named `name` refers the returned class.
* @note If a class named `name` is already defined and its superclass is
* `super`, the function just returns the defined class.
- * @note The compaction GC does not move classes returned by this
- * function.
+ * @note The GC does not collect nor move classes returned by this
+ * function. They are immortal.
*
* @internal
*
@@ -75,8 +75,8 @@ RBIMPL_ATTR_NONNULL(())
* constant is not a module.
* @return The created module.
* @post Top-level constant named `name` refers the returned module.
- * @note The compaction GC does not move classes returned by this
- * function.
+ * @note The GC does not collect nor move modules returned by this
+ * function. They are immortal.
*
* @internal
*
@@ -103,8 +103,8 @@ RBIMPL_ATTR_NONNULL(())
* @post `outer::name` refers the returned class.
* @note If a class named `name` is already defined and its superclass
* is `super`, the function just returns the defined class.
- * @note The compaction GC does not move classes returned by this
- * function.
+ * @note The GC does not collect nor move classes returned by this
+ * function. They are immortal.
*/
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super);
@@ -118,8 +118,8 @@ RBIMPL_ATTR_NONNULL(())
* the constant is not a class.
* @return The created module.
* @post `outer::name` refers the returned module.
- * @note The compaction GC does not move classes returned by this
- * function.
+ * @note The GC does not collect nor move modules returned by this
+ * function. They are immortal.
*/
VALUE rb_define_module_under(VALUE outer, const char *name);
diff --git a/include/ruby/internal/newobj.h b/include/ruby/internal/newobj.h
index ba1d7cbe59..6eee2fa5fa 100644
--- a/include/ruby/internal/newobj.h
+++ b/include/ruby/internal/newobj.h
@@ -29,63 +29,14 @@
#include "ruby/internal/value.h"
#include "ruby/assert.h"
-/**
- * Declares, allocates, then assigns a new object to the given variable.
- *
- * @param obj Variable name.
- * @param type Variable type.
- * @exception rb_eNoMemError No space left.
- * @return An allocated object, not initialised.
- * @note Modern programs tend to use #NEWOBJ_OF instead.
- *
- * @internal
- *
- * :FIXME: Should we deprecate it?
- */
-#define RB_NEWOBJ(obj,type) type *(obj) = RBIMPL_CAST((type *)rb_newobj())
-
-/**
- * Identical to #RB_NEWOBJ, except it also accepts the allocating object's
- * class and flags.
- *
- * @param obj Variable name.
- * @param type Variable type.
- * @param klass Object's class.
- * @param flags Object's flags.
- * @exception rb_eNoMemError No space left.
- * @return An allocated object, filled with the arguments.
- */
-#define RB_NEWOBJ_OF(obj,type,klass,flags) type *(obj) = RBIMPL_CAST((type *)rb_newobj_of(klass, flags))
-
-#define NEWOBJ RB_NEWOBJ /**< @old{RB_NEWOBJ} */
-#define NEWOBJ_OF RB_NEWOBJ_OF /**< @old{RB_NEWOBJ_OF} */
#define OBJSETUP rb_obj_setup /**< @old{rb_obj_setup} */
#define CLONESETUP rb_clone_setup /**< @old{rb_clone_setup} */
#define DUPSETUP rb_dup_setup /**< @old{rb_dup_setup} */
RBIMPL_SYMBOL_EXPORT_BEGIN()
/**
- * This is the implementation detail of #RB_NEWOBJ.
- *
- * @exception rb_eNoMemError No space left.
- * @return An allocated object, not initialised.
- */
-VALUE rb_newobj(void);
-
-/**
- * This is the implementation detail of #RB_NEWOBJ_OF.
- *
- * @param klass Object's class.
- * @param flags Object's flags.
- * @exception rb_eNoMemError No space left.
- * @return An allocated object, filled with the arguments.
- */
-VALUE rb_newobj_of(VALUE klass, VALUE flags);
-
-/**
* Fills common fields in the object.
*
- * @note Prefer rb_newobj_of() to this function.
* @param[in,out] obj A Ruby object to be set up.
* @param[in] klass `obj` will belong to this class.
* @param[in] type One of ::ruby_value_type.
diff --git a/include/ruby/internal/special_consts.h b/include/ruby/internal/special_consts.h
index dc0a6b41d6..85579e33f0 100644
--- a/include/ruby/internal/special_consts.h
+++ b/include/ruby/internal/special_consts.h
@@ -156,7 +156,7 @@ RB_TEST(VALUE obj)
*
* RTEST(v) can be 0 if and only if (v == Qfalse || v == Qnil).
*/
- return obj & ~RUBY_Qnil;
+ return obj & RBIMPL_CAST((VALUE)~RUBY_Qnil);
}
RBIMPL_ATTR_CONST()
@@ -226,7 +226,7 @@ RB_NIL_OR_UNDEF_P(VALUE obj)
*
* NIL_OR_UNDEF_P(v) can be true only when v is Qundef or Qnil.
*/
- const VALUE mask = ~(RUBY_Qundef ^ RUBY_Qnil);
+ const VALUE mask = RBIMPL_CAST((VALUE)~(RUBY_Qundef ^ RUBY_Qnil));
const VALUE common_bits = RUBY_Qundef & RUBY_Qnil;
return (obj & mask) == common_bits;
}
diff --git a/include/ruby/internal/static_assert.h b/include/ruby/internal/static_assert.h
index 594c2b2917..b9ff6646e7 100644
--- a/include/ruby/internal/static_assert.h
+++ b/include/ruby/internal/static_assert.h
@@ -71,7 +71,7 @@
#else
# define RBIMPL_STATIC_ASSERT(name, expr) \
- typedef int static_assert_ ## name ## _check[1 - 2 * !(expr)]
+ MAYBE_UNUSED(typedef int static_assert_ ## name ## _check[1 - 2 * !(expr)])
#endif
#endif /* RBIMPL_STATIC_ASSERT_H */
diff --git a/include/ruby/internal/stdckdint.h b/include/ruby/internal/stdckdint.h
new file mode 100644
index 0000000000..e5b5b8b751
--- /dev/null
+++ b/include/ruby/internal/stdckdint.h
@@ -0,0 +1,68 @@
+#ifndef RBIMPL_STDCKDINT_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_STDCKDINT_H
+/**
+ * @author Ruby developers <ruby-core@ruby-lang.org>
+ * @copyright This file is a part of the programming language Ruby.
+ * Permission is hereby granted, to either redistribute and/or
+ * modify this file, provided that the conditions mentioned in the
+ * file COPYING are met. Consult the file for details.
+ * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are
+ * implementation details. Don't take them as canon. They could
+ * rapidly appear then vanish. The name (path) of this header file
+ * is also an implementation detail. Do not expect it to persist
+ * at the place it is now. Developers are free to move it anywhere
+ * anytime at will.
+ * @note To ruby-core: remember that this header can be possibly
+ * recursively included from extension libraries written in C++.
+ * Do not expect for instance `__VA_ARGS__` is always available.
+ * We assume C99 for ruby itself but we don't assume languages of
+ * extension libraries. They could be written in C++98.
+ * @brief C23 shim for <stdckdint.h>
+ */
+#include "ruby/internal/config.h"
+#include "ruby/internal/cast.h"
+#include "ruby/internal/has/builtin.h"
+#include "ruby/internal/stdbool.h"
+
+#ifdef __has_include
+# if __has_include(<stdckdint.h>)
+# /* Conforming C23 situation; e.g. recent clang */
+# define RBIMPL_HAVE_STDCKDINT_H
+# endif
+#endif
+
+#ifdef HAVE_STDCKDINT_H
+# /* Some OSes (most notably FreeBSD) have this file. */
+# define RBIMPL_HAVE_STDCKDINT_H
+#endif
+
+#ifdef __cplusplus
+# /* It seems OS/Compiler provided stdckdint.h tend not support C++ yet.
+# * Situations could improve someday but in a meantime let us work around.
+# */
+# undef RBIMPL_HAVE_STDCKDINT_H
+#endif
+
+#ifdef RBIMPL_HAVE_STDCKDINT_H
+# /* Take that. */
+# include <stdckdint.h>
+
+#elif RBIMPL_HAS_BUILTIN(__builtin_add_overflow)
+# define ckd_add(x, y, z) RBIMPL_CAST((bool)__builtin_add_overflow((y), (z), (x)))
+# define ckd_sub(x, y, z) RBIMPL_CAST((bool)__builtin_sub_overflow((y), (z), (x)))
+# define ckd_mul(x, y, z) RBIMPL_CAST((bool)__builtin_mul_overflow((y), (z), (x)))
+# define __STDC_VERSION_STDCKDINT_H__ 202311L
+
+#/* elif defined(__cplusplus) */
+#/* :TODO: if we assume C++11 we can use `<type_traits>` to implement them. */
+
+#else
+# /* intentionally leave them undefined */
+# /* to make `#ifdef ckd_add` etc. work as intended. */
+# undef ckd_add
+# undef ckd_sub
+# undef ckd_mul
+# undef __STDC_VERSION_STDCKDINT_H__
+#endif
+
+#endif /* RBIMPL_STDCKDINT_H */
diff --git a/include/ruby/internal/value_type.h b/include/ruby/internal/value_type.h
index 977f60a009..557f18813b 100644
--- a/include/ruby/internal/value_type.h
+++ b/include/ruby/internal/value_type.h
@@ -443,7 +443,7 @@ Check_Type(VALUE v, enum ruby_value_type t)
}
unexpected_type:
- rb_unexpected_type(v, t);
+ rb_unexpected_type(v, RBIMPL_CAST((int)t));
}
#endif /* RBIMPL_VALUE_TYPE_H */
diff --git a/include/ruby/io/buffer.h b/include/ruby/io/buffer.h
index f2ab8f1195..e4d98bf051 100644
--- a/include/ruby/io/buffer.h
+++ b/include/ruby/io/buffer.h
@@ -23,10 +23,18 @@ RBIMPL_SYMBOL_EXPORT_BEGIN()
#define RUBY_IO_BUFFER_VERSION 2
+// The `IO::Buffer` class.
RUBY_EXTERN VALUE rb_cIOBuffer;
+
+// The operating system page size.
RUBY_EXTERN size_t RUBY_IO_BUFFER_PAGE_SIZE;
+
+// The default buffer size, usually a (small) multiple of the page size.
+// Can be overridden by the RUBY_IO_BUFFER_DEFAULT_SIZE environment variable.
RUBY_EXTERN size_t RUBY_IO_BUFFER_DEFAULT_SIZE;
+// Represents the internal state of the buffer.
+// More than one flag can be set at a time.
enum rb_io_buffer_flags {
// The memory in the buffer is owned by someone else.
// More specifically, it means that someone else owns the buffer and we shouldn't try to resize it.
@@ -49,21 +57,22 @@ enum rb_io_buffer_flags {
RB_IO_BUFFER_PRIVATE = 64,
// The buffer is read-only and cannot be modified.
- RB_IO_BUFFER_READONLY = 128
+ RB_IO_BUFFER_READONLY = 128,
+
+ // The buffer is backed by a file.
+ RB_IO_BUFFER_FILE = 256,
};
+// Represents the endian of the data types.
enum rb_io_buffer_endian {
+ // The least significant units are put first.
RB_IO_BUFFER_LITTLE_ENDIAN = 4,
RB_IO_BUFFER_BIG_ENDIAN = 8,
-#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
- RB_IO_BUFFER_HOST_ENDIAN = RB_IO_BUFFER_LITTLE_ENDIAN,
-#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#if defined(WORDS_BIGENDIAN)
RB_IO_BUFFER_HOST_ENDIAN = RB_IO_BUFFER_BIG_ENDIAN,
-#elif defined(REG_DWORD) && REG_DWORD == REG_DWORD_LITTLE_ENDIAN
+#else
RB_IO_BUFFER_HOST_ENDIAN = RB_IO_BUFFER_LITTLE_ENDIAN,
-#elif defined(REG_DWORD) && REG_DWORD == REG_DWORD_BIG_ENDIAN
- RB_IO_BUFFER_HOST_ENDIAN = RB_IO_BUFFER_BIG_ENDIAN,
#endif
RB_IO_BUFFER_NETWORK_ENDIAN = RB_IO_BUFFER_BIG_ENDIAN
@@ -79,7 +88,10 @@ int rb_io_buffer_try_unlock(VALUE self);
VALUE rb_io_buffer_free(VALUE self);
VALUE rb_io_buffer_free_locked(VALUE self);
-int rb_io_buffer_get_bytes(VALUE self, void **base, size_t *size);
+// Access the internal buffer and flags. Validates the pointers.
+// The points may not remain valid if the source buffer is manipulated.
+// Consider using rb_io_buffer_lock if needed.
+enum rb_io_buffer_flags rb_io_buffer_get_bytes(VALUE self, void **base, size_t *size);
void rb_io_buffer_get_bytes_for_reading(VALUE self, const void **base, size_t *size);
void rb_io_buffer_get_bytes_for_writing(VALUE self, void **base, size_t *size);
diff --git a/include/ruby/random.h b/include/ruby/random.h
index 39bdb6f3e3..f3df0d96fb 100644
--- a/include/ruby/random.h
+++ b/include/ruby/random.h
@@ -11,7 +11,7 @@
*
* This is a set of APIs to roll your own subclass of ::rb_cRandom. An
* illustrative example of such PRNG can be found at
- * `ext/-test-/ramdom/loop.c`.
+ * `ext/-test-/random/loop.c`.
*/
#include "ruby/ruby.h"
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index 91e24bcebd..035f02c70b 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -272,23 +272,123 @@ RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 0)
*/
int ruby_vsnprintf(char *str, size_t n, char const *fmt, va_list ap);
-// TODO: doc
-
#include <errno.h>
+/**
+ * @name Errno handling routines for userland threads
+ * @note POSIX chapter 2 section 3 states that for each thread of a process,
+ * the value of `errno` shall not be affected by function calls or
+ * assignments to `errno` by other threads.
+ *
+ * Soooo this `#define errno` below seems like a noob mistake at first sight.
+ * If you look at its actual implementation, the functions are just adding one
+ * level of indirection. It doesn't make any sense sorry? But yes! @ko1 told
+ * @shyouhei that this is inevitable.
+ *
+ * The ultimate reason is because Ruby now has N:M threads implemented.
+ * Threads of that sort change their context in user land. A function can be
+ * "transferred" between threads in middle of their executions. Let us for
+ * instance consider:
+ *
+ * ```cxx
+ * void foo()
+ * {
+ * auto i = errno;
+ * close(0);
+ * errno = i;
+ * }
+ * ```
+ *
+ * This function (if ran under our Ractor) could change its running thread at
+ * the `close` function. But the two `errno` invocations are different! Look
+ * how the source code above is compiled by clang 17 with `-O3` flag @ Linux:
+ *
+ * ```
+ * foo(int): # @foo(int)
+ * push rbp
+ * push r14
+ * push rbx
+ * mov ebx, edi
+ * call __errno_location@PLT
+ * mov r14, rax
+ * mov ebp, dword ptr [rax]
+ * mov edi, ebx
+ * call close@PLT
+ * mov dword ptr [r14], ebp
+ * pop rbx
+ * pop r14
+ * pop rbp
+ * ret
+ * ```
+ *
+ * Notice how `__errno_location@PLT` is `call`-ed only once. The compiler
+ * assumes that the location of `errno` does not change during a function call.
+ * Sadly this is no longer true for us. The `close@PLT` now changes threads,
+ * which should also change where `errno` is stored.
+ *
+ * With the `#define errno` below the compilation result changes to this:
+ *
+ * ```
+ * foo(int): # @foo(int)
+ * push rbp
+ * push rbx
+ * push rax
+ * mov ebx, edi
+ * call rb_errno_ptr()@PLT
+ * mov ebp, dword ptr [rax]
+ * mov edi, ebx
+ * call close@PLT
+ * call rb_errno_ptr()@PLT
+ * mov dword ptr [rax], ebp
+ * add rsp, 8
+ * pop rbx
+ * pop rbp
+ * ret
+ * ```
+ *
+ * Which fixes the problem.
+ */
+
+/**
+ * Identical to system `errno`.
+ *
+ * @return The last set `errno` number.
+ */
int rb_errno(void);
-void rb_errno_set(int);
+
+/**
+ * Set the errno.
+ *
+ * @param err New `errno`.
+ * @post `errno` is now set to `err`.
+ */
+void rb_errno_set(int err);
+
+/**
+ * The location of `errno`
+ *
+ * @return The (thread-specific) location of `errno`.
+ */
int *rb_errno_ptr(void);
+/**
+ * Not sure if it is necessary for extension libraries but this is where the
+ * "bare" errno is located.
+ *
+ * @return The location of `errno`.
+ */
static inline int *
rb_orig_errno_ptr(void)
{
return &errno;
}
-#define rb_orig_errno errno
+#define rb_orig_errno errno /**< System-provided original `errno`. */
#undef errno
-#define errno (*rb_errno_ptr())
+#define errno (*rb_errno_ptr()) /**< Ractor-aware version of `errno`. */
+
+/** @} */
+
/** @cond INTERNAL_MACRO */
#if RBIMPL_HAS_WARNING("-Wgnu-zero-variadic-macro-arguments")
diff --git a/include/ruby/st.h b/include/ruby/st.h
index ba69c066c9..f35ab43603 100644
--- a/include/ruby/st.h
+++ b/include/ruby/st.h
@@ -104,8 +104,6 @@ st_table *rb_st_init_table(const struct st_hash_type *);
#define st_init_table rb_st_init_table
st_table *rb_st_init_table_with_size(const struct st_hash_type *, st_index_t);
#define st_init_table_with_size rb_st_init_table_with_size
-st_table *rb_st_init_existing_table_with_size(st_table *tab, const struct st_hash_type *type, st_index_t size);
-#define st_init_existing_table_with_size rb_st_init_existing_table_with_size
st_table *rb_st_init_numtable(void);
#define st_init_numtable rb_st_init_numtable
st_table *rb_st_init_numtable_with_size(st_index_t);
@@ -162,8 +160,6 @@ void rb_st_cleanup_safe(st_table *, st_data_t);
#define st_cleanup_safe rb_st_cleanup_safe
void rb_st_clear(st_table *);
#define st_clear rb_st_clear
-st_table *rb_st_replace(st_table *new_tab, st_table *old_tab);
-#define st_replace rb_st_replace
st_table *rb_st_copy(st_table *);
#define st_copy rb_st_copy
CONSTFUNC(int rb_st_numcmp(st_data_t, st_data_t));
diff --git a/include/ruby/thread.h b/include/ruby/thread.h
index f6eea65b70..337f477fd0 100644
--- a/include/ruby/thread.h
+++ b/include/ruby/thread.h
@@ -191,6 +191,19 @@ void *rb_nogvl(void *(*func)(void *), void *data1,
#define RUBY_CALL_WO_GVL_FLAG_SKIP_CHECK_INTS_
/**
+ * Declare the current Ruby thread should acquire a dedicated
+ * native thread on M:N thread scheduler.
+ *
+ * If a C extension (or a library which the extension relies on) should
+ * keep to run on a native thread (e.g. using thread-local-storage),
+ * this function allocates a dedicated native thread for the thread.
+ *
+ * @return `false` if the thread already running on a dedicated native
+ * thread. Otherwise `true`.
+ */
+bool rb_thread_lock_native_thread(void);
+
+/**
* Triggered when a new thread is started.
*
* @note The callback will be called *without* the GVL held.
@@ -205,7 +218,7 @@ void *rb_nogvl(void *(*func)(void *), void *data1,
#define RUBY_INTERNAL_THREAD_EVENT_READY 1 << 1 /** acquiring GVL */
/**
- * Triggered when a thread successfuly acquired the GVL.
+ * Triggered when a thread successfully acquired the GVL.
*
* @note The callback will be called *with* the GVL held.
*/
@@ -243,9 +256,12 @@ typedef struct rb_internal_thread_event_hook rb_internal_thread_event_hook_t;
* @param[in] events A set of events that `func` should run.
* @param[in] data Passed as-is to `func`.
* @return An opaque pointer to the hook, to unregister it later.
- * @note This functionality is a noop on Windows.
+ * @note This functionality is a noop on Windows and WebAssembly.
* @note The callback will be called without the GVL held, except for the
* RESUMED event.
+ * @note Callbacks are not guaranteed to be executed on the native threads
+ * that corresponds to the Ruby thread. To identify which Ruby thread
+ * the event refers to, you must use `event_data->thread`.
* @warning This function MUST not be called from a thread event callback.
*/
rb_internal_thread_event_hook_t *rb_internal_thread_add_event_hook(
@@ -257,13 +273,53 @@ rb_internal_thread_event_hook_t *rb_internal_thread_add_event_hook(
* Unregister the passed hook.
*
* @param[in] hook. The hook to unregister.
- * @return Wether the hook was found and unregistered.
- * @note This functionality is a noop on Windows.
+ * @return Whether the hook was found and unregistered.
+ * @note This functionality is a noop on Windows and WebAssembly.
* @warning This function MUST not be called from a thread event callback.
*/
bool rb_internal_thread_remove_event_hook(
rb_internal_thread_event_hook_t * hook);
+
+typedef int rb_internal_thread_specific_key_t;
+#define RB_INTERNAL_THREAD_SPECIFIC_KEY_MAX 8
+/**
+ * Create a key to store thread specific data.
+ *
+ * These APIs are designed for tools using
+ * rb_internal_thread_event_hook APIs.
+ *
+ * Note that only `RB_INTERNAL_THREAD_SPECIFIC_KEY_MAX` keys
+ * can be created. raises `ThreadError` if exceeded.
+ *
+ * Usage:
+ * // at initialize time:
+ * int tool_key; // gvar
+ * Init_tool() {
+ * tool_key = rb_internal_thread_specific_key_create();
+ * }
+ *
+ * // at any timing:
+ * rb_internal_thread_specific_set(thread, tool_key, per_thread_data);
+ * ...
+ * per_thread_data = rb_internal_thread_specific_get(thread, tool_key);
+ */
+rb_internal_thread_specific_key_t rb_internal_thread_specific_key_create(void);
+
+/**
+ * Get thread and tool specific data.
+ *
+ * This function is async signal safe and thread safe.
+ */
+void *rb_internal_thread_specific_get(VALUE thread_val, rb_internal_thread_specific_key_t key);
+
+/**
+ * Set thread and tool specific data.
+ *
+ * This function is async signal safe and thread safe.
+ */
+void rb_internal_thread_specific_set(VALUE thread_val, rb_internal_thread_specific_key_t key, void *data);
+
RBIMPL_SYMBOL_EXPORT_END()
#endif /* RUBY_THREAD_H */
diff --git a/include/ruby/version.h b/include/ruby/version.h
index 08c0aadb07..e9113177de 100644
--- a/include/ruby/version.h
+++ b/include/ruby/version.h
@@ -67,7 +67,7 @@
* Minor version. As of writing this version changes annually. Greater
* version doesn't mean "better"; they just mean years passed.
*/
-#define RUBY_API_VERSION_MINOR 3
+#define RUBY_API_VERSION_MINOR 4
/**
* Teeny version. This digit is kind of reserved these days. Kept 0 for the
diff --git a/include/ruby/vm.h b/include/ruby/vm.h
index 3458c28be7..8779780952 100644
--- a/include/ruby/vm.h
+++ b/include/ruby/vm.h
@@ -49,6 +49,13 @@ int ruby_vm_destruct(ruby_vm_t *vm);
*/
void ruby_vm_at_exit(void(*func)(ruby_vm_t *));
+/**
+ * Returns whether the Ruby VM will free all memory at shutdown.
+ *
+ * @return true if free-at-exit is enabled, false otherwise.
+ */
+bool ruby_free_at_exit_p(void);
+
RBIMPL_SYMBOL_EXPORT_END()
#endif /* RUBY_VM_H */
diff --git a/include/ruby/win32.h b/include/ruby/win32.h
index dfb56f4182..27a3467606 100644
--- a/include/ruby/win32.h
+++ b/include/ruby/win32.h
@@ -35,6 +35,7 @@ extern "C++" { /* template without extern "C++" */
#endif
#include <winsock2.h>
#include <ws2tcpip.h>
+#include <mswsock.h>
#if !defined(_MSC_VER) || _MSC_VER >= 1400
#include <iphlpapi.h>
#endif
diff --git a/inits.c b/inits.c
index 46530bb6d0..677a384f9a 100644
--- a/inits.c
+++ b/inits.c
@@ -22,7 +22,6 @@ rb_call_inits(void)
{
CALL(default_shapes);
CALL(Thread_Mutex);
- CALL(vm_postponed_job);
CALL(RandomSeedCore);
CALL(encodings);
CALL(sym);
@@ -52,7 +51,6 @@ rb_call_inits(void)
CALL(Dir);
CALL(Time);
CALL(Random);
- CALL(signal);
CALL(load);
CALL(Proc);
CALL(Binding);
@@ -64,6 +62,7 @@ rb_call_inits(void)
CALL(VM);
CALL(ISeq);
CALL(Thread);
+ CALL(signal);
CALL(Fiber_Scheduler);
CALL(process);
CALL(Cont);
@@ -74,7 +73,6 @@ rb_call_inits(void)
CALL(vm_trace);
CALL(vm_stack_canary);
CALL(ast);
- CALL(gc_stress);
CALL(shape);
CALL(Prism);
diff --git a/insns.def b/insns.def
index b784d7c043..f7df92cf06 100644
--- a/insns.def
+++ b/insns.def
@@ -222,7 +222,7 @@ setinstancevariable
(ID id, IVC ic)
(VALUE val)
()
-// attr bool leaf = false; /* has rb_check_frozen_internal() */
+// attr bool leaf = false; /* has rb_check_frozen() */
{
vm_setinstancevariable(GET_ISEQ(), GET_SELF(), id, val, ic);
}
@@ -375,7 +375,17 @@ putstring
()
(VALUE val)
{
- val = rb_ec_str_resurrect(ec, str);
+ val = rb_ec_str_resurrect(ec, str, false);
+}
+
+/* put chilled string val. string will be copied but frozen in the future. */
+DEFINE_INSN
+putchilledstring
+(VALUE str)
+()
+(VALUE val)
+{
+ val = rb_ec_str_resurrect(ec, str, true);
}
/* put concatenate strings */
@@ -462,6 +472,20 @@ newarraykwsplat
}
}
+/* push hash onto array unless the hash is empty (as empty keyword
+ splats should be ignored).
+ */
+DEFINE_INSN
+pushtoarraykwsplat
+()
+(VALUE ary, VALUE hash)
+(VALUE ary)
+{
+ if (!RHASH_EMPTY_P(hash)) {
+ rb_ary_push(ary, hash);
+ }
+}
+
/* dup array */
DEFINE_INSN
duparray
@@ -498,13 +522,16 @@ expandarray
(rb_num_t num, rb_num_t flag)
(..., VALUE ary)
(...)
+// attr bool handles_sp = true;
// attr bool leaf = false; /* has rb_check_array_type() */
// attr rb_snum_t sp_inc = (rb_snum_t)num - 1 + (flag & 1 ? 1 : 0);
{
- vm_expandarray(GET_SP(), ary, num, (int)flag);
+ vm_expandarray(GET_CFP(), ary, num, (int)flag);
}
-/* concat two arrays */
+/* concat two arrays, without modifying first array.
+ * attempts to convert both objects to arrays using to_a.
+ */
DEFINE_INSN
concatarray
()
@@ -515,6 +542,32 @@ concatarray
ary = vm_concat_array(ary1, ary2);
}
+/* concat second array to first array.
+ * first argument must already be an array.
+ * attempts to convert second object to array using to_a.
+ */
+DEFINE_INSN
+concattoarray
+()
+(VALUE ary1, VALUE ary2)
+(VALUE ary)
+// attr bool leaf = false; /* has rb_check_array_type() */
+{
+ ary = vm_concat_to_array(ary1, ary2);
+}
+
+/* push given number of objects to array directly before. */
+DEFINE_INSN
+pushtoarray
+(rb_num_t num)
+(...)
+(VALUE val)
+// attr rb_snum_t sp_inc = -(rb_snum_t)num;
+{
+ const VALUE *objp = STACK_ADDR_FROM_TOP(num);
+ val = rb_ary_cat(*(objp-1), objp, num);
+}
+
/* call to_a on array ary to splat */
DEFINE_INSN
splatarray
@@ -526,6 +579,22 @@ splatarray
obj = vm_splat_array(flag, ary);
}
+/* call to_hash on hash to keyword splat before converting block */
+DEFINE_INSN
+splatkw
+()
+(VALUE hash, VALUE block)
+(VALUE obj, VALUE block)
+// attr bool leaf = false; /* has rb_to_hash_type() */
+{
+ if (NIL_P(hash)) {
+ obj = Qnil;
+ }
+ else {
+ obj = rb_to_hash_type(hash);
+ }
+}
+
/* put new Hash from n elements. n must be an even number. */
DEFINE_INSN
newhash
@@ -697,7 +766,7 @@ definedivar
// attr bool leaf = false;
{
val = Qnil;
- if (vm_getivar(GET_SELF(), id, GET_ISEQ(), ic, NULL, FALSE, Qundef) != Qundef) {
+ if (!UNDEF_P(vm_getivar(GET_SELF(), id, GET_ISEQ(), ic, NULL, FALSE, Qundef))) {
val = pushval;
}
}
@@ -802,7 +871,7 @@ send
val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_method);
JIT_EXEC(ec, val);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
RESTORE_REGS();
NEXT_INSN();
}
@@ -822,7 +891,7 @@ opt_send_without_block
val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_method);
JIT_EXEC(ec, val);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
RESTORE_REGS();
NEXT_INSN();
}
@@ -838,7 +907,7 @@ objtostring
{
val = vm_objtostring(GET_ISEQ(), recv, cd);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -851,7 +920,7 @@ opt_str_freeze
{
val = vm_opt_str_freeze(str, BOP_FREEZE, idFreeze);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
PUSH(rb_str_resurrect(str));
CALL_SIMPLE_METHOD();
}
@@ -866,7 +935,7 @@ opt_nil_p
{
val = vm_opt_nil_p(GET_ISEQ(), cd, recv);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -879,7 +948,7 @@ opt_str_uminus
{
val = vm_opt_str_freeze(str, BOP_UMINUS, idUMinus);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
PUSH(rb_str_resurrect(str));
CALL_SIMPLE_METHOD();
}
@@ -908,6 +977,9 @@ opt_newarray_send
case idMax:
val = vm_opt_newarray_max(ec, num, STACK_ADDR_FROM_TOP(num));
break;
+ case idPack:
+ val = rb_vm_opt_newarray_pack(ec, (long)num-1, STACK_ADDR_FROM_TOP(num), TOPN(0));
+ break;
default:
rb_bug("unreachable");
}
@@ -926,7 +998,7 @@ invokesuper
val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_super);
JIT_EXEC(ec, val);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
RESTORE_REGS();
NEXT_INSN();
}
@@ -946,7 +1018,7 @@ invokeblock
val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_invokeblock);
JIT_EXEC(ec, val);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
RESTORE_REGS();
NEXT_INSN();
}
@@ -1104,7 +1176,7 @@ opt_plus
{
val = vm_opt_plus(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1118,7 +1190,7 @@ opt_minus
{
val = vm_opt_minus(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1132,7 +1204,7 @@ opt_mult
{
val = vm_opt_mult(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1149,7 +1221,7 @@ opt_div
{
val = vm_opt_div(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1165,7 +1237,7 @@ opt_mod
{
val = vm_opt_mod(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1179,7 +1251,7 @@ opt_eq
{
val = opt_equality(GET_ISEQ(), recv, obj, cd);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1193,7 +1265,7 @@ opt_neq
{
val = vm_opt_neq(GET_ISEQ(), cd, cd_eq, recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1207,7 +1279,7 @@ opt_lt
{
val = vm_opt_lt(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1221,7 +1293,7 @@ opt_le
{
val = vm_opt_le(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1235,7 +1307,7 @@ opt_gt
{
val = vm_opt_gt(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1249,7 +1321,7 @@ opt_ge
{
val = vm_opt_ge(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1267,7 +1339,7 @@ opt_ltlt
{
val = vm_opt_ltlt(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1281,7 +1353,7 @@ opt_and
{
val = vm_opt_and(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1295,7 +1367,7 @@ opt_or
{
val = vm_opt_or(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1314,7 +1386,7 @@ opt_aref
{
val = vm_opt_aref(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1331,7 +1403,7 @@ opt_aset
{
val = vm_opt_aset(recv, obj, set);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1347,7 +1419,7 @@ opt_aset_with
{
VALUE tmp = vm_opt_aset_with(recv, key, val);
- if (tmp != Qundef) {
+ if (!UNDEF_P(tmp)) {
val = tmp;
}
else {
@@ -1368,7 +1440,7 @@ opt_aref_with
{
val = vm_opt_aref_with(recv, key);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
PUSH(rb_str_resurrect(key));
CALL_SIMPLE_METHOD();
}
@@ -1383,7 +1455,7 @@ opt_length
{
val = vm_opt_length(recv, BOP_LENGTH);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1397,7 +1469,7 @@ opt_size
{
val = vm_opt_length(recv, BOP_SIZE);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1411,7 +1483,7 @@ opt_empty_p
{
val = vm_opt_empty_p(recv);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1425,7 +1497,7 @@ opt_succ
{
val = vm_opt_succ(recv);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1439,7 +1511,7 @@ opt_not
{
val = vm_opt_not(GET_ISEQ(), cd, recv);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1454,7 +1526,7 @@ opt_regexpmatch2
{
val = vm_opt_regexpmatch2(obj2, obj1);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
diff --git a/internal.h b/internal.h
index c66e057f60..4fb99d1c08 100644
--- a/internal.h
+++ b/internal.h
@@ -40,10 +40,6 @@
#undef RClass
#undef RCLASS_SUPER
-/* internal/gc.h */
-#undef NEWOBJ_OF
-#undef RB_NEWOBJ_OF
-
/* internal/hash.h */
#undef RHASH_IFNONE
#undef RHASH_SIZE
diff --git a/internal/basic_operators.h b/internal/basic_operators.h
index a59403631e..4732a65403 100644
--- a/internal/basic_operators.h
+++ b/internal/basic_operators.h
@@ -37,6 +37,7 @@ enum ruby_basic_operators {
BOP_OR,
BOP_CMP,
BOP_DEFAULT,
+ BOP_PACK,
BOP_LAST_
};
diff --git a/internal/class.h b/internal/class.h
index b055f07317..8a6c956233 100644
--- a/internal/class.h
+++ b/internal/class.h
@@ -19,6 +19,7 @@
#include "shape.h"
#include "ruby_assert.h"
#include "vm_core.h"
+#include "vm_sync.h"
#include "method.h" /* for rb_cref_t */
#ifdef RCLASS_SUPER
@@ -43,7 +44,7 @@ struct rb_classext_struct {
VALUE *iv_ptr;
struct rb_id_table *const_tbl;
struct rb_id_table *callable_m_tbl;
- struct rb_id_table *cc_tbl; /* ID -> [[ci, cc1], cc2, ...] */
+ struct rb_id_table *cc_tbl; /* ID -> [[ci1, cc1], [ci2, cc2] ...] */
struct rb_id_table *cvc_tbl;
size_t superclass_depth;
VALUE *superclasses;
@@ -107,10 +108,56 @@ struct RClass_and_rb_classext_t {
#define RCLASS_SUPERCLASSES(c) (RCLASS_EXT(c)->superclasses)
#define RCLASS_ATTACHED_OBJECT(c) (RCLASS_EXT(c)->as.singleton_class.attached_object)
+#define RCLASS_IS_ROOT FL_USER0
#define RICLASS_IS_ORIGIN FL_USER0
#define RCLASS_SUPERCLASSES_INCLUDE_SELF FL_USER2
#define RICLASS_ORIGIN_SHARED_MTBL FL_USER3
+static inline st_table *
+RCLASS_IV_HASH(VALUE obj)
+{
+ RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE));
+ RUBY_ASSERT(rb_shape_obj_too_complex(obj));
+ return (st_table *)RCLASS_IVPTR(obj);
+}
+
+static inline void
+RCLASS_SET_IV_HASH(VALUE obj, const st_table *tbl)
+{
+ RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE));
+ RUBY_ASSERT(rb_shape_obj_too_complex(obj));
+ RCLASS_IVPTR(obj) = (VALUE *)tbl;
+}
+
+static inline uint32_t
+RCLASS_IV_COUNT(VALUE obj)
+{
+ RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE));
+ if (rb_shape_obj_too_complex(obj)) {
+ uint32_t count;
+
+ // "Too complex" classes could have their IV hash mutated in
+ // parallel, so lets lock around getting the hash size.
+ RB_VM_LOCK_ENTER();
+ {
+ count = (uint32_t)rb_st_table_size(RCLASS_IV_HASH(obj));
+ }
+ RB_VM_LOCK_LEAVE();
+
+ return count;
+ }
+ else {
+ return rb_shape_get_shape_by_id(RCLASS_SHAPE_ID(obj))->next_iv_index;
+ }
+}
+
+static inline void
+RCLASS_SET_M_TBL(VALUE klass, struct rb_id_table *table)
+{
+ RUBY_ASSERT(!RB_OBJ_PROMOTED(klass));
+ RCLASS_M_TBL(klass) = table;
+}
+
/* class.c */
void rb_class_subclass_add(VALUE super, VALUE klass);
void rb_class_remove_from_super_subclasses(VALUE);
@@ -129,6 +176,7 @@ void rb_class_foreach_subclass(VALUE klass, void (*f)(VALUE, VALUE), VALUE);
void rb_class_detach_subclasses(VALUE);
void rb_class_detach_module_subclasses(VALUE);
void rb_class_remove_from_module_subclasses(VALUE);
+VALUE rb_define_class_id_under_no_pin(VALUE outer, ID id, VALUE super);
VALUE rb_obj_methods(int argc, const VALUE *argv, VALUE obj);
VALUE rb_obj_protected_methods(int argc, const VALUE *argv, VALUE obj);
VALUE rb_obj_private_methods(int argc, const VALUE *argv, VALUE obj);
@@ -148,10 +196,16 @@ static inline void RCLASS_SET_INCLUDER(VALUE iclass, VALUE klass);
VALUE rb_class_inherited(VALUE, VALUE);
VALUE rb_keyword_error_new(const char *, VALUE);
+static inline bool
+RCLASS_SINGLETON_P(VALUE klass)
+{
+ return RB_TYPE_P(klass, T_CLASS) && FL_TEST_RAW(klass, FL_SINGLETON);
+}
+
static inline rb_alloc_func_t
RCLASS_ALLOCATOR(VALUE klass)
{
- if (FL_TEST_RAW(klass, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON_P(klass)) {
return 0;
}
return RCLASS_EXT(klass)->as.class.allocator;
@@ -160,7 +214,7 @@ RCLASS_ALLOCATOR(VALUE klass)
static inline void
RCLASS_SET_ALLOCATOR(VALUE klass, rb_alloc_func_t allocator)
{
- assert(!FL_TEST(klass, FL_SINGLETON));
+ assert(!RCLASS_SINGLETON_P(klass));
RCLASS_EXT(klass)->as.class.allocator = allocator;
}
@@ -220,8 +274,7 @@ RCLASS_SET_CLASSPATH(VALUE klass, VALUE classpath, bool permanent)
static inline VALUE
RCLASS_SET_ATTACHED_OBJECT(VALUE klass, VALUE attached_object)
{
- assert(BUILTIN_TYPE(klass) == T_CLASS);
- assert(FL_TEST_RAW(klass, FL_SINGLETON));
+ assert(RCLASS_SINGLETON_P(klass));
RB_OBJ_WRITE(klass, &RCLASS_EXT(klass)->as.singleton_class.attached_object, attached_object);
return attached_object;
diff --git a/internal/cont.h b/internal/cont.h
index c3b091668a..3c2528a02a 100644
--- a/internal/cont.h
+++ b/internal/cont.h
@@ -22,6 +22,9 @@ void rb_jit_cont_init(void);
void rb_jit_cont_each_iseq(rb_iseq_callback callback, void *data);
void rb_jit_cont_finish(void);
+/* vm.c */
+void rb_free_shared_fiber_pool(void);
+
// Copy locals from the current execution to the specified fiber.
VALUE rb_fiber_inherit_storage(struct rb_execution_context_struct *ec, struct rb_fiber_struct *fiber);
diff --git a/internal/encoding.h b/internal/encoding.h
index a3b81bd388..fe9ea10ec4 100644
--- a/internal/encoding.h
+++ b/internal/encoding.h
@@ -18,6 +18,7 @@
/* encoding.c */
ID rb_id_encoding(void);
+const char * rb_enc_inspect_name(rb_encoding *enc);
rb_encoding *rb_enc_get_from_index(int index);
rb_encoding *rb_enc_check_str(VALUE str1, VALUE str2);
int rb_encdb_replicate(const char *alias, const char *orig);
@@ -29,4 +30,7 @@ void rb_enc_set_base(const char *name, const char *orig);
int rb_enc_set_dummy(int index);
PUREFUNC(int rb_data_is_encoding(VALUE obj));
+/* vm.c */
+void rb_free_global_enc_table(void);
+
#endif /* INTERNAL_ENCODING_H */
diff --git a/internal/error.h b/internal/error.h
index 5fee468929..7a4daca6b3 100644
--- a/internal/error.h
+++ b/internal/error.h
@@ -142,6 +142,8 @@ VALUE rb_syntax_error_append(VALUE, VALUE, int, int, rb_encoding*, const char*,
PRINTF_ARGS(void rb_enc_warn(rb_encoding *enc, const char *fmt, ...), 2, 3);
PRINTF_ARGS(void rb_sys_enc_warning(rb_encoding *enc, const char *fmt, ...), 2, 3);
PRINTF_ARGS(void rb_syserr_enc_warning(int err, rb_encoding *enc, const char *fmt, ...), 3, 4);
+PRINTF_ARGS(void rb_enc_compile_warning(rb_encoding *enc, const char *file, int line, const char *fmt, ...), 4, 5);
+PRINTF_ARGS(void rb_enc_compile_warn(rb_encoding *enc, const char *file, int line, const char *fmt, ...), 4, 5);
rb_warning_category_t rb_warning_category_from_name(VALUE category);
bool rb_warning_category_enabled_p(rb_warning_category_t category);
VALUE rb_name_err_new(VALUE mesg, VALUE recv, VALUE method);
@@ -169,6 +171,9 @@ VALUE rb_syserr_new_path_in(const char *func_name, int n, VALUE path);
#endif
RUBY_SYMBOL_EXPORT_END
+/* vm.c */
+void rb_free_warning(void);
+
static inline void
rb_raise_cstr_i(VALUE etype, VALUE mesg)
{
diff --git a/internal/eval.h b/internal/eval.h
index 73bb656d96..e594d8516d 100644
--- a/internal/eval.h
+++ b/internal/eval.h
@@ -21,6 +21,7 @@ extern ID ruby_static_id_status;
VALUE rb_refinement_module_get_refined_class(VALUE module);
void rb_class_modify_check(VALUE);
NORETURN(VALUE rb_f_raise(int argc, VALUE *argv));
+VALUE rb_top_main_class(const char *method);
/* eval_error.c */
VALUE rb_get_backtrace(VALUE info);
diff --git a/internal/gc.h b/internal/gc.h
index 188497b007..ecc3f11b2c 100644
--- a/internal/gc.h
+++ b/internal/gc.h
@@ -16,6 +16,10 @@
#include "ruby/ruby.h" /* for rb_event_flag_t */
#include "vm_core.h" /* for GET_EC() */
+#ifndef USE_SHARED_GC
+# define USE_SHARED_GC 0
+#endif
+
#if defined(__x86_64__) && !defined(_ILP32) && defined(__GNUC__)
#define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("movq\t%%rsp, %0" : "=r" (*(p)))
#elif defined(__i386) && defined(__GNUC__)
@@ -79,14 +83,6 @@ rb_gc_debug_body(const char *mode, const char *msg, int st, void *ptr)
#define RUBY_GC_INFO if(0)printf
#endif
-#define RUBY_MARK_MOVABLE_UNLESS_NULL(ptr) do { \
- VALUE markobj = (ptr); \
- if (RTEST(markobj)) {rb_gc_mark_movable(markobj);} \
-} while (0)
-#define RUBY_MARK_UNLESS_NULL(ptr) do { \
- VALUE markobj = (ptr); \
- if (RTEST(markobj)) {rb_gc_mark(markobj);} \
-} while (0)
#define RUBY_FREE_UNLESS_NULL(ptr) if(ptr){ruby_xfree(ptr);(ptr)=NULL;}
#if STACK_GROW_DIRECTION > 0
@@ -123,30 +119,14 @@ int ruby_get_stack_grow_direction(volatile VALUE *addr);
const char *rb_obj_info(VALUE obj);
const char *rb_raw_obj_info(char *const buff, const size_t buff_size, VALUE obj);
-size_t rb_size_pool_slot_size(unsigned char pool_id);
-
struct rb_execution_context_struct; /* in vm_core.h */
struct rb_objspace; /* in vm_core.h */
-#ifdef NEWOBJ_OF
-# undef NEWOBJ_OF
-# undef RB_NEWOBJ_OF
-#endif
-
-#define NEWOBJ_OF_0(var, T, c, f, s, ec) \
- T *(var) = (T *)(((f) & FL_WB_PROTECTED) ? \
- rb_wb_protected_newobj_of(GET_EC(), (c), (f) & ~FL_WB_PROTECTED, s) : \
- rb_wb_unprotected_newobj_of((c), (f), s))
-#define NEWOBJ_OF_ec(var, T, c, f, s, ec) \
+#define NEWOBJ_OF(var, T, c, f, s, ec) \
T *(var) = (T *)(((f) & FL_WB_PROTECTED) ? \
- rb_wb_protected_newobj_of((ec), (c), (f) & ~FL_WB_PROTECTED, s) : \
+ rb_wb_protected_newobj_of((ec ? ec : GET_EC()), (c), (f) & ~FL_WB_PROTECTED, s) : \
rb_wb_unprotected_newobj_of((c), (f), s))
-#define NEWOBJ_OF(var, T, c, f, s, ec) \
- NEWOBJ_OF_HELPER(ec)(var, T, c, f, s, ec)
-
-#define NEWOBJ_OF_HELPER(ec) NEWOBJ_OF_ ## ec
-
#define RB_OBJ_GC_FLAGS_MAX 6 /* used in ext/objspace */
#ifndef USE_UNALIGNED_MEMBER_ACCESS
@@ -211,20 +191,16 @@ typedef struct ractor_newobj_cache {
} rb_ractor_newobj_cache_t;
/* gc.c */
-extern VALUE *ruby_initial_gc_stress_ptr;
extern int ruby_disable_gc;
RUBY_ATTR_MALLOC void *ruby_mimmalloc(size_t size);
+RUBY_ATTR_MALLOC void *ruby_mimcalloc(size_t num, size_t size);
void ruby_mimfree(void *ptr);
void rb_gc_prepare_heap(void);
void rb_objspace_set_event_hook(const rb_event_flag_t event);
VALUE rb_objspace_gc_enable(struct rb_objspace *);
VALUE rb_objspace_gc_disable(struct rb_objspace *);
void ruby_gc_set_params(void);
-void rb_copy_wb_protected_attribute(VALUE dest, VALUE obj);
-#if __has_attribute(alloc_align)
-__attribute__((__alloc_align__(1)))
-#endif
-RUBY_ATTR_MALLOC void *rb_aligned_malloc(size_t, size_t) RUBY_ATTR_ALLOC_SIZE((2));
+void rb_gc_copy_attributes(VALUE dest, VALUE obj);
size_t rb_size_mul_or_raise(size_t, size_t, VALUE); /* used in compile.c */
size_t rb_size_mul_add_or_raise(size_t, size_t, size_t, VALUE); /* used in iseq.h */
size_t rb_malloc_grow_capa(size_t current_capacity, size_t type_size);
@@ -236,20 +212,22 @@ RUBY_ATTR_MALLOC void *rb_xcalloc_mul_add_mul(size_t, size_t, size_t, size_t);
static inline void *ruby_sized_xrealloc_inlined(void *ptr, size_t new_size, size_t old_size) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2));
static inline void *ruby_sized_xrealloc2_inlined(void *ptr, size_t new_count, size_t elemsiz, size_t old_count) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2, 3));
static inline void ruby_sized_xfree_inlined(void *ptr, size_t size);
-VALUE rb_class_allocate_instance(VALUE klass);
void rb_gc_ractor_newobj_cache_clear(rb_ractor_newobj_cache_t *newobj_cache);
-size_t rb_gc_obj_slot_size(VALUE obj);
bool rb_gc_size_allocatable_p(size_t size);
+size_t *rb_gc_size_pool_sizes(void);
+size_t rb_gc_size_pool_id_for_size(size_t size);
int rb_objspace_garbage_object_p(VALUE obj);
-bool rb_gc_is_ptr_to_obj(void *ptr);
-VALUE rb_gc_id2ref_obj_tbl(VALUE objid);
-VALUE rb_define_finalizer_no_check(VALUE obj, VALUE block);
+bool rb_gc_is_ptr_to_obj(const void *ptr);
void rb_gc_mark_and_move(VALUE *ptr);
void rb_gc_mark_weak(VALUE *ptr);
void rb_gc_remove_weak(VALUE parent_obj, VALUE *ptr);
+void rb_gc_ref_update_table_values_only(st_table *tbl);
+
+void rb_gc_initial_stress_set(VALUE flag);
+
#define rb_gc_mark_and_move_ptr(ptr) do { \
VALUE _obj = (VALUE)*(ptr); \
rb_gc_mark_and_move(&_obj); \
@@ -258,21 +236,15 @@ void rb_gc_remove_weak(VALUE parent_obj, VALUE *ptr);
RUBY_SYMBOL_EXPORT_BEGIN
/* exports for objspace module */
-size_t rb_objspace_data_type_memsize(VALUE obj);
void rb_objspace_reachable_objects_from(VALUE obj, void (func)(VALUE, void *), void *data);
void rb_objspace_reachable_objects_from_root(void (func)(const char *category, VALUE, void *), void *data);
int rb_objspace_markable_object_p(VALUE obj);
int rb_objspace_internal_object_p(VALUE obj);
-int rb_objspace_marked_object_p(VALUE obj);
void rb_objspace_each_objects(
int (*callback)(void *start, void *end, size_t stride, void *data),
void *data);
-void rb_objspace_each_objects_without_setup(
- int (*callback)(void *, void *, size_t, void *),
- void *data);
-
size_t rb_gc_obj_slot_size(VALUE obj);
VALUE rb_gc_disable_no_rest(void);
diff --git a/internal/imemo.h b/internal/imemo.h
index 65335285ab..36c0776987 100644
--- a/internal/imemo.h
+++ b/internal/imemo.h
@@ -39,7 +39,7 @@ enum imemo_type {
imemo_ment = 6,
imemo_iseq = 7,
imemo_tmpbuf = 8,
- imemo_ast = 9,
+ imemo_ast = 9, // Obsolete due to the universal parser
imemo_parser_strterm = 10,
imemo_callinfo = 11,
imemo_callcache = 12,
@@ -113,11 +113,12 @@ struct MEMO {
} u3;
};
+#define IMEMO_NEW(T, type, v0) ((T *)rb_imemo_new((type), (v0)))
+
/* ment is in method.h */
#define THROW_DATA_P(err) imemo_throw_data_p((VALUE)err)
#define MEMO_CAST(m) ((struct MEMO *)(m))
-#define MEMO_NEW(a, b, c) ((struct MEMO *)rb_imemo_new(imemo_memo, (VALUE)(a), (VALUE)(b), (VALUE)(c), 0))
#define MEMO_FOR(type, value) ((type *)RARRAY_PTR(value))
#define NEW_MEMO_FOR(type, value) \
((value) = rb_ary_hidden_new_fill(type_roomof(type, VALUE)), MEMO_FOR(type, value))
@@ -126,7 +127,9 @@ struct MEMO {
rb_ary_set_len((value), offsetof(type, member) / sizeof(VALUE)), \
MEMO_FOR(type, value))
+#ifndef RUBY_RUBYPARSER_H
typedef struct rb_imemo_tmpbuf_struct rb_imemo_tmpbuf_t;
+#endif
rb_imemo_tmpbuf_t *rb_imemo_tmpbuf_parser_heap(void *buf, rb_imemo_tmpbuf_t *old_heap, size_t cnt);
struct vm_ifunc *rb_vm_ifunc_new(rb_block_call_func_t func, const void *data, int min_argc, int max_argc);
static inline enum imemo_type imemo_type(VALUE imemo);
@@ -140,16 +143,33 @@ static inline VALUE rb_imemo_tmpbuf_auto_free_pointer_new_from_an_RString(VALUE
static inline void MEMO_V1_SET(struct MEMO *m, VALUE v);
static inline void MEMO_V2_SET(struct MEMO *m, VALUE v);
+size_t rb_imemo_memsize(VALUE obj);
+void rb_cc_table_mark(VALUE klass);
+void rb_imemo_mark_and_move(VALUE obj, bool reference_updating);
+void rb_cc_table_free(VALUE klass);
+void rb_imemo_free(VALUE obj);
+
RUBY_SYMBOL_EXPORT_BEGIN
#if IMEMO_DEBUG
-VALUE rb_imemo_new_debug(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0, const char *file, int line);
+VALUE rb_imemo_new_debug(enum imemo_type type, VALUE v0, const char *file, int line);
#define rb_imemo_new(type, v1, v2, v3, v0) rb_imemo_new_debug(type, v1, v2, v3, v0, __FILE__, __LINE__)
#else
-VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0);
+VALUE rb_imemo_new(enum imemo_type type, VALUE v0);
#endif
const char *rb_imemo_name(enum imemo_type type);
RUBY_SYMBOL_EXPORT_END
+static inline struct MEMO *
+MEMO_NEW(VALUE a, VALUE b, VALUE c)
+{
+ struct MEMO *memo = IMEMO_NEW(struct MEMO, imemo_memo, 0);
+ *((VALUE *)&memo->v1) = a;
+ *((VALUE *)&memo->v2) = b;
+ *((VALUE *)&memo->u3.value) = c;
+
+ return memo;
+}
+
static inline enum imemo_type
imemo_type(VALUE imemo)
{
@@ -171,7 +191,7 @@ imemo_type_p(VALUE imemo, enum imemo_type imemo_type)
}
}
-#define IMEMO_TYPE_P(v, t) imemo_type_p((VALUE)v, t)
+#define IMEMO_TYPE_P(v, t) imemo_type_p((VALUE)(v), t)
static inline bool
imemo_throw_data_p(VALUE imemo)
@@ -188,7 +208,7 @@ rb_vm_ifunc_proc_new(rb_block_call_func_t func, const void *data)
static inline VALUE
rb_imemo_tmpbuf_auto_free_pointer(void)
{
- return rb_imemo_new(imemo_tmpbuf, 0, 0, 0, 0);
+ return rb_imemo_new(imemo_tmpbuf, 0);
}
static inline void *
@@ -213,7 +233,7 @@ rb_imemo_tmpbuf_auto_free_pointer_new_from_an_RString(VALUE str)
void *dst;
size_t len;
- SafeStringValue(str);
+ StringValue(str);
/* create tmpbuf to keep the pointer before xmalloc */
imemo = rb_imemo_tmpbuf_auto_free_pointer();
tmpbuf = (rb_imemo_tmpbuf_t *)imemo;
diff --git a/internal/inits.h b/internal/inits.h
index 03e180f77b..03de289dd4 100644
--- a/internal/inits.h
+++ b/internal/inits.h
@@ -19,9 +19,6 @@ void Init_ext(void);
/* file.c */
void Init_File(void);
-/* gc.c */
-void Init_heap(void);
-
/* localeinit.c */
int Init_enc_set_filesystem_encoding(void);
diff --git a/internal/io.h b/internal/io.h
index f16d9efc9c..1891248a19 100644
--- a/internal/io.h
+++ b/internal/io.h
@@ -15,6 +15,9 @@ struct rb_io;
#include "ruby/io.h" /* for rb_io_t */
+#define IO_WITHOUT_GVL(func, arg) rb_thread_call_without_gvl(func, arg, RUBY_UBF_IO, 0)
+#define IO_WITHOUT_GVL_INT(func, arg) (int)(VALUE)IO_WITHOUT_GVL(func, arg)
+
/** Ruby's IO, metadata and buffers. */
struct rb_io {
diff --git a/internal/missing.h b/internal/missing.h
index c0992a151a..6ca508c8f9 100644
--- a/internal/missing.h
+++ b/internal/missing.h
@@ -13,6 +13,7 @@
/* missing/setproctitle.c */
#ifndef HAVE_SETPROCTITLE
extern void ruby_init_setproctitle(int argc, char *argv[]);
+extern void ruby_free_proctitle(void);
#endif
#endif /* INTERNAL_MISSING_H */
diff --git a/internal/numeric.h b/internal/numeric.h
index f7b8d0ad2d..6406cfc2fa 100644
--- a/internal/numeric.h
+++ b/internal/numeric.h
@@ -86,6 +86,7 @@ VALUE rb_int_equal(VALUE x, VALUE y);
VALUE rb_int_divmod(VALUE x, VALUE y);
VALUE rb_int_and(VALUE x, VALUE y);
VALUE rb_int_lshift(VALUE x, VALUE y);
+VALUE rb_int_rshift(VALUE x, VALUE y);
VALUE rb_int_div(VALUE x, VALUE y);
int rb_int_positive_p(VALUE num);
int rb_int_negative_p(VALUE num);
@@ -158,7 +159,7 @@ rb_num_compare_with_zero(VALUE num, ID mid)
{
VALUE zero = INT2FIX(0);
VALUE r = rb_check_funcall(num, mid, 1, &zero);
- if (r == Qundef) {
+ if (RB_UNDEF_P(r)) {
rb_cmperr(num, zero);
}
return r;
diff --git a/internal/object.h b/internal/object.h
index 58e989562a..92ad37fdc8 100644
--- a/internal/object.h
+++ b/internal/object.h
@@ -11,10 +11,14 @@
#include "ruby/ruby.h" /* for VALUE */
/* object.c */
+size_t rb_obj_embedded_size(uint32_t numiv);
+VALUE rb_class_allocate_instance(VALUE klass);
VALUE rb_class_search_ancestor(VALUE klass, VALUE super);
NORETURN(void rb_undefined_alloc(VALUE klass));
double rb_num_to_dbl(VALUE val);
VALUE rb_obj_dig(int argc, VALUE *argv, VALUE self, VALUE notfound);
+VALUE rb_obj_clone_setup(VALUE obj, VALUE clone, VALUE kwfreeze);
+VALUE rb_obj_dup_setup(VALUE obj, VALUE dup);
VALUE rb_immutable_obj_clone(int, VALUE *, VALUE);
VALUE rb_check_convert_type_with_id(VALUE,int,const char*,ID);
int rb_bool_expected(VALUE, const char *, int raise);
diff --git a/internal/parse.h b/internal/parse.h
index bd6d295be1..4a9c4acf8a 100644
--- a/internal/parse.h
+++ b/internal/parse.h
@@ -13,13 +13,11 @@
#include "internal/static_assert.h"
#ifdef UNIVERSAL_PARSER
-#define rb_encoding void
+#define rb_encoding const void
#endif
struct rb_iseq_struct; /* in vm_core.h */
-#define STRTERM_HEREDOC IMEMO_FL_USER0
-
/* structs for managing terminator of string literal and heredocment */
typedef struct rb_strterm_literal_struct {
long nest;
@@ -29,7 +27,7 @@ typedef struct rb_strterm_literal_struct {
} rb_strterm_literal_t;
typedef struct rb_strterm_heredoc_struct {
- VALUE lastline; /* the string of line that contains `<<"END"` */
+ rb_parser_string_t *lastline; /* the string of line that contains `<<"END"` */
long offset; /* the column of END in `<<"END"` */
int sourceline; /* lineno of the line that contains `<<"END"` */
unsigned length; /* the length of END in `<<"END"` */
@@ -40,7 +38,7 @@ typedef struct rb_strterm_heredoc_struct {
#define HERETERM_LENGTH_MAX UINT_MAX
typedef struct rb_strterm_struct {
- VALUE flags;
+ bool heredoc;
union {
rb_strterm_literal_t literal;
rb_strterm_heredoc_t heredoc;
@@ -53,22 +51,31 @@ size_t rb_ruby_parser_memsize(const void *ptr);
void rb_ruby_parser_set_options(rb_parser_t *p, int print, int loop, int chomp, int split);
rb_parser_t *rb_ruby_parser_set_context(rb_parser_t *p, const struct rb_iseq_struct *base, int main);
-void rb_ruby_parser_set_script_lines(rb_parser_t *p, VALUE lines_array);
+void rb_ruby_parser_set_script_lines(rb_parser_t *p);
void rb_ruby_parser_error_tolerant(rb_parser_t *p);
-rb_ast_t* rb_ruby_parser_compile_file_path(rb_parser_t *p, VALUE fname, VALUE file, int start);
void rb_ruby_parser_keep_tokens(rb_parser_t *p);
-rb_ast_t* rb_ruby_parser_compile_generic(rb_parser_t *p, VALUE (*lex_gets)(VALUE, int), VALUE fname, VALUE input, int start);
-rb_ast_t* rb_ruby_parser_compile_string_path(rb_parser_t *p, VALUE f, VALUE s, int line);
+typedef rb_parser_string_t*(rb_parser_lex_gets_func)(struct parser_params*, rb_parser_input_data, int);
+rb_ast_t *rb_parser_compile(rb_parser_t *p, rb_parser_lex_gets_func *gets, VALUE fname, rb_parser_input_data input, int line);
RUBY_SYMBOL_EXPORT_BEGIN
-VALUE rb_ruby_parser_encoding(rb_parser_t *p);
+rb_encoding *rb_ruby_parser_encoding(rb_parser_t *p);
int rb_ruby_parser_end_seen_p(rb_parser_t *p);
int rb_ruby_parser_set_yydebug(rb_parser_t *p, int flag);
+rb_parser_string_t *rb_str_to_parser_string(rb_parser_t *p, VALUE str);
+
+int rb_parser_dvar_defined_ref(struct parser_params*, ID, ID**);
+ID rb_parser_internal_id(struct parser_params*);
+int rb_parser_reg_fragment_check(struct parser_params*, rb_parser_string_t*, int);
+int rb_reg_named_capture_assign_iter_impl(struct parser_params *p, const char *s, long len, rb_encoding *enc, NODE **succ_block, const rb_code_location_t *loc);
+int rb_parser_local_defined(struct parser_params *p, ID id, const struct rb_iseq_struct *iseq);
RUBY_SYMBOL_EXPORT_END
-int rb_reg_named_capture_assign_iter_impl(struct parser_params *p, const char *s, long len, rb_encoding *enc, NODE **succ_block, const rb_code_location_t *loc);
+#ifndef UNIVERSAL_PARSER
+rb_parser_t *rb_ruby_parser_allocate(void);
+rb_parser_t *rb_ruby_parser_new(void);
+#endif
#ifdef RIPPER
void ripper_parser_mark(void *ptr);
@@ -83,7 +90,7 @@ VALUE rb_ruby_parser_debug_output(rb_parser_t *p);
void rb_ruby_parser_set_debug_output(rb_parser_t *p, VALUE output);
VALUE rb_ruby_parser_parsing_thread(rb_parser_t *p);
void rb_ruby_parser_set_parsing_thread(rb_parser_t *p, VALUE parsing_thread);
-void rb_ruby_parser_ripper_initialize(rb_parser_t *p, VALUE (*gets)(struct parser_params*,VALUE), VALUE input, VALUE sourcefile_string, const char *sourcefile, int sourceline);
+void rb_ruby_parser_ripper_initialize(rb_parser_t *p, rb_parser_lex_gets_func *gets, rb_parser_input_data input, VALUE sourcefile_string, const char *sourcefile, int sourceline);
VALUE rb_ruby_parser_result(rb_parser_t *p);
rb_encoding *rb_ruby_parser_enc(rb_parser_t *p);
VALUE rb_ruby_parser_ruby_sourcefile_string(rb_parser_t *p);
@@ -91,13 +98,15 @@ int rb_ruby_parser_ruby_sourceline(rb_parser_t *p);
int rb_ruby_parser_lex_state(rb_parser_t *p);
void rb_ruby_ripper_parse0(rb_parser_t *p);
int rb_ruby_ripper_dedent_string(rb_parser_t *p, VALUE string, int width);
-VALUE rb_ruby_ripper_lex_get_str(rb_parser_t *p, VALUE s);
int rb_ruby_ripper_initialized_p(rb_parser_t *p);
void rb_ruby_ripper_parser_initialize(rb_parser_t *p);
long rb_ruby_ripper_column(rb_parser_t *p);
long rb_ruby_ripper_token_len(rb_parser_t *p);
-VALUE rb_ruby_ripper_lex_lastline(rb_parser_t *p);
+rb_parser_string_t *rb_ruby_ripper_lex_lastline(rb_parser_t *p);
VALUE rb_ruby_ripper_lex_state_name(struct parser_params *p, int state);
+#ifdef UNIVERSAL_PARSER
+rb_parser_t *rb_ripper_parser_params_allocate(const rb_parser_config_t *config);
+#endif
struct parser_params *rb_ruby_ripper_parser_allocate(void);
#endif
diff --git a/internal/random.h b/internal/random.h
index 231e2d5d7e..127b908e16 100644
--- a/internal/random.h
+++ b/internal/random.h
@@ -12,5 +12,6 @@
/* random.c */
int ruby_fill_random_bytes(void *, size_t, int);
+void rb_free_default_rand_key(void);
#endif /* INTERNAL_RANDOM_H */
diff --git a/internal/ruby_parser.h b/internal/ruby_parser.h
index 6beb2808ab..8e306d18de 100644
--- a/internal/ruby_parser.h
+++ b/internal/ruby_parser.h
@@ -2,31 +2,60 @@
#define INTERNAL_RUBY_PARSE_H
#include "internal.h"
-#include "internal/imemo.h"
+#include "internal/bignum.h"
+#include "internal/compilers.h"
+#include "internal/complex.h"
+#include "internal/parse.h"
+#include "internal/rational.h"
#include "rubyparser.h"
#include "vm.h"
+struct lex_pointer_string {
+ VALUE str;
+ long ptr;
+};
+
RUBY_SYMBOL_EXPORT_BEGIN
#ifdef UNIVERSAL_PARSER
-void rb_parser_config_initialize(rb_parser_config_t *config);
+const rb_parser_config_t *rb_ruby_parser_config(void);
+rb_parser_t *rb_parser_params_new(void);
#endif
VALUE rb_parser_set_context(VALUE, const struct rb_iseq_struct *, int);
VALUE rb_parser_new(void);
-rb_ast_t *rb_parser_compile_string_path(VALUE vparser, VALUE fname, VALUE src, int line);
+VALUE rb_parser_compile_string_path(VALUE vparser, VALUE fname, VALUE src, int line);
+VALUE rb_str_new_parser_string(rb_parser_string_t *str);
+VALUE rb_str_new_mutable_parser_string(rb_parser_string_t *str);
+rb_parser_string_t *rb_parser_lex_get_str(struct parser_params *p, struct lex_pointer_string *ptr_str);
+
+VALUE rb_node_str_string_val(const NODE *);
+VALUE rb_node_sym_string_val(const NODE *);
+VALUE rb_node_dstr_string_val(const NODE *);
+VALUE rb_node_regx_string_val(const NODE *);
+VALUE rb_node_dregx_string_val(const NODE *);
+VALUE rb_node_line_lineno_val(const NODE *);
+VALUE rb_node_file_path_val(const NODE *);
+VALUE rb_node_encoding_val(const NODE *);
+
+VALUE rb_node_integer_literal_val(const NODE *);
+VALUE rb_node_float_literal_val(const NODE *);
+VALUE rb_node_rational_literal_val(const NODE *);
+VALUE rb_node_imaginary_literal_val(const NODE *);
RUBY_SYMBOL_EXPORT_END
VALUE rb_parser_end_seen_p(VALUE);
VALUE rb_parser_encoding(VALUE);
VALUE rb_parser_set_yydebug(VALUE, VALUE);
+VALUE rb_parser_build_script_lines_from(rb_parser_ary_t *script_lines);
void rb_parser_set_options(VALUE, int, int, int, int);
-void *rb_parser_load_file(VALUE parser, VALUE name);
-void rb_parser_set_script_lines(VALUE vparser, VALUE lines_array);
+VALUE rb_parser_load_file(VALUE parser, VALUE name);
+void rb_parser_set_script_lines(VALUE vparser);
void rb_parser_error_tolerant(VALUE vparser);
void rb_parser_keep_tokens(VALUE vparser);
-rb_ast_t *rb_parser_compile_string(VALUE, const char*, VALUE, int);
-rb_ast_t *rb_parser_compile_file_path(VALUE vparser, VALUE fname, VALUE input, int line);
-rb_ast_t *rb_parser_compile_generic(VALUE vparser, VALUE (*lex_gets)(VALUE, int), VALUE fname, VALUE input, int line);
+VALUE rb_parser_compile_string(VALUE, const char*, VALUE, int);
+VALUE rb_parser_compile_file_path(VALUE vparser, VALUE fname, VALUE input, int line);
+VALUE rb_parser_compile_generic(VALUE vparser, rb_parser_lex_gets_func *lex_gets, VALUE fname, VALUE input, int line);
+VALUE rb_parser_compile_array(VALUE vparser, VALUE fname, VALUE array, int start);
enum lex_state_bits {
EXPR_BEG_bit, /* ignore newline, +/- is a sign. */
@@ -66,4 +95,8 @@ enum lex_state_e {
EXPR_END_ANY = (EXPR_END | EXPR_ENDARG | EXPR_ENDFN),
EXPR_NONE = 0
};
+
+VALUE rb_ruby_ast_new(const NODE *const root);
+rb_ast_t *rb_ruby_ast_data_get(VALUE ast_value);
+
#endif /* INTERNAL_RUBY_PARSE_H */
diff --git a/internal/sanitizers.h b/internal/sanitizers.h
index 7b7d166c74..b0eb1fc851 100644
--- a/internal/sanitizers.h
+++ b/internal/sanitizers.h
@@ -16,11 +16,15 @@
#endif
#ifdef HAVE_SANITIZER_ASAN_INTERFACE_H
-# include <sanitizer/asan_interface.h>
+# if __has_feature(address_sanitizer)
+# define RUBY_ASAN_ENABLED
+# include <sanitizer/asan_interface.h>
+# endif
#endif
#ifdef HAVE_SANITIZER_MSAN_INTERFACE_H
# if __has_feature(memory_sanitizer)
+# define RUBY_MSAN_ENABLED
# include <sanitizer/msan_interface.h>
# endif
#endif
@@ -29,10 +33,10 @@
#include "ruby/ruby.h" /* for VALUE */
#if 0
-#elif __has_feature(memory_sanitizer) && __has_feature(address_sanitizer)
+#elif defined(RUBY_ASAN_ENABLED) && defined(RUBY_MSAN_ENABLED)
# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \
__attribute__((__no_sanitize__("memory, address"), __noinline__)) x
-#elif __has_feature(address_sanitizer)
+#elif defined(RUBY_ASAN_ENABLED)
# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \
__attribute__((__no_sanitize__("address"), __noinline__)) x
#elif defined(NO_SANITIZE_ADDRESS)
@@ -60,13 +64,15 @@
# define NO_SANITIZE(x, y) y
#endif
-#if !__has_feature(address_sanitizer)
+#ifndef RUBY_ASAN_ENABLED
# define __asan_poison_memory_region(x, y)
# define __asan_unpoison_memory_region(x, y)
# define __asan_region_is_poisoned(x, y) 0
+# define __asan_get_current_fake_stack() NULL
+# define __asan_addr_is_in_fake_stack(fake_stack, slot, start, end) NULL
#endif
-#if !__has_feature(memory_sanitizer)
+#ifndef RUBY_MSAN_ENABLED
# define __msan_allocated_memory(x, y) ((void)(x), (void)(y))
# define __msan_poison(x, y) ((void)(x), (void)(y))
# define __msan_unpoison(x, y) ((void)(x), (void)(y))
@@ -89,7 +95,7 @@
# define VALGRIND_MAKE_MEM_UNDEFINED(p, n) 0
#endif
-/*!
+/**
* This function asserts that a (continuous) memory region from ptr to size
* being "poisoned". Both read / write access to such memory region are
* prohibited until properly unpoisoned. The region must be previously
@@ -99,8 +105,8 @@
* region to reuse later: poison when you keep it unused, and unpoison when you
* reuse.
*
- * \param[in] ptr pointer to the beginning of the memory region to poison.
- * \param[in] size the length of the memory region to poison.
+ * @param[in] ptr pointer to the beginning of the memory region to poison.
+ * @param[in] size the length of the memory region to poison.
*/
static inline void
asan_poison_memory_region(const volatile void *ptr, size_t size)
@@ -109,10 +115,10 @@ asan_poison_memory_region(const volatile void *ptr, size_t size)
__asan_poison_memory_region(ptr, size);
}
-/*!
+/**
* This is a variant of asan_poison_memory_region that takes a VALUE.
*
- * \param[in] obj target object.
+ * @param[in] obj target object.
*/
static inline void
asan_poison_object(VALUE obj)
@@ -121,20 +127,20 @@ asan_poison_object(VALUE obj)
asan_poison_memory_region(ptr, SIZEOF_VALUE);
}
-#if !__has_feature(address_sanitizer)
-#define asan_poison_object_if(ptr, obj) ((void)(ptr), (void)(obj))
-#else
+#ifdef RUBY_ASAN_ENABLED
#define asan_poison_object_if(ptr, obj) do { \
if (ptr) asan_poison_object(obj); \
} while (0)
+#else
+#define asan_poison_object_if(ptr, obj) ((void)(ptr), (void)(obj))
#endif
-/*!
+/**
* This function predicates if the given object is fully addressable or not.
*
- * \param[in] obj target object.
- * \retval 0 the given object is fully addressable.
- * \retval otherwise pointer to first such byte who is poisoned.
+ * @param[in] obj target object.
+ * @retval 0 the given object is fully addressable.
+ * @retval otherwise pointer to first such byte who is poisoned.
*/
static inline void *
asan_poisoned_object_p(VALUE obj)
@@ -143,7 +149,7 @@ asan_poisoned_object_p(VALUE obj)
return __asan_region_is_poisoned(ptr, SIZEOF_VALUE);
}
-/*!
+/**
* This function asserts that a (formally poisoned) memory region from ptr to
* size is now addressable. Write access to such memory region gets allowed.
* However read access might or might not be possible depending on situations,
@@ -154,9 +160,9 @@ asan_poisoned_object_p(VALUE obj)
* the other hand, that memory region is fully defined and can be read
* immediately.
*
- * \param[in] ptr pointer to the beginning of the memory region to unpoison.
- * \param[in] size the length of the memory region.
- * \param[in] malloc_p if the memory region is like a malloc's return value or not.
+ * @param[in] ptr pointer to the beginning of the memory region to unpoison.
+ * @param[in] size the length of the memory region.
+ * @param[in] malloc_p if the memory region is like a malloc's return value or not.
*/
static inline void
asan_unpoison_memory_region(const volatile void *ptr, size_t size, bool malloc_p)
@@ -170,11 +176,11 @@ asan_unpoison_memory_region(const volatile void *ptr, size_t size, bool malloc_p
}
}
-/*!
+/**
* This is a variant of asan_unpoison_memory_region that takes a VALUE.
*
- * \param[in] obj target object.
- * \param[in] malloc_p if the memory region is like a malloc's return value or not.
+ * @param[in] obj target object.
+ * @param[in] malloc_p if the memory region is like a malloc's return value or not.
*/
static inline void
asan_unpoison_object(VALUE obj, bool newobj_p)
@@ -183,4 +189,109 @@ asan_unpoison_object(VALUE obj, bool newobj_p)
asan_unpoison_memory_region(ptr, SIZEOF_VALUE, newobj_p);
}
+static inline void *
+asan_unpoison_object_temporary(VALUE obj)
+{
+ void *ptr = asan_poisoned_object_p(obj);
+ asan_unpoison_object(obj, false);
+ return ptr;
+}
+
+static inline void *
+asan_poison_object_restore(VALUE obj, void *ptr)
+{
+ if (ptr) {
+ asan_poison_object(obj);
+ }
+ return NULL;
+}
+
+
+/**
+ * Checks if the given pointer is on an ASAN fake stack. If so, it returns the
+ * address this variable has on the real frame; if not, it returns the origin
+ * address unmodified.
+ *
+ * n.b. - _dereferencing_ the returned address is meaningless and should not
+ * be done; even though ASAN reserves space for the variable in both the real and
+ * fake stacks, the _value_ of that variable is only in the fake stack.
+ *
+ * n.b. - this only works for addresses passed in from local variables on the same
+ * thread, because the ASAN fake stacks are threadlocal.
+ *
+ * @param[in] slot the address of some local variable
+ * @retval a pointer to something from that frame on the _real_ machine stack
+ */
+static inline void *
+asan_get_real_stack_addr(void* slot)
+{
+ VALUE *addr;
+ addr = __asan_addr_is_in_fake_stack(__asan_get_current_fake_stack(), slot, NULL, NULL);
+ return addr ? addr : slot;
+}
+
+/**
+ * Gets the current thread's fake stack handle, which can be passed into get_fake_stack_extents
+ *
+ * @retval An opaque value which can be passed to asan_get_fake_stack_extents
+ */
+static inline void *
+asan_get_thread_fake_stack_handle(void)
+{
+ return __asan_get_current_fake_stack();
+}
+
+/**
+ * Checks if the given VALUE _actually_ represents a pointer to an ASAN fake stack.
+ *
+ * If the given slot _is_ actually a reference to an ASAN fake stack, and that fake stack
+ * contains the real values for the passed-in range of machine stack addresses, returns true
+ * and the range of the fake stack through the outparams.
+ *
+ * Otherwise, returns false, and sets the outparams to NULL.
+ *
+ * Note that this function expects "start" to be > "end" on downward-growing stack architectures;
+ *
+ * @param[in] thread_fake_stack_handle The asan fake stack reference for the thread we're scanning
+ * @param[in] slot The value on the machine stack we want to inspect
+ * @param[in] machine_stack_start The extents of the real machine stack on which slot lives
+ * @param[in] machine_stack_end The extents of the real machine stack on which slot lives
+ * @param[out] fake_stack_start_out The extents of the fake stack which contains real VALUEs
+ * @param[out] fake_stack_end_out The extents of the fake stack which contains real VALUEs
+ * @return Whether slot is a pointer to a fake stack for the given machine stack range
+*/
+
+static inline bool
+asan_get_fake_stack_extents(void *thread_fake_stack_handle, VALUE slot,
+ void *machine_stack_start, void *machine_stack_end,
+ void **fake_stack_start_out, void **fake_stack_end_out)
+{
+ /* the ifdef is needed here to suppress a warning about fake_frame_{start/end} being
+ uninitialized if __asan_addr_is_in_fake_stack is an empty macro */
+#ifdef RUBY_ASAN_ENABLED
+ void *fake_frame_start;
+ void *fake_frame_end;
+ void *real_stack_frame = __asan_addr_is_in_fake_stack(
+ thread_fake_stack_handle, (void *)slot, &fake_frame_start, &fake_frame_end
+ );
+ if (real_stack_frame) {
+ bool in_range;
+#if STACK_GROW_DIRECTION < 0
+ in_range = machine_stack_start >= real_stack_frame && real_stack_frame >= machine_stack_end;
+#else
+ in_range = machine_stack_start <= real_stack_frame && real_stack_frame <= machine_stack_end;
+#endif
+ if (in_range) {
+ *fake_stack_start_out = fake_frame_start;
+ *fake_stack_end_out = fake_frame_end;
+ return true;
+ }
+ }
+#endif
+ *fake_stack_start_out = 0;
+ *fake_stack_end_out = 0;
+ return false;
+}
+
+
#endif /* INTERNAL_SANITIZERS_H */
diff --git a/internal/signal.h b/internal/signal.h
index 660cd95f78..2363bf412c 100644
--- a/internal/signal.h
+++ b/internal/signal.h
@@ -19,7 +19,6 @@ void (*ruby_posix_signal(int, void (*)(int)))(int);
RUBY_SYMBOL_EXPORT_BEGIN
/* signal.c (export) */
-int rb_grantpt(int fd);
RUBY_SYMBOL_EXPORT_END
#endif /* INTERNAL_SIGNAL_H */
diff --git a/internal/st.h b/internal/st.h
new file mode 100644
index 0000000000..a26b224505
--- /dev/null
+++ b/internal/st.h
@@ -0,0 +1,11 @@
+#ifndef INTERNAL_ST_H
+#define INTERNAL_ST_H
+
+#include "include/ruby/st.h"
+
+st_table *rb_st_replace(st_table *new_tab, st_table *old_tab);
+#define st_replace rb_st_replace
+st_table *rb_st_init_existing_table_with_size(st_table *tab, const struct st_hash_type *type, st_index_t size);
+#define st_init_existing_table_with_size rb_st_init_existing_table_with_size
+
+#endif
diff --git a/internal/string.h b/internal/string.h
index abb0a536ad..3533766ffb 100644
--- a/internal/string.h
+++ b/internal/string.h
@@ -17,6 +17,11 @@
#define STR_NOEMBED FL_USER1
#define STR_SHARED FL_USER2 /* = ELTS_SHARED */
+#define STR_CHILLED FL_USER3
+
+enum ruby_rstring_private_flags {
+ RSTRING_CHILLED = STR_CHILLED,
+};
#ifdef rb_fstring_cstr
# undef rb_fstring_cstr
@@ -45,6 +50,7 @@ void rb_str_make_independent(VALUE str);
int rb_enc_str_coderange_scan(VALUE str, rb_encoding *enc);
int rb_ascii8bit_appendable_encoding_index(rb_encoding *enc, unsigned int code);
VALUE rb_str_include(VALUE str, VALUE arg);
+VALUE rb_str_byte_substr(VALUE str, VALUE beg, VALUE len);
static inline bool STR_EMBED_P(VALUE str);
static inline bool STR_SHARED_P(VALUE str);
@@ -57,6 +63,7 @@ static inline VALUE rb_str_eql_internal(const VALUE str1, const VALUE str2);
RUBY_SYMBOL_EXPORT_BEGIN
/* string.c (export) */
VALUE rb_str_tmp_frozen_acquire(VALUE str);
+VALUE rb_str_tmp_frozen_no_embed_acquire(VALUE str);
void rb_str_tmp_frozen_release(VALUE str, VALUE tmp);
VALUE rb_setup_fake_str(struct RString *fake_str, const char *name, long len, rb_encoding *enc);
VALUE rb_str_upto_each(VALUE, VALUE, int, int (*each)(VALUE, VALUE), VALUE);
@@ -64,7 +71,6 @@ VALUE rb_str_upto_endless_each(VALUE, int (*each)(VALUE, VALUE), VALUE);
void rb_str_make_embedded(VALUE);
size_t rb_str_size_as_embedded(VALUE);
bool rb_str_reembeddable_p(VALUE);
-void rb_str_update_shared_ary(VALUE str, VALUE old_root, VALUE new_root);
RUBY_SYMBOL_EXPORT_END
VALUE rb_fstring_new(const char *ptr, long len);
@@ -74,9 +80,10 @@ VALUE rb_str_concat_literals(size_t num, const VALUE *strary);
VALUE rb_str_eql(VALUE str1, VALUE str2);
VALUE rb_id_quote_unprintable(ID);
VALUE rb_sym_proc_call(ID mid, int argc, const VALUE *argv, int kw_splat, VALUE passed_proc);
+VALUE rb_enc_literal_str(const char *ptr, long len, rb_encoding *enc);
struct rb_execution_context_struct;
-VALUE rb_ec_str_resurrect(struct rb_execution_context_struct *ec, VALUE str);
+VALUE rb_ec_str_resurrect(struct rb_execution_context_struct *ec, VALUE str, bool chilled);
#define rb_fstring_lit(str) rb_fstring_new((str), rb_strlen_lit(str))
#define rb_fstring_literal(str) rb_fstring_lit(str)
@@ -108,6 +115,25 @@ STR_SHARED_P(VALUE str)
}
static inline bool
+CHILLED_STRING_P(VALUE obj)
+{
+ return RB_TYPE_P(obj, T_STRING) && FL_TEST_RAW(obj, STR_CHILLED);
+}
+
+static inline void
+CHILLED_STRING_MUTATED(VALUE str)
+{
+ FL_UNSET_RAW(str, STR_CHILLED);
+ rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "literal string will be frozen in the future");
+}
+
+static inline void
+STR_CHILL_RAW(VALUE str)
+{
+ FL_SET_RAW(str, STR_CHILLED);
+}
+
+static inline bool
is_ascii_string(VALUE str)
{
return rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT;
diff --git a/internal/symbol.h b/internal/symbol.h
index 30c81ea004..e7730cb70f 100644
--- a/internal/symbol.h
+++ b/internal/symbol.h
@@ -32,6 +32,9 @@ ID rb_make_temporary_id(size_t n);
void rb_gc_free_dsymbol(VALUE);
int rb_static_id_valid_p(ID id);
+/* vm.c */
+void rb_free_static_symid_str(void);
+
#if __has_builtin(__builtin_constant_p)
#define rb_sym_intern_ascii_cstr(ptr) \
(__builtin_constant_p(ptr) ? \
diff --git a/internal/thread.h b/internal/thread.h
index 647d1c40c5..47273436e3 100644
--- a/internal/thread.h
+++ b/internal/thread.h
@@ -63,13 +63,17 @@ int rb_notify_fd_close(int fd, struct rb_io_close_wait_list *busy);
void rb_notify_fd_close_wait(struct rb_io_close_wait_list *busy);
RUBY_SYMBOL_EXPORT_BEGIN
+
/* Temporary. This API will be removed (renamed). */
VALUE rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd);
+VALUE rb_thread_io_blocking_call(rb_blocking_function_t *func, void *data1, int fd, int events);
/* thread.c (export) */
int ruby_thread_has_gvl_p(void); /* for ext/fiddle/closure.c */
+
RUBY_SYMBOL_EXPORT_END
int rb_threadptr_execute_interrupts(struct rb_thread_struct *th, int blocking_timing);
+bool rb_thread_mn_schedulable(VALUE thread);
#endif /* INTERNAL_THREAD_H */
diff --git a/internal/transcode.h b/internal/transcode.h
index 9922332ea9..ce4f2341be 100644
--- a/internal/transcode.h
+++ b/internal/transcode.h
@@ -17,4 +17,7 @@
extern VALUE rb_cEncodingConverter;
size_t rb_econv_memsize(rb_econv_t *);
+/* vm.c */
+void rb_free_transcoder_table(void);
+
#endif /* INTERNAL_TRANSCODE_H */
diff --git a/internal/variable.h b/internal/variable.h
index e7e24d2a15..b2a30c7c58 100644
--- a/internal/variable.h
+++ b/internal/variable.h
@@ -47,12 +47,14 @@ VALUE rb_mod_set_temporary_name(VALUE, VALUE);
struct gen_ivtbl;
int rb_gen_ivtbl_get(VALUE obj, ID id, struct gen_ivtbl **ivtbl);
-int rb_obj_evacuate_ivs_to_hash_table(ID key, VALUE val, st_data_t arg);
-void rb_evict_ivars_to_hash(VALUE obj, rb_shape_t * shape);
+void rb_obj_copy_ivs_to_hash_table(VALUE obj, st_table *table);
+void rb_obj_convert_to_too_complex(VALUE obj, st_table *table);
+void rb_evict_ivars_to_hash(VALUE obj);
RUBY_SYMBOL_EXPORT_BEGIN
/* variable.c (export) */
-void rb_mark_and_update_generic_ivar(VALUE);
+void rb_mark_generic_ivar(VALUE obj);
+void rb_ref_update_generic_ivar(VALUE);
void rb_mv_generic_ivar(VALUE src, VALUE dst);
VALUE rb_const_missing(VALUE klass, VALUE name);
int rb_class_ivar_set(VALUE klass, ID vid, VALUE value);
diff --git a/internal/vm.h b/internal/vm.h
index d10c14eb4d..74635e6ad8 100644
--- a/internal/vm.h
+++ b/internal/vm.h
@@ -45,13 +45,13 @@ VALUE rb_vm_push_frame_fname(struct rb_execution_context_struct *ec, VALUE fname
/* vm.c */
VALUE rb_obj_is_thread(VALUE obj);
void rb_vm_mark(void *ptr);
+void rb_vm_register_global_object(VALUE obj);
void rb_vm_each_stack_value(void *ptr, void (*cb)(VALUE, void*), void *ctx);
PUREFUNC(VALUE rb_vm_top_self(void));
const void **rb_vm_get_insns_address_table(void);
VALUE rb_source_location(int *pline);
const char *rb_source_location_cstr(int *pline);
void rb_vm_pop_cfunc_frame(void);
-int rb_vm_add_root_module(VALUE module);
void rb_vm_check_redefinition_by_prepend(VALUE klass);
int rb_vm_check_optimizable_mid(VALUE mid);
VALUE rb_yield_refine_block(VALUE refinement, VALUE refinements);
@@ -83,6 +83,11 @@ void rb_check_stack_overflow(void);
extern uint64_t rb_vm_insns_count;
#endif
+extern bool rb_free_at_exit;
+
+/* miniinit.c and builtin.c */
+void rb_free_loaded_builtin_table(void);
+
/* vm_insnhelper.c */
VALUE rb_equal_opt(VALUE obj1, VALUE obj2);
VALUE rb_eql_opt(VALUE obj1, VALUE obj2);
@@ -109,6 +114,7 @@ void rb_backtrace_print_as_bugreport(FILE*);
int rb_backtrace_p(VALUE obj);
VALUE rb_backtrace_to_str_ary(VALUE obj);
VALUE rb_backtrace_to_location_ary(VALUE obj);
+VALUE rb_location_ary_to_backtrace(VALUE ary);
void rb_backtrace_each(VALUE (*iter)(VALUE recv, VALUE str), VALUE output);
int rb_frame_info_p(VALUE obj);
int rb_get_node_id_from_frame_info(VALUE obj);
diff --git a/io.c b/io.c
index 7ded212804..8acb1f562e 100644
--- a/io.c
+++ b/io.c
@@ -112,6 +112,7 @@
#include "encindex.h"
#include "id.h"
#include "internal.h"
+#include "internal/class.h"
#include "internal/encoding.h"
#include "internal/error.h"
#include "internal/inits.h"
@@ -533,10 +534,12 @@ static rb_io_t *flush_before_seek(rb_io_t *fptr);
extern ID ruby_static_id_signo;
-NORETURN(static void raise_on_write(rb_io_t *fptr, int e, VALUE errinfo));
+NORETURN(static void rb_sys_fail_on_write(rb_io_t *fptr));
static void
-raise_on_write(rb_io_t *fptr, int e, VALUE errinfo)
+rb_sys_fail_on_write(rb_io_t *fptr)
{
+ int e = errno;
+ VALUE errinfo = rb_syserr_new_path(e, (fptr)->pathv);
#if defined EPIPE
if (fptr_signal_on_epipe(fptr) && (e == EPIPE)) {
const VALUE sig =
@@ -550,12 +553,6 @@ raise_on_write(rb_io_t *fptr, int e, VALUE errinfo)
rb_exc_raise(errinfo);
}
-#define rb_sys_fail_on_write(fptr) \
- do { \
- int e = errno; \
- raise_on_write(fptr, e, rb_syserr_new_path(e, (fptr)->pathv)); \
- } while (0)
-
#define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE)
#define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) ((fptr)->mode & FMODE_TEXTMODE)
#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
@@ -1146,6 +1143,11 @@ static int nogvl_wait_for(VALUE th, rb_io_t *fptr, short events, struct timeval
static inline int
io_internal_wait(VALUE thread, rb_io_t *fptr, int error, int events, struct timeval *timeout)
{
+ if (!timeout && rb_thread_mn_schedulable(thread)) {
+ RUBY_ASSERT(errno == EWOULDBLOCK || errno == EAGAIN);
+ return -1;
+ }
+
int ready = nogvl_wait_for(thread, fptr, events, timeout);
if (ready > 0) {
@@ -1286,7 +1288,7 @@ rb_io_read_memory(rb_io_t *fptr, void *buf, size_t count)
iis.timeout = &timeout_storage;
}
- return (ssize_t)rb_thread_io_blocking_region(internal_read_func, &iis, fptr->fd);
+ return (ssize_t)rb_thread_io_blocking_call(internal_read_func, &iis, fptr->fd, RB_WAITFD_IN);
}
static ssize_t
@@ -1319,7 +1321,7 @@ rb_io_write_memory(rb_io_t *fptr, const void *buf, size_t count)
iis.timeout = &timeout_storage;
}
- return (ssize_t)rb_thread_io_blocking_region(internal_write_func, &iis, fptr->fd);
+ return (ssize_t)rb_thread_io_blocking_call(internal_write_func, &iis, fptr->fd, RB_WAITFD_OUT);
}
#ifdef HAVE_WRITEV
@@ -1356,7 +1358,7 @@ rb_writev_internal(rb_io_t *fptr, const struct iovec *iov, int iovcnt)
iis.timeout = &timeout_storage;
}
- return (ssize_t)rb_thread_io_blocking_region(internal_writev_func, &iis, fptr->fd);
+ return (ssize_t)rb_thread_io_blocking_call(internal_writev_func, &iis, fptr->fd, RB_WAITFD_OUT);
}
#endif
@@ -1386,7 +1388,7 @@ static VALUE
io_flush_buffer_async(VALUE arg)
{
rb_io_t *fptr = (rb_io_t *)arg;
- return rb_thread_io_blocking_region(io_flush_buffer_sync, fptr, fptr->fd);
+ return rb_thread_io_blocking_call(io_flush_buffer_sync, fptr, fptr->fd, RB_WAITFD_OUT);
}
static inline int
@@ -1699,7 +1701,6 @@ make_writeconv(rb_io_t *fptr)
/* writing functions */
struct binwrite_arg {
rb_io_t *fptr;
- VALUE str;
const char *ptr;
long length;
};
@@ -1795,13 +1796,11 @@ io_binwrite_string(VALUE arg)
// Write as much as possible:
ssize_t result = io_binwrite_string_internal(p->fptr, ptr, remaining);
- // If only the internal buffer is written, result will be zero [bytes of given data written]. This means we
- // should try again.
if (result == 0) {
- errno = EWOULDBLOCK;
+ // If only the internal buffer is written, result will be zero [bytes of given data written]. This means we
+ // should try again immediately.
}
-
- if (result > 0) {
+ else if (result > 0) {
if ((size_t)result == remaining) break;
ptr += result;
remaining -= result;
@@ -1851,7 +1850,7 @@ io_binwrite_requires_flush_write(rb_io_t *fptr, long len, int nosync)
}
static long
-io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
+io_binwrite(const char *ptr, long len, rb_io_t *fptr, int nosync)
{
if (len <= 0) return len;
@@ -1864,7 +1863,6 @@ io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
struct binwrite_arg arg;
arg.fptr = fptr;
- arg.str = str;
arg.ptr = ptr;
arg.length = len;
@@ -1972,9 +1970,9 @@ io_fwrite(VALUE str, rb_io_t *fptr, int nosync)
if (converted)
OBJ_FREEZE(str);
- tmp = rb_str_tmp_frozen_acquire(str);
+ tmp = rb_str_tmp_frozen_no_embed_acquire(str);
RSTRING_GETMEM(tmp, ptr, len);
- n = io_binwrite(tmp, ptr, len, fptr, nosync);
+ n = io_binwrite(ptr, len, fptr, nosync);
rb_str_tmp_frozen_release(str, tmp);
return n;
@@ -1987,7 +1985,7 @@ rb_io_bufwrite(VALUE io, const void *buf, size_t size)
GetOpenFile(io, fptr);
rb_io_check_writable(fptr);
- return (ssize_t)io_binwrite(0, buf, (long)size, fptr, 0);
+ return (ssize_t)io_binwrite(buf, (long)size, fptr, 0);
}
static VALUE
@@ -2279,7 +2277,7 @@ rb_io_writev(VALUE io, int argc, const VALUE *argv)
if (argc > 1 && rb_obj_method_arity(io, id_write) == 1) {
if (io != rb_ractor_stderr() && RTEST(ruby_verbose)) {
VALUE klass = CLASS_OF(io);
- char sep = FL_TEST(klass, FL_SINGLETON) ? (klass = io, '.') : '#';
+ char sep = RCLASS_SINGLETON_P(klass) ? (klass = io, '.') : '#';
rb_category_warning(
RB_WARN_CATEGORY_DEPRECATED, "%+"PRIsVALUE"%c""write is outdated interface"
" which accepts just one argument",
@@ -2673,7 +2671,7 @@ rb_io_eof(VALUE io)
READ_CHECK(fptr);
#if RUBY_CRLF_ENVIRONMENT
if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
- return RBOOL(eof(fptr->fd));;
+ return RBOOL(eof(fptr->fd));
}
#endif
return RBOOL(io_fillbuf(fptr) < 0);
@@ -3410,7 +3408,12 @@ io_read_memory_call(VALUE arg)
}
}
- return rb_thread_io_blocking_region(internal_read_func, iis, iis->fptr->fd);
+ if (iis->nonblock) {
+ return rb_thread_io_blocking_call(internal_read_func, iis, iis->fptr->fd, 0);
+ }
+ else {
+ return rb_thread_io_blocking_call(internal_read_func, iis, iis->fptr->fd, RB_WAITFD_IN);
+ }
}
static long
@@ -4294,11 +4297,8 @@ rb_io_gets_internal(VALUE io)
* File.open('t.txt') {|f| f.gets(12) } # => "First line\n"
*
* With arguments +sep+ and +limit+ given,
- * combines the two behaviors:
- *
- * - Returns the next line as determined by line separator +sep+,
- * or +nil+ if none.
- * - But returns no more bytes than are allowed by the limit.
+ * combines the two behaviors
+ * (see {Line Separator and Line Limit}[rdoc-ref:IO@Line+Separator+and+Line+Limit]).
*
* Optional keyword argument +chomp+ specifies whether line separators
* are to be omitted:
@@ -4447,10 +4447,8 @@ static VALUE io_readlines(const struct getline_arg *arg, VALUE io);
* f.close
*
* With arguments +sep+ and +limit+ given,
- * combines the two behaviors:
- *
- * - Returns lines as determined by line separator +sep+.
- * - But returns no more bytes in a line than are allowed by the limit.
+ * combines the two behaviors
+ * (see {Line Separator and Line Limit}[rdoc-ref:IO@Line+Separator+and+Line+Limit]).
*
* Optional keyword argument +chomp+ specifies whether line separators
* are to be omitted:
@@ -4570,10 +4568,8 @@ io_readlines(const struct getline_arg *arg, VALUE io)
* "ne\n"
*
* With arguments +sep+ and +limit+ given,
- * combines the two behaviors:
- *
- * - Calls with the next line as determined by line separator +sep+.
- * - But returns no more bytes than are allowed by the limit.
+ * combines the two behaviors
+ * (see {Line Separator and Line Limit}[rdoc-ref:IO@Line+Separator+and+Line+Limit]).
*
* Optional keyword argument +chomp+ specifies whether line separators
* are to be omitted:
@@ -5111,7 +5107,7 @@ rb_io_ungetbyte(VALUE io, VALUE b)
b = rb_str_new((const char *)&c, 1);
break;
default:
- SafeStringValue(b);
+ StringValue(b);
}
io_ungetbyte(b, fptr);
return Qnil;
@@ -5173,7 +5169,7 @@ rb_io_ungetc(VALUE io, VALUE c)
c = rb_enc_uint_chr(NUM2UINT(c), io_read_encoding(fptr));
}
else {
- SafeStringValue(c);
+ StringValue(c);
}
if (NEED_READCONV(fptr)) {
SET_BINARY_MODE(fptr);
@@ -5419,7 +5415,7 @@ maygvl_close(int fd, int keepgvl)
* close() may block for certain file types (NFS, SO_LINGER sockets,
* inotify), so let other threads run.
*/
- return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_close, &fd, RUBY_UBF_IO, 0);
+ return IO_WITHOUT_GVL_INT(nogvl_close, &fd);
}
static void*
@@ -5436,7 +5432,7 @@ maygvl_fclose(FILE *file, int keepgvl)
if (keepgvl)
return fclose(file);
- return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_fclose, file, RUBY_UBF_IO, 0);
+ return IO_WITHOUT_GVL_INT(nogvl_fclose, file);
}
static void free_io_buffer(rb_io_buffer_t *buf);
@@ -5623,7 +5619,7 @@ rb_io_fptr_finalize(rb_io_t *fptr)
}
#define rb_io_fptr_finalize(fptr) rb_io_fptr_finalize_internal(fptr)
-RUBY_FUNC_EXPORTED size_t
+size_t
rb_io_memsize(const rb_io_t *fptr)
{
size_t size = sizeof(rb_io_t);
@@ -6115,7 +6111,7 @@ pread_internal_call(VALUE _arg)
}
}
- return rb_thread_io_blocking_region(internal_pread_func, arg, arg->fd);
+ return rb_thread_io_blocking_call(internal_pread_func, arg, arg->fd, RB_WAITFD_IN);
}
/*
@@ -6248,7 +6244,7 @@ rb_io_pwrite(VALUE io, VALUE str, VALUE offset)
arg.buf = RSTRING_PTR(tmp);
arg.count = (size_t)RSTRING_LEN(tmp);
- n = (ssize_t)rb_thread_io_blocking_region(internal_pwrite_func, &arg, fptr->fd);
+ n = (ssize_t)rb_thread_io_blocking_call(internal_pwrite_func, &arg, fptr->fd, RB_WAITFD_OUT);
if (n < 0) rb_sys_fail_path(fptr->pathv);
rb_str_tmp_frozen_release(str, tmp);
@@ -6824,7 +6820,7 @@ rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
else {
const char *p;
- SafeStringValue(vmode);
+ StringValue(vmode);
p = StringValueCStr(vmode);
fmode = rb_io_modestr_fmode(p);
oflags = rb_io_fmode_oflags(fmode);
@@ -6957,8 +6953,7 @@ sysopen_func(void *ptr)
static inline int
rb_sysopen_internal(struct sysopen_struct *data)
{
- int fd;
- fd = (int)(VALUE)rb_thread_call_without_gvl(sysopen_func, data, RUBY_UBF_IO, 0);
+ int fd = IO_WITHOUT_GVL_INT(sysopen_func, data);
if (0 <= fd)
rb_update_max_fd(fd);
return fd;
@@ -7156,8 +7151,6 @@ rb_file_open_internal(VALUE io, VALUE filename, const char *modestr)
if (p) {
parse_mode_enc(p+1, rb_usascii_encoding(),
&convconfig.enc, &convconfig.enc2, &fmode);
- convconfig.ecflags = 0;
- convconfig.ecopts = Qnil;
}
else {
rb_encoding *e;
@@ -7165,10 +7158,19 @@ rb_file_open_internal(VALUE io, VALUE filename, const char *modestr)
e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
rb_io_ext_int_to_encs(e, NULL, &convconfig.enc, &convconfig.enc2, fmode);
- convconfig.ecflags = 0;
- convconfig.ecopts = Qnil;
}
+ convconfig.ecflags = (fmode & FMODE_READABLE) ?
+ MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR,
+ 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR) : 0;
+#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
+ convconfig.ecflags |= (fmode & FMODE_WRITABLE) ?
+ MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
+ 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
+#endif
+ SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(convconfig.enc2, convconfig.ecflags);
+ convconfig.ecopts = Qnil;
+
return rb_file_open_generic(io, filename,
rb_io_fmode_oflags(fmode),
fmode,
@@ -7933,7 +7935,7 @@ rb_io_popen(VALUE pname, VALUE pmode, VALUE env, VALUE opt)
RB_GC_GUARD(tmp);
}
else {
- SafeStringValue(pname);
+ StringValue(pname);
execarg_obj = Qnil;
if (!is_popen_fork(pname))
execarg_obj = rb_execarg_new(1, &pname, TRUE, FALSE);
@@ -8024,37 +8026,18 @@ ruby_popen_writer(char *const *argv, rb_pid_t *pid)
return NULL;
}
-static void
-rb_scan_open_args(int argc, const VALUE *argv,
- VALUE *fname_p, int *oflags_p, int *fmode_p,
- struct rb_io_encoding *convconfig_p, mode_t *perm_p)
+static VALUE
+rb_open_file(VALUE io, VALUE fname, VALUE vmode, VALUE vperm, VALUE opt)
{
- VALUE opt, fname, vmode, vperm;
+ struct rb_io_encoding convconfig;
int oflags, fmode;
mode_t perm;
- argc = rb_scan_args(argc, argv, "12:", &fname, &vmode, &vperm, &opt);
FilePathValue(fname);
- rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, convconfig_p);
-
- perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
-
- *fname_p = fname;
- *oflags_p = oflags;
- *fmode_p = fmode;
- *perm_p = perm;
-}
-
-static VALUE
-rb_open_file(int argc, const VALUE *argv, VALUE io)
-{
- VALUE fname;
- int oflags, fmode;
- struct rb_io_encoding convconfig;
- mode_t perm;
+ rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, &convconfig);
+ perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
- rb_scan_open_args(argc, argv, &fname, &oflags, &fmode, &convconfig, &perm);
rb_file_open_generic(io, fname, oflags, fmode, &convconfig, perm);
return io;
@@ -8138,7 +8121,7 @@ rb_io_s_sysopen(int argc, VALUE *argv, VALUE _)
else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int")))
oflags = NUM2INT(intmode);
else {
- SafeStringValue(vmode);
+ StringValue(vmode);
oflags = rb_io_modestr_oflags(StringValueCStr(vmode));
}
if (NIL_P(vperm)) perm = 0666;
@@ -8598,7 +8581,7 @@ deprecated_str_setter(VALUE val, ID id, VALUE *var)
{
rb_str_setter(val, id, &val);
if (!NIL_P(val)) {
- rb_warn_deprecated("`%s'", NULL, rb_id2name(id));
+ rb_warn_deprecated("'%s'", NULL, rb_id2name(id));
}
*var = val;
}
@@ -9231,11 +9214,27 @@ static VALUE
prep_io(int fd, int fmode, VALUE klass, const char *path)
{
VALUE path_value = Qnil;
+ rb_encoding *e;
+ struct rb_io_encoding convconfig;
+
if (path) {
path_value = rb_obj_freeze(rb_str_new_cstr(path));
}
- VALUE self = rb_io_open_descriptor(klass, fd, fmode, path_value, Qnil, NULL);
+ e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
+ rb_io_ext_int_to_encs(e, NULL, &convconfig.enc, &convconfig.enc2, fmode);
+ convconfig.ecflags = (fmode & FMODE_READABLE) ?
+ MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR,
+ 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR) : 0;
+#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
+ convconfig.ecflags |= (fmode & FMODE_WRITABLE) ?
+ MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
+ 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
+#endif
+ SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(convconfig.enc2, convconfig.ecflags);
+ convconfig.ecopts = Qnil;
+
+ VALUE self = rb_io_open_descriptor(klass, fd, fmode, path_value, Qnil, &convconfig);
rb_io_t*io = RFILE(self)->fptr;
if (!io_check_tty(io)) {
@@ -9361,6 +9360,8 @@ rb_io_make_open_file(VALUE obj)
return fp;
}
+static VALUE io_initialize(VALUE io, VALUE fnum, VALUE vmode, VALUE opt);
+
/*
* call-seq:
* IO.new(fd, mode = 'r', **opts) -> io
@@ -9406,18 +9407,24 @@ static VALUE
rb_io_initialize(int argc, VALUE *argv, VALUE io)
{
VALUE fnum, vmode;
+ VALUE opt;
+
+ rb_scan_args(argc, argv, "11:", &fnum, &vmode, &opt);
+ return io_initialize(io, fnum, vmode, opt);
+}
+
+static VALUE
+io_initialize(VALUE io, VALUE fnum, VALUE vmode, VALUE opt)
+{
rb_io_t *fp;
int fd, fmode, oflags = O_RDONLY;
struct rb_io_encoding convconfig;
- VALUE opt;
#if defined(HAVE_FCNTL) && defined(F_GETFL)
int ofmode;
#else
struct stat st;
#endif
-
- argc = rb_scan_args(argc, argv, "11:", &fnum, &vmode, &opt);
rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &fmode, &convconfig);
fd = NUM2INT(fnum);
@@ -9566,17 +9573,16 @@ rb_file_initialize(int argc, VALUE *argv, VALUE io)
if (RFILE(io)->fptr) {
rb_raise(rb_eRuntimeError, "reinitializing File");
}
- if (0 < argc && argc < 3) {
- VALUE fd = rb_check_to_int(argv[0]);
+ VALUE fname, vmode, vperm, opt;
+ int posargc = rb_scan_args(argc, argv, "12:", &fname, &vmode, &vperm, &opt);
+ if (posargc < 3) { /* perm is File only */
+ VALUE fd = rb_check_to_int(fname);
if (!NIL_P(fd)) {
- argv[0] = fd;
- return rb_io_initialize(argc, argv, io);
+ return io_initialize(io, fd, vmode, opt);
}
}
- rb_open_file(argc, argv, io);
-
- return io;
+ return rb_open_file(io, fname, vmode, vperm, opt);
}
/* :nodoc: */
@@ -10443,8 +10449,9 @@ static VALUE argf_readlines(int, VALUE *, VALUE);
* $cat t.txt | ruby -e "p readlines 12"
* ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"]
*
- * With arguments +sep+ and +limit+ given, combines the two behaviors;
- * see {Line Separator and Line Limit}[rdoc-ref:IO@Line+Separator+and+Line+Limit].
+ * With arguments +sep+ and +limit+ given,
+ * combines the two behaviors
+ * (see {Line Separator and Line Limit}[rdoc-ref:IO@Line+Separator+and+Line+Limit]).
*
* Optional keyword argument +chomp+ specifies whether line separators
* are to be omitted:
@@ -10468,19 +10475,21 @@ rb_f_readlines(int argc, VALUE *argv, VALUE recv)
/*
* call-seq:
- * ARGF.readlines(sep = $/) -> array
- * ARGF.readlines(limit) -> array
- * ARGF.readlines(sep, limit) -> array
+ * ARGF.readlines(sep = $/, chomp: false) -> array
+ * ARGF.readlines(limit, chomp: false) -> array
+ * ARGF.readlines(sep, limit, chomp: false) -> array
*
- * ARGF.to_a(sep = $/) -> array
- * ARGF.to_a(limit) -> array
- * ARGF.to_a(sep, limit) -> array
+ * ARGF.to_a(sep = $/, chomp: false) -> array
+ * ARGF.to_a(limit, chomp: false) -> array
+ * ARGF.to_a(sep, limit, chomp: false) -> array
*
* Reads each file in ARGF in its entirety, returning an Array containing
* lines from the files. Lines are assumed to be separated by _sep_.
*
* lines = ARGF.readlines
* lines[0] #=> "This is line one\n"
+ *
+ * See +IO.readlines+ for a full description of all options.
*/
static VALUE
argf_readlines(int argc, VALUE *argv, VALUE argf)
@@ -10534,7 +10543,7 @@ rb_f_backquote(VALUE obj, VALUE str)
VALUE result;
rb_io_t *fptr;
- SafeStringValue(str);
+ StringValue(str);
rb_last_status_clear();
port = pipe_open_s(str, "r", FMODE_READABLE|DEFAULT_TEXTMODE, NULL);
if (NIL_P(port)) return rb_str_new(0,0);
@@ -10881,7 +10890,8 @@ rb_io_advise(int argc, VALUE *argv, VALUE io)
* Each of the arguments +read_ios+, +write_ios+, and +error_ios+
* is an array of IO objects.
*
- * Argument +timeout+ is an integer timeout interval in seconds.
+ * Argument +timeout+ is a numeric value (such as integer or float) timeout
+ * interval in seconds.
*
* The method monitors the \IO objects given in all three arrays,
* waiting for some to be ready;
@@ -11540,7 +11550,7 @@ rb_f_syscall(int argc, VALUE *argv, VALUE _)
VALUE v = rb_check_string_type(argv[i]);
if (!NIL_P(v)) {
- SafeStringValue(v);
+ StringValue(v);
rb_str_modify(v);
arg[i] = (VALUE)StringValueCStr(v);
}
@@ -11953,7 +11963,7 @@ io_s_foreach(VALUE v)
*
* With argument +limit+ given, parses lines as determined by the default
* line separator and the given line-length limit
- * (see {Line Limit}[rdoc-ref:IO@Line+Limit]):
+ * (see {Line Separator}[rdoc-ref:IO@Line+Separator] and {Line Limit}[rdoc-ref:IO@Line+Limit]):
*
* File.foreach('t.txt', 7) {|line| p line }
*
@@ -11969,10 +11979,9 @@ io_s_foreach(VALUE v)
* "Fourth l"
* "line\n"
*
- * With arguments +sep+ and +limit+ given,
- * parses lines as determined by the given
- * line separator and the given line-length limit
- * (see {Line Separator and Line Limit}[rdoc-ref:IO@Line+Separator+and+Line+Limit]):
+ * With arguments +sep+ and +limit+ given,
+ * combines the two behaviors
+ * (see {Line Separator and Line Limit}[rdoc-ref:IO@Line+Separator+and+Line+Limit]).
*
* Optional keyword arguments +opts+ specify:
*
@@ -12045,15 +12054,14 @@ io_s_readlines(VALUE v)
*
* With argument +limit+ given, parses lines as determined by the default
* line separator and the given line-length limit
- * (see {Line Limit}[rdoc-ref:IO@Line+Limit]):
+ * (see {Line Separator}[rdoc-ref:IO@Line+Separator] and {Line Limit}[rdoc-ref:IO@Line+Limit]:
*
* IO.readlines('t.txt', 7)
* # => ["First l", "ine\n", "Second ", "line\n", "\n", "Third l", "ine\n", "Fourth ", "line\n"]
*
- * With arguments +sep+ and +limit+ given,
- * parses lines as determined by the given
- * line separator and the given line-length limit
- * (see {Line Separator and Line Limit}[rdoc-ref:IO@Line+Separator+and+Line+Limit]):
+ * With arguments +sep+ and +limit+ given,
+ * combines the two behaviors
+ * (see {Line Separator and Line Limit}[rdoc-ref:IO@Line+Separator+and+Line+Limit]).
*
* Optional keyword arguments +opts+ specify:
*
@@ -13203,7 +13211,7 @@ copy_stream_body(VALUE arg)
rb_str_resize(str,len);
read_buffered_data(RSTRING_PTR(str), len, stp->src_fptr);
if (stp->dst_fptr) { /* IO or filename */
- if (io_binwrite(str, RSTRING_PTR(str), RSTRING_LEN(str), stp->dst_fptr, 0) < 0)
+ if (io_binwrite(RSTRING_PTR(str), RSTRING_LEN(str), stp->dst_fptr, 0) < 0)
rb_sys_fail_on_write(stp->dst_fptr);
}
else /* others such as StringIO */
@@ -13225,7 +13233,7 @@ copy_stream_body(VALUE arg)
return copy_stream_fallback(stp);
}
- rb_thread_call_without_gvl(nogvl_copy_stream_func, (void*)stp, RUBY_UBF_IO, 0);
+ IO_WITHOUT_GVL(nogvl_copy_stream_func, stp);
return Qnil;
}
@@ -14552,14 +14560,14 @@ argf_write_io(VALUE argf)
/*
* call-seq:
- * ARGF.write(string) -> integer
+ * ARGF.write(*objects) -> integer
*
- * Writes _string_ if inplace mode.
+ * Writes each of the given +objects+ if inplace mode.
*/
static VALUE
-argf_write(VALUE argf, VALUE str)
+argf_write(int argc, VALUE *argv, VALUE argf)
{
- return rb_io_write(argf_write_io(argf), str);
+ return rb_io_writev(argf_write_io(argf), argc, argv);
}
void
@@ -14665,47 +14673,253 @@ set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
/*
* Document-class: ARGF
*
- * ARGF is a stream designed for use in scripts that process files given as
- * command-line arguments or passed in via STDIN.
+ * == \ARGF and +ARGV+
+ *
+ * The \ARGF object works with the array at global variable +ARGV+
+ * to make <tt>$stdin</tt> and file streams available in the Ruby program:
+ *
+ * - **ARGV** may be thought of as the <b>argument vector</b> array.
+ *
+ * Initially, it contains the command-line arguments and options
+ * that are passed to the Ruby program;
+ * the program can modify that array as it likes.
+ *
+ * - **ARGF** may be thought of as the <b>argument files</b> object.
+ *
+ * It can access file streams and/or the <tt>$stdin</tt> stream,
+ * based on what it finds in +ARGV+.
+ * This provides a convenient way for the command line
+ * to specify streams for a Ruby program to read.
+ *
+ * == Reading
+ *
+ * \ARGF may read from _source_ streams,
+ * which at any particular time are determined by the content of +ARGV+.
+ *
+ * === Simplest Case
+ *
+ * When the <i>very first</i> \ARGF read occurs with an empty +ARGV+ (<tt>[]</tt>),
+ * the source is <tt>$stdin</tt>:
+ *
+ * - \File +t.rb+:
+ *
+ * p ['ARGV', ARGV]
+ * p ['ARGF.read', ARGF.read]
+ *
+ * - Commands and outputs
+ * (see below for the content of files +foo.txt+ and +bar.txt+):
+ *
+ * $ echo "Open the pod bay doors, Hal." | ruby t.rb
+ * ["ARGV", []]
+ * ["ARGF.read", "Open the pod bay doors, Hal.\n"]
+ *
+ * $ cat foo.txt bar.txt | ruby t.rb
+ * ["ARGV", []]
+ * ["ARGF.read", "Foo 0\nFoo 1\nBar 0\nBar 1\nBar 2\nBar 3\n"]
+ *
+ * === About the Examples
+ *
+ * Many examples here assume the existence of files +foo.txt+ and +bar.txt+:
+ *
+ * $ cat foo.txt
+ * Foo 0
+ * Foo 1
+ * $ cat bar.txt
+ * Bar 0
+ * Bar 1
+ * Bar 2
+ * Bar 3
+ *
+ * === Sources in +ARGV+
+ *
+ * For any \ARGF read _except_ the {simplest case}[rdoc-ref:ARGF@Simplest+Case]
+ * (that is, _except_ for the <i>very first</i> \ARGF read with an empty +ARGV+),
+ * the sources are found in +ARGV+.
+ *
+ * \ARGF assumes that each element in array +ARGV+ is a potential source,
+ * and is one of:
+ *
+ * - The string path to a file that may be opened as a stream.
+ * - The character <tt>'-'</tt>, meaning stream <tt>$stdin</tt>.
+ *
+ * Each element that is _not_ one of these
+ * should be removed from +ARGV+ before \ARGF accesses that source.
+ *
+ * In the following example:
+ *
+ * - Filepaths +foo.txt+ and +bar.txt+ may be retained as potential sources.
+ * - Options <tt>--xyzzy</tt> and <tt>--mojo</tt> should be removed.
+ *
+ * Example:
+ *
+ * - \File +t.rb+:
+ *
+ * # Print arguments (and options, if any) found on command line.
+ * p ['ARGV', ARGV]
*
- * The arguments passed to your script are stored in the +ARGV+ Array, one
- * argument per element. ARGF assumes that any arguments that aren't
- * filenames have been removed from +ARGV+. For example:
+ * - Command and output:
*
- * $ ruby argf.rb --verbose file1 file2
+ * $ ruby t.rb --xyzzy --mojo foo.txt bar.txt
+ * ["ARGV", ["--xyzzy", "--mojo", "foo.txt", "bar.txt"]]
*
- * ARGV #=> ["--verbose", "file1", "file2"]
- * option = ARGV.shift #=> "--verbose"
- * ARGV #=> ["file1", "file2"]
+ * \ARGF's stream access considers the elements of +ARGV+, left to right:
*
- * You can now use ARGF to work with a concatenation of each of these named
- * files. For instance, ARGF.read will return the contents of _file1_
- * followed by the contents of _file2_.
+ * - \File +t.rb+:
*
- * After a file in +ARGV+ has been read ARGF removes it from the Array.
- * Thus, after all files have been read +ARGV+ will be empty.
+ * p "ARGV: #{ARGV}"
+ * p "Line: #{ARGF.read}" # Read everything from all specified streams.
*
- * You can manipulate +ARGV+ yourself to control what ARGF operates on. If
- * you remove a file from +ARGV+, it is ignored by ARGF; if you add files to
- * +ARGV+, they are treated as if they were named on the command line. For
- * example:
+ * - Command and output:
*
- * ARGV.replace ["file1"]
- * ARGF.readlines # Returns the contents of file1 as an Array
- * ARGV #=> []
- * ARGV.replace ["file2", "file3"]
- * ARGF.read # Returns the contents of file2 and file3
+ * $ ruby t.rb foo.txt bar.txt
+ * "ARGV: [\"foo.txt\", \"bar.txt\"]"
+ * "Read: Foo 0\nFoo 1\nBar 0\nBar 1\nBar 2\nBar 3\n"
*
- * If +ARGV+ is empty, ARGF acts as if it contained <tt>"-"</tt> that
- * makes ARGF read from STDIN, i.e. the data piped or typed to your
- * script. For example:
+ * Because the value at +ARGV+ is an ordinary array,
+ * you can manipulate it to control which sources \ARGF considers:
*
- * $ echo "glark" | ruby -e 'p ARGF.read'
- * "glark\n"
+ * - If you remove an element from +ARGV+, \ARGF will not consider the corresponding source.
+ * - If you add an element to +ARGV+, \ARGF will consider the corresponding source.
+ *
+ * Each element in +ARGV+ is removed when its corresponding source is accessed;
+ * when all sources have been accessed, the array is empty:
+ *
+ * - \File +t.rb+:
+ *
+ * until ARGV.empty? && ARGF.eof?
+ * p "ARGV: #{ARGV}"
+ * p "Line: #{ARGF.readline}" # Read each line from each specified stream.
+ * end
+ *
+ * - Command and output:
+ *
+ * $ ruby t.rb foo.txt bar.txt
+ * "ARGV: [\"foo.txt\", \"bar.txt\"]"
+ * "Line: Foo 0\n"
+ * "ARGV: [\"bar.txt\"]"
+ * "Line: Foo 1\n"
+ * "ARGV: [\"bar.txt\"]"
+ * "Line: Bar 0\n"
+ * "ARGV: []"
+ * "Line: Bar 1\n"
+ * "ARGV: []"
+ * "Line: Bar 2\n"
+ * "ARGV: []"
+ * "Line: Bar 3\n"
+ *
+ * ==== Filepaths in +ARGV+
+ *
+ * The +ARGV+ array may contain filepaths the specify sources for \ARGF reading.
+ *
+ * This program prints what it reads from files at the paths specified
+ * on the command line:
+ *
+ * - \File +t.rb+:
+ *
+ * p ['ARGV', ARGV]
+ * # Read and print all content from the specified sources.
+ * p ['ARGF.read', ARGF.read]
+ *
+ * - Command and output:
+ *
+ * $ ruby t.rb foo.txt bar.txt
+ * ["ARGV", [foo.txt, bar.txt]
+ * ["ARGF.read", "Foo 0\nFoo 1\nBar 0\nBar 1\nBar 2\nBar 3\n"]
+ *
+ * ==== Specifying <tt>$stdin</tt> in +ARGV+
+ *
+ * To specify stream <tt>$stdin</tt> in +ARGV+, us the character <tt>'-'</tt>:
+ *
+ * - \File +t.rb+:
+ *
+ * p ['ARGV', ARGV]
+ * p ['ARGF.read', ARGF.read]
+ *
+ * - Command and output:
+ *
+ * $ echo "Open the pod bay doors, Hal." | ruby t.rb -
+ * ["ARGV", ["-"]]
+ * ["ARGF.read", "Open the pod bay doors, Hal.\n"]
+ *
+ * When no character <tt>'-'</tt> is given, stream <tt>$stdin</tt> is ignored
+ * (exception:
+ * see {Specifying $stdin in ARGV}[rdoc-ref:ARGF@Specifying+-24stdin+in+ARGV]):
+ *
+ * - Command and output:
+ *
+ * $ echo "Open the pod bay doors, Hal." | ruby t.rb foo.txt bar.txt
+ * "ARGV: [\"foo.txt\", \"bar.txt\"]"
+ * "Read: Foo 0\nFoo 1\nBar 0\nBar 1\nBar 2\nBar 3\n"
+ *
+ * ==== Mixtures and Repetitions in +ARGV+
+ *
+ * For an \ARGF reader, +ARGV+ may contain any mixture of filepaths
+ * and character <tt>'-'</tt>, including repetitions.
+ *
+ * ==== Modifications to +ARGV+
+ *
+ * The running Ruby program may make any modifications to the +ARGV+ array;
+ * the current value of +ARGV+ affects \ARGF reading.
+ *
+ * ==== Empty +ARGV+
+ *
+ * For an empty +ARGV+, an \ARGF read method either returns +nil+
+ * or raises an exception, depending on the specific method.
+ *
+ * === More Read Methods
+ *
+ * As seen above, method ARGF#read reads the content of all sources
+ * into a single string.
+ * Other \ARGF methods provide other ways to access that content;
+ * these include:
+ *
+ * - Byte access: #each_byte, #getbyte, #readbyte.
+ * - Character access: #each_char, #getc, #readchar.
+ * - Codepoint access: #each_codepoint.
+ * - Line access: #each_line, #gets, #readline, #readlines.
+ * - Source access: #read, #read_nonblock, #readpartial.
+ *
+ * === About \Enumerable
+ *
+ * \ARGF includes module Enumerable.
+ * Virtually all methods in \Enumerable call method <tt>#each</tt> in the including class.
+ *
+ * <b>Note well</b>: In \ARGF, method #each returns data from the _sources_,
+ * _not_ from +ARGV+;
+ * therefore, for example, <tt>ARGF#entries</tt> returns an array of lines from the sources,
+ * not an array of the strings from +ARGV+:
+ *
+ * - \File +t.rb+:
+ *
+ * p ['ARGV', ARGV]
+ * p ['ARGF.entries', ARGF.entries]
+ *
+ * - Command and output:
+ *
+ * $ ruby t.rb foo.txt bar.txt
+ * ["ARGV", ["foo.txt", "bar.txt"]]
+ * ["ARGF.entries", ["Foo 0\n", "Foo 1\n", "Bar 0\n", "Bar 1\n", "Bar 2\n", "Bar 3\n"]]
+ *
+ * == Writing
+ *
+ * If <i>inplace mode</i> is in effect,
+ * \ARGF may write to target streams,
+ * which at any particular time are determined by the content of ARGV.
+ *
+ * Methods about inplace mode:
+ *
+ * - #inplace_mode
+ * - #inplace_mode=
+ * - #to_write_io
+ *
+ * Methods for writing:
+ *
+ * - #print
+ * - #printf
+ * - #putc
+ * - #puts
+ * - #write
*
- * $ echo Glark > file1
- * $ echo "glark" | ruby -e 'p ARGF.read' -- - file1
- * "glark\nGlark\n"
*/
/*
@@ -14857,56 +15071,64 @@ set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
*
* == Line \IO
*
- * You can read an \IO stream line-by-line using these methods:
+ * \Class \IO supports line-oriented
+ * {input}[rdoc-ref:IO@Line+Input] and {output}[rdoc-ref:IO@Line+Output]
*
- * - IO#each_line: Reads each remaining line, passing it to the given block.
- * - IO#gets: Returns the next line.
- * - IO#readline: Like #gets, but raises an exception at end-of-stream.
- * - IO#readlines: Returns all remaining lines in an array.
+ * === Line Input
+ *
+ * \Class \IO supports line-oriented input for
+ * {files}[rdoc-ref:IO@File+Line+Input] and {IO streams}[rdoc-ref:IO@Stream+Line+Input]
+ *
+ * ==== \File Line Input
+ *
+ * You can read lines from a file using these methods:
+ *
+ * - IO.foreach: Reads each line and passes it to the given block.
+ * - IO.readlines: Reads and returns all lines in an array.
*
- * Each of these reader methods accepts:
+ * For each of these methods:
*
- * - An optional line separator, +sep+;
+ * - You can specify {open options}[rdoc-ref:IO@Open+Options].
+ * - Line parsing depends on the effective <i>line separator</i>;
* see {Line Separator}[rdoc-ref:IO@Line+Separator].
- * - An optional line-size limit, +limit+;
+ * - The length of each returned line depends on the effective <i>line limit</i>;
* see {Line Limit}[rdoc-ref:IO@Line+Limit].
*
- * For each of these reader methods, reading may begin mid-line,
- * depending on the stream's position;
- * see {Position}[rdoc-ref:IO@Position]:
- *
- * f = File.new('t.txt')
- * f.pos = 27
- * f.each_line {|line| p line }
- * f.close
+ * ==== Stream Line Input
*
- * Output:
+ * You can read lines from an \IO stream using these methods:
*
- * "rth line\n"
- * "Fifth line\n"
+ * - IO#each_line: Reads each remaining line, passing it to the given block.
+ * - IO#gets: Returns the next line.
+ * - IO#readline: Like #gets, but raises an exception at end-of-stream.
+ * - IO#readlines: Returns all remaining lines in an array.
*
- * You can write to an \IO stream line-by-line using this method:
+ * For each of these methods:
*
- * - IO#puts: Writes objects to the stream.
+ * - Reading may begin mid-line,
+ * depending on the stream's _position_;
+ * see {Position}[rdoc-ref:IO@Position].
+ * - Line parsing depends on the effective <i>line separator</i>;
+ * see {Line Separator}[rdoc-ref:IO@Line+Separator].
+ * - The length of each returned line depends on the effective <i>line limit</i>;
+ * see {Line Limit}[rdoc-ref:IO@Line+Limit].
*
- * === Line Separator
+ * ===== Line Separator
*
- * Each of these methods uses a <i>line separator</i>,
- * which is the string that delimits lines:
+ * Each of the {line input methods}[rdoc-ref:IO@Line+Input] uses a <i>line separator</i>:
+ * the string that determines what is considered a line;
+ * it is sometimes called the <i>input record separator</i>.
*
- * - IO.foreach.
- * - IO.readlines.
- * - IO#each_line.
- * - IO#gets.
- * - IO#readline.
- * - IO#readlines.
+ * The default line separator is taken from global variable <tt>$/</tt>,
+ * whose initial value is <tt>"\n"</tt>.
*
- * The default line separator is the given by the global variable <tt>$/</tt>,
- * whose value is by default <tt>"\n"</tt>.
- * The line to be read next is all data from the current position
- * to the next line separator:
+ * Generally, the line to be read next is all data
+ * from the current {position}[rdoc-ref:IO@Position]
+ * to the next line separator
+ * (but see {Special Line Separator Values}[rdoc-ref:IO@Special+Line+Separator+Values]):
*
* f = File.new('t.txt')
+ * # Method gets with no sep argument returns the next line, according to $/.
* f.gets # => "First line\n"
* f.gets # => "Second line\n"
* f.gets # => "\n"
@@ -14914,7 +15136,7 @@ set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
* f.gets # => "Fifth line\n"
* f.close
*
- * You can specify a different line separator:
+ * You can use a different line separator by passing argument +sep+:
*
* f = File.new('t.txt')
* f.gets('l') # => "First l"
@@ -14923,15 +15145,27 @@ set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
* f.gets # => "e\n"
* f.close
*
- * There are two special line separators:
+ * Or by setting global variable <tt>$/</tt>:
+ *
+ * f = File.new('t.txt')
+ * $/ = 'l'
+ * f.gets # => "First l"
+ * f.gets # => "ine\nSecond l"
+ * f.gets # => "ine\n\nFourth l"
+ * f.close
+ *
+ * ===== Special Line Separator Values
*
- * - +nil+: The entire stream is read into a single string:
+ * Each of the {line input methods}[rdoc-ref:IO@Line+Input]
+ * accepts two special values for parameter +sep+:
+ *
+ * - +nil+: The entire stream is to be read ("slurped") into a single string:
*
* f = File.new('t.txt')
* f.gets(nil) # => "First line\nSecond line\n\nFourth line\nFifth line\n"
* f.close
*
- * - <tt>''</tt> (the empty string): The next "paragraph" is read
+ * - <tt>''</tt> (the empty string): The next "paragraph" is to be read
* (paragraphs being separated by two consecutive line separators):
*
* f = File.new('t.txt')
@@ -14939,23 +15173,18 @@ set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
* f.gets('') # => "Fourth line\nFifth line\n"
* f.close
*
- * === Line Limit
- *
- * Each of these methods uses a <i>line limit</i>,
- * which specifies that the number of bytes returned may not be (much) longer
- * than the given +limit+;
+ * ===== Line Limit
*
- * - IO.foreach.
- * - IO.readlines.
- * - IO#each_line.
- * - IO#gets.
- * - IO#readline.
- * - IO#readlines.
+ * Each of the {line input methods}[rdoc-ref:IO@Line+Input]
+ * uses an integer <i>line limit</i>,
+ * which restricts the number of bytes that may be returned.
+ * (A multi-byte character will not be split, and so a returned line may be slightly longer
+ * than the limit).
*
- * A multi-byte character will not be split, and so a line may be slightly longer
- * than the given limit.
+ * The default limit value is <tt>-1</tt>;
+ * any negative limit value means that there is no limit.
*
- * If +limit+ is not given, the line is determined only by +sep+.
+ * If there is no limit, the line is determined only by +sep+.
*
* # Text with 1-byte characters.
* File.open('t.txt') {|f| f.gets(1) } # => "F"
@@ -14973,24 +15202,21 @@ set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
* File.open('t.rus') {|f| f.gets(3).size } # => 2
* File.open('t.rus') {|f| f.gets(4).size } # => 2
*
- * === Line Separator and Line Limit
+ * ===== Line Separator and Line Limit
*
- * With arguments +sep+ and +limit+ given,
- * combines the two behaviors:
+ * With arguments +sep+ and +limit+ given, combines the two behaviors:
*
* - Returns the next line as determined by line separator +sep+.
- * - But returns no more bytes than are allowed by the limit.
+ * - But returns no more bytes than are allowed by the limit +limit+.
*
* Example:
*
* File.open('t.txt') {|f| f.gets('li', 20) } # => "First li"
* File.open('t.txt') {|f| f.gets('li', 2) } # => "Fi"
*
- * === Line Number
+ * ===== Line Number
*
- * A readable \IO stream has a non-negative integer <i>line number</i>.
- *
- * The relevant methods:
+ * A readable \IO stream has a non-negative integer <i>line number</i>:
*
* - IO#lineno: Returns the line number.
* - IO#lineno=: Resets and returns the line number.
@@ -14998,7 +15224,7 @@ set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
* Unless modified by a call to method IO#lineno=,
* the line number is the number of lines read
* by certain line-oriented methods,
- * according to the given line separator +sep+:
+ * according to the effective {line separator}[rdoc-ref:IO@Line+Separator]:
*
* - IO.foreach: Increments the line number on each call to the block.
* - IO#each_line: Increments the line number on each call to the block.
@@ -15088,6 +15314,12 @@ set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
* $. # => 5
* f.close
*
+ * === Line Output
+ *
+ * You can write to an \IO stream line-by-line using this method:
+ *
+ * - IO#puts: Writes objects to the stream.
+ *
* == Character \IO
*
* You can process an \IO stream character-by-character using these methods:
@@ -15319,8 +15551,11 @@ Init_IO(void)
/* Can be raised by IO operations when IO#timeout= is set. */
rb_eIOTimeoutError = rb_define_class_under(rb_cIO, "TimeoutError", rb_eIOError);
+ /* Readable event mask for IO#wait. */
rb_define_const(rb_cIO, "READABLE", INT2NUM(RUBY_IO_READABLE));
+ /* Writable event mask for IO#wait. */
rb_define_const(rb_cIO, "WRITABLE", INT2NUM(RUBY_IO_WRITABLE));
+ /* Priority event mask for IO#wait. */
rb_define_const(rb_cIO, "PRIORITY", INT2NUM(RUBY_IO_PRIORITY));
/* exception to wait for reading. see IO.select. */
@@ -15383,7 +15618,7 @@ Init_IO(void)
rb_define_hooked_variable("$,", &rb_output_fs, 0, deprecated_str_setter);
rb_default_rs = rb_fstring_lit("\n"); /* avoid modifying RS_default */
- rb_gc_register_mark_object(rb_default_rs);
+ rb_vm_register_global_object(rb_default_rs);
rb_rs = rb_default_rs;
rb_output_rs = Qnil;
rb_define_hooked_variable("$/", &rb_rs, 0, deprecated_str_setter);
@@ -15577,7 +15812,7 @@ Init_IO(void)
rb_define_method(rb_cARGF, "binmode", argf_binmode_m, 0);
rb_define_method(rb_cARGF, "binmode?", argf_binmode_p, 0);
- rb_define_method(rb_cARGF, "write", argf_write, 1);
+ rb_define_method(rb_cARGF, "write", argf_write, -1);
rb_define_method(rb_cARGF, "print", rb_io_print, -1);
rb_define_method(rb_cARGF, "putc", rb_io_putc, 1);
rb_define_method(rb_cARGF, "puts", rb_io_puts, -1);
diff --git a/io_buffer.c b/io_buffer.c
index 942ab268ae..e6ca61bdae 100644
--- a/io_buffer.c
+++ b/io_buffer.c
@@ -34,6 +34,18 @@ size_t RUBY_IO_BUFFER_DEFAULT_SIZE;
#include <sys/mman.h>
#endif
+enum {
+ RB_IO_BUFFER_HEXDUMP_DEFAULT_WIDTH = 16,
+
+ RB_IO_BUFFER_INSPECT_HEXDUMP_MAXIMUM_SIZE = 256,
+ RB_IO_BUFFER_INSPECT_HEXDUMP_WIDTH = 16,
+
+ // This is used to validate the flags given by the user.
+ RB_IO_BUFFER_FLAGS_MASK = RB_IO_BUFFER_EXTERNAL | RB_IO_BUFFER_INTERNAL | RB_IO_BUFFER_MAPPED | RB_IO_BUFFER_SHARED | RB_IO_BUFFER_LOCKED | RB_IO_BUFFER_PRIVATE | RB_IO_BUFFER_READONLY,
+
+ RB_IO_BUFFER_DEBUG = 0,
+};
+
struct rb_io_buffer {
void *base;
size_t size;
@@ -91,11 +103,9 @@ io_buffer_map_file(struct rb_io_buffer *buffer, int descriptor, size_t size, rb_
access = FILE_MAP_WRITE;
}
- HANDLE mapping = CreateFileMapping(file, NULL, protect, 0, 0, NULL);
- if (!mapping) rb_sys_fail("io_buffer_map_descriptor:CreateFileMapping");
-
if (flags & RB_IO_BUFFER_PRIVATE) {
- access |= FILE_MAP_COPY;
+ protect = PAGE_WRITECOPY;
+ access = FILE_MAP_COPY;
buffer->flags |= RB_IO_BUFFER_PRIVATE;
}
else {
@@ -104,6 +114,10 @@ io_buffer_map_file(struct rb_io_buffer *buffer, int descriptor, size_t size, rb_
buffer->flags |= RB_IO_BUFFER_SHARED;
}
+ HANDLE mapping = CreateFileMapping(file, NULL, protect, 0, 0, NULL);
+ if (RB_IO_BUFFER_DEBUG) fprintf(stderr, "io_buffer_map_file:CreateFileMapping -> %p\n", mapping);
+ if (!mapping) rb_sys_fail("io_buffer_map_descriptor:CreateFileMapping");
+
void *base = MapViewOfFile(mapping, access, (DWORD)(offset >> 32), (DWORD)(offset & 0xFFFFFFFF), size);
if (!base) {
@@ -124,6 +138,7 @@ io_buffer_map_file(struct rb_io_buffer *buffer, int descriptor, size_t size, rb_
if (flags & RB_IO_BUFFER_PRIVATE) {
buffer->flags |= RB_IO_BUFFER_PRIVATE;
+ access |= MAP_PRIVATE;
}
else {
// This buffer refers to external buffer.
@@ -143,16 +158,7 @@ io_buffer_map_file(struct rb_io_buffer *buffer, int descriptor, size_t size, rb_
buffer->size = size;
buffer->flags |= RB_IO_BUFFER_MAPPED;
-}
-
-static inline void
-io_buffer_unmap(void* base, size_t size)
-{
-#ifdef _WIN32
- VirtualFree(base, 0, MEM_RELEASE);
-#else
- munmap(base, size);
-#endif
+ buffer->flags |= RB_IO_BUFFER_FILE;
}
static void
@@ -183,7 +189,7 @@ io_buffer_zero(struct rb_io_buffer *buffer)
}
static void
-io_buffer_initialize(struct rb_io_buffer *buffer, void *base, size_t size, enum rb_io_buffer_flags flags, VALUE source)
+io_buffer_initialize(VALUE self, struct rb_io_buffer *buffer, void *base, size_t size, enum rb_io_buffer_flags flags, VALUE source)
{
if (base) {
// If we are provided a pointer, we use it.
@@ -209,10 +215,14 @@ io_buffer_initialize(struct rb_io_buffer *buffer, void *base, size_t size, enum
buffer->base = base;
buffer->size = size;
buffer->flags = flags;
- buffer->source = source;
+ RB_OBJ_WRITE(self, &buffer->source, source);
+
+#if defined(_WIN32)
+ buffer->mapping = NULL;
+#endif
}
-static int
+static void
io_buffer_free(struct rb_io_buffer *buffer)
{
if (buffer->base) {
@@ -221,7 +231,16 @@ io_buffer_free(struct rb_io_buffer *buffer)
}
if (buffer->flags & RB_IO_BUFFER_MAPPED) {
- io_buffer_unmap(buffer->base, buffer->size);
+#ifdef _WIN32
+ if (buffer->flags & RB_IO_BUFFER_FILE) {
+ UnmapViewOfFile(buffer->base);
+ }
+ else {
+ VirtualFree(buffer->base, 0, MEM_RELEASE);
+ }
+#else
+ munmap(buffer->base, buffer->size);
+#endif
}
// Previously we had this, but we found out due to the way GC works, we
@@ -232,20 +251,20 @@ io_buffer_free(struct rb_io_buffer *buffer)
buffer->base = NULL;
-#if defined(_WIN32)
- if (buffer->mapping) {
- CloseHandle(buffer->mapping);
- buffer->mapping = NULL;
- }
-#endif
buffer->size = 0;
buffer->flags = 0;
buffer->source = Qnil;
-
- return 1;
}
- return 0;
+#if defined(_WIN32)
+ if (buffer->mapping) {
+ if (RB_IO_BUFFER_DEBUG) fprintf(stderr, "io_buffer_free:CloseHandle -> %p\n", buffer->mapping);
+ if (!CloseHandle(buffer->mapping)) {
+ fprintf(stderr, "io_buffer_free:GetLastError -> %lu\n", GetLastError());
+ }
+ buffer->mapping = NULL;
+ }
+#endif
}
void
@@ -261,8 +280,6 @@ rb_io_buffer_type_free(void *_buffer)
struct rb_io_buffer *buffer = _buffer;
io_buffer_free(buffer);
-
- free(buffer);
}
size_t
@@ -286,10 +303,23 @@ static const rb_data_type_t rb_io_buffer_type = {
.dsize = rb_io_buffer_type_size,
},
.data = NULL,
- .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE,
};
-// Extract an offset argument, which must be a positive integer.
+static inline enum rb_io_buffer_flags
+io_buffer_extract_flags(VALUE argument)
+{
+ if (rb_int_negative_p(argument)) {
+ rb_raise(rb_eArgError, "Flags can't be negative!");
+ }
+
+ enum rb_io_buffer_flags flags = RB_NUM2UINT(argument);
+
+ // We deliberately ignore unknown flags. Any future flags which are exposed this way should be safe to ignore.
+ return flags & RB_IO_BUFFER_FLAGS_MASK;
+}
+
+// Extract an offset argument, which must be a non-negative integer.
static inline size_t
io_buffer_extract_offset(VALUE argument)
{
@@ -300,7 +330,7 @@ io_buffer_extract_offset(VALUE argument)
return NUM2SIZET(argument);
}
-// Extract a length argument, which must be a positive integer.
+// Extract a length argument, which must be a non-negative integer.
// Length is generally considered a mutable property of an object and
// semantically should be considered a subset of "size" as a concept.
static inline size_t
@@ -313,7 +343,7 @@ io_buffer_extract_length(VALUE argument)
return NUM2SIZET(argument);
}
-// Extract a size argument, which must be a positive integer.
+// Extract a size argument, which must be a non-negative integer.
// Size is generally considered an immutable property of an object.
static inline size_t
io_buffer_extract_size(VALUE argument)
@@ -325,6 +355,24 @@ io_buffer_extract_size(VALUE argument)
return NUM2SIZET(argument);
}
+// Extract a width argument, which must be a non-negative integer, and must be
+// at least the given minimum.
+static inline size_t
+io_buffer_extract_width(VALUE argument, size_t minimum)
+{
+ if (rb_int_negative_p(argument)) {
+ rb_raise(rb_eArgError, "Width can't be negative!");
+ }
+
+ size_t width = NUM2SIZET(argument);
+
+ if (width < minimum) {
+ rb_raise(rb_eArgError, "Width must be at least %" PRIuSIZE "!", minimum);
+ }
+
+ return width;
+}
+
// Compute the default length for a buffer, given an offset into that buffer.
// The default length is the size of the buffer minus the offset. The offset
// must be less than the size of the buffer otherwise the length will be
@@ -351,7 +399,7 @@ io_buffer_extract_length_offset(VALUE self, int argc, VALUE argv[], size_t *leng
struct rb_io_buffer *buffer = NULL;
TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
- if (argc >= 2) {
+ if (argc >= 2 && !NIL_P(argv[1])) {
*offset = io_buffer_extract_offset(argv[1]);
}
else {
@@ -369,22 +417,28 @@ io_buffer_extract_length_offset(VALUE self, int argc, VALUE argv[], size_t *leng
}
// Extract the optional offset and length arguments, returning the buffer.
-// Similar to `io_buffer_extract_length_offset` but with the order of
-// arguments reversed.
+// Similar to `io_buffer_extract_length_offset` but with the order of arguments
+// reversed.
+//
+// After much consideration, I decided to accept both forms.
+// The `(offset, length)` order is more natural when referring about data,
+// while the `(length, offset)` order is more natural when referring to
+// read/write operations. In many cases, with the latter form, `offset`
+// is usually not supplied.
static inline struct rb_io_buffer *
io_buffer_extract_offset_length(VALUE self, int argc, VALUE argv[], size_t *offset, size_t *length)
{
struct rb_io_buffer *buffer = NULL;
TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
- if (argc >= 1) {
+ if (argc >= 1 && !NIL_P(argv[0])) {
*offset = io_buffer_extract_offset(argv[0]);
}
else {
*offset = 0;
}
- if (argc >= 2) {
+ if (argc >= 2 && !NIL_P(argv[1])) {
*length = io_buffer_extract_length(argv[1]);
}
else {
@@ -420,7 +474,7 @@ static VALUE io_buffer_for_make_instance(VALUE klass, VALUE string, enum rb_io_b
if (!(flags & RB_IO_BUFFER_READONLY))
rb_str_modify(string);
- io_buffer_initialize(buffer, RSTRING_PTR(string), RSTRING_LEN(string), flags, string);
+ io_buffer_initialize(instance, buffer, RSTRING_PTR(string), RSTRING_LEN(string), flags, string);
return instance;
}
@@ -463,11 +517,11 @@ io_buffer_for_yield_instance_ensure(VALUE _arguments)
* IO::Buffer.for(string) -> readonly io_buffer
* IO::Buffer.for(string) {|io_buffer| ... read/write io_buffer ...}
*
- * Creates a IO::Buffer from the given string's memory. Without a block a
- * frozen internal copy of the string is created efficiently and used as the
- * buffer source. When a block is provided, the buffer is associated directly
- * with the string's internal buffer and updating the buffer will update the
- * string.
+ * Creates a zero-copy IO::Buffer from the given string's memory. Without a
+ * block a frozen internal copy of the string is created efficiently and used
+ * as the buffer source. When a block is provided, the buffer is associated
+ * directly with the string's internal buffer and updating the buffer will
+ * update the string.
*
* Until #free is invoked on the buffer, either explicitly or via the garbage
* collector, the source string will be locked and cannot be modified.
@@ -522,9 +576,9 @@ rb_io_buffer_type_for(VALUE klass, VALUE string)
* call-seq:
* IO::Buffer.string(length) {|io_buffer| ... read/write io_buffer ...} -> string
*
- * Creates a new string of the given length and yields a IO::Buffer instance
- * to the block which uses the string as a source. The block is expected to
- * write to the buffer and the string will be returned.
+ * Creates a new string of the given length and yields a zero-copy IO::Buffer
+ * instance to the block which uses the string as a source. The block is
+ * expected to write to the buffer and the string will be returned.
*
* IO::Buffer.string(4) do |buffer|
* buffer.set_string("Ruby")
@@ -555,7 +609,7 @@ rb_io_buffer_new(void *base, size_t size, enum rb_io_buffer_flags flags)
struct rb_io_buffer *buffer = NULL;
TypedData_Get_Struct(instance, struct rb_io_buffer, &rb_io_buffer_type, buffer);
- io_buffer_initialize(buffer, base, size, flags, Qnil);
+ io_buffer_initialize(instance, buffer, base, size, flags, Qnil);
return instance;
}
@@ -589,8 +643,6 @@ rb_io_buffer_map(VALUE io, size_t size, rb_off_t offset, enum rb_io_buffer_flags
* mapping, you need to open a file in read-write mode, and explicitly pass
* +flags+ argument without IO::Buffer::IMMUTABLE.
*
- * Example:
- *
* File.write('test.txt', 'test')
*
* buffer = IO::Buffer.map(File.open('test.txt'), nil, 0, IO::Buffer::READONLY)
@@ -653,7 +705,7 @@ io_buffer_map(int argc, VALUE *argv, VALUE klass)
enum rb_io_buffer_flags flags = 0;
if (argc >= 4) {
- flags = RB_NUM2UINT(argv[3]);
+ flags = io_buffer_extract_flags(argv[3]);
}
return rb_io_buffer_map(io, size, offset, flags);
@@ -681,8 +733,6 @@ io_flags_for_size(size_t size)
* on Windows). The behavior can be forced by passing IO::Buffer::MAPPED
* as a second parameter.
*
- * Examples
- *
* buffer = IO::Buffer.new(4)
* # =>
* # #<IO::Buffer 0x000055b34497ea10+4 INTERNAL>
@@ -716,13 +766,13 @@ rb_io_buffer_initialize(int argc, VALUE *argv, VALUE self)
enum rb_io_buffer_flags flags = 0;
if (argc >= 2) {
- flags = RB_NUM2UINT(argv[1]);
+ flags = io_buffer_extract_flags(argv[1]);
}
else {
flags |= io_flags_for_size(size);
}
- io_buffer_initialize(buffer, NULL, size, flags, Qnil);
+ io_buffer_initialize(self, buffer, NULL, size, flags, Qnil);
return self;
}
@@ -768,6 +818,82 @@ io_buffer_validate(struct rb_io_buffer *buffer)
}
}
+enum rb_io_buffer_flags
+rb_io_buffer_get_bytes(VALUE self, void **base, size_t *size)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ if (io_buffer_validate(buffer)) {
+ if (buffer->base) {
+ *base = buffer->base;
+ *size = buffer->size;
+
+ return buffer->flags;
+ }
+ }
+
+ *base = NULL;
+ *size = 0;
+
+ return 0;
+}
+
+// Internal function for accessing bytes for writing, wil
+static inline void
+io_buffer_get_bytes_for_writing(struct rb_io_buffer *buffer, void **base, size_t *size)
+{
+ if (buffer->flags & RB_IO_BUFFER_READONLY) {
+ rb_raise(rb_eIOBufferAccessError, "Buffer is not writable!");
+ }
+
+ if (!io_buffer_validate(buffer)) {
+ rb_raise(rb_eIOBufferInvalidatedError, "Buffer is invalid!");
+ }
+
+ if (buffer->base) {
+ *base = buffer->base;
+ *size = buffer->size;
+ } else {
+ *base = NULL;
+ *size = 0;
+ }
+}
+
+void
+rb_io_buffer_get_bytes_for_writing(VALUE self, void **base, size_t *size)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ io_buffer_get_bytes_for_writing(buffer, base, size);
+}
+
+static void
+io_buffer_get_bytes_for_reading(struct rb_io_buffer *buffer, const void **base, size_t *size)
+{
+ if (!io_buffer_validate(buffer)) {
+ rb_raise(rb_eIOBufferInvalidatedError, "Buffer has been invalidated!");
+ }
+
+ if (buffer->base) {
+ *base = buffer->base;
+ *size = buffer->size;
+ } else {
+ *base = NULL;
+ *size = 0;
+ }
+}
+
+void
+rb_io_buffer_get_bytes_for_reading(VALUE self, const void **base, size_t *size)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ io_buffer_get_bytes_for_reading(buffer, base, size);
+}
+
/*
* call-seq: to_s -> string
*
@@ -804,6 +930,10 @@ rb_io_buffer_to_s(VALUE self)
rb_str_cat2(result, " MAPPED");
}
+ if (buffer->flags & RB_IO_BUFFER_FILE) {
+ rb_str_cat2(result, " FILE");
+ }
+
if (buffer->flags & RB_IO_BUFFER_SHARED) {
rb_str_cat2(result, " SHARED");
}
@@ -812,6 +942,10 @@ rb_io_buffer_to_s(VALUE self)
rb_str_cat2(result, " LOCKED");
}
+ if (buffer->flags & RB_IO_BUFFER_PRIVATE) {
+ rb_str_cat2(result, " PRIVATE");
+ }
+
if (buffer->flags & RB_IO_BUFFER_READONLY) {
rb_str_cat2(result, " READONLY");
}
@@ -827,13 +961,38 @@ rb_io_buffer_to_s(VALUE self)
return rb_str_cat2(result, ">");
}
+// Compute the output size of a hexdump of the given width (bytes per line), total size, and whether it is the first line in the output.
+// This is used to preallocate the output string.
+inline static size_t
+io_buffer_hexdump_output_size(size_t width, size_t size, int first)
+{
+ // The preview on the right hand side is 1:1:
+ size_t total = size;
+
+ size_t whole_lines = (size / width);
+ size_t partial_line = (size % width) ? 1 : 0;
+
+ // For each line:
+ // 1 byte 10 bytes 1 byte width*3 bytes 1 byte size bytes
+ // (newline) (address) (space) (hexdump ) (space) (preview)
+ total += (whole_lines + partial_line) * (1 + 10 + width*3 + 1 + 1);
+
+ // If the hexdump is the first line, one less newline will be emitted:
+ if (size && first) total -= 1;
+
+ return total;
+}
+
+// Append a hexdump of the given width (bytes per line), base address, size, and whether it is the first line in the output.
+// If the hexdump is not the first line, it will prepend a newline if there is any output at all.
+// If formatting here is adjusted, please update io_buffer_hexdump_output_size accordingly.
static VALUE
-io_buffer_hexdump(VALUE string, size_t width, char *base, size_t size, int first)
+io_buffer_hexdump(VALUE string, size_t width, const char *base, size_t length, size_t offset, int first)
{
char *text = alloca(width+1);
text[width] = '\0';
- for (size_t offset = 0; offset < size; offset += width) {
+ for (; offset < length; offset += width) {
memset(text, '\0', width);
if (first) {
rb_str_catf(string, "0x%08" PRIxSIZE " ", offset);
@@ -844,7 +1003,7 @@ io_buffer_hexdump(VALUE string, size_t width, char *base, size_t size, int first
}
for (size_t i = 0; i < width; i += 1) {
- if (offset+i < size) {
+ if (offset+i < length) {
unsigned char value = ((unsigned char*)base)[offset+i];
if (value < 127 && isprint(value)) {
@@ -867,23 +1026,18 @@ io_buffer_hexdump(VALUE string, size_t width, char *base, size_t size, int first
return string;
}
-static VALUE
-rb_io_buffer_hexdump(VALUE self)
-{
- struct rb_io_buffer *buffer = NULL;
- TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
-
- VALUE result = Qnil;
-
- if (io_buffer_validate(buffer) && buffer->base) {
- result = rb_str_buf_new(buffer->size*3 + (buffer->size/16)*12 + 1);
-
- io_buffer_hexdump(result, 16, buffer->base, buffer->size, 1);
- }
-
- return result;
-}
-
+/*
+ * call-seq: inspect -> string
+ *
+ * Inspect the buffer and report useful information about it's internal state.
+ * Only a limited portion of the buffer will be displayed in a hexdump style
+ * format.
+ *
+ * buffer = IO::Buffer.for("Hello World")
+ * puts buffer.inspect
+ * # #<IO::Buffer 0x000000010198ccd8+11 EXTERNAL READONLY SLICE>
+ * # 0x00000000 48 65 6c 6c 6f 20 57 6f 72 6c 64 Hello World
+ */
VALUE
rb_io_buffer_inspect(VALUE self)
{
@@ -893,9 +1047,19 @@ rb_io_buffer_inspect(VALUE self)
VALUE result = rb_io_buffer_to_s(self);
if (io_buffer_validate(buffer)) {
- // Limit the maximum size generated by inspect.
- if (buffer->size <= 256) {
- io_buffer_hexdump(result, 16, buffer->base, buffer->size, 0);
+ // Limit the maximum size generated by inspect:
+ size_t size = buffer->size;
+ int clamped = 0;
+
+ if (size > RB_IO_BUFFER_INSPECT_HEXDUMP_MAXIMUM_SIZE) {
+ size = RB_IO_BUFFER_INSPECT_HEXDUMP_MAXIMUM_SIZE;
+ clamped = 1;
+ }
+
+ io_buffer_hexdump(result, RB_IO_BUFFER_INSPECT_HEXDUMP_WIDTH, buffer->base, size, 0, 0);
+
+ if (clamped) {
+ rb_str_catf(result, "\n(and %" PRIuSIZE " more bytes not printed)", buffer->size - size);
}
}
@@ -922,8 +1086,8 @@ rb_io_buffer_size(VALUE self)
*
* Returns whether the buffer buffer is accessible.
*
- * A buffer becomes invalid if it is a slice of another buffer which has been
- * freed.
+ * A buffer becomes invalid if it is a slice of another buffer (or string)
+ * which has been freed or re-allocated at a different address.
*/
static VALUE
rb_io_buffer_valid_p(VALUE self)
@@ -937,8 +1101,16 @@ rb_io_buffer_valid_p(VALUE self)
/*
* call-seq: null? -> true or false
*
- * If the buffer was freed with #free or was never allocated in the first
- * place.
+ * If the buffer was freed with #free, transferred with #transfer, or was
+ * never allocated in the first place.
+ *
+ * buffer = IO::Buffer.new(0)
+ * buffer.null? #=> true
+ *
+ * buffer = IO::Buffer.new(4)
+ * buffer.null? #=> false
+ * buffer.free
+ * buffer.null? #=> true
*/
static VALUE
rb_io_buffer_null_p(VALUE self)
@@ -1038,6 +1210,22 @@ rb_io_buffer_mapped_p(VALUE self)
* If the buffer is _shared_, meaning it references memory that can be shared
* with other processes (and thus might change without being modified
* locally).
+ *
+ * # Create a test file:
+ * File.write('test.txt', 'test')
+ *
+ * # Create a shared mapping from the given file, the file must be opened in
+ * # read-write mode unless we also specify IO::Buffer::READONLY:
+ * buffer = IO::Buffer.map(File.open('test.txt', 'r+'), nil, 0)
+ * # => #<IO::Buffer 0x00007f1bffd5e000+4 EXTERNAL MAPPED SHARED>
+ *
+ * # Write to the buffer, which will modify the mapped file:
+ * buffer.set_string('b', 0)
+ * # => 1
+ *
+ * # The file itself is modified:
+ * File.read('test.txt')
+ * # => "best"
*/
static VALUE
rb_io_buffer_shared_p(VALUE self)
@@ -1058,8 +1246,6 @@ rb_io_buffer_shared_p(VALUE self)
* Locking is not thread safe, but is a semantic used to ensure buffers don't
* move while being used by a system call.
*
- * Example:
- *
* buffer.locked do
* buffer.write(io) # theoretical system call interface
* end
@@ -1073,6 +1259,37 @@ rb_io_buffer_locked_p(VALUE self)
return RBOOL(buffer->flags & RB_IO_BUFFER_LOCKED);
}
+/* call-seq: private? -> true or false
+ *
+ * If the buffer is _private_, meaning modifications to the buffer will not
+ * be replicated to the underlying file mapping.
+ *
+ * # Create a test file:
+ * File.write('test.txt', 'test')
+ *
+ * # Create a private mapping from the given file. Note that the file here
+ * # is opened in read-only mode, but it doesn't matter due to the private
+ * # mapping:
+ * buffer = IO::Buffer.map(File.open('test.txt'), nil, 0, IO::Buffer::PRIVATE)
+ * # => #<IO::Buffer 0x00007fce63f11000+4 MAPPED PRIVATE>
+ *
+ * # Write to the buffer (invoking CoW of the underlying file buffer):
+ * buffer.set_string('b', 0)
+ * # => 1
+ *
+ * # The file itself is not modified:
+ * File.read('test.txt')
+ * # => "test"
+ */
+static VALUE
+rb_io_buffer_private_p(VALUE self)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ return RBOOL(buffer->flags & RB_IO_BUFFER_PRIVATE);
+}
+
int
rb_io_buffer_readonly_p(VALUE self)
{
@@ -1166,8 +1383,6 @@ rb_io_buffer_try_unlock(VALUE self)
* non-blocking system calls. You can only share a buffer between threads with
* appropriate synchronisation techniques.
*
- * Example:
- *
* buffer = IO::Buffer.new(4)
* buffer.locked? #=> false
*
@@ -1215,8 +1430,6 @@ rb_io_buffer_locked(VALUE self)
*
* You can resize a freed buffer to re-allocate it.
*
- * Example:
- *
* buffer = IO::Buffer.for('test')
* buffer.free
* # => #<IO::Buffer 0x0000000000000000+0 NULL>
@@ -1267,6 +1480,49 @@ io_buffer_validate_range(struct rb_io_buffer *buffer, size_t offset, size_t leng
}
}
+/*
+ * call-seq: hexdump([offset, [length, [width]]]) -> string
+ *
+ * Returns a human-readable string representation of the buffer. The exact
+ * format is subject to change.
+ *
+ * buffer = IO::Buffer.for("Hello World")
+ * puts buffer.hexdump
+ * # 0x00000000 48 65 6c 6c 6f 20 57 6f 72 6c 64 Hello World
+ *
+ * As buffers are usually fairly big, you may want to limit the output by
+ * specifying the offset and length:
+ *
+ * puts buffer.hexdump(6, 5)
+ * # 0x00000006 57 6f 72 6c 64 World
+ */
+static VALUE
+rb_io_buffer_hexdump(int argc, VALUE *argv, VALUE self)
+{
+ rb_check_arity(argc, 0, 3);
+
+ size_t offset, length;
+ struct rb_io_buffer *buffer = io_buffer_extract_offset_length(self, argc, argv, &offset, &length);
+
+ size_t width = RB_IO_BUFFER_HEXDUMP_DEFAULT_WIDTH;
+ if (argc >= 3) {
+ width = io_buffer_extract_width(argv[2], 1);
+ }
+
+ // This may raise an exception if the offset/length is invalid:
+ io_buffer_validate_range(buffer, offset, length);
+
+ VALUE result = Qnil;
+
+ if (io_buffer_validate(buffer) && buffer->base) {
+ result = rb_str_buf_new(io_buffer_hexdump_output_size(width, length, 1));
+
+ io_buffer_hexdump(result, width, buffer->base, offset+length, offset, 1);
+ }
+
+ return result;
+}
+
static VALUE
rb_io_buffer_slice(struct rb_io_buffer *buffer, VALUE self, size_t offset, size_t length)
{
@@ -1280,10 +1536,12 @@ rb_io_buffer_slice(struct rb_io_buffer *buffer, VALUE self, size_t offset, size_
slice->size = length;
// The source should be the root buffer:
- if (buffer->source != Qnil)
- slice->source = buffer->source;
- else
- slice->source = self;
+ if (buffer->source != Qnil) {
+ RB_OBJ_WRITE(instance, &slice->source, buffer->source);
+ }
+ else {
+ RB_OBJ_WRITE(instance, &slice->source, self);
+ }
return instance;
}
@@ -1307,8 +1565,6 @@ rb_io_buffer_slice(struct rb_io_buffer *buffer, VALUE self, size_t offset, size_
* Raises RuntimeError if the <tt>offset+length</tt> is out of the current
* buffer's bounds.
*
- * Example:
- *
* string = 'test'
* buffer = IO::Buffer.for(string)
*
@@ -1355,89 +1611,11 @@ io_buffer_slice(int argc, VALUE *argv, VALUE self)
return rb_io_buffer_slice(buffer, self, offset, length);
}
-int
-rb_io_buffer_get_bytes(VALUE self, void **base, size_t *size)
-{
- struct rb_io_buffer *buffer = NULL;
- TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
-
- if (io_buffer_validate(buffer)) {
- if (buffer->base) {
- *base = buffer->base;
- *size = buffer->size;
-
- return buffer->flags;
- }
- }
-
- *base = NULL;
- *size = 0;
-
- return 0;
-}
-
-static inline void
-io_buffer_get_bytes_for_writing(struct rb_io_buffer *buffer, void **base, size_t *size)
-{
- if (buffer->flags & RB_IO_BUFFER_READONLY) {
- rb_raise(rb_eIOBufferAccessError, "Buffer is not writable!");
- }
-
- if (!io_buffer_validate(buffer)) {
- rb_raise(rb_eIOBufferInvalidatedError, "Buffer is invalid!");
- }
-
- if (buffer->base) {
- *base = buffer->base;
- *size = buffer->size;
-
- return;
- }
-
- rb_raise(rb_eIOBufferAllocationError, "The buffer is not allocated!");
-}
-
-void
-rb_io_buffer_get_bytes_for_writing(VALUE self, void **base, size_t *size)
-{
- struct rb_io_buffer *buffer = NULL;
- TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
-
- io_buffer_get_bytes_for_writing(buffer, base, size);
-}
-
-static void
-io_buffer_get_bytes_for_reading(struct rb_io_buffer *buffer, const void **base, size_t *size)
-{
- if (!io_buffer_validate(buffer)) {
- rb_raise(rb_eIOBufferInvalidatedError, "Buffer has been invalidated!");
- }
-
- if (buffer->base) {
- *base = buffer->base;
- *size = buffer->size;
-
- return;
- }
-
- rb_raise(rb_eIOBufferAllocationError, "The buffer is not allocated!");
-}
-
-void
-rb_io_buffer_get_bytes_for_reading(VALUE self, const void **base, size_t *size)
-{
- struct rb_io_buffer *buffer = NULL;
- TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
-
- io_buffer_get_bytes_for_reading(buffer, base, size);
-}
-
/*
* call-seq: transfer -> new_io_buffer
*
- * Transfers ownership to a new buffer, deallocating the current one.
- *
- * Example:
+ * Transfers ownership of the underlying memory to a new buffer, causing the
+ * current buffer to become uninitialized.
*
* buffer = IO::Buffer.new('test')
* other = buffer.transfer
@@ -1480,11 +1658,11 @@ io_buffer_resize_clear(struct rb_io_buffer *buffer, void* base, size_t size)
}
static void
-io_buffer_resize_copy(struct rb_io_buffer *buffer, size_t size)
+io_buffer_resize_copy(VALUE self, struct rb_io_buffer *buffer, size_t size)
{
// Slow path:
struct rb_io_buffer resized;
- io_buffer_initialize(&resized, NULL, size, io_flags_for_size(size), Qnil);
+ io_buffer_initialize(self, &resized, NULL, size, io_flags_for_size(size), Qnil);
if (buffer->base) {
size_t preserve = buffer->size;
@@ -1509,7 +1687,7 @@ rb_io_buffer_resize(VALUE self, size_t size)
}
if (buffer->base == NULL) {
- io_buffer_initialize(buffer, NULL, size, io_flags_for_size(size), Qnil);
+ io_buffer_initialize(self, buffer, NULL, size, io_flags_for_size(size), Qnil);
return;
}
@@ -1554,7 +1732,7 @@ rb_io_buffer_resize(VALUE self, size_t size)
return;
}
- io_buffer_resize_copy(buffer, size);
+ io_buffer_resize_copy(self, buffer, size);
}
/*
@@ -1749,8 +1927,6 @@ io_buffer_buffer_type_size(ID buffer_type)
*
* Returns the size of the given buffer type(s) in bytes.
*
- * Example:
- *
* IO::Buffer.size_of(:u32) # => 4
* IO::Buffer.size_of([:u32, :u32]) # => 8
*/
@@ -1829,8 +2005,6 @@ rb_io_buffer_get_value(const void* base, size_t size, ID buffer_type, size_t *of
* in the buffer. For example, a +:u32+ buffer type is a 32-bit unsigned
* integer in little-endian format.
*
- * Example:
- *
* string = [1.5].pack('f')
* # => "\x00\x00\xC0?"
* IO::Buffer.for(string).get_value(:f32, 0)
@@ -1854,8 +2028,6 @@ io_buffer_get_value(VALUE self, VALUE type, VALUE _offset)
* Similar to #get_value, except that it can handle multiple buffer types and
* returns an array of values.
*
- * Example:
- *
* string = [1.5, 2.5].pack('ff')
* IO::Buffer.for(string).get_values([:f32, :f32], 0)
* # => [1.5, 2.5]
@@ -1928,8 +2100,6 @@ io_buffer_extract_offset_count(ID buffer_type, size_t size, int argc, VALUE *arg
*
* If +count+ is given, only +count+ values will be yielded.
*
- * Example:
- *
* IO::Buffer.for("Hello World").each(:U8, 2, 2) do |offset, value|
* puts "#{offset}: #{value}"
* end
@@ -1973,8 +2143,6 @@ io_buffer_each(int argc, VALUE *argv, VALUE self)
*
* If +count+ is given, only +count+ values will be returned.
*
- * Example:
- *
* IO::Buffer.for("Hello World").values(:U8, 2, 2)
* # => [108, 108]
*/
@@ -2016,8 +2184,6 @@ io_buffer_values(int argc, VALUE *argv, VALUE self)
*
* If +count+ is given, only +count+ bytes will be yielded.
*
- * Example:
- *
* IO::Buffer.for("Hello World").each_byte(2, 2) do |offset, byte|
* puts "#{offset}: #{byte}"
* end
@@ -2127,8 +2293,6 @@ io_buffer_set_value(VALUE self, VALUE type, VALUE _offset, VALUE value)
* should be an array of symbols as described in #get_value. +values+ should
* be an array of values to write.
*
- * Example:
- *
* buffer = IO::Buffer.new(8)
* buffer.set_values([:U8, :U16], 0, [1, 2])
* buffer
@@ -2249,7 +2413,7 @@ rb_io_buffer_initialize_copy(VALUE self, VALUE source)
rb_io_buffer_get_bytes_for_reading(source, &source_base, &source_size);
- io_buffer_initialize(buffer, NULL, source_size, io_flags_for_size(source_size), Qnil);
+ io_buffer_initialize(self, buffer, NULL, source_size, io_flags_for_size(source_size), Qnil);
return io_buffer_copy_from(buffer, source_base, source_size, 0, NULL);
}
@@ -2277,13 +2441,13 @@ rb_io_buffer_initialize_copy(VALUE self, VALUE source)
*
* #copy can be used to put buffer into strings associated with buffer:
*
- * string= "buffer: "
- * # => "buffer: "
+ * string= "data: "
+ * # => "data: "
* buffer = IO::Buffer.for(string)
* buffer.copy(IO::Buffer.for("test"), 5)
* # => 4
* string
- * # => "buffer:test"
+ * # => "data:test"
*
* Attempt to copy into a read-only buffer will fail:
*
@@ -2367,8 +2531,8 @@ io_buffer_get_string(int argc, VALUE *argv, VALUE self)
/*
* call-seq: set_string(string, [offset, [length, [source_offset]]]) -> size
*
- * Efficiently copy buffer from a source String into the buffer,
- * at +offset+ using +memcpy+.
+ * Efficiently copy from a source String into the buffer, at +offset+ using
+ * +memcpy+.
*
* buf = IO::Buffer.new(8)
* # =>
@@ -2628,8 +2792,6 @@ rb_io_buffer_read(VALUE self, VALUE io, size_t length, size_t offset)
* If +offset+ is not given, it defaults to zero, i.e. the beginning of the
* buffer.
*
- * Example:
- *
* IO::Buffer.for('test') do |buffer|
* p buffer
* # =>
@@ -2749,8 +2911,6 @@ rb_io_buffer_pread(VALUE self, VALUE io, rb_off_t from, size_t length, size_t of
* If +offset+ is not given, it defaults to zero, i.e. the beginning of the
* buffer.
*
- * Example:
- *
* IO::Buffer.for('test') do |buffer|
* p buffer
* # =>
@@ -2869,8 +3029,6 @@ rb_io_buffer_write(VALUE self, VALUE io, size_t length, size_t offset)
* If +offset+ is not given, it defaults to zero, i.e. the beginning of the
* buffer.
*
- * Example:
- *
* out = File.open('output.txt', 'wb')
* IO::Buffer.for('1234567').write(out, 3)
*
@@ -2993,8 +3151,6 @@ rb_io_buffer_pwrite(VALUE self, VALUE io, rb_off_t from, size_t length, size_t o
* If the +from+ position is beyond the end of the file, the gap will be
* filled with null (0 value) bytes.
*
- * Example:
- *
* out = File.open('output.txt', File::RDWR) # open for read/write, no truncation
* IO::Buffer.for('1234567').pwrite(out, 2, 3, 1)
*
@@ -3375,24 +3531,28 @@ io_buffer_not_inplace(VALUE self)
/*
* Document-class: IO::Buffer
*
- * IO::Buffer is a low-level efficient buffer for input/output. There are three
- * ways of using buffer:
+ * IO::Buffer is a efficient zero-copy buffer for input/output. There are
+ * typical use cases:
*
* * Create an empty buffer with ::new, fill it with buffer using #copy or
- * #set_value, #set_string, get buffer with #get_string;
+ * #set_value, #set_string, get buffer with #get_string or write it directly
+ * to some file with #write.
* * Create a buffer mapped to some string with ::for, then it could be used
* both for reading with #get_string or #get_value, and writing (writing will
- * change the source string, too);
+ * change the source string, too).
* * Create a buffer mapped to some file with ::map, then it could be used for
* reading and writing the underlying file.
+ * * Create a string of a fixed size with ::string, then #read into it, or
+ * modify it using #set_value.
*
* Interaction with string and file memory is performed by efficient low-level
* C mechanisms like `memcpy`.
*
* The class is meant to be an utility for implementing more high-level mechanisms
- * like Fiber::SchedulerInterface#io_read and Fiber::SchedulerInterface#io_write.
+ * like Fiber::Scheduler#io_read and Fiber::Scheduler#io_write and parsing binary
+ * protocols.
*
- * <b>Examples of usage:</b>
+ * == Examples of Usage
*
* Empty buffer:
*
@@ -3411,30 +3571,28 @@ io_buffer_not_inplace(VALUE self)
*
* \Buffer from string:
*
- * string = 'buffer'
- * buffer = IO::Buffer.for(string)
- * # =>
- * # #<IO::Buffer 0x00007f3f02be9b18+4 SLICE>
- * # ...
- * buffer
- * # =>
- * # #<IO::Buffer 0x00007f3f02be9b18+4 SLICE>
- * # 0x00000000 64 61 74 61 buffer
- *
- * buffer.get_string(2) # read content starting from offset 2
- * # => "ta"
- * buffer.set_string('---', 1) # write content, starting from offset 1
- * # => 3
- * buffer
- * # =>
- * # #<IO::Buffer 0x00007f3f02be9b18+4 SLICE>
- * # 0x00000000 64 2d 2d 2d d---
- * string # original string changed, too
- * # => "d---"
+ * string = 'data'
+ * IO::Buffer.for(string) do |buffer|
+ * buffer
+ * # =>
+ * # #<IO::Buffer 0x00007f3f02be9b18+4 SLICE>
+ * # 0x00000000 64 61 74 61 data
+ *
+ * buffer.get_string(2) # read content starting from offset 2
+ * # => "ta"
+ * buffer.set_string('---', 1) # write content, starting from offset 1
+ * # => 3
+ * buffer
+ * # =>
+ * # #<IO::Buffer 0x00007f3f02be9b18+4 SLICE>
+ * # 0x00000000 64 2d 2d 2d d---
+ * string # original string changed, too
+ * # => "d---"
+ * end
*
* \Buffer from file:
*
- * File.write('test.txt', 'test buffer')
+ * File.write('test.txt', 'test data')
* # => 9
* buffer = IO::Buffer.map(File.open('test.txt'))
* # =>
@@ -3451,18 +3609,30 @@ io_buffer_not_inplace(VALUE self)
* buffer.set_string('---', 1)
* # => 3 -- bytes written
* File.read('test.txt')
- * # => "t--- buffer"
+ * # => "t--- data"
*
- * <b>The class is experimental and the interface is subject to change.</b>
+ * <b>The class is experimental and the interface is subject to change, this
+ * is especially true of file mappings which may be removed entirely in
+ * the future.</b>
*/
void
Init_IO_Buffer(void)
{
rb_cIOBuffer = rb_define_class_under(rb_cIO, "Buffer", rb_cObject);
+
+ /* Raised when an operation would resize or re-allocate a locked buffer. */
rb_eIOBufferLockedError = rb_define_class_under(rb_cIOBuffer, "LockedError", rb_eRuntimeError);
+
+ /* Raised when the buffer cannot be allocated for some reason, or you try to use a buffer that's not allocated. */
rb_eIOBufferAllocationError = rb_define_class_under(rb_cIOBuffer, "AllocationError", rb_eRuntimeError);
+
+ /* Raised when you try to write to a read-only buffer, or resize an external buffer. */
rb_eIOBufferAccessError = rb_define_class_under(rb_cIOBuffer, "AccessError", rb_eRuntimeError);
+
+ /* Raised if you try to access a buffer slice which no longer references a valid memory range of the underlying source. */
rb_eIOBufferInvalidatedError = rb_define_class_under(rb_cIOBuffer, "InvalidatedError", rb_eRuntimeError);
+
+ /* Raised if the mask given to a binary operation is invalid, e.g. zero length or overlaps the target buffer. */
rb_eIOBufferMaskError = rb_define_class_under(rb_cIOBuffer, "MaskError", rb_eArgError);
rb_define_alloc_func(rb_cIOBuffer, rb_io_buffer_type_allocate);
@@ -3479,37 +3649,57 @@ Init_IO_Buffer(void)
RUBY_IO_BUFFER_DEFAULT_SIZE = io_buffer_default_size(RUBY_IO_BUFFER_PAGE_SIZE);
- // Efficient sizing of mapped buffers:
+ /* The operating system page size. Used for efficient page-aligned memory allocations. */
rb_define_const(rb_cIOBuffer, "PAGE_SIZE", SIZET2NUM(RUBY_IO_BUFFER_PAGE_SIZE));
+
+ /* The default buffer size, typically a (small) multiple of the PAGE_SIZE.
+ Can be explicitly specified by setting the RUBY_IO_BUFFER_DEFAULT_SIZE
+ environment variable. */
rb_define_const(rb_cIOBuffer, "DEFAULT_SIZE", SIZET2NUM(RUBY_IO_BUFFER_DEFAULT_SIZE));
rb_define_singleton_method(rb_cIOBuffer, "map", io_buffer_map, -1);
- // General use:
rb_define_method(rb_cIOBuffer, "initialize", rb_io_buffer_initialize, -1);
rb_define_method(rb_cIOBuffer, "initialize_copy", rb_io_buffer_initialize_copy, 1);
rb_define_method(rb_cIOBuffer, "inspect", rb_io_buffer_inspect, 0);
- rb_define_method(rb_cIOBuffer, "hexdump", rb_io_buffer_hexdump, 0);
+ rb_define_method(rb_cIOBuffer, "hexdump", rb_io_buffer_hexdump, -1);
rb_define_method(rb_cIOBuffer, "to_s", rb_io_buffer_to_s, 0);
rb_define_method(rb_cIOBuffer, "size", rb_io_buffer_size, 0);
rb_define_method(rb_cIOBuffer, "valid?", rb_io_buffer_valid_p, 0);
- // Ownership:
rb_define_method(rb_cIOBuffer, "transfer", rb_io_buffer_transfer, 0);
- // Flags:
+ /* Indicates that the memory in the buffer is owned by someone else. See #external? for more details. */
rb_define_const(rb_cIOBuffer, "EXTERNAL", RB_INT2NUM(RB_IO_BUFFER_EXTERNAL));
+
+ /* Indicates that the memory in the buffer is owned by the buffer. See #internal? for more details. */
rb_define_const(rb_cIOBuffer, "INTERNAL", RB_INT2NUM(RB_IO_BUFFER_INTERNAL));
+
+ /* Indicates that the memory in the buffer is mapped by the operating system. See #mapped? for more details. */
rb_define_const(rb_cIOBuffer, "MAPPED", RB_INT2NUM(RB_IO_BUFFER_MAPPED));
+
+ /* Indicates that the memory in the buffer is also mapped such that it can be shared with other processes. See #shared? for more details. */
rb_define_const(rb_cIOBuffer, "SHARED", RB_INT2NUM(RB_IO_BUFFER_SHARED));
+
+ /* Indicates that the memory in the buffer is locked and cannot be resized or freed. See #locked? and #locked for more details. */
rb_define_const(rb_cIOBuffer, "LOCKED", RB_INT2NUM(RB_IO_BUFFER_LOCKED));
+
+ /* Indicates that the memory in the buffer is mapped privately and changes won't be replicated to the underlying file. See #private? for more details. */
rb_define_const(rb_cIOBuffer, "PRIVATE", RB_INT2NUM(RB_IO_BUFFER_PRIVATE));
+
+ /* Indicates that the memory in the buffer is read only, and attempts to modify it will fail. See #readonly? for more details.*/
rb_define_const(rb_cIOBuffer, "READONLY", RB_INT2NUM(RB_IO_BUFFER_READONLY));
- // Endian:
+ /* Refers to little endian byte order, where the least significant byte is stored first. See #get_value for more details. */
rb_define_const(rb_cIOBuffer, "LITTLE_ENDIAN", RB_INT2NUM(RB_IO_BUFFER_LITTLE_ENDIAN));
+
+ /* Refers to big endian byte order, where the most significant byte is stored first. See #get_value for more details. */
rb_define_const(rb_cIOBuffer, "BIG_ENDIAN", RB_INT2NUM(RB_IO_BUFFER_BIG_ENDIAN));
+
+ /* Refers to the byte order of the host machine. See #get_value for more details. */
rb_define_const(rb_cIOBuffer, "HOST_ENDIAN", RB_INT2NUM(RB_IO_BUFFER_HOST_ENDIAN));
+
+ /* Refers to network byte order, which is the same as big endian. See #get_value for more details. */
rb_define_const(rb_cIOBuffer, "NETWORK_ENDIAN", RB_INT2NUM(RB_IO_BUFFER_NETWORK_ENDIAN));
rb_define_method(rb_cIOBuffer, "null?", rb_io_buffer_null_p, 0);
@@ -3519,6 +3709,7 @@ Init_IO_Buffer(void)
rb_define_method(rb_cIOBuffer, "mapped?", rb_io_buffer_mapped_p, 0);
rb_define_method(rb_cIOBuffer, "shared?", rb_io_buffer_shared_p, 0);
rb_define_method(rb_cIOBuffer, "locked?", rb_io_buffer_locked_p, 0);
+ rb_define_method(rb_cIOBuffer, "private?", rb_io_buffer_private_p, 0);
rb_define_method(rb_cIOBuffer, "readonly?", io_buffer_readonly_p, 0);
// Locking to prevent changes while using pointer:
diff --git a/iseq.c b/iseq.c
index 0b58b51b48..05d52b61b4 100644
--- a/iseq.c
+++ b/iseq.c
@@ -28,6 +28,7 @@
#include "internal/file.h"
#include "internal/gc.h"
#include "internal/hash.h"
+#include "internal/io.h"
#include "internal/ruby_parser.h"
#include "internal/sanitizers.h"
#include "internal/symbol.h"
@@ -43,7 +44,6 @@
#include "builtin.h"
#include "insns.inc"
#include "insns_info.inc"
-#include "prism_compile.h"
VALUE rb_cISeq;
static VALUE iseqw_new(const rb_iseq_t *iseq);
@@ -167,9 +167,11 @@ rb_iseq_free(const rb_iseq_t *iseq)
struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
rb_rjit_free_iseq(iseq); /* Notify RJIT */
#if USE_YJIT
- rb_yjit_iseq_free(body->yjit_payload);
- RUBY_ASSERT(rb_yjit_live_iseq_count > 0);
- rb_yjit_live_iseq_count--;
+ rb_yjit_iseq_free(iseq);
+ if (FL_TEST_RAW((VALUE)iseq, ISEQ_TRANSLATED)) {
+ RUBY_ASSERT(rb_yjit_live_iseq_count > 0);
+ rb_yjit_live_iseq_count--;
+ }
#endif
ruby_xfree((void *)body->iseq_encoded);
ruby_xfree((void *)body->insns_info.body);
@@ -180,10 +182,7 @@ rb_iseq_free(const rb_iseq_t *iseq)
if (LIKELY(body->local_table != rb_iseq_shared_exc_local_tbl))
ruby_xfree((void *)body->local_table);
ruby_xfree((void *)body->is_entries);
-
- if (body->call_data) {
- ruby_xfree(body->call_data);
- }
+ ruby_xfree(body->call_data);
ruby_xfree((void *)body->catch_table);
ruby_xfree((void *)body->param.opt_table);
if (ISEQ_MBITS_BUFLEN(body->iseq_size) > 1 && body->mark_bits.list) {
@@ -293,6 +292,10 @@ static bool
cc_is_active(const struct rb_callcache *cc, bool reference_updating)
{
if (cc) {
+ if (cc == rb_vm_empty_cc() || rb_vm_empty_cc_for_super()) {
+ return false;
+ }
+
if (reference_updating) {
cc = (const struct rb_callcache *)rb_gc_location((VALUE)cc);
}
@@ -343,7 +346,7 @@ rb_iseq_mark_and_move(rb_iseq_t *iseq, bool reference_updating)
if (cc_is_active(cds[i].cc, reference_updating)) {
rb_gc_mark_and_move_ptr(&cds[i].cc);
}
- else {
+ else if (cds[i].cc != rb_vm_empty_cc()) {
cds[i].cc = rb_vm_empty_cc();
}
}
@@ -374,7 +377,7 @@ rb_iseq_mark_and_move(rb_iseq_t *iseq, bool reference_updating)
rb_rjit_iseq_update_references(body);
#endif
#if USE_YJIT
- rb_yjit_iseq_update_references(body->yjit_payload);
+ rb_yjit_iseq_update_references(iseq);
#endif
}
else {
@@ -393,7 +396,14 @@ rb_iseq_mark_and_move(rb_iseq_t *iseq, bool reference_updating)
else if (FL_TEST_RAW((VALUE)iseq, ISEQ_USE_COMPILE_DATA)) {
const struct iseq_compile_data *const compile_data = ISEQ_COMPILE_DATA(iseq);
- rb_iseq_mark_and_move_insn_storage(compile_data->insn.storage_head);
+ if (!reference_updating) {
+ /* The operands in each instruction needs to be pinned because
+ * if auto-compaction runs in iseq_set_sequence, then the objects
+ * could exist on the generated_iseq buffer, which would not be
+ * reference updated which can lead to T_MOVED (and subsequently
+ * T_NONE) objects on the iseq. */
+ rb_iseq_mark_and_pin_insn_storage(compile_data->insn.storage_head);
+ }
rb_gc_mark_and_move((VALUE *)&compile_data->err_info);
rb_gc_mark_and_move((VALUE *)&compile_data->catch_table_ary);
@@ -532,6 +542,11 @@ iseq_location_setup(rb_iseq_t *iseq, VALUE name, VALUE path, VALUE realpath, int
RB_OBJ_WRITE(iseq, &loc->label, name);
RB_OBJ_WRITE(iseq, &loc->base_label, name);
loc->first_lineno = first_lineno;
+
+ if (ISEQ_BODY(iseq)->local_iseq == iseq && strcmp(RSTRING_PTR(name), "initialize") == 0) {
+ ISEQ_BODY(iseq)->param.flags.use_block = 1;
+ }
+
if (code_location) {
loc->node_id = node_id;
loc->code_location = *code_location;
@@ -714,18 +729,26 @@ finish_iseq_build(rb_iseq_t *iseq)
}
static rb_compile_option_t COMPILE_OPTION_DEFAULT = {
- OPT_INLINE_CONST_CACHE, /* int inline_const_cache; */
- OPT_PEEPHOLE_OPTIMIZATION, /* int peephole_optimization; */
- OPT_TAILCALL_OPTIMIZATION, /* int tailcall_optimization */
- OPT_SPECIALISED_INSTRUCTION, /* int specialized_instruction; */
- OPT_OPERANDS_UNIFICATION, /* int operands_unification; */
- OPT_INSTRUCTIONS_UNIFICATION, /* int instructions_unification; */
- OPT_FROZEN_STRING_LITERAL,
- OPT_DEBUG_FROZEN_STRING_LITERAL,
- TRUE, /* coverage_enabled */
+ .inline_const_cache = OPT_INLINE_CONST_CACHE,
+ .peephole_optimization = OPT_PEEPHOLE_OPTIMIZATION,
+ .tailcall_optimization = OPT_TAILCALL_OPTIMIZATION,
+ .specialized_instruction = OPT_SPECIALISED_INSTRUCTION,
+ .operands_unification = OPT_OPERANDS_UNIFICATION,
+ .instructions_unification = OPT_INSTRUCTIONS_UNIFICATION,
+ .frozen_string_literal = OPT_FROZEN_STRING_LITERAL,
+ .debug_frozen_string_literal = OPT_DEBUG_FROZEN_STRING_LITERAL,
+ .coverage_enabled = TRUE,
+};
+
+static const rb_compile_option_t COMPILE_OPTION_FALSE = {
+ .frozen_string_literal = -1, // unspecified
};
-static const rb_compile_option_t COMPILE_OPTION_FALSE = {0};
+int
+rb_iseq_opt_frozen_string_literal(void)
+{
+ return COMPILE_OPTION_DEFAULT.frozen_string_literal;
+}
static void
set_compile_option_from_hash(rb_compile_option_t *option, VALUE opt)
@@ -758,9 +781,11 @@ set_compile_option_from_ast(rb_compile_option_t *option, const rb_ast_body_t *as
{
#define SET_COMPILE_OPTION(o, a, mem) \
((a)->mem < 0 ? 0 : ((o)->mem = (a)->mem > 0))
- SET_COMPILE_OPTION(option, ast, frozen_string_literal);
SET_COMPILE_OPTION(option, ast, coverage_enabled);
#undef SET_COMPILE_OPTION
+ if (ast->frozen_string_literal >= 0) {
+ option->frozen_string_literal = ast->frozen_string_literal;
+ }
return option;
}
@@ -802,42 +827,36 @@ make_compile_option_value(rb_compile_option_t *option)
SET_COMPILE_OPTION(option, opt, specialized_instruction);
SET_COMPILE_OPTION(option, opt, operands_unification);
SET_COMPILE_OPTION(option, opt, instructions_unification);
- SET_COMPILE_OPTION(option, opt, frozen_string_literal);
SET_COMPILE_OPTION(option, opt, debug_frozen_string_literal);
SET_COMPILE_OPTION(option, opt, coverage_enabled);
SET_COMPILE_OPTION_NUM(option, opt, debug_level);
}
#undef SET_COMPILE_OPTION
#undef SET_COMPILE_OPTION_NUM
+ VALUE frozen_string_literal = option->frozen_string_literal == -1 ? Qnil : RBOOL(option->frozen_string_literal);
+ rb_hash_aset(opt, ID2SYM(rb_intern("frozen_string_literal")), frozen_string_literal);
return opt;
}
rb_iseq_t *
-rb_iseq_new(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath,
+rb_iseq_new(const VALUE ast_value, VALUE name, VALUE path, VALUE realpath,
const rb_iseq_t *parent, enum rb_iseq_type type)
{
- return rb_iseq_new_with_opt(ast, name, path, realpath, 0, parent,
- 0, type, &COMPILE_OPTION_DEFAULT);
+ return rb_iseq_new_with_opt(ast_value, name, path, realpath, 0, parent,
+ 0, type, &COMPILE_OPTION_DEFAULT,
+ Qnil);
}
static int
-ast_line_count(const rb_ast_body_t *ast)
+ast_line_count(const VALUE ast_value)
{
- if (ast->script_lines == Qfalse) {
- // this occurs when failed to parse the source code with a syntax error
- return 0;
- }
- if (RB_TYPE_P(ast->script_lines, T_ARRAY)){
- return (int)RARRAY_LEN(ast->script_lines);
- }
- return FIX2INT(ast->script_lines);
+ rb_ast_t *ast = rb_ruby_ast_data_get(ast_value);
+ return ast->body.line_count;
}
static VALUE
-iseq_setup_coverage(VALUE coverages, VALUE path, const rb_ast_body_t *ast, int line_offset)
+iseq_setup_coverage(VALUE coverages, VALUE path, int line_count)
{
- int line_count = line_offset + ast_line_count(ast);
-
if (line_count >= 0) {
int len = (rb_get_coverage_mode() & COVERAGE_TARGET_ONESHOT_LINES) ? 0 : line_count;
@@ -851,45 +870,89 @@ iseq_setup_coverage(VALUE coverages, VALUE path, const rb_ast_body_t *ast, int l
}
static inline void
-iseq_new_setup_coverage(VALUE path, const rb_ast_body_t *ast, int line_offset)
+iseq_new_setup_coverage(VALUE path, int line_count)
{
VALUE coverages = rb_get_coverages();
if (RTEST(coverages)) {
- iseq_setup_coverage(coverages, path, ast, line_offset);
+ iseq_setup_coverage(coverages, path, line_count);
}
}
rb_iseq_t *
-rb_iseq_new_top(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent)
+rb_iseq_new_top(const VALUE ast_value, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent)
+{
+ iseq_new_setup_coverage(path, ast_line_count(ast_value));
+
+ return rb_iseq_new_with_opt(ast_value, name, path, realpath, 0, parent, 0,
+ ISEQ_TYPE_TOP, &COMPILE_OPTION_DEFAULT,
+ Qnil);
+}
+
+/**
+ * The main entry-point into the prism compiler when a file is required.
+ */
+rb_iseq_t *
+pm_iseq_new_top(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent)
{
- iseq_new_setup_coverage(path, ast, 0);
+ iseq_new_setup_coverage(path, (int) (node->parser->newline_list.size - 1));
- return rb_iseq_new_with_opt(ast, name, path, realpath, 0, parent, 0,
+ return pm_iseq_new_with_opt(node, name, path, realpath, 0, parent, 0,
ISEQ_TYPE_TOP, &COMPILE_OPTION_DEFAULT);
}
rb_iseq_t *
-rb_iseq_new_main(const rb_ast_body_t *ast, VALUE path, VALUE realpath, const rb_iseq_t *parent, int opt)
+rb_iseq_new_main(const VALUE ast_value, VALUE path, VALUE realpath, const rb_iseq_t *parent, int opt)
+{
+ iseq_new_setup_coverage(path, ast_line_count(ast_value));
+
+ return rb_iseq_new_with_opt(ast_value, rb_fstring_lit("<main>"),
+ path, realpath, 0,
+ parent, 0, ISEQ_TYPE_MAIN, opt ? &COMPILE_OPTION_DEFAULT : &COMPILE_OPTION_FALSE,
+ Qnil);
+}
+
+/**
+ * The main entry-point into the prism compiler when a file is executed as the
+ * main file in the program.
+ */
+rb_iseq_t *
+pm_iseq_new_main(pm_scope_node_t *node, VALUE path, VALUE realpath, const rb_iseq_t *parent, int opt)
{
- iseq_new_setup_coverage(path, ast, 0);
+ iseq_new_setup_coverage(path, (int) (node->parser->newline_list.size - 1));
- return rb_iseq_new_with_opt(ast, rb_fstring_lit("<main>"),
+ return pm_iseq_new_with_opt(node, rb_fstring_lit("<main>"),
path, realpath, 0,
parent, 0, ISEQ_TYPE_MAIN, opt ? &COMPILE_OPTION_DEFAULT : &COMPILE_OPTION_FALSE);
}
rb_iseq_t *
-rb_iseq_new_eval(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, int first_lineno, const rb_iseq_t *parent, int isolated_depth)
+rb_iseq_new_eval(const VALUE ast_value, VALUE name, VALUE path, VALUE realpath, int first_lineno, const rb_iseq_t *parent, int isolated_depth)
{
if (rb_get_coverage_mode() & COVERAGE_TARGET_EVAL) {
VALUE coverages = rb_get_coverages();
if (RTEST(coverages) && RTEST(path) && !RTEST(rb_hash_has_key(coverages, path))) {
- iseq_setup_coverage(coverages, path, ast, first_lineno - 1);
+ iseq_setup_coverage(coverages, path, ast_line_count(ast_value) + first_lineno - 1);
}
}
- return rb_iseq_new_with_opt(ast, name, path, realpath, first_lineno,
+ return rb_iseq_new_with_opt(ast_value, name, path, realpath, first_lineno,
+ parent, isolated_depth, ISEQ_TYPE_EVAL, &COMPILE_OPTION_DEFAULT,
+ Qnil);
+}
+
+rb_iseq_t *
+pm_iseq_new_eval(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpath,
+ int first_lineno, const rb_iseq_t *parent, int isolated_depth)
+{
+ if (rb_get_coverage_mode() & COVERAGE_TARGET_EVAL) {
+ VALUE coverages = rb_get_coverages();
+ if (RTEST(coverages) && RTEST(path) && !RTEST(rb_hash_has_key(coverages, path))) {
+ iseq_setup_coverage(coverages, path, ((int) (node->parser->newline_list.size - 1)) + first_lineno - 1);
+ }
+ }
+
+ return pm_iseq_new_with_opt(node, name, path, realpath, first_lineno,
parent, isolated_depth, ISEQ_TYPE_EVAL, &COMPILE_OPTION_DEFAULT);
}
@@ -908,25 +971,29 @@ iseq_translate(rb_iseq_t *iseq)
}
rb_iseq_t *
-rb_iseq_new_with_opt(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath,
+rb_iseq_new_with_opt(const VALUE ast_value, VALUE name, VALUE path, VALUE realpath,
int first_lineno, const rb_iseq_t *parent, int isolated_depth,
- enum rb_iseq_type type, const rb_compile_option_t *option)
+ enum rb_iseq_type type, const rb_compile_option_t *option,
+ VALUE script_lines)
{
- const NODE *node = ast ? ast->root : 0;
+ rb_ast_t *ast = rb_ruby_ast_data_get(ast_value);
+ rb_ast_body_t *body = ast ? &ast->body : NULL;
+ const NODE *node = body ? body->root : 0;
/* TODO: argument check */
rb_iseq_t *iseq = iseq_alloc();
rb_compile_option_t new_opt;
if (!option) option = &COMPILE_OPTION_DEFAULT;
- if (ast) {
+ if (body) {
new_opt = *option;
- option = set_compile_option_from_ast(&new_opt, ast);
+ option = set_compile_option_from_ast(&new_opt, body);
}
- VALUE script_lines = Qnil;
-
- if (ast && !FIXNUM_P(ast->script_lines) && ast->script_lines) {
- script_lines = ast->script_lines;
+ if (!NIL_P(script_lines)) {
+ // noop
+ }
+ else if (body && body->script_lines) {
+ script_lines = rb_parser_build_script_lines_from(body->script_lines);
}
else if (parent) {
script_lines = ISEQ_BODY(parent)->variable.script_lines;
@@ -941,40 +1008,49 @@ rb_iseq_new_with_opt(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE rea
return iseq_translate(iseq);
}
-VALUE rb_iseq_compile_prism_node(rb_iseq_t * iseq, pm_scope_node_t *scope_node, pm_parser_t *parser);
-
+/**
+ * This is a step in the prism compiler that is called once all of the various
+ * options have been established. It is called from one of the pm_iseq_new_*
+ * functions or from the RubyVM::InstructionSequence APIs. It is responsible for
+ * allocating the instruction sequence, calling into the compiler, and returning
+ * the built instruction sequence.
+ *
+ * Importantly, this is also the function where the compiler is re-entered to
+ * compile child instruction sequences. A child instruction sequence is always
+ * compiled using a scope node, which is why we cast it explicitly to that here
+ * in the parameters (as opposed to accepting a generic pm_node_t *).
+ */
rb_iseq_t *
-pm_iseq_new_with_opt(pm_scope_node_t *scope_node, pm_parser_t *parser, VALUE name, VALUE path, VALUE realpath,
+pm_iseq_new_with_opt(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpath,
int first_lineno, const rb_iseq_t *parent, int isolated_depth,
enum rb_iseq_type type, const rb_compile_option_t *option)
{
rb_iseq_t *iseq = iseq_alloc();
- VALUE script_lines = Qnil;
- rb_code_location_t code_loc;
+ ISEQ_BODY(iseq)->prism = true;
+ ISEQ_BODY(iseq)->param.flags.use_block = true; // unused block warning is not supported yet
+ rb_compile_option_t next_option;
if (!option) option = &COMPILE_OPTION_DEFAULT;
- pm_line_column_t start_line_col = pm_newline_list_line_column(&parser->newline_list, scope_node->base.location.start);
- pm_line_column_t end_line_col = pm_newline_list_line_column(&parser->newline_list, scope_node->base.location.end);
-
- code_loc = (rb_code_location_t) {
- .beg_pos = {
- .lineno = (int) start_line_col.line,
- .column = (int) start_line_col.column
- },
- .end_pos = {
- .lineno = (int) end_line_col.line,
- .column = (int) end_line_col.column
- },
- };
+ next_option = *option;
+ next_option.coverage_enabled = node->coverage_enabled < 0 ? 0 : node->coverage_enabled > 0;
+ option = &next_option;
- // TODO: node_id
- int node_id = -1;
- prepare_iseq_build(iseq, name, path, realpath, first_lineno, &code_loc, node_id,
- parent, isolated_depth, type, script_lines, option);
+ pm_location_t *location = &node->base.location;
+ int32_t start_line = node->parser->start_line;
- rb_iseq_compile_prism_node(iseq, scope_node, parser);
+ pm_line_column_t start = pm_newline_list_line_column(&node->parser->newline_list, location->start, start_line);
+ pm_line_column_t end = pm_newline_list_line_column(&node->parser->newline_list, location->end, start_line);
+ rb_code_location_t code_location = (rb_code_location_t) {
+ .beg_pos = { .lineno = (int) start.line, .column = (int) start.column },
+ .end_pos = { .lineno = (int) end.line, .column = (int) end.column }
+ };
+
+ prepare_iseq_build(iseq, name, path, realpath, first_lineno, &code_location, -1,
+ parent, isolated_depth, type, Qnil, option);
+
+ pm_iseq_compile_node(iseq, node);
finish_iseq_build(iseq);
return iseq_translate(iseq);
@@ -1101,6 +1177,10 @@ iseq_load(VALUE data, const rb_iseq_t *parent, VALUE opt)
tmp_loc.end_pos.column = NUM2INT(rb_ary_entry(code_location, 3));
}
+ if (SYM2ID(rb_hash_aref(misc, ID2SYM(rb_intern("parser")))) == rb_intern("prism")) {
+ ISEQ_BODY(iseq)->prism = true;
+ }
+
make_compile_option(&option, opt);
option.peephole_optimization = FALSE; /* because peephole optimization can modify original iseq */
prepare_iseq_build(iseq, name, path, realpath, first_lineno, &tmp_loc, NUM2INT(node_id),
@@ -1140,9 +1220,10 @@ rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE realpath, VALUE line, V
#else
# define INITIALIZED /* volatile */
#endif
- rb_ast_t *(*parse)(VALUE vparser, VALUE fname, VALUE file, int start);
+ VALUE (*parse)(VALUE vparser, VALUE fname, VALUE file, int start);
int ln;
- rb_ast_t *INITIALIZED ast;
+ VALUE INITIALIZED ast_value;
+ rb_ast_t *ast;
VALUE name = rb_fstring_lit("<compiled>");
/* safe results first */
@@ -1158,27 +1239,84 @@ rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE realpath, VALUE line, V
}
{
const VALUE parser = rb_parser_new();
- const rb_iseq_t *outer_scope = rb_iseq_new(NULL, name, name, Qnil, 0, ISEQ_TYPE_TOP);
+ const rb_iseq_t *outer_scope = rb_iseq_new(Qnil, name, name, Qnil, 0, ISEQ_TYPE_TOP);
VALUE outer_scope_v = (VALUE)outer_scope;
rb_parser_set_context(parser, outer_scope, FALSE);
- rb_parser_set_script_lines(parser, RBOOL(ruby_vm_keep_script_lines));
+ if (ruby_vm_keep_script_lines) rb_parser_set_script_lines(parser);
RB_GC_GUARD(outer_scope_v);
- ast = (*parse)(parser, file, src, ln);
+ ast_value = (*parse)(parser, file, src, ln);
}
- if (!ast->body.root) {
+ ast = rb_ruby_ast_data_get(ast_value);
+
+ if (!ast || !ast->body.root) {
rb_ast_dispose(ast);
rb_exc_raise(GET_EC()->errinfo);
}
else {
- iseq = rb_iseq_new_with_opt(&ast->body, name, file, realpath, ln,
- NULL, 0, ISEQ_TYPE_TOP, &option);
+ iseq = rb_iseq_new_with_opt(ast_value, name, file, realpath, ln,
+ NULL, 0, ISEQ_TYPE_TOP, &option,
+ Qnil);
rb_ast_dispose(ast);
}
return iseq;
}
+static rb_iseq_t *
+pm_iseq_compile_with_option(VALUE src, VALUE file, VALUE realpath, VALUE line, VALUE opt)
+{
+ rb_iseq_t *iseq = NULL;
+ rb_compile_option_t option;
+ int ln;
+ VALUE name = rb_fstring_lit("<compiled>");
+
+ /* safe results first */
+ make_compile_option(&option, opt);
+ ln = NUM2INT(line);
+ StringValueCStr(file);
+
+ pm_parse_result_t result = { 0 };
+ pm_options_line_set(&result.options, NUM2INT(line));
+ result.node.coverage_enabled = 1;
+
+ switch (option.frozen_string_literal) {
+ case ISEQ_FROZEN_STRING_LITERAL_UNSET:
+ break;
+ case ISEQ_FROZEN_STRING_LITERAL_DISABLED:
+ pm_options_frozen_string_literal_set(&result.options, false);
+ break;
+ case ISEQ_FROZEN_STRING_LITERAL_ENABLED:
+ pm_options_frozen_string_literal_set(&result.options, true);
+ break;
+ default:
+ rb_bug("pm_iseq_compile_with_option: invalid frozen_string_literal=%d", option.frozen_string_literal);
+ break;
+ }
+
+ VALUE error;
+ if (RB_TYPE_P(src, T_FILE)) {
+ VALUE filepath = rb_io_path(src);
+ error = pm_load_parse_file(&result, filepath);
+ RB_GC_GUARD(filepath);
+ }
+ else {
+ src = StringValue(src);
+ error = pm_parse_string(&result, src, file);
+ }
+
+ if (error == Qnil) {
+ iseq = pm_iseq_new_with_opt(&result.node, name, file, realpath, ln, NULL, 0, ISEQ_TYPE_TOP, &option);
+ pm_parse_result_free(&result);
+ }
+ else {
+ pm_parse_result_free(&result);
+ rb_exc_raise(error);
+ }
+
+ return iseq;
+}
+
VALUE
rb_iseq_path(const rb_iseq_t *iseq)
{
@@ -1287,18 +1425,30 @@ rb_iseq_remove_coverage_all(void)
static void
iseqw_mark(void *ptr)
{
- rb_gc_mark((VALUE)ptr);
+ rb_gc_mark_movable(*(VALUE *)ptr);
}
static size_t
iseqw_memsize(const void *ptr)
{
- return rb_iseq_memsize((const rb_iseq_t *)ptr);
+ return rb_iseq_memsize(*(const rb_iseq_t **)ptr);
+}
+
+static void
+iseqw_ref_update(void *ptr)
+{
+ VALUE *vptr = ptr;
+ *vptr = rb_gc_location(*vptr);
}
static const rb_data_type_t iseqw_data_type = {
"T_IMEMO/iseq",
- {iseqw_mark, NULL, iseqw_memsize,},
+ {
+ iseqw_mark,
+ RUBY_TYPED_DEFAULT_FREE,
+ iseqw_memsize,
+ iseqw_ref_update,
+ },
0, 0, RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED
};
@@ -1306,14 +1456,16 @@ static VALUE
iseqw_new(const rb_iseq_t *iseq)
{
if (iseq->wrapper) {
+ if (*(const rb_iseq_t **)rb_check_typeddata(iseq->wrapper, &iseqw_data_type) != iseq) {
+ rb_raise(rb_eTypeError, "wrong iseq wrapper: %" PRIsVALUE " for %p",
+ iseq->wrapper, (void *)iseq);
+ }
return iseq->wrapper;
}
else {
- union { const rb_iseq_t *in; void *out; } deconst;
- VALUE obj;
- deconst.in = iseq;
- obj = TypedData_Wrap_Struct(rb_cISeq, &iseqw_data_type, deconst.out);
- RB_OBJ_WRITTEN(obj, Qundef, iseq);
+ rb_iseq_t **ptr;
+ VALUE obj = TypedData_Make_Struct(rb_cISeq, rb_iseq_t *, &iseqw_data_type, ptr);
+ RB_OBJ_WRITE(obj, ptr, iseq);
/* cache a wrapper object */
RB_OBJ_WRITE((VALUE)iseq, &iseq->wrapper, obj);
@@ -1329,6 +1481,44 @@ rb_iseqw_new(const rb_iseq_t *iseq)
return iseqw_new(iseq);
}
+/**
+ * Accept the options given to InstructionSequence.compile and
+ * InstructionSequence.compile_prism and share the logic for creating the
+ * instruction sequence.
+ */
+static VALUE
+iseqw_s_compile_parser(int argc, VALUE *argv, VALUE self, bool prism)
+{
+ VALUE src, file = Qnil, path = Qnil, line = Qnil, opt = Qnil;
+ int i;
+
+ i = rb_scan_args(argc, argv, "1*:", &src, NULL, &opt);
+ if (i > 4+NIL_P(opt)) rb_error_arity(argc, 1, 5);
+ switch (i) {
+ case 5: opt = argv[--i];
+ case 4: line = argv[--i];
+ case 3: path = argv[--i];
+ case 2: file = argv[--i];
+ }
+
+ if (NIL_P(file)) file = rb_fstring_lit("<compiled>");
+ if (NIL_P(path)) path = file;
+ if (NIL_P(line)) line = INT2FIX(1);
+
+ Check_Type(path, T_STRING);
+ Check_Type(file, T_STRING);
+
+ rb_iseq_t *iseq;
+ if (prism) {
+ iseq = pm_iseq_compile_with_option(src, file, path, line, opt);
+ }
+ else {
+ iseq = rb_iseq_compile_with_option(src, file, path, line, opt);
+ }
+
+ return iseqw_new(iseq);
+}
+
/*
* call-seq:
* InstructionSequence.compile(source[, file[, path[, line[, options]]]]) -> iseq
@@ -1369,91 +1559,49 @@ rb_iseqw_new(const rb_iseq_t *iseq)
static VALUE
iseqw_s_compile(int argc, VALUE *argv, VALUE self)
{
- VALUE src, file = Qnil, path = Qnil, line = Qnil, opt = Qnil;
- int i;
-
- i = rb_scan_args(argc, argv, "1*:", &src, NULL, &opt);
- if (i > 4+NIL_P(opt)) rb_error_arity(argc, 1, 5);
- switch (i) {
- case 5: opt = argv[--i];
- case 4: line = argv[--i];
- case 3: path = argv[--i];
- case 2: file = argv[--i];
- }
-
- if (NIL_P(file)) file = rb_fstring_lit("<compiled>");
- if (NIL_P(path)) path = file;
- if (NIL_P(line)) line = INT2FIX(1);
-
- Check_Type(path, T_STRING);
- Check_Type(file, T_STRING);
-
- return iseqw_new(rb_iseq_compile_with_option(src, file, path, line, opt));
+ return iseqw_s_compile_parser(argc, argv, self, *rb_ruby_prism_ptr());
}
+/*
+ * call-seq:
+ * InstructionSequence.compile_prism(source[, file[, path[, line[, options]]]]) -> iseq
+ *
+ * Takes +source+, which can be a string of Ruby code, or an open +File+ object.
+ * that contains Ruby source code. It parses and compiles using prism.
+ *
+ * Optionally takes +file+, +path+, and +line+ which describe the file path,
+ * real path and first line number of the ruby code in +source+ which are
+ * metadata attached to the returned +iseq+.
+ *
+ * +file+ is used for `__FILE__` and exception backtrace. +path+ is used for
+ * +require_relative+ base. It is recommended these should be the same full
+ * path.
+ *
+ * +options+, which can be +true+, +false+ or a +Hash+, is used to
+ * modify the default behavior of the Ruby iseq compiler.
+ *
+ * For details regarding valid compile options see ::compile_option=.
+ *
+ * RubyVM::InstructionSequence.compile("a = 1 + 2")
+ * #=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
+ *
+ * path = "test.rb"
+ * RubyVM::InstructionSequence.compile(File.read(path), path, File.expand_path(path))
+ * #=> <RubyVM::InstructionSequence:<compiled>@test.rb:1>
+ *
+ * file = File.open("test.rb")
+ * RubyVM::InstructionSequence.compile(file)
+ * #=> <RubyVM::InstructionSequence:<compiled>@<compiled>:1>
+ *
+ * path = File.expand_path("test.rb")
+ * RubyVM::InstructionSequence.compile(File.read(path), path, path)
+ * #=> <RubyVM::InstructionSequence:<compiled>@/absolute/path/to/test.rb:1>
+ *
+ */
static VALUE
iseqw_s_compile_prism(int argc, VALUE *argv, VALUE self)
{
- VALUE src, file = Qnil, path = Qnil, line = Qnil, opt = Qnil;
- int i;
-
- i = rb_scan_args(argc, argv, "1*:", &src, NULL, &opt);
- if (i > 4+NIL_P(opt)) rb_error_arity(argc, 1, 5);
- switch (i) {
- case 5: opt = argv[--i];
- case 4: line = argv[--i];
- case 3: path = argv[--i];
- case 2: file = argv[--i];
- }
-
- if (NIL_P(file)) file = rb_fstring_lit("<compiled>");
- if (NIL_P(path)) path = file;
- if (NIL_P(line)) line = INT2FIX(1);
-
- Check_Type(path, T_STRING);
- Check_Type(file, T_STRING);
-
- rb_iseq_t *iseq = iseq_alloc();
- int start_line = NUM2INT(line);
-
- pm_options_t options = { 0 };
- pm_options_filepath_set(&options, RSTRING_PTR(file));
- pm_options_line_set(&options, start_line);
-
- pm_parser_t parser;
- pm_parser_init(&parser, (const uint8_t *) RSTRING_PTR(src), RSTRING_LEN(src), &options);
-
- pm_node_t *node = pm_parse(&parser);
- pm_line_column_t start_loc = pm_newline_list_line_column(&parser.newline_list, node->location.start);
- pm_line_column_t end_loc = pm_newline_list_line_column(&parser.newline_list, node->location.end);
-
- rb_code_location_t node_location;
- node_location.beg_pos.lineno = (int) start_loc.line;
- node_location.beg_pos.column = (int) start_loc.column;
- node_location.end_pos.lineno = (int) end_loc.line;
- node_location.end_pos.column = (int) end_loc.column;
-
- int node_id = 0;
- rb_iseq_t *parent = NULL;
- enum rb_iseq_type iseq_type = ISEQ_TYPE_TOP;
- rb_compile_option_t option;
-
- make_compile_option(&option, opt);
-
- VALUE name = rb_fstring_lit("<compiled>");
- prepare_iseq_build(iseq, name, file, path, start_line, &node_location, node_id,
- parent, 0, (enum rb_iseq_type)iseq_type, Qnil, &option);
-
- pm_scope_node_t scope_node;
- pm_scope_node_init(node, &scope_node, NULL, &parser);
- rb_iseq_compile_prism_node(iseq, &scope_node, &parser);
-
- finish_iseq_build(iseq);
- pm_node_destroy(&parser, node);
- pm_parser_free(&parser);
- pm_options_free(&options);
-
- return iseqw_new(iseq);
+ return iseqw_s_compile_parser(argc, argv, self, true);
}
/*
@@ -1482,6 +1630,7 @@ iseqw_s_compile_file(int argc, VALUE *argv, VALUE self)
VALUE file, opt = Qnil;
VALUE parser, f, exc = Qnil, ret;
rb_ast_t *ast;
+ VALUE ast_value;
rb_compile_option_t option;
int i;
@@ -1500,7 +1649,8 @@ iseqw_s_compile_file(int argc, VALUE *argv, VALUE self)
parser = rb_parser_new();
rb_parser_set_context(parser, NULL, FALSE);
- ast = (rb_ast_t *)rb_parser_load_file(parser, file);
+ ast_value = rb_parser_load_file(parser, file);
+ ast = rb_ruby_ast_data_get(ast_value);
if (!ast->body.root) exc = GET_EC()->errinfo;
rb_io_close(f);
@@ -1511,10 +1661,11 @@ iseqw_s_compile_file(int argc, VALUE *argv, VALUE self)
make_compile_option(&option, opt);
- ret = iseqw_new(rb_iseq_new_with_opt(&ast->body, rb_fstring_lit("<main>"),
+ ret = iseqw_new(rb_iseq_new_with_opt(ast_value, rb_fstring_lit("<main>"),
file,
rb_realpath_internal(Qnil, file, 1),
- 1, NULL, 0, ISEQ_TYPE_TOP, &option));
+ 1, NULL, 0, ISEQ_TYPE_TOP, &option,
+ Qnil));
rb_ast_dispose(ast);
rb_vm_pop_frame(ec);
@@ -1524,6 +1675,70 @@ iseqw_s_compile_file(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
+ * InstructionSequence.compile_file_prism(file[, options]) -> iseq
+ *
+ * Takes +file+, a String with the location of a Ruby source file, reads,
+ * parses and compiles the file, and returns +iseq+, the compiled
+ * InstructionSequence with source location metadata set. It parses and
+ * compiles using prism.
+ *
+ * Optionally takes +options+, which can be +true+, +false+ or a +Hash+, to
+ * modify the default behavior of the Ruby iseq compiler.
+ *
+ * For details regarding valid compile options see ::compile_option=.
+ *
+ * # /tmp/hello.rb
+ * puts "Hello, world!"
+ *
+ * # elsewhere
+ * RubyVM::InstructionSequence.compile_file_prism("/tmp/hello.rb")
+ * #=> <RubyVM::InstructionSequence:<main>@/tmp/hello.rb>
+ */
+static VALUE
+iseqw_s_compile_file_prism(int argc, VALUE *argv, VALUE self)
+{
+ VALUE file, opt = Qnil, ret;
+ rb_compile_option_t option;
+ int i;
+
+ i = rb_scan_args(argc, argv, "1*:", &file, NULL, &opt);
+ if (i > 1+NIL_P(opt)) rb_error_arity(argc, 1, 2);
+ switch (i) {
+ case 2: opt = argv[--i];
+ }
+ FilePathValue(file);
+ file = rb_fstring(file); /* rb_io_t->pathv gets frozen anyways */
+
+ rb_execution_context_t *ec = GET_EC();
+ VALUE v = rb_vm_push_frame_fname(ec, file);
+
+ pm_parse_result_t result = { 0 };
+ result.options.line = 1;
+ result.node.coverage_enabled = 1;
+
+ VALUE error = pm_load_parse_file(&result, file);
+
+ if (error == Qnil) {
+ make_compile_option(&option, opt);
+
+ ret = iseqw_new(pm_iseq_new_with_opt(&result.node, rb_fstring_lit("<main>"),
+ file,
+ rb_realpath_internal(Qnil, file, 1),
+ 1, NULL, 0, ISEQ_TYPE_TOP, &option));
+ pm_parse_result_free(&result);
+ rb_vm_pop_frame(ec);
+ RB_GC_GUARD(v);
+ return ret;
+ } else {
+ pm_parse_result_free(&result);
+ rb_vm_pop_frame(ec);
+ RB_GC_GUARD(v);
+ rb_exc_raise(error);
+ }
+}
+
+/*
+ * call-seq:
* InstructionSequence.compile_option = options
*
* Sets the default values for various optimizations in the Ruby iseq
@@ -1578,7 +1793,9 @@ iseqw_s_compile_option_get(VALUE self)
static const rb_iseq_t *
iseqw_check(VALUE iseqw)
{
- rb_iseq_t *iseq = DATA_PTR(iseqw);
+ rb_iseq_t **iseq_ptr;
+ TypedData_Get_Struct(iseqw, rb_iseq_t *, &iseqw_data_type, iseq_ptr);
+ rb_iseq_t *iseq = *iseq_ptr;
if (!ISEQ_BODY(iseq)) {
rb_ibf_load_iseq_complete(iseq);
@@ -2071,7 +2288,7 @@ local_var_name(const rb_iseq_t *diseq, VALUE level, VALUE op)
if (!name) {
name = rb_str_new_cstr("?");
}
- else if (!rb_str_symname_p(name)) {
+ else if (!rb_is_local_id(lid)) {
name = rb_str_inspect(name);
}
else {
@@ -2221,6 +2438,7 @@ rb_insn_operand_intern(const rb_iseq_t *iseq,
VALUE flags = rb_ary_new();
# define CALL_FLAG(n) if (vm_ci_flag(ci) & VM_CALL_##n) rb_ary_push(flags, rb_str_new2(#n))
CALL_FLAG(ARGS_SPLAT);
+ CALL_FLAG(ARGS_SPLAT_MUT);
CALL_FLAG(ARGS_BLOCKARG);
CALL_FLAG(FCALL);
CALL_FLAG(VCALL);
@@ -2432,6 +2650,15 @@ rb_iseq_disasm_recursive(const rb_iseq_t *iseq, VALUE indent)
rb_str_modify_expand(str, header_minlen - l);
memset(RSTRING_END(str), '=', header_minlen - l);
}
+ if (iseq->body->builtin_attrs) {
+#define disasm_builtin_attr(str, iseq, attr) \
+ if (iseq->body->builtin_attrs & BUILTIN_ATTR_ ## attr) { \
+ rb_str_cat2(str, " " #attr); \
+ }
+ disasm_builtin_attr(str, iseq, LEAF);
+ disasm_builtin_attr(str, iseq, SINGLE_NOARG_LEAF);
+ disasm_builtin_attr(str, iseq, INLINE_BLOCK);
+ }
rb_str_cat2(str, "\n");
/* show catch table information */
@@ -3004,6 +3231,7 @@ iseq_data_to_ary(const rb_iseq_t *iseq)
}
if (iseq_body->param.flags.has_kwrest) rb_hash_aset(params, ID2SYM(rb_intern("kwrest")), INT2FIX(keyword->rest_start));
if (iseq_body->param.flags.ambiguous_param0) rb_hash_aset(params, ID2SYM(rb_intern("ambiguous_param0")), Qtrue);
+ if (iseq_body->param.flags.use_block) rb_hash_aset(params, ID2SYM(rb_intern("use_block")), Qtrue);
}
/* body */
@@ -3225,6 +3453,7 @@ iseq_data_to_ary(const rb_iseq_t *iseq)
#ifdef USE_ISEQ_NODE_ID
rb_hash_aset(misc, ID2SYM(rb_intern("node_ids")), node_ids);
#endif
+ rb_hash_aset(misc, ID2SYM(rb_intern("parser")), iseq_body->prism ? ID2SYM(rb_intern("prism")) : ID2SYM(rb_intern("parse.y")));
/*
* [:magic, :major_version, :minor_version, :format_type, :misc,
@@ -3390,6 +3619,12 @@ typedef struct insn_data_struct {
static insn_data_t insn_data[VM_INSTRUCTION_SIZE/2];
void
+rb_free_encoded_insn_data(void)
+{
+ st_free_table(encoded_insn_data);
+}
+
+void
rb_vm_encoded_insn_data_table_init(void)
{
#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
@@ -4029,6 +4264,7 @@ Init_ISeq(void)
rb_define_singleton_method(rb_cISeq, "compile", iseqw_s_compile, -1);
rb_define_singleton_method(rb_cISeq, "compile_prism", iseqw_s_compile_prism, -1);
+ rb_define_singleton_method(rb_cISeq, "compile_file_prism", iseqw_s_compile_file_prism, -1);
rb_define_singleton_method(rb_cISeq, "new", iseqw_s_compile, -1);
rb_define_singleton_method(rb_cISeq, "compile_file", iseqw_s_compile_file, -1);
rb_define_singleton_method(rb_cISeq, "compile_option", iseqw_s_compile_option_get, 0);
diff --git a/iseq.h b/iseq.h
index 1ad07e9065..a0b59c441f 100644
--- a/iseq.h
+++ b/iseq.h
@@ -13,6 +13,7 @@
#include "internal/gc.h"
#include "shape.h"
#include "vm_core.h"
+#include "prism_compile.h"
RUBY_EXTERN const int ruby_api_version[];
#define ISEQ_MAJOR_VERSION ((unsigned int)ruby_api_version[0])
@@ -46,6 +47,10 @@ extern const ID rb_iseq_shared_exc_local_tbl[];
#define ISEQ_FLIP_CNT(iseq) ISEQ_BODY(iseq)->variable.flip_count
+#define ISEQ_FROZEN_STRING_LITERAL_ENABLED 1
+#define ISEQ_FROZEN_STRING_LITERAL_DISABLED 0
+#define ISEQ_FROZEN_STRING_LITERAL_UNSET -1
+
static inline rb_snum_t
ISEQ_FLIP_CNT_INCREMENT(const rb_iseq_t *iseq)
{
@@ -65,9 +70,7 @@ ISEQ_ORIGINAL_ISEQ_CLEAR(const rb_iseq_t *iseq)
{
void *ptr = ISEQ_BODY(iseq)->variable.original_iseq;
ISEQ_BODY(iseq)->variable.original_iseq = NULL;
- if (ptr) {
- ruby_xfree(ptr);
- }
+ ruby_xfree(ptr);
}
static inline VALUE *
@@ -161,7 +164,7 @@ ISEQ_COMPILE_DATA_CLEAR(rb_iseq_t *iseq)
static inline rb_iseq_t *
iseq_imemo_alloc(void)
{
- return (rb_iseq_t *)rb_imemo_new(imemo_iseq, 0, 0, 0, 0);
+ return IMEMO_NEW(rb_iseq_t, imemo_iseq, 0);
}
VALUE rb_iseq_ibf_dump(const rb_iseq_t *iseq, VALUE opt);
@@ -173,6 +176,7 @@ void rb_iseq_init_trace(rb_iseq_t *iseq);
int rb_iseq_add_local_tracepoint_recursively(const rb_iseq_t *iseq, rb_event_flag_t turnon_events, VALUE tpval, unsigned int target_line, bool target_bmethod);
int rb_iseq_remove_local_tracepoint_recursively(const rb_iseq_t *iseq, VALUE tpval);
const rb_iseq_t *rb_iseq_load_iseq(VALUE fname);
+int rb_iseq_opt_frozen_string_literal(void);
#if VM_INSN_INFO_TABLE_IMPL == 2
unsigned int *rb_iseq_insns_info_decode_positions(const struct rb_iseq_constant_body *body);
@@ -189,7 +193,7 @@ VALUE *rb_iseq_original_iseq(const rb_iseq_t *iseq);
void rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc,
VALUE locals, VALUE args,
VALUE exception, VALUE body);
-void rb_iseq_mark_and_move_insn_storage(struct iseq_compile_data_storage *arena);
+void rb_iseq_mark_and_pin_insn_storage(struct iseq_compile_data_storage *arena);
VALUE rb_iseq_load(VALUE data, VALUE parent, VALUE opt);
VALUE rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc);
@@ -227,7 +231,7 @@ struct rb_compile_option_struct {
unsigned int specialized_instruction: 1;
unsigned int operands_unification: 1;
unsigned int instructions_unification: 1;
- unsigned int frozen_string_literal: 1;
+ signed int frozen_string_literal: 2; /* -1: not specified, 0: false, 1: true */
unsigned int debug_frozen_string_literal: 1;
unsigned int coverage_enabled: 1;
int debug_level;
@@ -329,6 +333,8 @@ VALUE rb_iseq_local_variables(const rb_iseq_t *iseq);
attr_index_t rb_estimate_iv_count(VALUE klass, const rb_iseq_t * initialize_iseq);
+void rb_free_encoded_insn_data(void);
+
RUBY_SYMBOL_EXPORT_END
#endif /* RUBY_ISEQ_H */
diff --git a/kernel.rb b/kernel.rb
index c6b3e44000..541d0cfd9d 100644
--- a/kernel.rb
+++ b/kernel.rb
@@ -58,10 +58,10 @@ module Kernel
# a.freeze #=> ["a", "b", "c"]
# a.frozen? #=> true
#--
- # Determines if the object is frozen. Equivalent to \c Object\#frozen? in Ruby.
- # \param[in] obj the object to be determines
- # \retval Qtrue if frozen
- # \retval Qfalse if not frozen
+ # Determines if the object is frozen. Equivalent to `Object#frozen?` in Ruby.
+ # @param[in] obj the object to be determines
+ # @retval Qtrue if frozen
+ # @retval Qfalse if not frozen
#++
#
def frozen?
@@ -87,6 +87,7 @@ module Kernel
#++
#
def tap
+ Primitive.attr! :inline_block
yield(self)
self
end
@@ -127,7 +128,8 @@ module Kernel
# then {|response| JSON.parse(response) }
#
def then
- unless block_given?
+ Primitive.attr! :inline_block
+ unless defined?(yield)
return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, rb_obj_size)'
end
yield(self)
@@ -142,7 +144,8 @@ module Kernel
# "my string".yield_self {|s| s.upcase } #=> "MY STRING"
#
def yield_self
- unless block_given?
+ Primitive.attr! :inline_block
+ unless defined?(yield)
return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, rb_obj_size)'
end
yield(self)
@@ -178,8 +181,9 @@ module Kernel
# puts enum.next
# } #=> :ok
def loop
- unless block_given?
- return enum_for(:loop) { Float::INFINITY }
+ Primitive.attr! :inline_block
+ unless defined?(yield)
+ return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, rb_f_loop_size)'
end
begin
diff --git a/lib/abbrev.gemspec b/lib/abbrev.gemspec
deleted file mode 100644
index 50c500bbc7..0000000000
--- a/lib/abbrev.gemspec
+++ /dev/null
@@ -1,29 +0,0 @@
-name = File.basename(__FILE__, ".gemspec")
-version = ["lib", Array.new(name.count("-")+1, ".").join("/")].find do |dir|
- break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
- /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
- end rescue nil
-end
-
-Gem::Specification.new do |spec|
- spec.name = name
- spec.version = version
- spec.authors = ["Akinori MUSHA"]
- spec.email = ["knu@idaemons.org"]
-
- spec.summary = %q{Calculates a set of unique abbreviations for a given set of strings}
- spec.description = %q{Calculates a set of unique abbreviations for a given set of strings}
- spec.homepage = "https://github.com/ruby/abbrev"
- spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
- spec.licenses = ["Ruby", "BSD-2-Clause"]
-
- spec.metadata["homepage_uri"] = spec.homepage
- spec.metadata["source_code_uri"] = spec.homepage
-
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
- end
- spec.bindir = "exe"
- spec.executables = []
- spec.require_paths = ["lib"]
-end
diff --git a/lib/abbrev.rb b/lib/abbrev.rb
deleted file mode 100644
index ee86f06874..0000000000
--- a/lib/abbrev.rb
+++ /dev/null
@@ -1,133 +0,0 @@
-# frozen_string_literal: true
-#--
-# Copyright (c) 2001,2003 Akinori MUSHA <knu@iDaemons.org>
-#
-# All rights reserved. You can redistribute and/or modify it under
-# the same terms as Ruby.
-#
-# $Idaemons: /home/cvs/rb/abbrev.rb,v 1.2 2001/05/30 09:37:45 knu Exp $
-# $RoughId: abbrev.rb,v 1.4 2003/10/14 19:45:42 knu Exp $
-# $Id$
-#++
-
-##
-# Calculates the set of unambiguous abbreviations for a given set of strings.
-#
-# require 'abbrev'
-# require 'pp'
-#
-# pp Abbrev.abbrev(['ruby'])
-# #=> {"ruby"=>"ruby", "rub"=>"ruby", "ru"=>"ruby", "r"=>"ruby"}
-#
-# pp Abbrev.abbrev(%w{ ruby rules })
-#
-# _Generates:_
-# { "ruby" => "ruby",
-# "rub" => "ruby",
-# "rules" => "rules",
-# "rule" => "rules",
-# "rul" => "rules" }
-#
-# It also provides an array core extension, Array#abbrev.
-#
-# pp %w{ summer winter }.abbrev
-#
-# _Generates:_
-# { "summer" => "summer",
-# "summe" => "summer",
-# "summ" => "summer",
-# "sum" => "summer",
-# "su" => "summer",
-# "s" => "summer",
-# "winter" => "winter",
-# "winte" => "winter",
-# "wint" => "winter",
-# "win" => "winter",
-# "wi" => "winter",
-# "w" => "winter" }
-
-module Abbrev
- VERSION = "0.1.1"
-
- # Given a set of strings, calculate the set of unambiguous abbreviations for
- # those strings, and return a hash where the keys are all the possible
- # abbreviations and the values are the full strings.
- #
- # Thus, given +words+ is "car" and "cone", the keys pointing to "car" would
- # be "ca" and "car", while those pointing to "cone" would be "co", "con", and
- # "cone".
- #
- # require 'abbrev'
- #
- # Abbrev.abbrev(%w{ car cone })
- # #=> {"ca"=>"car", "con"=>"cone", "co"=>"cone", "car"=>"car", "cone"=>"cone"}
- #
- # The optional +pattern+ parameter is a pattern or a string. Only input
- # strings that match the pattern or start with the string are included in the
- # output hash.
- #
- # Abbrev.abbrev(%w{car box cone crab}, /b/)
- # #=> {"box"=>"box", "bo"=>"box", "b"=>"box", "crab" => "crab"}
- #
- # Abbrev.abbrev(%w{car box cone}, 'ca')
- # #=> {"car"=>"car", "ca"=>"car"}
- def abbrev(words, pattern = nil)
- table = {}
- seen = Hash.new(0)
-
- if pattern.is_a?(String)
- pattern = /\A#{Regexp.quote(pattern)}/ # regard as a prefix
- end
-
- words.each do |word|
- next if word.empty?
- word.size.downto(1) { |len|
- abbrev = word[0...len]
-
- next if pattern && pattern !~ abbrev
-
- case seen[abbrev] += 1
- when 1
- table[abbrev] = word
- when 2
- table.delete(abbrev)
- else
- break
- end
- }
- end
-
- words.each do |word|
- next if pattern && pattern !~ word
-
- table[word] = word
- end
-
- table
- end
-
- module_function :abbrev
-end
-
-class Array
- # Calculates the set of unambiguous abbreviations for the strings in +self+.
- #
- # require 'abbrev'
- # %w{ car cone }.abbrev
- # #=> {"car"=>"car", "ca"=>"car", "cone"=>"cone", "con"=>"cone", "co"=>"cone"}
- #
- # The optional +pattern+ parameter is a pattern or a string. Only input
- # strings that match the pattern or start with the string are included in the
- # output hash.
- #
- # %w{ fast boat day }.abbrev(/^.a/)
- # #=> {"fast"=>"fast", "fas"=>"fast", "fa"=>"fast", "day"=>"day", "da"=>"day"}
- #
- # Abbrev.abbrev(%w{car box cone}, "ca")
- # #=> {"car"=>"car", "ca"=>"car"}
- #
- # See also Abbrev.abbrev
- def abbrev(pattern = nil)
- Abbrev::abbrev(self, pattern)
- end
-end
diff --git a/lib/base64.gemspec b/lib/base64.gemspec
deleted file mode 100644
index c013b7c1c2..0000000000
--- a/lib/base64.gemspec
+++ /dev/null
@@ -1,27 +0,0 @@
-name = File.basename(__FILE__, ".gemspec")
-version = ["lib", Array.new(name.count("-")+1).join("/")].find do |dir|
- break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
- /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
- end rescue nil
-end
-
-Gem::Specification.new do |spec|
- spec.name = name
- spec.version = version
- spec.authors = ["Yusuke Endoh"]
- spec.email = ["mame@ruby-lang.org"]
-
- spec.summary = %q{Support for encoding and decoding binary data using a Base64 representation.}
- spec.description = %q{Support for encoding and decoding binary data using a Base64 representation.}
- spec.homepage = "https://github.com/ruby/base64"
- spec.required_ruby_version = Gem::Requirement.new(">= 2.4")
- spec.licenses = ["Ruby", "BSD-2-Clause"]
-
- spec.metadata["homepage_uri"] = spec.homepage
- spec.metadata["source_code_uri"] = spec.homepage
-
- spec.files = ["README.md", "LICENSE.txt", "lib/base64.rb"]
- spec.bindir = "exe"
- spec.executables = []
- spec.require_paths = ["lib"]
-end
diff --git a/lib/base64.rb b/lib/base64.rb
deleted file mode 100644
index cd2ecc18ea..0000000000
--- a/lib/base64.rb
+++ /dev/null
@@ -1,363 +0,0 @@
-# frozen_string_literal: true
-#
-# \Module \Base64 provides methods for:
-#
-# - Encoding a binary string (containing non-ASCII characters)
-# as a string of printable ASCII characters.
-# - Decoding such an encoded string.
-#
-# \Base64 is commonly used in contexts where binary data
-# is not allowed or supported:
-#
-# - Images in HTML or CSS files, or in URLs.
-# - Email attachments.
-#
-# A \Base64-encoded string is about one-third larger that its source.
-# See the {Wikipedia article}[https://en.wikipedia.org/wiki/Base64]
-# for more information.
-#
-# This module provides three pairs of encode/decode methods.
-# Your choices among these methods should depend on:
-#
-# - Which character set is to be used for encoding and decoding.
-# - Whether "padding" is to be used.
-# - Whether encoded strings are to contain newlines.
-#
-# Note: Examples on this page assume that the including program has executed:
-#
-# require 'base64'
-#
-# == Encoding Character Sets
-#
-# A \Base64-encoded string consists only of characters from a 64-character set:
-#
-# - <tt>('A'..'Z')</tt>.
-# - <tt>('a'..'z')</tt>.
-# - <tt>('0'..'9')</tt>.
-# - <tt>=</tt>, the 'padding' character.
-# - Either:
-# - <tt>%w[+ /]</tt>:
-# {RFC-2045-compliant}[https://datatracker.ietf.org/doc/html/rfc2045];
-# _not_ safe for URLs.
-# - <tt>%w[- _]</tt>:
-# {RFC-4648-compliant}[https://datatracker.ietf.org/doc/html/rfc4648];
-# safe for URLs.
-#
-# If you are working with \Base64-encoded strings that will come from
-# or be put into URLs, you should choose this encoder-decoder pair
-# of RFC-4648-compliant methods:
-#
-# - Base64.urlsafe_encode64 and Base64.urlsafe_decode64.
-#
-# Otherwise, you may choose any of the pairs in this module,
-# including the pair above, or the RFC-2045-compliant pairs:
-#
-# - Base64.encode64 and Base64.decode64.
-# - Base64.strict_encode64 and Base64.strict_decode64.
-#
-# == Padding
-#
-# \Base64-encoding changes a triplet of input bytes
-# into a quartet of output characters.
-#
-# <b>Padding in Encode Methods</b>
-#
-# Padding -- extending an encoded string with zero, one, or two trailing
-# <tt>=</tt> characters -- is performed by methods Base64.encode64,
-# Base64.strict_encode64, and, by default, Base64.urlsafe_encode64:
-#
-# Base64.encode64('s') # => "cw==\n"
-# Base64.strict_encode64('s') # => "cw=="
-# Base64.urlsafe_encode64('s') # => "cw=="
-# Base64.urlsafe_encode64('s', padding: false) # => "cw"
-#
-# When padding is performed, the encoded string is always of length <em>4n</em>,
-# where +n+ is a non-negative integer:
-#
-# - Input bytes of length <em>3n</em> generate unpadded output characters
-# of length <em>4n</em>:
-#
-# # n = 1: 3 bytes => 4 characters.
-# Base64.strict_encode64('123') # => "MDEy"
-# # n = 2: 6 bytes => 8 characters.
-# Base64.strict_encode64('123456') # => "MDEyMzQ1"
-#
-# - Input bytes of length <em>3n+1</em> generate padded output characters
-# of length <em>4(n+1)</em>, with two padding characters at the end:
-#
-# # n = 1: 4 bytes => 8 characters.
-# Base64.strict_encode64('1234') # => "MDEyMw=="
-# # n = 2: 7 bytes => 12 characters.
-# Base64.strict_encode64('1234567') # => "MDEyMzQ1Ng=="
-#
-# - Input bytes of length <em>3n+2</em> generate padded output characters
-# of length <em>4(n+1)</em>, with one padding character at the end:
-#
-# # n = 1: 5 bytes => 8 characters.
-# Base64.strict_encode64('12345') # => "MDEyMzQ="
-# # n = 2: 8 bytes => 12 characters.
-# Base64.strict_encode64('12345678') # => "MDEyMzQ1Njc="
-#
-# When padding is suppressed, for a positive integer <em>n</em>:
-#
-# - Input bytes of length <em>3n</em> generate unpadded output characters
-# of length <em>4n</em>:
-#
-# # n = 1: 3 bytes => 4 characters.
-# Base64.urlsafe_encode64('123', padding: false) # => "MDEy"
-# # n = 2: 6 bytes => 8 characters.
-# Base64.urlsafe_encode64('123456', padding: false) # => "MDEyMzQ1"
-#
-# - Input bytes of length <em>3n+1</em> generate unpadded output characters
-# of length <em>4n+2</em>, with two padding characters at the end:
-#
-# # n = 1: 4 bytes => 6 characters.
-# Base64.urlsafe_encode64('1234', padding: false) # => "MDEyMw"
-# # n = 2: 7 bytes => 10 characters.
-# Base64.urlsafe_encode64('1234567', padding: false) # => "MDEyMzQ1Ng"
-#
-# - Input bytes of length <em>3n+2</em> generate unpadded output characters
-# of length <em>4n+3</em>, with one padding character at the end:
-#
-# # n = 1: 5 bytes => 7 characters.
-# Base64.urlsafe_encode64('12345', padding: false) # => "MDEyMzQ"
-# # m = 2: 8 bytes => 11 characters.
-# Base64.urlsafe_encode64('12345678', padding: false) # => "MDEyMzQ1Njc"
-#
-# <b>Padding in Decode Methods</b>
-#
-# All of the \Base64 decode methods support (but do not require) padding.
-#
-# \Method Base64.decode64 does not check the size of the padding:
-#
-# Base64.decode64("MDEyMzQ1Njc") # => "01234567"
-# Base64.decode64("MDEyMzQ1Njc=") # => "01234567"
-# Base64.decode64("MDEyMzQ1Njc==") # => "01234567"
-#
-# \Method Base64.strict_decode64 strictly enforces padding size:
-#
-# Base64.strict_decode64("MDEyMzQ1Njc") # Raises ArgumentError
-# Base64.strict_decode64("MDEyMzQ1Njc=") # => "01234567"
-# Base64.strict_decode64("MDEyMzQ1Njc==") # Raises ArgumentError
-#
-# \Method Base64.urlsafe_decode64 allows padding in +str+,
-# which if present, must be correct:
-# see {Padding}[Base64.html#module-Base64-label-Padding], above:
-#
-# Base64.urlsafe_decode64("MDEyMzQ1Njc") # => "01234567"
-# Base64.urlsafe_decode64("MDEyMzQ1Njc=") # => "01234567"
-# Base64.urlsafe_decode64("MDEyMzQ1Njc==") # Raises ArgumentError.
-#
-# == Newlines
-#
-# An encoded string returned by Base64.encode64 or Base64.urlsafe_encode64
-# has an embedded newline character
-# after each 60-character sequence, and, if non-empty, at the end:
-#
-# # No newline if empty.
-# encoded = Base64.encode64("\x00" * 0)
-# encoded.index("\n") # => nil
-#
-# # Newline at end of short output.
-# encoded = Base64.encode64("\x00" * 1)
-# encoded.size # => 4
-# encoded.index("\n") # => 4
-#
-# # Newline at end of longer output.
-# encoded = Base64.encode64("\x00" * 45)
-# encoded.size # => 60
-# encoded.index("\n") # => 60
-#
-# # Newlines embedded and at end of still longer output.
-# encoded = Base64.encode64("\x00" * 46)
-# encoded.size # => 65
-# encoded.rindex("\n") # => 65
-# encoded.split("\n").map {|s| s.size } # => [60, 4]
-#
-# The string to be encoded may itself contain newlines,
-# which are encoded as \Base64:
-#
-# # Base64.encode64("\n\n\n") # => "CgoK\n"
-# s = "This is line 1\nThis is line 2\n"
-# Base64.encode64(s) # => "VGhpcyBpcyBsaW5lIDEKVGhpcyBpcyBsaW5lIDIK\n"
-#
-module Base64
-
- VERSION = "0.2.0"
-
- module_function
-
- # Returns a string containing the RFC-2045-compliant \Base64-encoding of +bin+.
- #
- # Per RFC 2045, the returned string may contain the URL-unsafe characters
- # <tt>+</tt> or <tt>/</tt>;
- # see {Encoding Character Set}[Base64.html#module-Base64-label-Encoding+Character+Sets] above:
- #
- # Base64.encode64("\xFB\xEF\xBE") # => "++++\n"
- # Base64.encode64("\xFF\xFF\xFF") # => "////\n"
- #
- # The returned string may include padding;
- # see {Padding}[Base64.html#module-Base64-label-Padding] above.
- #
- # Base64.encode64('*') # => "Kg==\n"
- #
- # The returned string ends with a newline character, and if sufficiently long
- # will have one or more embedded newline characters;
- # see {Newlines}[Base64.html#module-Base64-label-Newlines] above:
- #
- # Base64.encode64('*') # => "Kg==\n"
- # Base64.encode64('*' * 46)
- # # => "KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq\nKg==\n"
- #
- # The string to be encoded may itself contain newlines,
- # which will be encoded as ordinary \Base64:
- #
- # Base64.encode64("\n\n\n") # => "CgoK\n"
- # s = "This is line 1\nThis is line 2\n"
- # Base64.encode64(s) # => "VGhpcyBpcyBsaW5lIDEKVGhpcyBpcyBsaW5lIDIK\n"
- #
- def encode64(bin)
- [bin].pack("m")
- end
-
- # Returns a string containing the decoding of an RFC-2045-compliant
- # \Base64-encoded string +str+:
- #
- # s = "VGhpcyBpcyBsaW5lIDEKVGhpcyBpcyBsaW5lIDIK\n"
- # Base64.decode64(s) # => "This is line 1\nThis is line 2\n"
- #
- # Non-\Base64 characters in +str+ are ignored;
- # see {Encoding Character Set}[Base64.html#module-Base64-label-Encoding+Character+Sets] above:
- # these include newline characters and characters <tt>-</tt> and <tt>/</tt>:
- #
- # Base64.decode64("\x00\n-_") # => ""
- #
- # Padding in +str+ (even if incorrect) is ignored:
- #
- # Base64.decode64("MDEyMzQ1Njc") # => "01234567"
- # Base64.decode64("MDEyMzQ1Njc=") # => "01234567"
- # Base64.decode64("MDEyMzQ1Njc==") # => "01234567"
- #
- def decode64(str)
- str.unpack1("m")
- end
-
- # Returns a string containing the RFC-2045-compliant \Base64-encoding of +bin+.
- #
- # Per RFC 2045, the returned string may contain the URL-unsafe characters
- # <tt>+</tt> or <tt>/</tt>;
- # see {Encoding Character Set}[Base64.html#module-Base64-label-Encoding+Character+Sets] above:
- #
- # Base64.strict_encode64("\xFB\xEF\xBE") # => "++++\n"
- # Base64.strict_encode64("\xFF\xFF\xFF") # => "////\n"
- #
- # The returned string may include padding;
- # see {Padding}[Base64.html#module-Base64-label-Padding] above.
- #
- # Base64.strict_encode64('*') # => "Kg==\n"
- #
- # The returned string will have no newline characters, regardless of its length;
- # see {Newlines}[Base64.html#module-Base64-label-Newlines] above:
- #
- # Base64.strict_encode64('*') # => "Kg=="
- # Base64.strict_encode64('*' * 46)
- # # => "KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKg=="
- #
- # The string to be encoded may itself contain newlines,
- # which will be encoded as ordinary \Base64:
- #
- # Base64.strict_encode64("\n\n\n") # => "CgoK"
- # s = "This is line 1\nThis is line 2\n"
- # Base64.strict_encode64(s) # => "VGhpcyBpcyBsaW5lIDEKVGhpcyBpcyBsaW5lIDIK"
- #
- def strict_encode64(bin)
- [bin].pack("m0")
- end
-
- # Returns a string containing the decoding of an RFC-2045-compliant
- # \Base64-encoded string +str+:
- #
- # s = "VGhpcyBpcyBsaW5lIDEKVGhpcyBpcyBsaW5lIDIK"
- # Base64.strict_decode64(s) # => "This is line 1\nThis is line 2\n"
- #
- # Non-\Base64 characters in +str+ not allowed;
- # see {Encoding Character Set}[Base64.html#module-Base64-label-Encoding+Character+Sets] above:
- # these include newline characters and characters <tt>-</tt> and <tt>/</tt>:
- #
- # Base64.strict_decode64("\n") # Raises ArgumentError
- # Base64.strict_decode64('-') # Raises ArgumentError
- # Base64.strict_decode64('_') # Raises ArgumentError
- #
- # Padding in +str+, if present, must be correct:
- #
- # Base64.strict_decode64("MDEyMzQ1Njc") # Raises ArgumentError
- # Base64.strict_decode64("MDEyMzQ1Njc=") # => "01234567"
- # Base64.strict_decode64("MDEyMzQ1Njc==") # Raises ArgumentError
- #
- def strict_decode64(str)
- str.unpack1("m0")
- end
-
- # Returns the RFC-4648-compliant \Base64-encoding of +bin+.
- #
- # Per RFC 4648, the returned string will not contain the URL-unsafe characters
- # <tt>+</tt> or <tt>/</tt>,
- # but instead may contain the URL-safe characters
- # <tt>-</tt> and <tt>_</tt>;
- # see {Encoding Character Set}[Base64.html#module-Base64-label-Encoding+Character+Sets] above:
- #
- # Base64.urlsafe_encode64("\xFB\xEF\xBE") # => "----"
- # Base64.urlsafe_encode64("\xFF\xFF\xFF") # => "____"
- #
- # By default, the returned string may have padding;
- # see {Padding}[Base64.html#module-Base64-label-Padding], above:
- #
- # Base64.urlsafe_encode64('*') # => "Kg=="
- #
- # Optionally, you can suppress padding:
- #
- # Base64.urlsafe_encode64('*', padding: false) # => "Kg"
- #
- # The returned string will have no newline characters, regardless of its length;
- # see {Newlines}[Base64.html#module-Base64-label-Newlines] above:
- #
- # Base64.urlsafe_encode64('*') # => "Kg=="
- # Base64.urlsafe_encode64('*' * 46)
- # # => "KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKg=="
- #
- def urlsafe_encode64(bin, padding: true)
- str = strict_encode64(bin)
- str.chomp!("==") or str.chomp!("=") unless padding
- str.tr!("+/", "-_")
- str
- end
-
- # Returns the decoding of an RFC-4648-compliant \Base64-encoded string +str+:
- #
- # +str+ may not contain non-Base64 characters;
- # see {Encoding Character Set}[Base64.html#module-Base64-label-Encoding+Character+Sets] above:
- #
- # Base64.urlsafe_decode64('+') # Raises ArgumentError.
- # Base64.urlsafe_decode64('/') # Raises ArgumentError.
- # Base64.urlsafe_decode64("\n") # Raises ArgumentError.
- #
- # Padding in +str+, if present, must be correct:
- # see {Padding}[Base64.html#module-Base64-label-Padding], above:
- #
- # Base64.urlsafe_decode64("MDEyMzQ1Njc") # => "01234567"
- # Base64.urlsafe_decode64("MDEyMzQ1Njc=") # => "01234567"
- # Base64.urlsafe_decode64("MDEyMzQ1Njc==") # Raises ArgumentError.
- #
- def urlsafe_decode64(str)
- # NOTE: RFC 4648 does say nothing about unpadded input, but says that
- # "the excess pad characters MAY also be ignored", so it is inferred that
- # unpadded input is also acceptable.
- if !str.end_with?("=") && str.length % 4 != 0
- str = str.ljust((str.length + 3) & ~3, "=")
- str.tr!("-_", "+/")
- else
- str = str.tr("-_", "+/")
- end
- strict_decode64(str)
- end
-end
diff --git a/lib/bundled_gems.rb b/lib/bundled_gems.rb
index ceb546f580..932949576b 100644
--- a/lib/bundled_gems.rb
+++ b/lib/bundled_gems.rb
@@ -1,3 +1,7 @@
+# -*- frozen-string-literal: true -*-
+
+# :stopdoc:
+
module Gem::BUNDLED_GEMS
SINCE = {
"rexml" => "3.0.0",
@@ -9,6 +13,7 @@ module Gem::BUNDLED_GEMS
"net-pop" => "3.1.0",
"net-smtp" => "3.1.0",
"prime" => "3.1.0",
+ "racc" => "3.3.0",
"abbrev" => "3.4.0",
"base64" => "3.4.0",
"bigdecimal" => "3.4.0",
@@ -18,25 +23,19 @@ module Gem::BUNDLED_GEMS
"mutex_m" => "3.4.0",
"nkf" => "3.4.0",
"observer" => "3.4.0",
- "racc" => "3.4.0",
"resolv-replace" => "3.4.0",
"rinda" => "3.4.0",
"syslog" => "3.4.0",
+ "ostruct" => "3.5.0",
+ "pstore" => "3.5.0",
+ "rdoc" => "3.5.0",
+ "win32ole" => "3.5.0",
+ "fiddle" => "3.5.0",
+ "logger" => "3.5.0",
}.freeze
EXACT = {
- "abbrev" => true,
- "base64" => true,
- "bigdecimal" => true,
- "csv" => true,
- "drb" => true,
- "getoptlong" => true,
- "mutex_m" => true,
- "nkf" => true, "kconv" => "nkf",
- "observer" => true,
- "resolv-replace" => true,
- "rinda" => true,
- "syslog" => true,
+ "kconv" => "nkf",
}.freeze
PREFIXED = {
@@ -56,6 +55,27 @@ module Gem::BUNDLED_GEMS
DLEXT = /\.#{Regexp.union(dlext)}\z/
LIBEXT = /\.#{Regexp.union("rb", *dlext)}\z/
+ def self.replace_require(specs)
+ return if [::Kernel.singleton_class, ::Kernel].any? {|klass| klass.respond_to?(:no_warning_require) }
+
+ spec_names = specs.to_a.each_with_object({}) {|spec, h| h[spec.name] = true }
+
+ [::Kernel.singleton_class, ::Kernel].each do |kernel_class|
+ kernel_class.send(:alias_method, :no_warning_require, :require)
+ kernel_class.send(:define_method, :require) do |name|
+ if message = ::Gem::BUNDLED_GEMS.warning?(name, specs: spec_names) # rubocop:disable Style/HashSyntax
+ warn message, :uplevel => 1
+ end
+ kernel_class.send(:no_warning_require, name)
+ end
+ if kernel_class == ::Kernel
+ kernel_class.send(:private, :require)
+ else
+ kernel_class.send(:public, :require)
+ end
+ end
+ end
+
def self.find_gem(path)
if !path
return
@@ -66,41 +86,62 @@ module Gem::BUNDLED_GEMS
else
return
end
- EXACT[n] or PREFIXED[n = n[%r[\A[^/]+(?=/)]]] && n
+ (EXACT[n] || !!SINCE[n]) or PREFIXED[n = n[%r[\A[^/]+(?=/)]]] && n
end
def self.warning?(name, specs: nil)
- name = File.path(name) # name can be a feature name or a file path with String or Pathname
- return if specs.to_a.map(&:name).include?(name.sub(LIBEXT, ""))
- name = name.tr("/", "-")
- _t, path = $:.resolve_feature_path(name)
- return unless gem = find_gem(path)
- caller = caller_locations(3, 3).find {|c| c&.absolute_path}
- return if find_gem(caller&.absolute_path)
- name = name.sub(LIBEXT, "") # assume "foo.rb"/"foo.so" belongs to "foo" gem
+ # name can be a feature name or a file path with String or Pathname
+ feature = File.path(name)
+ # bootsnap expands `require "csv"` to `require "#{LIBDIR}/csv.rb"`,
+ # and `require "syslog"` to `require "#{ARCHDIR}/syslog.so"`.
+ name = feature.delete_prefix(ARCHDIR)
+ name.delete_prefix!(LIBDIR)
+ name.tr!("/", "-")
+ name.sub!(LIBEXT, "")
+ return if specs.include?(name)
+ _t, path = $:.resolve_feature_path(feature)
+ if gem = find_gem(path)
+ return if specs.include?(gem)
+ caller = caller_locations(3, 3)&.find {|c| c&.absolute_path}
+ return if find_gem(caller&.absolute_path)
+ elsif SINCE[name] && !path
+ gem = true
+ else
+ return
+ end
+
return if WARNED[name]
WARNED[name] = true
if gem == true
gem = name
+ "#{feature} was loaded from the standard library, but"
elsif gem
return if WARNED[gem]
WARNED[gem] = true
- "#{name} is found in #{gem}"
+ "#{feature} is found in #{gem}, which"
else
return
end + build_message(gem)
end
def self.build_message(gem)
- msg = " which #{RUBY_VERSION < SINCE[gem] ? "will no longer be" : "is not"} part of the default gems since Ruby #{SINCE[gem]}."
+ msg = " #{RUBY_VERSION < SINCE[gem] ? "will no longer be" : "is not"} part of the default gems since Ruby #{SINCE[gem]}."
if defined?(Bundler)
msg += " Add #{gem} to your Gemfile or gemspec."
+
# We detect the gem name from caller_locations. We need to skip 2 frames like:
# lib/ruby/3.3.0+0/bundled_gems.rb:90:in `warning?'",
# lib/ruby/3.3.0+0/bundler/rubygems_integration.rb:247:in `block (2 levels) in replace_require'",
- location = caller_locations(3,3)[0]&.path
- if File.file?(location) && !location.start_with?(Gem::BUNDLED_GEMS::LIBDIR)
+ #
+ # Additionally, we need to skip Bootsnap and Zeitwerk if present, these
+ # gems decorate Kernel#require, so they are not really the ones issuing
+ # the require call users should be warned about. Those are upwards.
+ location = Thread.each_caller_location(2) do |cl|
+ break cl.path unless cl.base_label == "require"
+ end
+
+ if location && File.file?(location) && !location.start_with?(Gem::BUNDLED_GEMS::LIBDIR)
caller_gem = nil
Gem.path.each do |path|
if location =~ %r{#{path}/gems/([\w\-\.]+)}
@@ -126,9 +167,14 @@ end
# If loading library is not part of the default gems and the bundled gems, warn it.
class LoadError
def message
- if !defined?(Bundler) && Gem::BUNDLED_GEMS::SINCE[path] && !Gem::BUNDLED_GEMS::WARNED[path]
- warn path + Gem::BUNDLED_GEMS.build_message(path)
+ return super unless path
+
+ name = path.tr("/", "-")
+ if !defined?(Bundler) && Gem::BUNDLED_GEMS::SINCE[name] && !Gem::BUNDLED_GEMS::WARNED[name]
+ warn name + Gem::BUNDLED_GEMS.build_message(name)
end
super
end
end
+
+# :startdoc:
diff --git a/lib/bundler.rb b/lib/bundler.rb
index bc28b24e2e..0081b9554f 100644
--- a/lib/bundler.rb
+++ b/lib/bundler.rb
@@ -17,7 +17,7 @@ require_relative "bundler/build_metadata"
# Bundler provides a consistent environment for Ruby projects by
# tracking and installing the exact gems and versions that are needed.
#
-# Since Ruby 2.6, Bundler is a part of Ruby's standard library.
+# Bundler is a part of Ruby's standard library.
#
# Bundler is used by creating _gemfiles_ listing all the project dependencies
# and (optionally) their versions and then using
@@ -40,6 +40,9 @@ module Bundler
SUDO_MUTEX = Thread::Mutex.new
autoload :Checksum, File.expand_path("bundler/checksum", __dir__)
+ autoload :CLI, File.expand_path("bundler/cli", __dir__)
+ autoload :CIDetector, File.expand_path("bundler/ci_detector", __dir__)
+ autoload :CompactIndexClient, File.expand_path("bundler/compact_index_client", __dir__)
autoload :Definition, File.expand_path("bundler/definition", __dir__)
autoload :Dependency, File.expand_path("bundler/dependency", __dir__)
autoload :Deprecate, File.expand_path("bundler/deprecate", __dir__)
@@ -99,9 +102,7 @@ module Bundler
end
def create_bundle_path
- SharedHelpers.filesystem_access(bundle_path.to_s) do |p|
- mkdir_p(p)
- end unless bundle_path.exist?
+ mkdir_p(bundle_path) unless bundle_path.exist?
@bundle_path = bundle_path.realpath
rescue Errno::EEXIST
@@ -118,7 +119,7 @@ module Bundler
@bin_path ||= begin
path = settings[:bin] || "bin"
path = Pathname.new(path).expand_path(root).expand_path
- SharedHelpers.filesystem_access(path) {|p| FileUtils.mkdir_p(p) }
+ mkdir_p(path)
path
end
end
@@ -166,6 +167,25 @@ module Bundler
end
end
+ # Automatically install dependencies if Bundler.settings[:auto_install] exists.
+ # This is set through config cmd `bundle config set --global auto_install 1`.
+ #
+ # Note that this method `nil`s out the global Definition object, so it
+ # should be called first, before you instantiate anything like an
+ # `Installer` that'll keep a reference to the old one instead.
+ def auto_install
+ return unless settings[:auto_install]
+
+ begin
+ definition.specs
+ rescue GemNotFound, GitError
+ ui.info "Automatically installing missing gems."
+ reset!
+ CLI::Install.new({}).run
+ reset!
+ end
+ end
+
# Setups Bundler environment (see Bundler.setup) if it is not already set,
# and loads all gems from groups specified. Unlike ::setup, can be called
# multiple times with different groups (if they were allowed by setup).
@@ -185,6 +205,7 @@ module Bundler
# Bundler.require(:test) # requires second_gem
#
def require(*groups)
+ load_plugins
setup(*groups).require(*groups)
end
@@ -193,7 +214,7 @@ module Bundler
end
def environment
- SharedHelpers.major_deprecation 2, "Bundler.environment has been removed in favor of Bundler.load", :print_caller_location => true
+ SharedHelpers.major_deprecation 2, "Bundler.environment has been removed in favor of Bundler.load", print_caller_location: true
load
end
@@ -201,12 +222,13 @@ module Bundler
#
# @param unlock [Hash, Boolean, nil] Gems that have been requested
# to be updated or true if all gems should be updated
+ # @param lockfile [Pathname] Path to Gemfile.lock
# @return [Bundler::Definition]
- def definition(unlock = nil)
+ def definition(unlock = nil, lockfile = default_lockfile)
@definition = nil if unlock
@definition ||= begin
configure
- Definition.build(default_gemfile, default_lockfile, unlock)
+ Definition.build(default_gemfile, lockfile, unlock)
end
end
@@ -336,7 +358,7 @@ module Bundler
def settings
@settings ||= Settings.new(app_config_path)
rescue GemfileNotFound
- @settings = Settings.new(Pathname.new(".bundle").expand_path)
+ @settings = Settings.new
end
# @return [Hash] Environment present before Bundler was activated
@@ -346,13 +368,13 @@ module Bundler
# @deprecated Use `unbundled_env` instead
def clean_env
- Bundler::SharedHelpers.major_deprecation(
- 2,
+ message =
"`Bundler.clean_env` has been deprecated in favor of `Bundler.unbundled_env`. " \
- "If you instead want the environment before bundler was originally loaded, use `Bundler.original_env`",
- :print_caller_location => true
- )
-
+ "If you instead want the environment before bundler was originally loaded, use `Bundler.original_env`"
+ removed_message =
+ "`Bundler.clean_env` has been removed in favor of `Bundler.unbundled_env`. " \
+ "If you instead want the environment before bundler was originally loaded, use `Bundler.original_env`"
+ Bundler::SharedHelpers.major_deprecation(2, message, removed_message: removed_message, print_caller_location: true)
unbundled_env
end
@@ -389,13 +411,13 @@ module Bundler
# @deprecated Use `with_unbundled_env` instead
def with_clean_env
- Bundler::SharedHelpers.major_deprecation(
- 2,
+ message =
"`Bundler.with_clean_env` has been deprecated in favor of `Bundler.with_unbundled_env`. " \
- "If you instead want the environment before bundler was originally loaded, use `Bundler.with_original_env`",
- :print_caller_location => true
- )
-
+ "If you instead want the environment before bundler was originally loaded, use `Bundler.with_original_env`"
+ removed_message =
+ "`Bundler.with_clean_env` has been removed in favor of `Bundler.with_unbundled_env`. " \
+ "If you instead want the environment before bundler was originally loaded, use `Bundler.with_original_env`"
+ Bundler::SharedHelpers.major_deprecation(2, message, removed_message: removed_message, print_caller_location: true)
with_env(unbundled_env) { yield }
end
@@ -411,13 +433,13 @@ module Bundler
# @deprecated Use `unbundled_system` instead
def clean_system(*args)
- Bundler::SharedHelpers.major_deprecation(
- 2,
+ message =
"`Bundler.clean_system` has been deprecated in favor of `Bundler.unbundled_system`. " \
- "If you instead want to run the command in the environment before bundler was originally loaded, use `Bundler.original_system`",
- :print_caller_location => true
- )
-
+ "If you instead want to run the command in the environment before bundler was originally loaded, use `Bundler.original_system`"
+ removed_message =
+ "`Bundler.clean_system` has been removed in favor of `Bundler.unbundled_system`. " \
+ "If you instead want to run the command in the environment before bundler was originally loaded, use `Bundler.original_system`"
+ Bundler::SharedHelpers.major_deprecation(2, message, removed_message: removed_message, print_caller_location: true)
with_env(unbundled_env) { Kernel.system(*args) }
end
@@ -433,13 +455,13 @@ module Bundler
# @deprecated Use `unbundled_exec` instead
def clean_exec(*args)
- Bundler::SharedHelpers.major_deprecation(
- 2,
+ message =
"`Bundler.clean_exec` has been deprecated in favor of `Bundler.unbundled_exec`. " \
- "If you instead want to exec to a command in the environment before bundler was originally loaded, use `Bundler.original_exec`",
- :print_caller_location => true
- )
-
+ "If you instead want to exec to a command in the environment before bundler was originally loaded, use `Bundler.original_exec`"
+ removed_message =
+ "`Bundler.clean_exec` has been removed in favor of `Bundler.unbundled_exec`. " \
+ "If you instead want to exec to a command in the environment before bundler was originally loaded, use `Bundler.original_exec`"
+ Bundler::SharedHelpers.major_deprecation(2, message, removed_message: removed_message, print_caller_location: true)
with_env(unbundled_env) { Kernel.exec(*args) }
end
@@ -482,7 +504,7 @@ module Bundler
configured_bundle_path.use_system_gems?
end
- def mkdir_p(path, options = {})
+ def mkdir_p(path)
SharedHelpers.filesystem_access(path, :write) do |p|
FileUtils.mkdir_p(p)
end
@@ -516,7 +538,7 @@ module Bundler
raise MarshalError, "#{e.class}: #{e.message}"
end
else
- load_marshal(data, :marshal_proc => SafeMarshal.proc)
+ load_marshal(data, marshal_proc: SafeMarshal.proc)
end
end
@@ -560,6 +582,23 @@ module Bundler
@feature_flag ||= FeatureFlag.new(VERSION)
end
+ def load_plugins(definition = Bundler.definition)
+ return if defined?(@load_plugins_ran)
+
+ Bundler.rubygems.load_plugins
+
+ requested_path_gems = definition.requested_specs.select {|s| s.source.is_a?(Source::Path) }
+ path_plugin_files = requested_path_gems.map do |spec|
+ Bundler.rubygems.spec_matches_for_glob(spec, "rubygems_plugin#{Bundler.rubygems.suffix_pattern}")
+ rescue TypeError
+ error_message = "#{spec.name} #{spec.version} has an invalid gemspec"
+ raise Gem::InvalidSpecificationException, error_message
+ end.flatten
+ Bundler.rubygems.load_plugin_files(path_plugin_files)
+ Bundler.rubygems.load_env_plugins
+ @load_plugins_ran = true
+ end
+
def reset!
reset_paths!
Plugin.reset!
diff --git a/lib/bundler/build_metadata.rb b/lib/bundler/build_metadata.rb
index 29fa833588..5d2a8b53bb 100644
--- a/lib/bundler/build_metadata.rb
+++ b/lib/bundler/build_metadata.rb
@@ -29,7 +29,7 @@ module Bundler
# commit instance variable then we can't determine its commits SHA.
git_dir = File.expand_path("../../../.git", __dir__)
if File.directory?(git_dir)
- return @git_commit_sha = IO.popen(%w[git rev-parse --short HEAD], { :chdir => git_dir }, &:read).strip.freeze
+ return @git_commit_sha = IO.popen(%w[git rev-parse --short HEAD], { chdir: git_dir }, &:read).strip.freeze
end
@git_commit_sha ||= "unknown"
diff --git a/lib/bundler/bundler.gemspec b/lib/bundler/bundler.gemspec
index cc978f0dd4..2d6269fae1 100644
--- a/lib/bundler/bundler.gemspec
+++ b/lib/bundler/bundler.gemspec
@@ -39,7 +39,7 @@ Gem::Specification.new do |s|
# include the gemspec itself because warbler breaks w/o it
s.files += %w[lib/bundler/bundler.gemspec]
- s.bindir = "libexec"
+ s.bindir = "exe"
s.executables = %w[bundle bundler]
s.require_paths = ["lib"]
end
diff --git a/lib/bundler/capistrano.rb b/lib/bundler/capistrano.rb
index 1f3712d48e..705840143f 100644
--- a/lib/bundler/capistrano.rb
+++ b/lib/bundler/capistrano.rb
@@ -17,6 +17,6 @@ end
Capistrano::Configuration.instance(:must_exist).load do
before "deploy:finalize_update", "bundle:install"
- Bundler::Deployment.define_task(self, :task, :except => { :no_release => true })
+ Bundler::Deployment.define_task(self, :task, except: { no_release: true })
set :rake, lambda { "#{fetch(:bundle_cmd, "bundle")} exec rake" }
end
diff --git a/lib/bundler/checksum.rb b/lib/bundler/checksum.rb
index f8fd386569..60ba93417c 100644
--- a/lib/bundler/checksum.rb
+++ b/lib/bundler/checksum.rb
@@ -9,14 +9,28 @@ module Bundler
private_constant :DEFAULT_BLOCK_SIZE
class << self
+ def from_gem_package(gem_package, algo = DEFAULT_ALGORITHM)
+ return if Bundler.settings[:disable_checksum_validation]
+ return unless source = gem_package.instance_variable_get(:@gem)
+ return unless source.respond_to?(:with_read_io)
+
+ source.with_read_io do |io|
+ from_gem(io, source.path)
+ ensure
+ io.rewind
+ end
+ end
+
def from_gem(io, pathname, algo = DEFAULT_ALGORITHM)
digest = Bundler::SharedHelpers.digest(algo.upcase).new
- buf = String.new(:capacity => DEFAULT_BLOCK_SIZE)
+ buf = String.new(capacity: DEFAULT_BLOCK_SIZE)
digest << io.readpartial(DEFAULT_BLOCK_SIZE, buf) until io.eof?
Checksum.new(algo, digest.hexdigest!, Source.new(:gem, pathname))
end
def from_api(digest, source_uri, algo = DEFAULT_ALGORITHM)
+ return if Bundler.settings[:disable_checksum_validation]
+
Checksum.new(algo, to_hexdigest(digest, algo), Source.new(:api, source_uri))
end
@@ -28,12 +42,13 @@ module Bundler
def to_hexdigest(digest, algo = DEFAULT_ALGORITHM)
return digest unless algo == DEFAULT_ALGORITHM
return digest if digest.match?(/\A[0-9a-f]{64}\z/i)
+
if digest.match?(%r{\A[-0-9a-z_+/]{43}={0,2}\z}i)
digest = digest.tr("-_", "+/") # fix urlsafe base64
- # transform to hex. Use unpack1 when we drop older rubies
- return digest.unpack("m0").first.unpack("H*").first
+ digest.unpack1("m0").unpack1("H*")
+ else
+ raise ArgumentError, "#{digest.inspect} is not a valid SHA256 hex or base64 digest"
end
- raise ArgumentError, "#{digest.inspect} is not a valid SHA256 hex or base64 digest"
end
end
@@ -51,6 +66,10 @@ module Bundler
alias_method :eql?, :==
+ def same_source?(other)
+ sources.include?(other.sources.first)
+ end
+
def match?(other)
other.is_a?(self.class) && other.digest == digest && other.algo == algo
end
@@ -69,6 +88,7 @@ module Bundler
def merge!(other)
return nil unless match?(other)
+
@sources.concat(other.sources).uniq!
self
end
@@ -149,26 +169,17 @@ module Bundler
def initialize
@store = {}
- end
-
- def initialize_copy(other)
- @store = {}
- other.store.each do |name_tuple, checksums|
- store[name_tuple] = checksums.dup
- end
+ @store_mutex = Mutex.new
end
def inspect
"#<#{self.class}:#{object_id} size=#{store.size}>"
end
- def fetch(spec, algo = DEFAULT_ALGORITHM)
- store[spec.name_tuple]&.fetch(algo, nil)
- end
-
# Replace when the new checksum is from the same source.
- # The primary purpose of this registering checksums from gems where there are
+ # The primary purpose is registering checksums from gems where there are
# duplicates of the same gem (according to full_name) in the index.
+ #
# In particular, this is when 2 gems have two similar platforms, e.g.
# "darwin20" and "darwin-20", both of which resolve to darwin-20.
# In the Index, the later gem replaces the former, so we do that here.
@@ -177,59 +188,67 @@ module Bundler
# This ensures a mismatch error where there are multiple top level sources
# that contain the same gem with different checksums.
def replace(spec, checksum)
- return if Bundler.settings[:disable_checksum_validation]
return unless checksum
- name_tuple = spec.name_tuple
- checksums = (store[name_tuple] ||= {})
- existing = checksums[checksum.algo]
-
- # we assume only one source because this is used while building the index
- if !existing || existing.sources.first == checksum.sources.first
- checksums[checksum.algo] = checksum
- else
- register_checksum(name_tuple, checksum)
+ lock_name = spec.name_tuple.lock_name
+ @store_mutex.synchronize do
+ existing = fetch_checksum(lock_name, checksum.algo)
+ if !existing || existing.same_source?(checksum)
+ store_checksum(lock_name, checksum)
+ else
+ merge_checksum(lock_name, checksum, existing)
+ end
end
end
def register(spec, checksum)
- return if Bundler.settings[:disable_checksum_validation]
return unless checksum
- register_checksum(spec.name_tuple, checksum)
+
+ register_checksum(spec.name_tuple.lock_name, checksum)
end
def merge!(other)
- other.store.each do |name_tuple, checksums|
+ other.store.each do |lock_name, checksums|
checksums.each do |_algo, checksum|
- register_checksum(name_tuple, checksum)
+ register_checksum(lock_name, checksum)
end
end
end
def to_lock(spec)
- name_tuple = spec.name_tuple
- if checksums = store[name_tuple]
- "#{name_tuple.lock_name} #{checksums.values.map(&:to_lock).sort.join(",")}"
+ lock_name = spec.name_tuple.lock_name
+ checksums = @store[lock_name]
+ if checksums
+ "#{lock_name} #{checksums.values.map(&:to_lock).sort.join(",")}"
else
- name_tuple.lock_name
+ lock_name
end
end
private
- def register_checksum(name_tuple, checksum)
- return unless checksum
- checksums = (store[name_tuple] ||= {})
- existing = checksums[checksum.algo]
-
- if !existing
- checksums[checksum.algo] = checksum
- elsif existing.merge!(checksum)
- checksum
- else
- raise ChecksumMismatchError.new(name_tuple, existing, checksum)
+ def register_checksum(lock_name, checksum)
+ @store_mutex.synchronize do
+ existing = fetch_checksum(lock_name, checksum.algo)
+ if existing
+ merge_checksum(lock_name, checksum, existing)
+ else
+ store_checksum(lock_name, checksum)
+ end
end
end
+
+ def merge_checksum(lock_name, checksum, existing)
+ existing.merge!(checksum) || raise(ChecksumMismatchError.new(lock_name, existing, checksum))
+ end
+
+ def store_checksum(lock_name, checksum)
+ (@store[lock_name] ||= {})[checksum.algo] = checksum
+ end
+
+ def fetch_checksum(lock_name, algo)
+ @store[lock_name]&.fetch(algo, nil)
+ end
end
end
end
diff --git a/lib/bundler/ci_detector.rb b/lib/bundler/ci_detector.rb
new file mode 100644
index 0000000000..e5fedbdea8
--- /dev/null
+++ b/lib/bundler/ci_detector.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+module Bundler
+ module CIDetector
+ # NOTE: Any changes made here will need to be made to both lib/rubygems/ci_detector.rb and
+ # bundler/lib/bundler/ci_detector.rb (which are enforced duplicates).
+ # TODO: Drop that duplication once bundler drops support for RubyGems 3.4
+ #
+ # ## Recognized CI providers, their signifiers, and the relevant docs ##
+ #
+ # Travis CI - CI, TRAVIS https://docs.travis-ci.com/user/environment-variables/#default-environment-variables
+ # Cirrus CI - CI, CIRRUS_CI https://cirrus-ci.org/guide/writing-tasks/#environment-variables
+ # Circle CI - CI, CIRCLECI https://circleci.com/docs/variables/#built-in-environment-variables
+ # Gitlab CI - CI, GITLAB_CI https://docs.gitlab.com/ee/ci/variables/
+ # AppVeyor - CI, APPVEYOR https://www.appveyor.com/docs/environment-variables/
+ # CodeShip - CI_NAME https://docs.cloudbees.com/docs/cloudbees-codeship/latest/pro-builds-and-configuration/environment-variables#_default_environment_variables
+ # dsari - CI, DSARI https://github.com/rfinnie/dsari#running
+ # Jenkins - BUILD_NUMBER https://www.jenkins.io/doc/book/pipeline/jenkinsfile/#using-environment-variables
+ # TeamCity - TEAMCITY_VERSION https://www.jetbrains.com/help/teamcity/predefined-build-parameters.html#Predefined+Server+Build+Parameters
+ # Appflow - CI_BUILD_ID https://ionic.io/docs/appflow/automation/environments#predefined-environments
+ # TaskCluster - TASKCLUSTER_ROOT_URL https://docs.taskcluster.net/docs/manual/design/env-vars
+ # Semaphore - CI, SEMAPHORE https://docs.semaphoreci.com/ci-cd-environment/environment-variables/
+ # BuildKite - CI, BUILDKITE https://buildkite.com/docs/pipelines/environment-variables
+ # GoCD - GO_SERVER_URL https://docs.gocd.org/current/faq/dev_use_current_revision_in_build.html
+ # GH Actions - CI, GITHUB_ACTIONS https://docs.github.com/en/actions/learn-github-actions/variables#default-environment-variables
+ #
+ # ### Some "standard" ENVs that multiple providers may set ###
+ #
+ # * CI - this is set by _most_ (but not all) CI providers now; it's approaching a standard.
+ # * CI_NAME - Not as frequently used, but some providers set this to specify their own name
+
+ # Any of these being set is a reasonably reliable indicator that we are
+ # executing in a CI environment.
+ ENV_INDICATORS = [
+ "CI",
+ "CI_NAME",
+ "CONTINUOUS_INTEGRATION",
+ "BUILD_NUMBER",
+ "CI_APP_ID",
+ "CI_BUILD_ID",
+ "CI_BUILD_NUMBER",
+ "RUN_ID",
+ "TASKCLUSTER_ROOT_URL",
+ ].freeze
+
+ # For each CI, this env suffices to indicate that we're on _that_ CI's
+ # containers. (A few of them only supply a CI_NAME variable, which is also
+ # nice). And if they set "CI" but we can't tell which one they are, we also
+ # want to know that - a bare "ci" without another token tells us as much.
+ ENV_DESCRIPTORS = {
+ "TRAVIS" => "travis",
+ "CIRCLECI" => "circle",
+ "CIRRUS_CI" => "cirrus",
+ "DSARI" => "dsari",
+ "SEMAPHORE" => "semaphore",
+ "JENKINS_URL" => "jenkins",
+ "BUILDKITE" => "buildkite",
+ "GO_SERVER_URL" => "go",
+ "GITLAB_CI" => "gitlab",
+ "GITHUB_ACTIONS" => "github",
+ "TASKCLUSTER_ROOT_URL" => "taskcluster",
+ "CI" => "ci",
+ }.freeze
+
+ def self.ci?
+ ENV_INDICATORS.any? {|var| ENV.include?(var) }
+ end
+
+ def self.ci_strings
+ matching_names = ENV_DESCRIPTORS.select {|env, _| ENV[env] }.values
+ matching_names << ENV["CI_NAME"].downcase if ENV["CI_NAME"]
+ matching_names.reject(&:empty?).sort.uniq
+ end
+ end
+end
diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb
index dd91038d64..eb67668cd2 100644
--- a/lib/bundler/cli.rb
+++ b/lib/bundler/cli.rb
@@ -5,6 +5,7 @@ require_relative "vendored_thor"
module Bundler
class CLI < Thor
require_relative "cli/common"
+ require_relative "cli/install"
package_name "Bundler"
@@ -69,7 +70,7 @@ module Bundler
Bundler.settings.set_command_option_if_given :retry, options[:retry]
current_cmd = args.last[:current_command].name
- auto_install if AUTO_INSTALL_CMDS.include?(current_cmd)
+ Bundler.auto_install if AUTO_INSTALL_CMDS.include?(current_cmd)
rescue UnknownArgumentError => e
raise InvalidOption, e.message
ensure
@@ -80,10 +81,10 @@ module Bundler
unprinted_warnings.each {|w| Bundler.ui.warn(w) }
end
- check_unknown_options!(:except => [:config, :exec])
+ check_unknown_options!(except: [:config, :exec])
stop_on_unknown_option! :exec
- desc "cli_help", "Prints a summary of bundler commands", :hide => true
+ desc "cli_help", "Prints a summary of bundler commands", hide: true
def cli_help
version
Bundler.ui.info "\n"
@@ -99,21 +100,23 @@ module Bundler
shell.say "Bundler commands:\n\n"
shell.say " Primary commands:\n"
- shell.print_table(primary_commands, :indent => 4, :truncate => true)
+ shell.print_table(primary_commands, indent: 4, truncate: true)
shell.say
shell.say " Utilities:\n"
- shell.print_table(utilities, :indent => 4, :truncate => true)
+ shell.print_table(utilities, indent: 4, truncate: true)
shell.say
self.class.send(:class_options_help, shell)
end
default_task(Bundler.feature_flag.default_cli_command)
- class_option "no-color", :type => :boolean, :desc => "Disable colorization in output"
- class_option "retry", :type => :numeric, :aliases => "-r", :banner => "NUM",
- :desc => "Specify the number of times you wish to attempt network commands"
- class_option "verbose", :type => :boolean, :desc => "Enable verbose output mode", :aliases => "-V"
+ class_option "no-color", type: :boolean, desc: "Disable colorization in output"
+ class_option "retry", type: :numeric, aliases: "-r", banner: "NUM",
+ desc: "Specify the number of times you wish to attempt network commands"
+ class_option "verbose", type: :boolean, desc: "Enable verbose output mode", aliases: "-V"
def help(cli = nil)
+ cli = self.class.all_aliases[cli] if self.class.all_aliases[cli]
+
case cli
when "gemfile" then command = "gemfile"
when nil then command = "bundle"
@@ -127,8 +130,8 @@ module Bundler
if man_pages.include?(command)
man_page = man_pages[command]
- if Bundler.which("man") && man_path !~ %r{^file:/.+!/META-INF/jruby.home/.+}
- Kernel.exec "man #{man_page}"
+ if Bundler.which("man") && !man_path.match?(%r{^file:/.+!/META-INF/jruby.home/.+})
+ Kernel.exec("man", man_page)
else
puts File.read("#{man_path}/#{File.basename(man_page)}.ronn")
end
@@ -155,8 +158,8 @@ module Bundler
Gemfile to a gem with a gemspec, the --gemspec option will automatically add each
dependency listed in the gemspec file to the newly created Gemfile.
D
- method_option "gemspec", :type => :string, :banner => "Use the specified .gemspec to create the Gemfile"
- method_option "gemfile", :type => :string, :banner => "Use the specified name for the gemfile instead of 'Gemfile'"
+ method_option "gemspec", type: :string, banner: "Use the specified .gemspec to create the Gemfile"
+ method_option "gemfile", type: :string, banner: "Use the specified name for the gemfile instead of 'Gemfile'"
def init
require_relative "cli/init"
Init.new(options.dup).run
@@ -168,12 +171,9 @@ module Bundler
all gems are found, Bundler prints a success message and exits with a status of 0.
If not, the first missing gem is listed and Bundler exits status 1.
D
- method_option "dry-run", :type => :boolean, :default => false, :banner =>
- "Lock the Gemfile"
- method_option "gemfile", :type => :string, :banner =>
- "Use the specified gemfile instead of Gemfile"
- method_option "path", :type => :string, :banner =>
- "Specify a different path than the system default ($BUNDLE_PATH or $GEM_HOME).#{" Bundler will remember this value for future installs on this machine" unless Bundler.feature_flag.forget_cli_options?}"
+ method_option "dry-run", type: :boolean, default: false, banner: "Lock the Gemfile"
+ method_option "gemfile", type: :string, banner: "Use the specified gemfile instead of Gemfile"
+ method_option "path", type: :string, banner: "Specify a different path than the system default ($BUNDLE_PATH or $GEM_HOME).#{" Bundler will remember this value for future installs on this machine" unless Bundler.feature_flag.forget_cli_options?}"
def check
remembered_flag_deprecation("path")
@@ -187,10 +187,14 @@ module Bundler
long_desc <<-D
Removes the given gems from the Gemfile while ensuring that the resulting Gemfile is still valid. If the gem is not found, Bundler prints a error message and if gem could not be removed due to any reason Bundler will display a warning.
D
- method_option "install", :type => :boolean, :banner =>
- "Runs 'bundle install' after removing the gems from the Gemfile"
+ method_option "install", type: :boolean, banner: "Runs 'bundle install' after removing the gems from the Gemfile"
def remove(*gems)
- SharedHelpers.major_deprecation(2, "The `--install` flag has been deprecated. `bundle install` is triggered by default.") if ARGV.include?("--install")
+ if ARGV.include?("--install")
+ message = "The `--install` flag has been deprecated. `bundle install` is triggered by default."
+ removed_message = "The `--install` flag has been removed. `bundle install` is triggered by default."
+ SharedHelpers.major_deprecation(2, message, removed_message: removed_message)
+ end
+
require_relative "cli/remove"
Remove.new(gems, options).run
end
@@ -206,58 +210,40 @@ module Bundler
If the bundle has already been installed, bundler will tell you so and then exit.
D
- method_option "binstubs", :type => :string, :lazy_default => "bin", :banner =>
- "Generate bin stubs for bundled gems to ./bin"
- method_option "clean", :type => :boolean, :banner =>
- "Run bundle clean automatically after install"
- method_option "deployment", :type => :boolean, :banner =>
- "Install using defaults tuned for deployment environments"
- method_option "frozen", :type => :boolean, :banner =>
- "Do not allow the Gemfile.lock to be updated after this install"
- method_option "full-index", :type => :boolean, :banner =>
- "Fall back to using the single-file index of all gems"
- method_option "gemfile", :type => :string, :banner =>
- "Use the specified gemfile instead of Gemfile"
- method_option "jobs", :aliases => "-j", :type => :numeric, :banner =>
- "Specify the number of jobs to run in parallel"
- method_option "local", :type => :boolean, :banner =>
- "Do not attempt to fetch gems remotely and use the gem cache instead"
- method_option "prefer-local", :type => :boolean, :banner =>
- "Only attempt to fetch gems remotely if not present locally, even if newer versions are available remotely"
- method_option "no-cache", :type => :boolean, :banner =>
- "Don't update the existing gem cache."
- method_option "redownload", :type => :boolean, :aliases => "--force", :banner =>
- "Force downloading every gem."
- method_option "no-prune", :type => :boolean, :banner =>
- "Don't remove stale gems from the cache."
- method_option "path", :type => :string, :banner =>
- "Specify a different path than the system default ($BUNDLE_PATH or $GEM_HOME).#{" Bundler will remember this value for future installs on this machine" unless Bundler.feature_flag.forget_cli_options?}"
- method_option "quiet", :type => :boolean, :banner =>
- "Only output warnings and errors."
- method_option "shebang", :type => :string, :banner =>
- "Specify a different shebang executable name than the default (usually 'ruby')"
- method_option "standalone", :type => :array, :lazy_default => [], :banner =>
- "Make a bundle that can work without the Bundler runtime"
- method_option "system", :type => :boolean, :banner =>
- "Install to the system location ($BUNDLE_PATH or $GEM_HOME) even if the bundle was previously installed somewhere else for this application"
- method_option "trust-policy", :alias => "P", :type => :string, :banner =>
- "Gem trust policy (like gem install -P). Must be one of " +
- Bundler.rubygems.security_policy_keys.join("|")
- method_option "without", :type => :array, :banner =>
- "Exclude gems that are part of the specified named group."
- method_option "with", :type => :array, :banner =>
- "Include gems that are part of the specified named group."
+ method_option "binstubs", type: :string, lazy_default: "bin", banner: "Generate bin stubs for bundled gems to ./bin"
+ method_option "clean", type: :boolean, banner: "Run bundle clean automatically after install"
+ method_option "deployment", type: :boolean, banner: "Install using defaults tuned for deployment environments"
+ method_option "frozen", type: :boolean, banner: "Do not allow the Gemfile.lock to be updated after this install"
+ method_option "full-index", type: :boolean, banner: "Fall back to using the single-file index of all gems"
+ method_option "gemfile", type: :string, banner: "Use the specified gemfile instead of Gemfile"
+ method_option "jobs", aliases: "-j", type: :numeric, banner: "Specify the number of jobs to run in parallel"
+ method_option "local", type: :boolean, banner: "Do not attempt to fetch gems remotely and use the gem cache instead"
+ method_option "prefer-local", type: :boolean, banner: "Only attempt to fetch gems remotely if not present locally, even if newer versions are available remotely"
+ method_option "no-cache", type: :boolean, banner: "Don't update the existing gem cache."
+ method_option "redownload", type: :boolean, aliases: "--force", banner: "Force downloading every gem."
+ method_option "no-prune", type: :boolean, banner: "Don't remove stale gems from the cache."
+ method_option "path", type: :string, banner: "Specify a different path than the system default ($BUNDLE_PATH or $GEM_HOME).#{" Bundler will remember this value for future installs on this machine" unless Bundler.feature_flag.forget_cli_options?}"
+ method_option "quiet", type: :boolean, banner: "Only output warnings and errors."
+ method_option "shebang", type: :string, banner: "Specify a different shebang executable name than the default (usually 'ruby')"
+ method_option "standalone", type: :array, lazy_default: [], banner: "Make a bundle that can work without the Bundler runtime"
+ method_option "system", type: :boolean, banner: "Install to the system location ($BUNDLE_PATH or $GEM_HOME) even if the bundle was previously installed somewhere else for this application"
+ method_option "trust-policy", alias: "P", type: :string, banner: "Gem trust policy (like gem install -P). Must be one of " +
+ Bundler.rubygems.security_policy_keys.join("|")
+ method_option "without", type: :array, banner: "Exclude gems that are part of the specified named group."
+ method_option "with", type: :array, banner: "Include gems that are part of the specified named group."
def install
SharedHelpers.major_deprecation(2, "The `--force` option has been renamed to `--redownload`") if ARGV.include?("--force")
- %w[clean deployment frozen no-prune path shebang system without with].each do |option|
+ %w[clean deployment frozen no-prune path shebang without with].each do |option|
remembered_flag_deprecation(option)
end
+ print_remembered_flag_deprecation("--system", "path.system", "true") if ARGV.include?("--system")
+
remembered_negative_flag_deprecation("no-deployment")
require_relative "cli/install"
- Bundler.settings.temporary(:no_install => false) do
+ Bundler.settings.temporary(no_install: false) do
Install.new(options.dup).run
end
end
@@ -270,44 +256,27 @@ module Bundler
update when you have changed the Gemfile, or if you want to get the newest
possible versions of the gems in the bundle.
D
- method_option "full-index", :type => :boolean, :banner =>
- "Fall back to using the single-file index of all gems"
- method_option "gemfile", :type => :string, :banner =>
- "Use the specified gemfile instead of Gemfile"
- method_option "group", :aliases => "-g", :type => :array, :banner =>
- "Update a specific group"
- method_option "jobs", :aliases => "-j", :type => :numeric, :banner =>
- "Specify the number of jobs to run in parallel"
- method_option "local", :type => :boolean, :banner =>
- "Do not attempt to fetch gems remotely and use the gem cache instead"
- method_option "quiet", :type => :boolean, :banner =>
- "Only output warnings and errors."
- method_option "source", :type => :array, :banner =>
- "Update a specific source (and all gems associated with it)"
- method_option "redownload", :type => :boolean, :aliases => "--force", :banner =>
- "Force downloading every gem."
- method_option "ruby", :type => :boolean, :banner =>
- "Update ruby specified in Gemfile.lock"
- method_option "bundler", :type => :string, :lazy_default => "> 0.a", :banner =>
- "Update the locked version of bundler"
- method_option "patch", :type => :boolean, :banner =>
- "Prefer updating only to next patch version"
- method_option "minor", :type => :boolean, :banner =>
- "Prefer updating only to next minor version"
- method_option "major", :type => :boolean, :banner =>
- "Prefer updating to next major version (default)"
- method_option "pre", :type => :boolean, :banner =>
- "Always choose the highest allowed version when updating gems, regardless of prerelease status"
- method_option "strict", :type => :boolean, :banner =>
- "Do not allow any gem to be updated past latest --patch | --minor | --major"
- method_option "conservative", :type => :boolean, :banner =>
- "Use bundle install conservative update behavior and do not allow shared dependencies to be updated."
- method_option "all", :type => :boolean, :banner =>
- "Update everything."
+ method_option "full-index", type: :boolean, banner: "Fall back to using the single-file index of all gems"
+ method_option "gemfile", type: :string, banner: "Use the specified gemfile instead of Gemfile"
+ method_option "group", aliases: "-g", type: :array, banner: "Update a specific group"
+ method_option "jobs", aliases: "-j", type: :numeric, banner: "Specify the number of jobs to run in parallel"
+ method_option "local", type: :boolean, banner: "Do not attempt to fetch gems remotely and use the gem cache instead"
+ method_option "quiet", type: :boolean, banner: "Only output warnings and errors."
+ method_option "source", type: :array, banner: "Update a specific source (and all gems associated with it)"
+ method_option "redownload", type: :boolean, aliases: "--force", banner: "Force downloading every gem."
+ method_option "ruby", type: :boolean, banner: "Update ruby specified in Gemfile.lock"
+ method_option "bundler", type: :string, lazy_default: "> 0.a", banner: "Update the locked version of bundler"
+ method_option "patch", type: :boolean, banner: "Prefer updating only to next patch version"
+ method_option "minor", type: :boolean, banner: "Prefer updating only to next minor version"
+ method_option "major", type: :boolean, banner: "Prefer updating to next major version (default)"
+ method_option "pre", type: :boolean, banner: "Always choose the highest allowed version when updating gems, regardless of prerelease status"
+ method_option "strict", type: :boolean, banner: "Do not allow any gem to be updated past latest --patch | --minor | --major"
+ method_option "conservative", type: :boolean, banner: "Use bundle install conservative update behavior and do not allow shared dependencies to be updated."
+ method_option "all", type: :boolean, banner: "Update everything."
def update(*gems)
SharedHelpers.major_deprecation(2, "The `--force` option has been renamed to `--redownload`") if ARGV.include?("--force")
require_relative "cli/update"
- Bundler.settings.temporary(:no_install => false) do
+ Bundler.settings.temporary(no_install: false) do
Update.new(options, gems).run
end
end
@@ -317,21 +286,25 @@ module Bundler
Show lists the names and versions of all gems that are required by your Gemfile.
Calling show with [GEM] will list the exact location of that gem on your machine.
D
- method_option "paths", :type => :boolean,
- :banner => "List the paths of all gems that are required by your Gemfile."
- method_option "outdated", :type => :boolean,
- :banner => "Show verbose output including whether gems are outdated."
+ method_option "paths", type: :boolean,
+ banner: "List the paths of all gems that are required by your Gemfile."
+ method_option "outdated", type: :boolean,
+ banner: "Show verbose output including whether gems are outdated."
def show(gem_name = nil)
- SharedHelpers.major_deprecation(2, "the `--outdated` flag to `bundle show` was undocumented and will be removed without replacement") if ARGV.include?("--outdated")
+ if ARGV.include?("--outdated")
+ message = "the `--outdated` flag to `bundle show` was undocumented and will be removed without replacement"
+ removed_message = "the `--outdated` flag to `bundle show` was undocumented and has been removed without replacement"
+ SharedHelpers.major_deprecation(2, message, removed_message: removed_message)
+ end
require_relative "cli/show"
Show.new(options, gem_name).run
end
desc "list", "List all gems in the bundle"
- method_option "name-only", :type => :boolean, :banner => "print only the gem names"
- method_option "only-group", :type => :array, :default => [], :banner => "print gems from a given set of groups"
- method_option "without-group", :type => :array, :default => [], :banner => "print all gems except from a given set of groups"
- method_option "paths", :type => :boolean, :banner => "print the path to each gem in the bundle"
+ method_option "name-only", type: :boolean, banner: "print only the gem names"
+ method_option "only-group", type: :array, default: [], banner: "print gems from a given set of groups"
+ method_option "without-group", type: :array, default: [], banner: "print all gems except from a given set of groups"
+ method_option "paths", type: :boolean, banner: "print the path to each gem in the bundle"
def list
require_relative "cli/list"
List.new(options).run
@@ -340,8 +313,8 @@ module Bundler
map aliases_for("list")
desc "info GEM [OPTIONS]", "Show information for the given gem"
- method_option "path", :type => :boolean, :banner => "Print full path to gem"
- method_option "version", :type => :boolean, :banner => "Print gem version"
+ method_option "path", type: :boolean, banner: "Print full path to gem"
+ method_option "version", type: :boolean, banner: "Print gem version"
def info(gem_name)
require_relative "cli/info"
Info.new(options, gem_name).run
@@ -353,18 +326,12 @@ module Bundler
or the --binstubs directory if one has been set. Calling binstubs with [GEM [GEM]]
will create binstubs for all given gems.
D
- method_option "force", :type => :boolean, :default => false, :banner =>
- "Overwrite existing binstubs if they exist"
- method_option "path", :type => :string, :lazy_default => "bin", :banner =>
- "Binstub destination directory (default bin)"
- method_option "shebang", :type => :string, :banner =>
- "Specify a different shebang executable name than the default (usually 'ruby')"
- method_option "standalone", :type => :boolean, :banner =>
- "Make binstubs that can work without the Bundler runtime"
- method_option "all", :type => :boolean, :banner =>
- "Install binstubs for all gems"
- method_option "all-platforms", :type => :boolean, :default => false, :banner =>
- "Install binstubs for all platforms"
+ method_option "force", type: :boolean, default: false, banner: "Overwrite existing binstubs if they exist"
+ method_option "path", type: :string, lazy_default: "bin", banner: "Binstub destination directory (default bin)"
+ method_option "shebang", type: :string, banner: "Specify a different shebang executable name than the default (usually 'ruby')"
+ method_option "standalone", type: :boolean, banner: "Make binstubs that can work without the Bundler runtime"
+ method_option "all", type: :boolean, banner: "Install binstubs for all gems"
+ method_option "all-platforms", type: :boolean, default: false, banner: "Install binstubs for all platforms"
def binstubs(*gems)
require_relative "cli/binstubs"
Binstubs.new(options, gems).run
@@ -374,19 +341,19 @@ module Bundler
long_desc <<-D
Adds the specified gem to Gemfile (if valid) and run 'bundle install' in one step.
D
- method_option "version", :aliases => "-v", :type => :string
- method_option "group", :aliases => "-g", :type => :string
- method_option "source", :aliases => "-s", :type => :string
- method_option "require", :aliases => "-r", :type => :string, :banner => "Adds require path to gem. Provide false, or a path as a string."
- method_option "path", :type => :string
- method_option "git", :type => :string
- method_option "github", :type => :string
- method_option "branch", :type => :string
- method_option "ref", :type => :string
- method_option "skip-install", :type => :boolean, :banner =>
- "Adds gem to the Gemfile but does not install it"
- method_option "optimistic", :type => :boolean, :banner => "Adds optimistic declaration of version to gem"
- method_option "strict", :type => :boolean, :banner => "Adds strict declaration of version to gem"
+ method_option "version", aliases: "-v", type: :string
+ method_option "group", aliases: "-g", type: :string
+ method_option "source", aliases: "-s", type: :string
+ method_option "require", aliases: "-r", type: :string, banner: "Adds require path to gem. Provide false, or a path as a string."
+ method_option "path", type: :string
+ method_option "git", type: :string
+ method_option "github", type: :string
+ method_option "branch", type: :string
+ method_option "ref", type: :string
+ method_option "glob", type: :string, banner: "The location of a dependency's .gemspec, expanded within Ruby (single quotes recommended)"
+ method_option "skip-install", type: :boolean, banner: "Adds gem to the Gemfile but does not install it"
+ method_option "optimistic", type: :boolean, banner: "Adds optimistic declaration of version to gem"
+ method_option "strict", type: :boolean, banner: "Adds strict declaration of version to gem"
def add(*gems)
require_relative "cli/add"
Add.new(options.dup, gems).run
@@ -402,54 +369,45 @@ module Bundler
For more information on patch level options (--major, --minor, --patch,
--strict) see documentation on the same options on the update command.
D
- method_option "group", :type => :string, :banner => "List gems from a specific group"
- method_option "groups", :type => :boolean, :banner => "List gems organized by groups"
- method_option "local", :type => :boolean, :banner =>
- "Do not attempt to fetch gems remotely and use the gem cache instead"
- method_option "pre", :type => :boolean, :banner => "Check for newer pre-release gems"
- method_option "source", :type => :array, :banner => "Check against a specific source"
- method_option "filter-strict", :type => :boolean, :aliases => "--strict", :banner =>
- "Only list newer versions allowed by your Gemfile requirements"
- method_option "update-strict", :type => :boolean, :banner =>
- "Strict conservative resolution, do not allow any gem to be updated past latest --patch | --minor | --major"
- method_option "minor", :type => :boolean, :banner => "Prefer updating only to next minor version"
- method_option "major", :type => :boolean, :banner => "Prefer updating to next major version (default)"
- method_option "patch", :type => :boolean, :banner => "Prefer updating only to next patch version"
- method_option "filter-major", :type => :boolean, :banner => "Only list major newer versions"
- method_option "filter-minor", :type => :boolean, :banner => "Only list minor newer versions"
- method_option "filter-patch", :type => :boolean, :banner => "Only list patch newer versions"
- method_option "parseable", :aliases => "--porcelain", :type => :boolean, :banner =>
- "Use minimal formatting for more parseable output"
- method_option "only-explicit", :type => :boolean, :banner =>
- "Only list gems specified in your Gemfile, not their dependencies"
+ method_option "group", type: :string, banner: "List gems from a specific group"
+ method_option "groups", type: :boolean, banner: "List gems organized by groups"
+ method_option "local", type: :boolean, banner: "Do not attempt to fetch gems remotely and use the gem cache instead"
+ method_option "pre", type: :boolean, banner: "Check for newer pre-release gems"
+ method_option "source", type: :array, banner: "Check against a specific source"
+ method_option "filter-strict", type: :boolean, aliases: "--strict", banner: "Only list newer versions allowed by your Gemfile requirements"
+ method_option "update-strict", type: :boolean, banner: "Strict conservative resolution, do not allow any gem to be updated past latest --patch | --minor | --major"
+ method_option "minor", type: :boolean, banner: "Prefer updating only to next minor version"
+ method_option "major", type: :boolean, banner: "Prefer updating to next major version (default)"
+ method_option "patch", type: :boolean, banner: "Prefer updating only to next patch version"
+ method_option "filter-major", type: :boolean, banner: "Only list major newer versions"
+ method_option "filter-minor", type: :boolean, banner: "Only list minor newer versions"
+ method_option "filter-patch", type: :boolean, banner: "Only list patch newer versions"
+ method_option "parseable", aliases: "--porcelain", type: :boolean, banner: "Use minimal formatting for more parseable output"
+ method_option "only-explicit", type: :boolean, banner: "Only list gems specified in your Gemfile, not their dependencies"
def outdated(*gems)
require_relative "cli/outdated"
Outdated.new(options, gems).run
end
desc "fund [OPTIONS]", "Lists information about gems seeking funding assistance"
- method_option "group", :aliases => "-g", :type => :array, :banner =>
- "Fetch funding information for a specific group"
+ method_option "group", aliases: "-g", type: :array, banner: "Fetch funding information for a specific group"
def fund
require_relative "cli/fund"
Fund.new(options).run
end
desc "cache [OPTIONS]", "Locks and then caches all of the gems into vendor/cache"
- method_option "all", :type => :boolean,
- :default => Bundler.feature_flag.cache_all?,
- :banner => "Include all sources (including path and git)."
- method_option "all-platforms", :type => :boolean, :banner => "Include gems for all platforms present in the lockfile, not only the current one"
- method_option "cache-path", :type => :string, :banner =>
- "Specify a different cache path than the default (vendor/cache)."
- method_option "gemfile", :type => :string, :banner => "Use the specified gemfile instead of Gemfile"
- method_option "no-install", :type => :boolean, :banner => "Don't install the gems, only update the cache."
- method_option "no-prune", :type => :boolean, :banner => "Don't remove stale gems from the cache."
- method_option "path", :type => :string, :banner =>
- "Specify a different path than the system default ($BUNDLE_PATH or $GEM_HOME).#{" Bundler will remember this value for future installs on this machine" unless Bundler.feature_flag.forget_cli_options?}"
- method_option "quiet", :type => :boolean, :banner => "Only output warnings and errors."
- method_option "frozen", :type => :boolean, :banner =>
- "Do not allow the Gemfile.lock to be updated after this bundle cache operation's install"
+ method_option "all", type: :boolean,
+ default: Bundler.feature_flag.cache_all?,
+ banner: "Include all sources (including path and git)."
+ method_option "all-platforms", type: :boolean, banner: "Include gems for all platforms present in the lockfile, not only the current one"
+ method_option "cache-path", type: :string, banner: "Specify a different cache path than the default (vendor/cache)."
+ method_option "gemfile", type: :string, banner: "Use the specified gemfile instead of Gemfile"
+ method_option "no-install", type: :boolean, banner: "Don't install the gems, only update the cache."
+ method_option "no-prune", type: :boolean, banner: "Don't remove stale gems from the cache."
+ method_option "path", type: :string, banner: "Specify a different path than the system default ($BUNDLE_PATH or $GEM_HOME).#{" Bundler will remember this value for future installs on this machine" unless Bundler.feature_flag.forget_cli_options?}"
+ method_option "quiet", type: :boolean, banner: "Only output warnings and errors."
+ method_option "frozen", type: :boolean, banner: "Do not allow the Gemfile.lock to be updated after this bundle cache operation's install"
long_desc <<-D
The cache command will copy the .gem files for every gem in the bundle into the
directory ./vendor/cache. If you then check that directory into your source
@@ -457,17 +415,20 @@ module Bundler
bundle without having to download any additional gems.
D
def cache
- SharedHelpers.major_deprecation 2,
- "The `--all` flag is deprecated because it relies on being " \
- "remembered across bundler invocations, which bundler will no longer " \
- "do in future versions. Instead please use `bundle config set cache_all true`, " \
- "and stop using this flag" if ARGV.include?("--all")
-
- SharedHelpers.major_deprecation 2,
- "The `--path` flag is deprecated because its semantics are unclear. " \
- "Use `bundle config cache_path` to configure the path of your cache of gems, " \
- "and `bundle config path` to configure the path where your gems are installed, " \
- "and stop using this flag" if ARGV.include?("--path")
+ print_remembered_flag_deprecation("--all", "cache_all", "true") if ARGV.include?("--all")
+
+ if ARGV.include?("--path")
+ message =
+ "The `--path` flag is deprecated because its semantics are unclear. " \
+ "Use `bundle config cache_path` to configure the path of your cache of gems, " \
+ "and `bundle config path` to configure the path where your gems are installed, " \
+ "and stop using this flag"
+ removed_message =
+ "The `--path` flag has been removed because its semantics were unclear. " \
+ "Use `bundle config cache_path` to configure the path of your cache of gems, " \
+ "and `bundle config path` to configure the path where your gems are installed."
+ SharedHelpers.major_deprecation 2, message, removed_message: removed_message
+ end
require_relative "cli/cache"
Cache.new(options).run
@@ -476,8 +437,8 @@ module Bundler
map aliases_for("cache")
desc "exec [OPTIONS]", "Run the command in context of the bundle"
- method_option :keep_file_descriptors, :type => :boolean, :default => true
- method_option :gemfile, :type => :string, :required => false
+ method_option :keep_file_descriptors, type: :boolean, default: true
+ method_option :gemfile, type: :string, required: false
long_desc <<-D
Exec runs a command, providing it access to the gems in the bundle. While using
bundle exec you can require and call the bundled gems as if they were installed
@@ -485,7 +446,9 @@ module Bundler
D
def exec(*args)
if ARGV.include?("--no-keep-file-descriptors")
- SharedHelpers.major_deprecation(2, "The `--no-keep-file-descriptors` has been deprecated. `bundle exec` no longer mess with your file descriptors. Close them in the exec'd script if you need to")
+ message = "The `--no-keep-file-descriptors` has been deprecated. `bundle exec` no longer mess with your file descriptors. Close them in the exec'd script if you need to"
+ removed_message = "The `--no-keep-file-descriptors` has been removed. `bundle exec` no longer mess with your file descriptors. Close them in the exec'd script if you need to"
+ SharedHelpers.major_deprecation(2, message, removed_message: removed_message)
end
require_relative "cli/exec"
@@ -510,7 +473,7 @@ module Bundler
subcommand "config", Config
desc "open GEM", "Opens the source directory of the given bundled gem"
- method_option "path", :type => :string, :lazy_default => "", :banner => "Open relative path of the gem source."
+ method_option "path", type: :string, lazy_default: "", banner: "Open relative path of the gem source."
def open(name)
require_relative "cli/open"
Open.new(options, name).run
@@ -555,17 +518,17 @@ module Bundler
end
unless Bundler.feature_flag.bundler_3_mode?
- desc "viz [OPTIONS]", "Generates a visual dependency graph", :hide => true
+ desc "viz [OPTIONS]", "Generates a visual dependency graph", hide: true
long_desc <<-D
Viz generates a PNG file of the current Gemfile as a dependency graph.
Viz requires the ruby-graphviz gem (and its dependencies).
The associated gems must also be installed via 'bundle install'.
D
- method_option :file, :type => :string, :default => "gem_graph", :aliases => "-f", :desc => "The name to use for the generated file. see format option"
- method_option :format, :type => :string, :default => "png", :aliases => "-F", :desc => "This is output format option. Supported format is png, jpg, svg, dot ..."
- method_option :requirements, :type => :boolean, :default => false, :aliases => "-R", :desc => "Set to show the version of each required dependency."
- method_option :version, :type => :boolean, :default => false, :aliases => "-v", :desc => "Set to show each gem version."
- method_option :without, :type => :array, :default => [], :aliases => "-W", :banner => "GROUP[ GROUP...]", :desc => "Exclude gems that are part of the specified named group."
+ method_option :file, type: :string, default: "gem_graph", aliases: "-f", desc: "The name to use for the generated file. see format option"
+ method_option :format, type: :string, default: "png", aliases: "-F", desc: "This is output format option. Supported format is png, jpg, svg, dot ..."
+ method_option :requirements, type: :boolean, default: false, aliases: "-R", desc: "Set to show the version of each required dependency."
+ method_option :version, type: :boolean, default: false, aliases: "-v", desc: "Set to show each gem version."
+ method_option :without, type: :array, default: [], aliases: "-W", banner: "GROUP[ GROUP...]", desc: "Exclude gems that are part of the specified named group."
def viz
SharedHelpers.major_deprecation 2, "The `viz` command has been renamed to `graph` and moved to a plugin. See https://github.com/rubygems/bundler-graph"
require_relative "cli/viz"
@@ -576,23 +539,23 @@ module Bundler
old_gem = instance_method(:gem)
desc "gem NAME [OPTIONS]", "Creates a skeleton for creating a rubygem"
- method_option :exe, :type => :boolean, :default => false, :aliases => ["--bin", "-b"], :desc => "Generate a binary executable for your library."
- method_option :coc, :type => :boolean, :desc => "Generate a code of conduct file. Set a default with `bundle config set --global gem.coc true`."
- method_option :edit, :type => :string, :aliases => "-e", :required => false, :banner => "EDITOR",
- :lazy_default => [ENV["BUNDLER_EDITOR"], ENV["VISUAL"], ENV["EDITOR"]].find {|e| !e.nil? && !e.empty? },
- :desc => "Open generated gemspec in the specified editor (defaults to $EDITOR or $BUNDLER_EDITOR)"
- method_option :ext, :type => :string, :desc => "Generate the boilerplate for C extension code.", :enum => EXTENSIONS
- method_option :git, :type => :boolean, :default => true, :desc => "Initialize a git repo inside your library."
- method_option :mit, :type => :boolean, :desc => "Generate an MIT license file. Set a default with `bundle config set --global gem.mit true`."
- method_option :rubocop, :type => :boolean, :desc => "Add rubocop to the generated Rakefile and gemspec. Set a default with `bundle config set --global gem.rubocop true`."
- method_option :changelog, :type => :boolean, :desc => "Generate changelog file. Set a default with `bundle config set --global gem.changelog true`."
- method_option :test, :type => :string, :lazy_default => Bundler.settings["gem.test"] || "", :aliases => "-t", :banner => "Use the specified test framework for your library",
- :desc => "Generate a test directory for your library, either rspec, minitest or test-unit. Set a default with `bundle config set --global gem.test (rspec|minitest|test-unit)`."
- method_option :ci, :type => :string, :lazy_default => Bundler.settings["gem.ci"] || "",
- :desc => "Generate CI configuration, either GitHub Actions, GitLab CI or CircleCI. Set a default with `bundle config set --global gem.ci (github|gitlab|circle)`"
- method_option :linter, :type => :string, :lazy_default => Bundler.settings["gem.linter"] || "",
- :desc => "Add a linter and code formatter, either RuboCop or Standard. Set a default with `bundle config set --global gem.linter (rubocop|standard)`"
- method_option :github_username, :type => :string, :default => Bundler.settings["gem.github_username"], :banner => "Set your username on GitHub", :desc => "Fill in GitHub username on README so that you don't have to do it manually. Set a default with `bundle config set --global gem.github_username <your_username>`."
+ method_option :exe, type: :boolean, default: false, aliases: ["--bin", "-b"], desc: "Generate a binary executable for your library."
+ method_option :coc, type: :boolean, desc: "Generate a code of conduct file. Set a default with `bundle config set --global gem.coc true`."
+ method_option :edit, type: :string, aliases: "-e", required: false, banner: "EDITOR",
+ lazy_default: [ENV["BUNDLER_EDITOR"], ENV["VISUAL"], ENV["EDITOR"]].find {|e| !e.nil? && !e.empty? },
+ desc: "Open generated gemspec in the specified editor (defaults to $EDITOR or $BUNDLER_EDITOR)"
+ method_option :ext, type: :string, desc: "Generate the boilerplate for C extension code.", enum: EXTENSIONS
+ method_option :git, type: :boolean, default: true, desc: "Initialize a git repo inside your library."
+ method_option :mit, type: :boolean, desc: "Generate an MIT license file. Set a default with `bundle config set --global gem.mit true`."
+ method_option :rubocop, type: :boolean, desc: "Add rubocop to the generated Rakefile and gemspec. Set a default with `bundle config set --global gem.rubocop true`."
+ method_option :changelog, type: :boolean, desc: "Generate changelog file. Set a default with `bundle config set --global gem.changelog true`."
+ method_option :test, type: :string, lazy_default: Bundler.settings["gem.test"] || "", aliases: "-t", banner: "Use the specified test framework for your library",
+ desc: "Generate a test directory for your library, either rspec, minitest or test-unit. Set a default with `bundle config set --global gem.test (rspec|minitest|test-unit)`."
+ method_option :ci, type: :string, lazy_default: Bundler.settings["gem.ci"] || "",
+ desc: "Generate CI configuration, either GitHub Actions, GitLab CI or CircleCI. Set a default with `bundle config set --global gem.ci (github|gitlab|circle)`"
+ method_option :linter, type: :string, lazy_default: Bundler.settings["gem.linter"] || "",
+ desc: "Add a linter and code formatter, either RuboCop or Standard. Set a default with `bundle config set --global gem.linter (rubocop|standard)`"
+ method_option :github_username, type: :string, default: Bundler.settings["gem.github_username"], banner: "Set your username on GitHub", desc: "Fill in GitHub username on README so that you don't have to do it manually. Set a default with `bundle config set --global gem.github_username <your_username>`."
def gem(name)
end
@@ -623,29 +586,24 @@ module Bundler
File.expand_path("templates", __dir__)
end
- desc "clean [OPTIONS]", "Cleans up unused gems in your bundler directory", :hide => true
- method_option "dry-run", :type => :boolean, :default => false, :banner =>
- "Only print out changes, do not clean gems"
- method_option "force", :type => :boolean, :default => false, :banner =>
- "Forces cleaning up unused gems even if Bundler is configured to use globally installed gems. As a consequence, removes all system gems except for the ones in the current application."
+ desc "clean [OPTIONS]", "Cleans up unused gems in your bundler directory", hide: true
+ method_option "dry-run", type: :boolean, default: false, banner: "Only print out changes, do not clean gems"
+ method_option "force", type: :boolean, default: false, banner: "Forces cleaning up unused gems even if Bundler is configured to use globally installed gems. As a consequence, removes all system gems except for the ones in the current application."
def clean
require_relative "cli/clean"
Clean.new(options.dup).run
end
desc "platform [OPTIONS]", "Displays platform compatibility information"
- method_option "ruby", :type => :boolean, :default => false, :banner =>
- "only display ruby related platform information"
+ method_option "ruby", type: :boolean, default: false, banner: "only display ruby related platform information"
def platform
require_relative "cli/platform"
Platform.new(options).run
end
- desc "inject GEM VERSION", "Add the named gem, with version requirements, to the resolved Gemfile", :hide => true
- method_option "source", :type => :string, :banner =>
- "Install gem from the given source"
- method_option "group", :type => :string, :banner =>
- "Install gem into a bundler group"
+ desc "inject GEM VERSION", "Add the named gem, with version requirements, to the resolved Gemfile", hide: true
+ method_option "source", type: :string, banner: "Install gem from the given source"
+ method_option "group", type: :string, banner: "Install gem into a bundler group"
def inject(name, version)
SharedHelpers.major_deprecation 2, "The `inject` command has been replaced by the `add` command"
require_relative "cli/inject"
@@ -653,36 +611,21 @@ module Bundler
end
desc "lock", "Creates a lockfile without installing"
- method_option "update", :type => :array, :lazy_default => true, :banner =>
- "ignore the existing lockfile, update all gems by default, or update list of given gems"
- method_option "local", :type => :boolean, :default => false, :banner =>
- "do not attempt to fetch remote gemspecs and use the local gem cache only"
- method_option "print", :type => :boolean, :default => false, :banner =>
- "print the lockfile to STDOUT instead of writing to the file system"
- method_option "gemfile", :type => :string, :banner =>
- "Use the specified gemfile instead of Gemfile"
- method_option "lockfile", :type => :string, :default => nil, :banner =>
- "the path the lockfile should be written to"
- method_option "full-index", :type => :boolean, :default => false, :banner =>
- "Fall back to using the single-file index of all gems"
- method_option "add-platform", :type => :array, :default => [], :banner =>
- "Add a new platform to the lockfile"
- method_option "remove-platform", :type => :array, :default => [], :banner =>
- "Remove a platform from the lockfile"
- method_option "patch", :type => :boolean, :banner =>
- "If updating, prefer updating only to next patch version"
- method_option "minor", :type => :boolean, :banner =>
- "If updating, prefer updating only to next minor version"
- method_option "major", :type => :boolean, :banner =>
- "If updating, prefer updating to next major version (default)"
- method_option "pre", :type => :boolean, :banner =>
- "If updating, always choose the highest allowed version, regardless of prerelease status"
- method_option "strict", :type => :boolean, :banner =>
- "If updating, do not allow any gem to be updated past latest --patch | --minor | --major"
- method_option "conservative", :type => :boolean, :banner =>
- "If updating, use bundle install conservative update behavior and do not allow shared dependencies to be updated"
- method_option "bundler", :type => :string, :lazy_default => "> 0.a", :banner =>
- "Update the locked version of bundler"
+ method_option "update", type: :array, lazy_default: true, banner: "ignore the existing lockfile, update all gems by default, or update list of given gems"
+ method_option "local", type: :boolean, default: false, banner: "do not attempt to fetch remote gemspecs and use the local gem cache only"
+ method_option "print", type: :boolean, default: false, banner: "print the lockfile to STDOUT instead of writing to the file system"
+ method_option "gemfile", type: :string, banner: "Use the specified gemfile instead of Gemfile"
+ method_option "lockfile", type: :string, default: nil, banner: "the path the lockfile should be written to"
+ method_option "full-index", type: :boolean, default: false, banner: "Fall back to using the single-file index of all gems"
+ method_option "add-platform", type: :array, default: [], banner: "Add a new platform to the lockfile"
+ method_option "remove-platform", type: :array, default: [], banner: "Remove a platform from the lockfile"
+ method_option "patch", type: :boolean, banner: "If updating, prefer updating only to next patch version"
+ method_option "minor", type: :boolean, banner: "If updating, prefer updating only to next minor version"
+ method_option "major", type: :boolean, banner: "If updating, prefer updating to next major version (default)"
+ method_option "pre", type: :boolean, banner: "If updating, always choose the highest allowed version, regardless of prerelease status"
+ method_option "strict", type: :boolean, banner: "If updating, do not allow any gem to be updated past latest --patch | --minor | --major"
+ method_option "conservative", type: :boolean, banner: "If updating, use bundle install conservative update behavior and do not allow shared dependencies to be updated"
+ method_option "bundler", type: :string, lazy_default: "> 0.a", banner: "Update the locked version of bundler"
def lock
require_relative "cli/lock"
Lock.new(options).run
@@ -699,10 +642,8 @@ module Bundler
missing dependencies are detected, Bundler prints them and exits status 1.
Otherwise, Bundler prints a success message and exits with a status of 0.
D
- method_option "gemfile", :type => :string, :banner =>
- "Use the specified gemfile instead of Gemfile"
- method_option "quiet", :type => :boolean, :banner =>
- "Only output warnings and errors."
+ method_option "gemfile", type: :string, banner: "Use the specified gemfile instead of Gemfile"
+ method_option "quiet", type: :boolean, banner: "Only output warnings and errors."
def doctor
require_relative "cli/doctor"
Doctor.new(options).run
@@ -722,7 +663,9 @@ module Bundler
D
def pristine(*gems)
require_relative "cli/pristine"
- Pristine.new(gems).run
+ Bundler.settings.temporary(no_install: false) do
+ Pristine.new(gems).run
+ end
end
if Bundler.feature_flag.plugins?
@@ -743,7 +686,6 @@ module Bundler
exec_used = args.index {|a| exec_commands.include? a }
command = args.find {|a| bundler_commands.include? a }
- command = all_aliases[command] if all_aliases[command]
if exec_used && help_used
if exec_used + help_used == 1
@@ -764,7 +706,9 @@ module Bundler
# when deprecated version of `--ext` is called
# print out deprecation warning and pretend `--ext=c` was provided
if deprecated_ext_value?(arguments)
- SharedHelpers.major_deprecation 2, "Extensions can now be generated using C or Rust, so `--ext` with no arguments has been deprecated. Please select a language, e.g. `--ext=rust` to generate a Rust extension. This gem will now be generated as if `--ext=c` was used."
+ message = "Extensions can now be generated using C or Rust, so `--ext` with no arguments has been deprecated. Please select a language, e.g. `--ext=rust` to generate a Rust extension. This gem will now be generated as if `--ext=c` was used."
+ removed_message = "Extensions can now be generated using C or Rust, so `--ext` with no arguments has been removed. Please select a language, e.g. `--ext=rust` to generate a Rust extension."
+ SharedHelpers.major_deprecation 2, message, removed_message: removed_message
arguments[arguments.index("--ext")] = "--ext=c"
end
end
@@ -794,26 +738,6 @@ module Bundler
private
- # Automatically invoke `bundle install` and resume if
- # Bundler.settings[:auto_install] exists. This is set through config cmd
- # `bundle config set --global auto_install 1`.
- #
- # Note that this method `nil`s out the global Definition object, so it
- # should be called first, before you instantiate anything like an
- # `Installer` that'll keep a reference to the old one instead.
- def auto_install
- return unless Bundler.settings[:auto_install]
-
- begin
- Bundler.definition.specs
- rescue GemNotFound
- Bundler.ui.info "Automatically installing missing gems."
- Bundler.reset!
- invoke :install, []
- Bundler.reset!
- end
- end
-
def current_command
_, _, config = @_initializer
config[:current_command]
@@ -843,13 +767,10 @@ module Bundler
return unless SharedHelpers.md5_available?
- latest = Fetcher::CompactIndex.
- new(nil, Source::Rubygems::Remote.new(Bundler::URI("https://rubygems.org")), nil).
- send(:compact_index_client).
- instance_variable_get(:@cache).
- dependencies("bundler").
- map {|d| Gem::Version.new(d.first) }.
- max
+ require_relative "vendored_uri"
+ remote = Source::Rubygems::Remote.new(Gem::URI("https://rubygems.org"))
+ cache_path = Bundler.user_cache.join("compact_index", remote.cache_slug)
+ latest = Bundler::CompactIndexClient.new(cache_path).latest_version("bundler")
return unless latest
current = Gem::Version.new(VERSION)
@@ -883,12 +804,23 @@ module Bundler
value = options[name]
value = value.join(" ").to_s if option.type == :array
+ value = "'#{value}'" unless option.type == :boolean
- Bundler::SharedHelpers.major_deprecation 2,
+ print_remembered_flag_deprecation(flag_name, name.tr("-", "_"), value)
+ end
+
+ def print_remembered_flag_deprecation(flag_name, option_name, option_value)
+ message =
"The `#{flag_name}` flag is deprecated because it relies on being " \
"remembered across bundler invocations, which bundler will no longer " \
- "do in future versions. Instead please use `bundle config set --local #{name.tr("-", "_")} " \
- "'#{value}'`, and stop using this flag"
+ "do in future versions. Instead please use `bundle config set #{option_name} " \
+ "#{option_value}`, and stop using this flag"
+ removed_message =
+ "The `#{flag_name}` flag has been removed because it relied on being " \
+ "remembered across bundler invocations, which bundler will no longer " \
+ "do. Instead please use `bundle config set #{option_name} " \
+ "#{option_value}`, and stop using this flag"
+ Bundler::SharedHelpers.major_deprecation 2, message, removed_message: removed_message
end
end
end
diff --git a/lib/bundler/cli/add.rb b/lib/bundler/cli/add.rb
index 08fa6547fb..002d9e1d33 100644
--- a/lib/bundler/cli/add.rb
+++ b/lib/bundler/cli/add.rb
@@ -28,9 +28,9 @@ module Bundler
dependencies = gems.map {|g| Bundler::Dependency.new(g, version, options) }
Injector.inject(dependencies,
- :conservative_versioning => options[:version].nil?, # Perform conservative versioning only when version is not specified
- :optimistic => options[:optimistic],
- :strict => options[:strict])
+ conservative_versioning: options[:version].nil?, # Perform conservative versioning only when version is not specified
+ optimistic: options[:optimistic],
+ strict: options[:strict])
end
def validate_options!
diff --git a/lib/bundler/cli/binstubs.rb b/lib/bundler/cli/binstubs.rb
index fc2fad47a5..8ce138df96 100644
--- a/lib/bundler/cli/binstubs.rb
+++ b/lib/bundler/cli/binstubs.rb
@@ -17,9 +17,9 @@ module Bundler
installer = Installer.new(Bundler.root, Bundler.definition)
installer_opts = {
- :force => options[:force],
- :binstubs_cmd => true,
- :all_platforms => options["all-platforms"],
+ force: options[:force],
+ binstubs_cmd: true,
+ all_platforms: options["all-platforms"],
}
if options[:all]
@@ -45,7 +45,7 @@ module Bundler
next
end
- Bundler.settings.temporary(:path => (Bundler.settings[:path] || Bundler.root)) do
+ Bundler.settings.temporary(path: Bundler.settings[:path] || Bundler.root) do
installer.generate_standalone_bundler_executable_stubs(spec, installer_opts)
end
else
diff --git a/lib/bundler/cli/cache.rb b/lib/bundler/cli/cache.rb
index c8698ed7e3..2e63a16ec3 100644
--- a/lib/bundler/cli/cache.rb
+++ b/lib/bundler/cli/cache.rb
@@ -19,7 +19,7 @@ module Bundler
# TODO: move cache contents here now that all bundles are locked
custom_path = Bundler.settings[:path] if options[:path]
- Bundler.settings.temporary(:cache_all_platforms => options["all-platforms"]) do
+ Bundler.settings.temporary(cache_all_platforms: options["all-platforms"]) do
Bundler.load.cache(custom_path)
end
end
diff --git a/lib/bundler/cli/check.rb b/lib/bundler/cli/check.rb
index 85c49f510a..33d31cdd27 100644
--- a/lib/bundler/cli/check.rb
+++ b/lib/bundler/cli/check.rb
@@ -32,7 +32,7 @@ module Bundler
Bundler.ui.error "This bundle has been frozen, but there is no #{SharedHelpers.relative_lockfile_path} present"
exit 1
else
- Bundler.load.lock(:preserve_unknown_sections => true) unless options[:"dry-run"]
+ Bundler.load.lock(preserve_unknown_sections: true) unless options[:"dry-run"]
Bundler.ui.info "The Gemfile's dependencies are satisfied"
end
end
diff --git a/lib/bundler/cli/common.rb b/lib/bundler/cli/common.rb
index d654406f65..7ef6deb2cf 100644
--- a/lib/bundler/cli/common.rb
+++ b/lib/bundler/cli/common.rb
@@ -54,9 +54,12 @@ module Bundler
Bundler.definition.specs.each do |spec|
return spec if spec.name == name
- specs << spec if regexp && spec.name =~ regexp
+ specs << spec if regexp && spec.name.match?(regexp)
end
+ default_spec = default_gem_spec(name)
+ specs << default_spec if default_spec
+
case specs.count
when 0
dep_in_other_group = Bundler.definition.current_dependencies.find {|dep|dep.name == name }
@@ -75,6 +78,11 @@ module Bundler
raise GemNotFound, gem_not_found_message(name, Bundler.definition.dependencies)
end
+ def self.default_gem_spec(name)
+ gem_spec = Gem::Specification.find_all_by_name(name).last
+ gem_spec if gem_spec&.default_gem?
+ end
+
def self.ask_for_spec_from(specs)
specs.each_with_index do |spec, index|
Bundler.ui.info "#{index.succ} : #{spec.name}", true
diff --git a/lib/bundler/cli/config.rb b/lib/bundler/cli/config.rb
index e1222c75dd..77b502fe60 100644
--- a/lib/bundler/cli/config.rb
+++ b/lib/bundler/cli/config.rb
@@ -2,17 +2,17 @@
module Bundler
class CLI::Config < Thor
- class_option :parseable, :type => :boolean, :banner => "Use minimal formatting for more parseable output"
+ class_option :parseable, type: :boolean, banner: "Use minimal formatting for more parseable output"
def self.scope_options
- method_option :global, :type => :boolean, :banner => "Only change the global config"
- method_option :local, :type => :boolean, :banner => "Only change the local config"
+ method_option :global, type: :boolean, banner: "Only change the global config"
+ method_option :local, type: :boolean, banner: "Only change the local config"
end
private_class_method :scope_options
- desc "base NAME [VALUE]", "The Bundler 1 config interface", :hide => true
+ desc "base NAME [VALUE]", "The Bundler 1 config interface", hide: true
scope_options
- method_option :delete, :type => :boolean, :banner => "delete"
+ method_option :delete, type: :boolean, banner: "delete"
def base(name = nil, *value)
new_args =
if ARGV.size == 1
@@ -25,8 +25,9 @@ module Bundler
["config", "get", ARGV[1]]
end
- SharedHelpers.major_deprecation 3,
- "Using the `config` command without a subcommand [list, get, set, unset] is deprecated and will be removed in the future. Use `bundle #{new_args.join(" ")}` instead."
+ message = "Using the `config` command without a subcommand [list, get, set, unset] is deprecated and will be removed in the future. Use `bundle #{new_args.join(" ")}` instead."
+ removed_message = "Using the `config` command without a subcommand [list, get, set, unset] is has been removed. Use `bundle #{new_args.join(" ")}` instead."
+ SharedHelpers.major_deprecation 3, message, removed_message: removed_message
Base.new(options, name, value, self).run
end
diff --git a/lib/bundler/cli/console.rb b/lib/bundler/cli/console.rb
index 1eb8ea8254..840cf14fd7 100644
--- a/lib/bundler/cli/console.rb
+++ b/lib/bundler/cli/console.rb
@@ -9,8 +9,9 @@ module Bundler
end
def run
- Bundler::SharedHelpers.major_deprecation 2, "bundle console will be replaced " \
- "by `bin/console` generated by `bundle gem <name>`"
+ message = "bundle console will be replaced by `bin/console` generated by `bundle gem <name>`"
+ removed_message = "bundle console has been replaced by `bin/console` generated by `bundle gem <name>`"
+ Bundler::SharedHelpers.major_deprecation 2, message, removed_message: removed_message
group ? Bundler.require(:default, *group.split(" ").map!(&:to_sym)) : Bundler.require
ARGV.clear
diff --git a/lib/bundler/cli/exec.rb b/lib/bundler/cli/exec.rb
index 42b602a055..f81cd5d2c4 100644
--- a/lib/bundler/cli/exec.rb
+++ b/lib/bundler/cli/exec.rb
@@ -12,7 +12,7 @@ module Bundler
@options = options
@cmd = args.shift
@args = args
- @args << { :close_others => !options.keep_file_descriptors? } unless Bundler.current_ruby.jruby?
+ @args << { close_others: !options.keep_file_descriptors? } unless Bundler.current_ruby.jruby?
end
def run
diff --git a/lib/bundler/cli/gem.rb b/lib/bundler/cli/gem.rb
index fb064ed702..b6571d0e86 100644
--- a/lib/bundler/cli/gem.rb
+++ b/lib/bundler/cli/gem.rb
@@ -11,7 +11,7 @@ module Bundler
class CLI::Gem
TEST_FRAMEWORK_VERSIONS = {
"rspec" => "3.0",
- "minitest" => "5.0",
+ "minitest" => "5.16",
"test-unit" => "3.0",
}.freeze
@@ -32,7 +32,6 @@ module Bundler
validate_ext_name if @extension
validate_rust_builder_rubygems_version if @extension == "rust"
- travis_removal_info
end
def run
@@ -59,23 +58,23 @@ module Bundler
end
config = {
- :name => name,
- :underscored_name => underscored_name,
- :namespaced_path => namespaced_path,
- :makefile_path => "#{underscored_name}/#{underscored_name}",
- :constant_name => constant_name,
- :constant_array => constant_array,
- :author => git_author_name.empty? ? "TODO: Write your name" : git_author_name,
- :email => git_user_email.empty? ? "TODO: Write your email address" : git_user_email,
- :test => options[:test],
- :ext => extension,
- :exe => options[:exe],
- :bundler_version => bundler_dependency_version,
- :git => use_git,
- :github_username => github_username.empty? ? "[USERNAME]" : github_username,
- :required_ruby_version => required_ruby_version,
- :rust_builder_required_rubygems_version => rust_builder_required_rubygems_version,
- :minitest_constant_name => minitest_constant_name,
+ name: name,
+ underscored_name: underscored_name,
+ namespaced_path: namespaced_path,
+ makefile_path: "#{underscored_name}/#{underscored_name}",
+ constant_name: constant_name,
+ constant_array: constant_array,
+ author: git_author_name.empty? ? "TODO: Write your name" : git_author_name,
+ email: git_user_email.empty? ? "TODO: Write your email address" : git_user_email,
+ test: options[:test],
+ ext: extension,
+ exe: options[:exe],
+ bundler_version: bundler_dependency_version,
+ git: use_git,
+ github_username: github_username.empty? ? "[USERNAME]" : github_username,
+ required_ruby_version: required_ruby_version,
+ rust_builder_required_rubygems_version: rust_builder_required_rubygems_version,
+ minitest_constant_name: minitest_constant_name,
}
ensure_safe_gem_name(name, constant_array)
@@ -236,7 +235,7 @@ module Bundler
end
if use_git
- IO.popen(%w[git add .], { :chdir => target }, &:read)
+ IO.popen(%w[git add .], { chdir: target }, &:read)
end
# Open gemspec in editor
@@ -380,15 +379,20 @@ module Bundler
def deprecated_rubocop_option
if !options[:rubocop].nil?
if options[:rubocop]
- Bundler::SharedHelpers.major_deprecation 2, "--rubocop is deprecated, use --linter=rubocop"
+ Bundler::SharedHelpers.major_deprecation 2,
+ "--rubocop is deprecated, use --linter=rubocop",
+ removed_message: "--rubocop has been removed, use --linter=rubocop"
"rubocop"
else
- Bundler::SharedHelpers.major_deprecation 2, "--no-rubocop is deprecated, use --linter"
+ Bundler::SharedHelpers.major_deprecation 2,
+ "--no-rubocop is deprecated, use --linter",
+ removed_message: "--no-rubocop has been removed, use --linter"
false
end
elsif !Bundler.settings["gem.rubocop"].nil?
Bundler::SharedHelpers.major_deprecation 2,
- "config gem.rubocop is deprecated; we've updated your config to use gem.linter instead"
+ "config gem.rubocop is deprecated; we've updated your config to use gem.linter instead",
+ removed_message: "config gem.rubocop has been removed; we've updated your config to use gem.linter instead"
Bundler.settings["gem.rubocop"] ? "rubocop" : false
end
end
@@ -432,7 +436,7 @@ module Bundler
end
def required_ruby_version
- "2.6.0"
+ "3.0.0"
end
def rubocop_version
@@ -443,19 +447,6 @@ module Bundler
"1.3"
end
- # TODO: remove at next minor release
- def travis_removal_info
- if options[:ci] == "travis"
- Bundler.ui.error "Support for Travis CI was removed from gem skeleton generator."
- exit 1
- end
-
- if Bundler.settings["gem.ci"] == "travis"
- Bundler.ui.error "Support for Travis CI was removed from gem skeleton generator, but it is present in bundle config. Please configure another provider using `bundle config set gem.ci SERVICE` (where SERVICE is one of github/gitlab/circle) or unset configuration using `bundle config unset gem.ci`."
- exit 1
- end
- end
-
def validate_rust_builder_rubygems_version
if Gem::Version.new(rust_builder_required_rubygems_version) > Gem.rubygems_version
Bundler.ui.error "Your RubyGems version (#{Gem.rubygems_version}) is too old to build Rust extension. Please update your RubyGems using `gem update --system` or any other way and try again."
diff --git a/lib/bundler/cli/info.rb b/lib/bundler/cli/info.rb
index 3facde1947..8f34956aca 100644
--- a/lib/bundler/cli/info.rb
+++ b/lib/bundler/cli/info.rb
@@ -25,19 +25,8 @@ module Bundler
private
- def spec_for_gem(gem_name)
- spec = Bundler.definition.specs.find {|s| s.name == gem_name }
- spec || default_gem_spec(gem_name) || Bundler::CLI::Common.select_spec(gem_name, :regex_match)
- end
-
- def default_gem_spec(gem_name)
- return unless Gem::Specification.respond_to?(:find_all_by_name)
- gem_spec = Gem::Specification.find_all_by_name(gem_name).last
- gem_spec if gem_spec&.default_gem?
- end
-
- def spec_not_found(gem_name)
- raise GemNotFound, Bundler::CLI::Common.gem_not_found_message(gem_name, Bundler.definition.dependencies)
+ def spec_for_gem(name)
+ Bundler::CLI::Common.select_spec(name, :regex_match)
end
def print_gem_version(spec)
diff --git a/lib/bundler/cli/install.rb b/lib/bundler/cli/install.rb
index f7228db623..a233d5d2e5 100644
--- a/lib/bundler/cli/install.rb
+++ b/lib/bundler/cli/install.rb
@@ -14,7 +14,7 @@ module Bundler
Bundler.self_manager.install_locked_bundler_and_restart_with_it_if_needed
- Bundler::SharedHelpers.set_env "RB_USER_INSTALL", "1" if Bundler::FREEBSD
+ Bundler::SharedHelpers.set_env "RB_USER_INSTALL", "1" if Gem.freebsd_platform?
# Disable color in deployment mode
Bundler.ui.shell = Thor::Shell::Basic.new if options[:deployment]
@@ -51,7 +51,8 @@ module Bundler
if options["binstubs"]
Bundler::SharedHelpers.major_deprecation 2,
- "The --binstubs option will be removed in favor of `bundle binstubs --all`"
+ "The --binstubs option will be removed in favor of `bundle binstubs --all`",
+ removed_message: "The --binstubs option have been removed in favor of `bundle binstubs --all`"
end
Plugin.gemfile_install(Bundler.default_gemfile) if Bundler.feature_flag.plugins?
@@ -61,7 +62,7 @@ module Bundler
installer = Installer.install(Bundler.root, definition, options)
- Bundler.settings.temporary(:cache_all_platforms => options[:local] ? false : Bundler.settings[:cache_all_platforms]) do
+ Bundler.settings.temporary(cache_all_platforms: options[:local] ? false : Bundler.settings[:cache_all_platforms]) do
Bundler.load.cache(nil, options[:local]) if Bundler.app_cache.exist? && !options["no-cache"] && !Bundler.frozen_bundle?
end
@@ -95,7 +96,7 @@ module Bundler
def warn_if_root
return if Bundler.settings[:silence_root_warning] || Gem.win_platform? || !Process.uid.zero?
Bundler.ui.warn "Don't run Bundler as root. Installing your bundle as root " \
- "will break this application for all non-root users on this machine.", :wrap => true
+ "will break this application for all non-root users on this machine.", wrap: true
end
def dependencies_count_for(definition)
@@ -148,7 +149,7 @@ module Bundler
Bundler.settings.set_command_option_if_given :path, options[:path]
if options["standalone"] && Bundler.settings[:path].nil? && !options["local"]
- Bundler.settings.temporary(:path_relative_to_cwd => false) do
+ Bundler.settings.temporary(path_relative_to_cwd: false) do
Bundler.settings.set_command_option :path, "bundle"
end
end
diff --git a/lib/bundler/cli/lock.rb b/lib/bundler/cli/lock.rb
index a03a5bae35..dac3d2a09a 100644
--- a/lib/bundler/cli/lock.rb
+++ b/lib/bundler/cli/lock.rb
@@ -26,15 +26,18 @@ module Bundler
if update.is_a?(Array) # unlocking specific gems
Bundler::CLI::Common.ensure_all_gems_in_lockfile!(update)
- update = { :gems => update, :conservative => conservative }
+ update = { gems: update, conservative: conservative }
elsif update && conservative
- update = { :conservative => conservative }
+ update = { conservative: conservative }
elsif update && bundler
- update = { :bundler => bundler }
+ update = { bundler: bundler }
end
- Bundler.settings.temporary(:frozen => false) do
- definition = Bundler.definition(update)
+ file = options[:lockfile]
+ file = file ? Pathname.new(file).expand_path : Bundler.default_lockfile
+
+ Bundler.settings.temporary(frozen: false) do
+ definition = Bundler.definition(update, file)
Bundler::CLI::Common.configure_gem_version_promoter(definition, options) if options[:update]
@@ -60,10 +63,8 @@ module Bundler
if print
puts definition.to_lock
else
- file = options[:lockfile]
- file = file ? File.expand_path(file) : Bundler.default_lockfile
puts "Writing lockfile to #{file}"
- definition.lock(file)
+ definition.lock
end
end
diff --git a/lib/bundler/cli/open.rb b/lib/bundler/cli/open.rb
index 87c1c3b1db..f24693b843 100644
--- a/lib/bundler/cli/open.rb
+++ b/lib/bundler/cli/open.rb
@@ -21,7 +21,7 @@ module Bundler
require "shellwords"
command = Shellwords.split(editor) << File.join([root_path, path].compact)
Bundler.with_original_env do
- system(*command, { :chdir => root_path })
+ system(*command, { chdir: root_path })
end || Bundler.ui.info("Could not run '#{command.join(" ")}'")
end
end
diff --git a/lib/bundler/cli/outdated.rb b/lib/bundler/cli/outdated.rb
index 68c701aefb..ec42e631bb 100644
--- a/lib/bundler/cli/outdated.rb
+++ b/lib/bundler/cli/outdated.rb
@@ -41,12 +41,12 @@ module Bundler
# We're doing a full update
Bundler.definition(true)
else
- Bundler.definition(:gems => gems, :sources => sources)
+ Bundler.definition(gems: gems, sources: sources)
end
Bundler::CLI::Common.configure_gem_version_promoter(
Bundler.definition,
- options.merge(:strict => @strict)
+ options.merge(strict: @strict)
)
definition_resolution = proc do
@@ -90,10 +90,10 @@ module Bundler
end
outdated_gems << {
- :active_spec => active_spec,
- :current_spec => current_spec,
- :dependency => dependency,
- :groups => groups,
+ active_spec: active_spec,
+ current_spec: current_spec,
+ dependency: dependency,
+ groups: groups,
}
end
diff --git a/lib/bundler/cli/plugin.rb b/lib/bundler/cli/plugin.rb
index fe3f4412fa..fd61ef0d95 100644
--- a/lib/bundler/cli/plugin.rb
+++ b/lib/bundler/cli/plugin.rb
@@ -5,20 +5,15 @@ module Bundler
class CLI::Plugin < Thor
desc "install PLUGINS", "Install the plugin from the source"
long_desc <<-D
- Install plugins either from the rubygems source provided (with --source option) or from a git source provided with --git (for remote repos) or --local_git (for local repos). If no sources are provided, it uses Gem.sources
+ Install plugins either from the rubygems source provided (with --source option), from a git source provided with --git, or a local path provided with --path. If no sources are provided, it uses Gem.sources
D
- method_option "source", :type => :string, :default => nil, :banner =>
- "URL of the RubyGems source to fetch the plugin from"
- method_option "version", :type => :string, :default => nil, :banner =>
- "The version of the plugin to fetch"
- method_option "git", :type => :string, :default => nil, :banner =>
- "URL of the git repo to fetch from"
- method_option "local_git", :type => :string, :default => nil, :banner =>
- "Path of the local git repo to fetch from"
- method_option "branch", :type => :string, :default => nil, :banner =>
- "The git branch to checkout"
- method_option "ref", :type => :string, :default => nil, :banner =>
- "The git revision to check out"
+ method_option "source", type: :string, default: nil, banner: "URL of the RubyGems source to fetch the plugin from"
+ method_option "version", type: :string, default: nil, banner: "The version of the plugin to fetch"
+ method_option "git", type: :string, default: nil, banner: "URL of the git repo to fetch from"
+ method_option "local_git", type: :string, default: nil, banner: "Path of the local git repo to fetch from (deprecated)"
+ method_option "branch", type: :string, default: nil, banner: "The git branch to checkout"
+ method_option "ref", type: :string, default: nil, banner: "The git revision to check out"
+ method_option "path", type: :string, default: nil, banner: "Path of a local gem to directly use"
def install(*plugins)
Bundler::Plugin.install(plugins, options)
end
@@ -27,8 +22,7 @@ module Bundler
long_desc <<-D
Uninstall given list of plugins. To uninstall all the plugins, use -all option.
D
- method_option "all", :type => :boolean, :default => nil, :banner =>
- "Uninstall all the installed plugins. If no plugin is installed, then it does nothing."
+ method_option "all", type: :boolean, default: nil, banner: "Uninstall all the installed plugins. If no plugin is installed, then it does nothing."
def uninstall(*plugins)
Bundler::Plugin.uninstall(plugins, options)
end
diff --git a/lib/bundler/cli/pristine.rb b/lib/bundler/cli/pristine.rb
index d6654f8053..e0d7452c44 100644
--- a/lib/bundler/cli/pristine.rb
+++ b/lib/bundler/cli/pristine.rb
@@ -12,40 +12,48 @@ module Bundler
definition.validate_runtime!
installer = Bundler::Installer.new(Bundler.root, definition)
- Bundler.load.specs.each do |spec|
- next if spec.name == "bundler" # Source::Rubygems doesn't install bundler
- next if !@gems.empty? && !@gems.include?(spec.name)
-
- gem_name = "#{spec.name} (#{spec.version}#{spec.git_version})"
- gem_name += " (#{spec.platform})" if !spec.platform.nil? && spec.platform != Gem::Platform::RUBY
-
- case source = spec.source
- when Source::Rubygems
- cached_gem = spec.cache_file
- unless File.exist?(cached_gem)
- Bundler.ui.error("Failed to pristine #{gem_name}. Cached gem #{cached_gem} does not exist.")
+ ProcessLock.lock do
+ installed_specs = definition.specs.reject do |spec|
+ next if spec.name == "bundler" # Source::Rubygems doesn't install bundler
+ next if !@gems.empty? && !@gems.include?(spec.name)
+
+ gem_name = "#{spec.name} (#{spec.version}#{spec.git_version})"
+ gem_name += " (#{spec.platform})" if !spec.platform.nil? && spec.platform != Gem::Platform::RUBY
+
+ case source = spec.source
+ when Source::Rubygems
+ cached_gem = spec.cache_file
+ unless File.exist?(cached_gem)
+ Bundler.ui.error("Failed to pristine #{gem_name}. Cached gem #{cached_gem} does not exist.")
+ next
+ end
+
+ FileUtils.rm_rf spec.full_gem_path
+ when Source::Git
+ if source.local?
+ Bundler.ui.warn("Cannot pristine #{gem_name}. Gem is locally overridden.")
+ next
+ end
+
+ source.remote!
+ if extension_cache_path = source.extension_cache_path(spec)
+ FileUtils.rm_rf extension_cache_path
+ end
+ FileUtils.rm_rf spec.extension_dir
+ FileUtils.rm_rf spec.full_gem_path
+ else
+ Bundler.ui.warn("Cannot pristine #{gem_name}. Gem is sourced from local path.")
next
end
- FileUtils.rm_rf spec.full_gem_path
- when Source::Git
- if source.local?
- Bundler.ui.warn("Cannot pristine #{gem_name}. Gem is locally overridden.")
- next
- end
+ true
+ end.map(&:name)
- source.remote!
- if extension_cache_path = source.extension_cache_path(spec)
- FileUtils.rm_rf extension_cache_path
- end
- FileUtils.rm_rf spec.extension_dir
- FileUtils.rm_rf spec.full_gem_path
- else
- Bundler.ui.warn("Cannot pristine #{gem_name}. Gem is sourced from local path.")
- next
- end
-
- Bundler::GemInstaller.new(spec, installer, false, 0, true).install_from_spec
+ jobs = installer.send(:installation_parallelization, {})
+ pristine_count = definition.specs.count - installed_specs.count
+ # allow a pristining a single gem to skip the parallel worker
+ jobs = [jobs, pristine_count].min
+ ParallelInstaller.call(installer, definition.specs, jobs, false, true, skip: installed_specs)
end
end
end
diff --git a/lib/bundler/cli/update.rb b/lib/bundler/cli/update.rb
index 22dd1a78dd..985e8db051 100644
--- a/lib/bundler/cli/update.rb
+++ b/lib/bundler/cli/update.rb
@@ -35,7 +35,7 @@ module Bundler
if full_update
if conservative
- Bundler.definition(:conservative => conservative)
+ Bundler.definition(conservative: conservative)
else
Bundler.definition(true)
end
@@ -51,9 +51,9 @@ module Bundler
gems.concat(deps.map(&:name))
end
- Bundler.definition(:gems => gems, :sources => sources, :ruby => options[:ruby],
- :conservative => conservative,
- :bundler => update_bundler)
+ Bundler.definition(gems: gems, sources: sources, ruby: options[:ruby],
+ conservative: conservative,
+ bundler: update_bundler)
end
Bundler::CLI::Common.configure_gem_version_promoter(Bundler.definition, options)
@@ -71,7 +71,7 @@ module Bundler
if locked_gems = Bundler.definition.locked_gems
previous_locked_info = locked_gems.specs.reduce({}) do |h, s|
- h[s.name] = { :spec => s, :version => s.version, :source => s.source.identifier }
+ h[s.name] = { spec: s, version: s.version, source: s.source.identifier }
h
end
end
diff --git a/lib/bundler/compact_index_client.rb b/lib/bundler/compact_index_client.rb
index 127a50e810..692d68e579 100644
--- a/lib/bundler/compact_index_client.rb
+++ b/lib/bundler/compact_index_client.rb
@@ -4,8 +4,44 @@ require "pathname"
require "set"
module Bundler
+ # The CompactIndexClient is responsible for fetching and parsing the compact index.
+ #
+ # The compact index is a set of caching optimized files that are used to fetch gem information.
+ # The files are:
+ # - names: a list of all gem names
+ # - versions: a list of all gem versions
+ # - info/[gem]: a list of all versions of a gem
+ #
+ # The client is instantiated with:
+ # - `directory`: the root directory where the cache files are stored.
+ # - `fetcher`: (optional) an object that responds to #call(uri_path, headers) and returns an http response.
+ # If the `fetcher` is not provided, the client will only read cached files from disk.
+ #
+ # The client is organized into:
+ # - `Updater`: updates the cached files on disk using the fetcher.
+ # - `Cache`: calls the updater, caches files, read and return them from disk
+ # - `Parser`: parses the compact index file data
+ # - `CacheFile`: a concurrency safe file reader/writer that verifies checksums
+ #
+ # The client is intended to optimize memory usage and performance.
+ # It is called 100s or 1000s of times, parsing files with hundreds of thousands of lines.
+ # It may be called concurrently without global interpreter lock in some Rubies.
+ # As a result, some methods may look more complex than necessary to save memory or time.
class CompactIndexClient
+ # NOTE: MD5 is here not because we expect a server to respond with it, but
+ # because we use it to generate the etag on first request during the upgrade
+ # to the compact index client that uses opaque etags saved to files.
+ # Remove once 2.5.0 has been out for a while.
+ SUPPORTED_DIGESTS = { "sha-256" => :SHA256, "md5" => :MD5 }.freeze
DEBUG_MUTEX = Thread::Mutex.new
+
+ # info returns an Array of INFO Arrays. Each INFO Array has the following indices:
+ INFO_NAME = 0
+ INFO_VERSION = 1
+ INFO_PLATFORM = 2
+ INFO_DEPS = 3
+ INFO_REQS = 4
+
def self.debug
return unless ENV["DEBUG_COMPACT_INDEX"]
DEBUG_MUTEX.synchronize { warn("[#{self}] #{yield}") }
@@ -14,106 +50,48 @@ module Bundler
class Error < StandardError; end
require_relative "compact_index_client/cache"
+ require_relative "compact_index_client/cache_file"
+ require_relative "compact_index_client/parser"
require_relative "compact_index_client/updater"
- attr_reader :directory
-
- def initialize(directory, fetcher)
- @directory = Pathname.new(directory)
- @updater = Updater.new(fetcher)
- @cache = Cache.new(@directory)
- @endpoints = Set.new
- @info_checksums_by_name = {}
- @parsed_checksums = false
- @mutex = Thread::Mutex.new
- end
-
- def execution_mode=(block)
- Bundler::CompactIndexClient.debug { "execution_mode=" }
- @endpoints = Set.new
-
- @execution_mode = block
- end
-
- # @return [Lambda] A lambda that takes an array of inputs and a block, and
- # maps the inputs with the block in parallel.
- #
- def execution_mode
- @execution_mode || sequentially
- end
-
- def sequential_execution_mode!
- self.execution_mode = sequentially
- end
-
- def sequentially
- @sequentially ||= lambda do |inputs, &blk|
- inputs.map(&blk)
- end
+ def initialize(directory, fetcher = nil)
+ @cache = Cache.new(directory, fetcher)
+ @parser = Parser.new(@cache)
end
def names
- Bundler::CompactIndexClient.debug { "/names" }
- update(@cache.names_path, "names")
- @cache.names
+ Bundler::CompactIndexClient.debug { "names" }
+ @parser.names
end
def versions
- Bundler::CompactIndexClient.debug { "/versions" }
- update(@cache.versions_path, "versions")
- versions, @info_checksums_by_name = @cache.versions
- versions
+ Bundler::CompactIndexClient.debug { "versions" }
+ @parser.versions
end
def dependencies(names)
Bundler::CompactIndexClient.debug { "dependencies(#{names})" }
- execution_mode.call(names) do |name|
- update_info(name)
- @cache.dependencies(name).map {|d| d.unshift(name) }
- end.flatten(1)
+ names.map {|name| info(name) }
end
- def update_and_parse_checksums!
- Bundler::CompactIndexClient.debug { "update_and_parse_checksums!" }
- return @info_checksums_by_name if @parsed_checksums
- update(@cache.versions_path, "versions")
- @info_checksums_by_name = @cache.checksums
- @parsed_checksums = true
- end
-
- private
-
- def update(local_path, remote_path)
- Bundler::CompactIndexClient.debug { "update(#{local_path}, #{remote_path})" }
- unless synchronize { @endpoints.add?(remote_path) }
- Bundler::CompactIndexClient.debug { "already fetched #{remote_path}" }
- return
- end
- @updater.update(local_path, url(remote_path))
+ def info(name)
+ Bundler::CompactIndexClient.debug { "info(#{names})" }
+ @parser.info(name)
end
- def update_info(name)
- Bundler::CompactIndexClient.debug { "update_info(#{name})" }
- path = @cache.info_path(name)
- checksum = @updater.checksum_for_file(path)
- unless existing = @info_checksums_by_name[name]
- Bundler::CompactIndexClient.debug { "skipping updating info for #{name} since it is missing from versions" }
- return
- end
- if checksum == existing
- Bundler::CompactIndexClient.debug { "skipping updating info for #{name} since the versions checksum matches the local checksum" }
- return
- end
- Bundler::CompactIndexClient.debug { "updating info for #{name} since the versions checksum #{existing} != the local checksum #{checksum}" }
- update(path, "info/#{name}")
+ def latest_version(name)
+ Bundler::CompactIndexClient.debug { "latest_version(#{name})" }
+ @parser.info(name).map {|d| Gem::Version.new(d[INFO_VERSION]) }.max
end
- def url(path)
- path
+ def available?
+ Bundler::CompactIndexClient.debug { "available?" }
+ @parser.available?
end
- def synchronize
- @mutex.synchronize { yield }
+ def reset!
+ Bundler::CompactIndexClient.debug { "reset!" }
+ @cache.reset!
end
end
end
diff --git a/lib/bundler/compact_index_client/cache.rb b/lib/bundler/compact_index_client/cache.rb
index b5607c8751..bedd7f8028 100644
--- a/lib/bundler/compact_index_client/cache.rb
+++ b/lib/bundler/compact_index_client/cache.rb
@@ -7,94 +7,89 @@ module Bundler
class Cache
attr_reader :directory
- def initialize(directory)
+ def initialize(directory, fetcher = nil)
@directory = Pathname.new(directory).expand_path
- info_roots.each do |dir|
- SharedHelpers.filesystem_access(dir) do
- FileUtils.mkdir_p(dir)
- end
- end
- end
+ @updater = Updater.new(fetcher) if fetcher
+ @mutex = Thread::Mutex.new
+ @endpoints = Set.new
- def names
- lines(names_path)
+ @info_root = mkdir("info")
+ @special_characters_info_root = mkdir("info-special-characters")
+ @info_etag_root = mkdir("info-etags")
end
- def names_path
- directory.join("names")
+ def names
+ fetch("names", names_path, names_etag_path)
end
def versions
- versions_by_name = Hash.new {|hash, key| hash[key] = [] }
- info_checksums_by_name = {}
-
- lines(versions_path).each do |line|
- name, versions_string, info_checksum = line.split(" ", 3)
- info_checksums_by_name[name] = info_checksum || ""
- versions_string.split(",").each do |version|
- delete = version.delete_prefix!("-")
- version = version.split("-", 2).unshift(name)
- if delete
- versions_by_name[name].delete(version)
- else
- versions_by_name[name] << version
- end
- end
- end
-
- [versions_by_name, info_checksums_by_name]
- end
-
- def versions_path
- directory.join("versions")
+ fetch("versions", versions_path, versions_etag_path)
end
- def checksums
- checksums = {}
+ def info(name, remote_checksum = nil)
+ path = info_path(name)
- lines(versions_path).each do |line|
- name, _, checksum = line.split(" ", 3)
- checksums[name] = checksum
+ if remote_checksum && remote_checksum != SharedHelpers.checksum_for_file(path, :MD5)
+ fetch("info/#{name}", path, info_etag_path(name))
+ else
+ Bundler::CompactIndexClient.debug { "update skipped info/#{name} (#{remote_checksum ? "versions index checksum is nil" : "versions index checksum matches local"})" }
+ read(path)
end
-
- checksums
end
- def dependencies(name)
- lines(info_path(name)).map do |line|
- parse_gem(line)
- end
+ def reset!
+ @mutex.synchronize { @endpoints.clear }
end
+ private
+
+ def names_path = directory.join("names")
+ def names_etag_path = directory.join("names.etag")
+ def versions_path = directory.join("versions")
+ def versions_etag_path = directory.join("versions.etag")
+
def info_path(name)
name = name.to_s
+ # TODO: converge this into the info_root by hashing all filenames like info_etag_path
if /[^a-z0-9_-]/.match?(name)
name += "-#{SharedHelpers.digest(:MD5).hexdigest(name).downcase}"
- info_roots.last.join(name)
+ @special_characters_info_root.join(name)
else
- info_roots.first.join(name)
+ @info_root.join(name)
end
end
- private
+ def info_etag_path(name)
+ name = name.to_s
+ @info_etag_root.join("#{name}-#{SharedHelpers.digest(:MD5).hexdigest(name).downcase}")
+ end
+
+ def mkdir(name)
+ directory.join(name).tap do |dir|
+ SharedHelpers.filesystem_access(dir) do
+ FileUtils.mkdir_p(dir)
+ end
+ end
+ end
+
+ def fetch(remote_path, path, etag_path)
+ if already_fetched?(remote_path)
+ Bundler::CompactIndexClient.debug { "already fetched #{remote_path}" }
+ else
+ Bundler::CompactIndexClient.debug { "fetching #{remote_path}" }
+ @updater&.update(remote_path, path, etag_path)
+ end
- def lines(path)
- return [] unless path.file?
- lines = SharedHelpers.filesystem_access(path, :read, &:read).split("\n")
- header = lines.index("---")
- header ? lines[header + 1..-1] : lines
+ read(path)
end
- def parse_gem(line)
- @dependency_parser ||= GemParser.new
- @dependency_parser.parse(line)
+ def already_fetched?(remote_path)
+ @mutex.synchronize { !@endpoints.add?(remote_path) }
end
- def info_roots
- [
- directory.join("info"),
- directory.join("info-special-characters"),
- ]
+ def read(path)
+ return unless path.file?
+ SharedHelpers.filesystem_access(path, :read, &:read)
end
end
end
diff --git a/lib/bundler/compact_index_client/cache_file.rb b/lib/bundler/compact_index_client/cache_file.rb
new file mode 100644
index 0000000000..299d683438
--- /dev/null
+++ b/lib/bundler/compact_index_client/cache_file.rb
@@ -0,0 +1,148 @@
+# frozen_string_literal: true
+
+require_relative "../vendored_fileutils"
+require "rubygems/package"
+
+module Bundler
+ class CompactIndexClient
+ # write cache files in a way that is robust to concurrent modifications
+ # if digests are given, the checksums will be verified
+ class CacheFile
+ DEFAULT_FILE_MODE = 0o644
+ private_constant :DEFAULT_FILE_MODE
+
+ class Error < RuntimeError; end
+ class ClosedError < Error; end
+
+ class DigestMismatchError < Error
+ def initialize(digests, expected_digests)
+ super "Calculated checksums #{digests.inspect} did not match expected #{expected_digests.inspect}."
+ end
+ end
+
+ # Initialize with a copy of the original file, then yield the instance.
+ def self.copy(path, &block)
+ new(path) do |file|
+ file.initialize_digests
+
+ SharedHelpers.filesystem_access(path, :read) do
+ path.open("rb") do |s|
+ file.open {|f| IO.copy_stream(s, f) }
+ end
+ end
+
+ yield file
+ end
+ end
+
+ # Write data to a temp file, then replace the original file with it verifying the digests if given.
+ def self.write(path, data, digests = nil)
+ return unless data
+ new(path) do |file|
+ file.digests = digests
+ file.write(data)
+ end
+ end
+
+ attr_reader :original_path, :path
+
+ def initialize(original_path, &block)
+ @original_path = original_path
+ @perm = original_path.file? ? original_path.stat.mode : DEFAULT_FILE_MODE
+ @path = original_path.sub(/$/, ".#{$$}.tmp")
+ return unless block_given?
+ begin
+ yield self
+ ensure
+ close
+ end
+ end
+
+ def size
+ path.size
+ end
+
+ # initialize the digests using CompactIndexClient::SUPPORTED_DIGESTS, or a subset based on keys.
+ def initialize_digests(keys = nil)
+ @digests = keys ? SUPPORTED_DIGESTS.slice(*keys) : SUPPORTED_DIGESTS.dup
+ @digests.transform_values! {|algo_class| SharedHelpers.digest(algo_class).new }
+ end
+
+ # reset the digests so they don't contain any previously read data
+ def reset_digests
+ @digests&.each_value(&:reset)
+ end
+
+ # set the digests that will be verified at the end
+ def digests=(expected_digests)
+ @expected_digests = expected_digests
+
+ if @expected_digests.nil?
+ @digests = nil
+ elsif @digests
+ @digests = @digests.slice(*@expected_digests.keys)
+ else
+ initialize_digests(@expected_digests.keys)
+ end
+ end
+
+ def digests?
+ @digests&.any?
+ end
+
+ # Open the temp file for writing, reusing original permissions, yielding the IO object.
+ def open(write_mode = "wb", perm = @perm, &block)
+ raise ClosedError, "Cannot reopen closed file" if @closed
+ SharedHelpers.filesystem_access(path, :write) do
+ path.open(write_mode, perm) do |f|
+ yield digests? ? Gem::Package::DigestIO.new(f, @digests) : f
+ end
+ end
+ end
+
+ # Returns false without appending when no digests since appending is too error prone to do without digests.
+ def append(data)
+ return false unless digests?
+ open("a") {|f| f.write data }
+ verify && commit
+ end
+
+ def write(data)
+ reset_digests
+ open {|f| f.write data }
+ commit!
+ end
+
+ def commit!
+ verify || raise(DigestMismatchError.new(@base64digests, @expected_digests))
+ commit
+ end
+
+ # Verify the digests, returning true on match, false on mismatch.
+ def verify
+ return true unless @expected_digests && digests?
+ @base64digests = @digests.transform_values!(&:base64digest)
+ @digests = nil
+ @base64digests.all? {|algo, digest| @expected_digests[algo] == digest }
+ end
+
+ # Replace the original file with the temp file without verifying digests.
+ # The file is permanently closed.
+ def commit
+ raise ClosedError, "Cannot commit closed file" if @closed
+ SharedHelpers.filesystem_access(original_path, :write) do
+ FileUtils.mv(path, original_path)
+ end
+ @closed = true
+ end
+
+ # Remove the temp file without replacing the original file.
+ # The file is permanently closed.
+ def close
+ return if @closed
+ FileUtils.remove_file(path) if @path&.file?
+ @closed = true
+ end
+ end
+ end
+end
diff --git a/lib/bundler/compact_index_client/parser.rb b/lib/bundler/compact_index_client/parser.rb
new file mode 100644
index 0000000000..3a0dec4907
--- /dev/null
+++ b/lib/bundler/compact_index_client/parser.rb
@@ -0,0 +1,111 @@
+# frozen_string_literal: true
+
+module Bundler
+ class CompactIndexClient
+ class Parser
+ # `compact_index` - an object responding to #names, #versions, #info(name, checksum),
+ # returning the file contents as a string
+ def initialize(compact_index)
+ @compact_index = compact_index
+ @info_checksums = nil
+ @versions_by_name = nil
+ @available = nil
+ @gem_parser = nil
+ @versions_data = nil
+ end
+
+ def names
+ lines(@compact_index.names)
+ end
+
+ def versions
+ @versions_by_name ||= Hash.new {|hash, key| hash[key] = [] }
+ @info_checksums = {}
+
+ lines(@compact_index.versions).each do |line|
+ name, versions_string, checksum = line.split(" ", 3)
+ @info_checksums[name] = checksum || ""
+ versions_string.split(",") do |version|
+ delete = version.delete_prefix!("-")
+ version = version.split("-", 2).unshift(name)
+ if delete
+ @versions_by_name[name].delete(version)
+ else
+ @versions_by_name[name] << version
+ end
+ end
+ end
+
+ @versions_by_name
+ end
+
+ def info(name)
+ data = @compact_index.info(name, info_checksum(name))
+ lines(data).map {|line| gem_parser.parse(line).unshift(name) }
+ end
+
+ # parse the last, most recently updated line of the versions file to determine availability
+ def available?
+ return @available unless @available.nil?
+ return @available = false unless versions_data&.size&.nonzero?
+
+ line_end = versions_data.size - 1
+ return @available = false if versions_data[line_end] != "\n"
+
+ line_start = versions_data.rindex("\n", line_end - 1)
+ line_start ||= -1 # allow a single line versions file
+
+ @available = !split_last_word(versions_data, line_start + 1, line_end).nil?
+ end
+
+ private
+
+ # Search for a line starting with gem name, then return last space-separated word (the checksum)
+ def info_checksum(name)
+ return unless versions_data
+ return unless (line_start = rindex_of_gem(name))
+ return unless (line_end = versions_data.index("\n", line_start))
+ split_last_word(versions_data, line_start, line_end)
+ end
+
+ def gem_parser
+ @gem_parser ||= GemParser.new
+ end
+
+ def versions_data
+ @versions_data ||= begin
+ data = @compact_index.versions
+ strip_header!(data) if data
+ data.freeze
+ end
+ end
+
+ def rindex_of_gem(name)
+ if (pos = versions_data.rindex("\n#{name} "))
+ pos + 1
+ elsif versions_data.start_with?("#{name} ")
+ 0
+ end
+ end
+
+ # This is similar to `string.split(" ").last` but it avoids allocating extra objects.
+ def split_last_word(string, line_start, line_end)
+ return unless line_start < line_end && line_start >= 0
+ word_start = string.rindex(" ", line_end).to_i + 1
+ return if word_start < line_start
+ string[word_start, line_end - word_start]
+ end
+
+ def lines(string)
+ return [] if string.nil? || string.empty?
+ strip_header!(string)
+ string.split("\n")
+ end
+
+ def strip_header!(string)
+ header_end = string.index("---\n")
+ string.slice!(0, header_end + 4) if header_end
+ end
+ end
+ end
+end
diff --git a/lib/bundler/compact_index_client/updater.rb b/lib/bundler/compact_index_client/updater.rb
index 3b75d5c129..88c7146900 100644
--- a/lib/bundler/compact_index_client/updater.rb
+++ b/lib/bundler/compact_index_client/updater.rb
@@ -1,20 +1,11 @@
# frozen_string_literal: true
-require_relative "../vendored_fileutils"
-
module Bundler
class CompactIndexClient
class Updater
- class MisMatchedChecksumError < Error
- def initialize(path, server_checksum, local_checksum)
- @path = path
- @server_checksum = server_checksum
- @local_checksum = local_checksum
- end
-
- def message
- "The checksum of /#{@path} does not match the checksum provided by the server! Something is wrong " \
- "(local checksum is #{@local_checksum.inspect}, was expecting #{@server_checksum.inspect})."
+ class MismatchedChecksumError < Error
+ def initialize(path, message)
+ super "The checksum of /#{path} does not match the checksum provided by the server! Something is wrong. #{message}"
end
end
@@ -22,100 +13,91 @@ module Bundler
@fetcher = fetcher
end
- def update(local_path, remote_path, retrying = nil)
- headers = {}
-
- local_temp_path = local_path.sub(/$/, ".#{$$}")
- local_temp_path = local_temp_path.sub(/$/, ".retrying") if retrying
- local_temp_path = local_temp_path.sub(/$/, ".tmp")
-
- # first try to fetch any new bytes on the existing file
- if retrying.nil? && local_path.file?
- copy_file local_path, local_temp_path
+ def update(remote_path, local_path, etag_path)
+ append(remote_path, local_path, etag_path) || replace(remote_path, local_path, etag_path)
+ rescue CacheFile::DigestMismatchError => e
+ raise MismatchedChecksumError.new(remote_path, e.message)
+ rescue Zlib::GzipFile::Error
+ raise Bundler::HTTPError
+ end
- headers["If-None-Match"] = etag_for(local_temp_path)
- headers["Range"] =
- if local_temp_path.size.nonzero?
- # Subtract a byte to ensure the range won't be empty.
- # Avoids 416 (Range Not Satisfiable) responses.
- "bytes=#{local_temp_path.size - 1}-"
- else
- "bytes=#{local_temp_path.size}-"
- end
- end
+ private
- response = @fetcher.call(remote_path, headers)
- return nil if response.is_a?(Net::HTTPNotModified)
+ def append(remote_path, local_path, etag_path)
+ return false unless local_path.file? && local_path.size.nonzero?
- content = response.body
+ CacheFile.copy(local_path) do |file|
+ etag = etag_path.read.tap(&:chomp!) if etag_path.file?
- etag = (response["ETag"] || "").gsub(%r{\AW/}, "")
- correct_response = SharedHelpers.filesystem_access(local_temp_path) do
- if response.is_a?(Net::HTTPPartialContent) && local_temp_path.size.nonzero?
- local_temp_path.open("a") {|f| f << slice_body(content, 1..-1) }
+ # Subtract a byte to ensure the range won't be empty.
+ # Avoids 416 (Range Not Satisfiable) responses.
+ response = @fetcher.call(remote_path, request_headers(etag, file.size - 1))
+ break true if response.is_a?(Gem::Net::HTTPNotModified)
- etag_for(local_temp_path) == etag
+ file.digests = parse_digests(response)
+ # server may ignore Range and return the full response
+ if response.is_a?(Gem::Net::HTTPPartialContent)
+ break false unless file.append(response.body.byteslice(1..-1))
else
- local_temp_path.open("wb") {|f| f << content }
-
- etag.length.zero? || etag_for(local_temp_path) == etag
- end
- end
-
- if correct_response
- SharedHelpers.filesystem_access(local_path) do
- FileUtils.mv(local_temp_path, local_path)
+ file.write(response.body)
end
- return nil
+ CacheFile.write(etag_path, etag_from_response(response))
+ true
end
+ end
- if retrying
- raise MisMatchedChecksumError.new(remote_path, etag, etag_for(local_temp_path))
- end
+ # request without range header to get the full file or a 304 Not Modified
+ def replace(remote_path, local_path, etag_path)
+ etag = etag_path.read.tap(&:chomp!) if etag_path.file?
+ response = @fetcher.call(remote_path, request_headers(etag))
+ return true if response.is_a?(Gem::Net::HTTPNotModified)
+ CacheFile.write(local_path, response.body, parse_digests(response))
+ CacheFile.write(etag_path, etag_from_response(response))
+ end
- update(local_path, remote_path, :retrying)
- rescue Zlib::GzipFile::Error
- raise Bundler::HTTPError
- ensure
- FileUtils.remove_file(local_temp_path) if File.exist?(local_temp_path)
+ def request_headers(etag, range_start = nil)
+ headers = {}
+ headers["Range"] = "bytes=#{range_start}-" if range_start
+ headers["If-None-Match"] = %("#{etag}") if etag
+ headers
end
- def etag_for(path)
- sum = checksum_for_file(path)
- sum ? %("#{sum}") : nil
+ def etag_for_request(etag_path)
+ etag_path.read.tap(&:chomp!) if etag_path.file?
end
- def slice_body(body, range)
- body.byteslice(range)
+ def etag_from_response(response)
+ return unless response["ETag"]
+ etag = response["ETag"].delete_prefix("W/")
+ return if etag.delete_prefix!('"') && !etag.delete_suffix!('"')
+ etag
end
- def checksum_for_file(path)
- return nil unless path.file?
- # This must use File.read instead of Digest.file().hexdigest
- # because we need to preserve \n line endings on windows when calculating
- # the checksum
- SharedHelpers.filesystem_access(path, :read) do
- File.open(path, "rb") do |f|
- digest = SharedHelpers.digest(:MD5).new
- buf = String.new(:capacity => 16_384, :encoding => Encoding::BINARY)
- digest << buf while f.read(16_384, buf)
- digest.hexdigest
- end
+ # Unwraps and returns a Hash of digest algorithms and base64 values
+ # according to RFC 8941 Structured Field Values for HTTP.
+ # https://www.rfc-editor.org/rfc/rfc8941#name-parsing-a-byte-sequence
+ # Ignores unsupported algorithms.
+ def parse_digests(response)
+ return unless header = response["Repr-Digest"] || response["Digest"]
+ digests = {}
+ header.split(",") do |param|
+ algorithm, value = param.split("=", 2)
+ algorithm.strip!
+ algorithm.downcase!
+ next unless SUPPORTED_DIGESTS.key?(algorithm)
+ next unless value = byte_sequence(value)
+ digests[algorithm] = value
end
+ digests.empty? ? nil : digests
end
- private
-
- def copy_file(source, dest)
- SharedHelpers.filesystem_access(source, :read) do
- File.open(source, "r") do |s|
- SharedHelpers.filesystem_access(dest, :write) do
- File.open(dest, "wb", s.stat.mode) do |f|
- IO.copy_stream(s, f)
- end
- end
- end
- end
+ # Unwrap surrounding colons (byte sequence)
+ # The wrapping characters must be matched or we return nil.
+ # Also handles quotes because right now rubygems.org sends them.
+ def byte_sequence(value)
+ return if value.delete_prefix!(":") && !value.delete_suffix!(":")
+ return if value.delete_prefix!('"') && !value.delete_suffix!('"')
+ value
end
end
end
diff --git a/lib/bundler/constants.rb b/lib/bundler/constants.rb
index de9698b577..9564771e78 100644
--- a/lib/bundler/constants.rb
+++ b/lib/bundler/constants.rb
@@ -1,7 +1,14 @@
# frozen_string_literal: true
+require "rbconfig"
+
module Bundler
WINDOWS = RbConfig::CONFIG["host_os"] =~ /(msdos|mswin|djgpp|mingw)/
+ deprecate_constant :WINDOWS
+
FREEBSD = RbConfig::CONFIG["host_os"].to_s.include?("bsd")
- NULL = File::NULL
+ deprecate_constant :FREEBSD
+
+ NULL = File::NULL
+ deprecate_constant :NULL
end
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb
index 9ef0abed93..6cf1f9a255 100644
--- a/lib/bundler/definition.rb
+++ b/lib/bundler/definition.rb
@@ -18,7 +18,8 @@ module Bundler
:platforms,
:ruby_version,
:lockfile,
- :gemfiles
+ :gemfiles,
+ :locked_checksums
)
# Given a gemfile and lockfile creates a Bundler definition
@@ -68,7 +69,6 @@ module Bundler
@sources = sources
@unlock = unlock
@optional_groups = optional_groups
- @remote = false
@prefer_local = false
@specs = nil
@ruby_version = ruby_version
@@ -91,10 +91,12 @@ module Bundler
@platforms = @locked_platforms.dup
@locked_bundler_version = @locked_gems.bundler_version
@locked_ruby_version = @locked_gems.ruby_version
+ @originally_locked_deps = @locked_gems.dependencies
@originally_locked_specs = SpecSet.new(@locked_gems.specs)
+ @locked_checksums = @locked_gems.checksums
if unlock != true
- @locked_deps = @locked_gems.dependencies
+ @locked_deps = @originally_locked_deps
@locked_specs = @originally_locked_specs
@locked_sources = @locked_gems.sources
else
@@ -109,9 +111,11 @@ module Bundler
@locked_gems = nil
@locked_deps = {}
@locked_specs = SpecSet.new([])
+ @originally_locked_deps = {}
@originally_locked_specs = @locked_specs
@locked_sources = []
@locked_platforms = []
+ @locked_checksums = nil
end
locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
@@ -127,7 +131,7 @@ module Bundler
@sources.merged_gem_lockfile_sections!(locked_gem_sources.first)
end
- @unlock[:sources] ||= []
+ @sources_to_unlock = @unlock.delete(:sources) || []
@unlock[:ruby] ||= if @ruby_version && locked_ruby_version_object
@ruby_version.diff(locked_ruby_version_object)
end
@@ -139,11 +143,13 @@ module Bundler
@path_changes = converge_paths
@source_changes = converge_sources
+ @explicit_unlocks = @unlock.delete(:gems) || []
+
if @unlock[:conservative]
- @unlock[:gems] ||= @dependencies.map(&:name)
+ @gems_to_unlock = @explicit_unlocks.any? ? @explicit_unlocks : @dependencies.map(&:name)
else
- eager_unlock = (@unlock[:gems] || []).map {|name| Dependency.new(name, ">= 0") }
- @unlock[:gems] = @locked_specs.for(eager_unlock, false, platforms).map(&:name).uniq
+ eager_unlock = @explicit_unlocks.map {|name| Dependency.new(name, ">= 0") }
+ @gems_to_unlock = @locked_specs.for(eager_unlock, false, platforms).map(&:name).uniq
end
@dependency_changes = converge_dependencies
@@ -157,37 +163,24 @@ module Bundler
end
def resolve_only_locally!
- @remote = false
sources.local_only!
resolve
end
def resolve_with_cache!
+ sources.local!
sources.cached!
resolve
end
def resolve_remotely!
- @remote = true
+ sources.cached!
sources.remote!
resolve
end
- def resolution_mode=(options)
- if options["local"]
- @remote = false
- else
- @remote = true
- @prefer_local = options["prefer-local"]
- end
- end
-
- def setup_sources_for_resolve
- if @remote == false
- sources.cached!
- else
- sources.remote!
- end
+ def prefer_local!
+ @prefer_local = true
end
# For given dependency list returns a SpecSet with Gemspec of all the required
@@ -222,7 +215,6 @@ module Bundler
@resolver = nil
@resolution_packages = nil
@specs = nil
- @gem_version_promoter = nil
Bundler.ui.debug "The definition is missing dependencies, failed to resolve & materialize locally (#{e})"
true
@@ -245,8 +237,9 @@ module Bundler
end
def filter_relevant(dependencies)
+ platforms_array = [generic_local_platform].freeze
dependencies.select do |d|
- d.should_include? && !d.gem_platforms([generic_local_platform]).empty?
+ d.should_include? && !d.gem_platforms(platforms_array).empty?
end
end
@@ -270,9 +263,15 @@ module Bundler
def dependencies_for(groups)
groups.map!(&:to_sym)
- current_dependencies.reject do |d|
- (d.groups & groups).empty?
+ deps = current_dependencies # always returns a new array
+ deps.select! do |d|
+ if RUBY_VERSION >= "3.1"
+ d.groups.intersect?(groups)
+ else
+ !(d.groups & groups).empty?
+ end
end
+ deps
end
# Resolve all the dependencies specified in Gemfile. It ensures that
@@ -297,15 +296,16 @@ module Bundler
end
end
else
- Bundler.ui.debug "Found changes from the lockfile, re-resolving dependencies because #{change_reason}"
+ if lockfile_exists?
+ Bundler.ui.debug "Found changes from the lockfile, re-resolving dependencies because #{change_reason}"
+ else
+ Bundler.ui.debug "Resolving dependencies because there's no lockfile"
+ end
+
start_resolution
end
end
- def should_complete_platforms?
- !lockfile_exists? && generic_local_platform_is_ruby? && !Bundler.settings[:force_ruby_platform]
- end
-
def spec_git_paths
sources.git_sources.map {|s| File.realpath(s.path) if File.exist?(s.path) }.compact
end
@@ -314,34 +314,26 @@ module Bundler
dependencies.map(&:groups).flatten.uniq
end
- def lock(file, preserve_unknown_sections = false)
- return if Definition.no_lock
-
- contents = to_lock
-
- # Convert to \r\n if the existing lock has them
- # i.e., Windows with `git config core.autocrlf=true`
- contents.gsub!(/\n/, "\r\n") if @lockfile_contents.match?("\r\n")
-
- if @locked_bundler_version
- locked_major = @locked_bundler_version.segments.first
- current_major = bundler_version_to_lock.segments.first
-
- updating_major = locked_major < current_major
- end
+ def lock(file_or_preserve_unknown_sections = false, preserve_unknown_sections_or_unused = false)
+ if [true, false, nil].include?(file_or_preserve_unknown_sections)
+ target_lockfile = lockfile || Bundler.default_lockfile
+ preserve_unknown_sections = file_or_preserve_unknown_sections
+ else
+ target_lockfile = file_or_preserve_unknown_sections
+ preserve_unknown_sections = preserve_unknown_sections_or_unused
- preserve_unknown_sections ||= !updating_major && (Bundler.frozen_bundle? || !(unlocking? || @unlocking_bundler))
+ suggestion = if target_lockfile == lockfile
+ "To fix this warning, remove it from the `Definition#lock` call."
+ else
+ "Instead, instantiate a new definition passing `#{target_lockfile}`, and call `lock` without a file argument on that definition"
+ end
- return if file && File.exist?(file) && lockfiles_equal?(@lockfile_contents, contents, preserve_unknown_sections)
+ msg = "`Definition#lock` was passed a target file argument. #{suggestion}"
- if Bundler.frozen_bundle?
- Bundler.ui.error "Cannot write a changed lockfile while frozen."
- return
+ Bundler::SharedHelpers.major_deprecation 2, msg
end
- SharedHelpers.filesystem_access(file) do |p|
- File.open(p, "wb") {|f| f.puts(contents) }
- end
+ write_lock(target_lockfile, preserve_unknown_sections)
end
def locked_ruby_version
@@ -482,7 +474,17 @@ module Bundler
private :sources
def nothing_changed?
- !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes && !@missing_lockfile_dep && !@unlocking_bundler && !@invalid_lockfile_dep
+ return false unless lockfile_exists?
+
+ !@source_changes &&
+ !@dependency_changes &&
+ !@new_platform &&
+ !@path_changes &&
+ !@local_changes &&
+ !@missing_lockfile_dep &&
+ !@unlocking_bundler &&
+ !@locked_spec_with_missing_deps &&
+ !@locked_spec_with_invalid_deps
end
def no_resolve_needed?
@@ -495,8 +497,50 @@ module Bundler
private
+ def should_add_extra_platforms?
+ !lockfile_exists? && generic_local_platform_is_ruby? && !Bundler.settings[:force_ruby_platform]
+ end
+
def lockfile_exists?
- lockfile && File.exist?(lockfile)
+ file_exists?(lockfile)
+ end
+
+ def file_exists?(file)
+ file && File.exist?(file)
+ end
+
+ def write_lock(file, preserve_unknown_sections)
+ return if Definition.no_lock
+
+ contents = to_lock
+
+ # Convert to \r\n if the existing lock has them
+ # i.e., Windows with `git config core.autocrlf=true`
+ contents.gsub!(/\n/, "\r\n") if @lockfile_contents.match?("\r\n")
+
+ if @locked_bundler_version
+ locked_major = @locked_bundler_version.segments.first
+ current_major = bundler_version_to_lock.segments.first
+
+ updating_major = locked_major < current_major
+ end
+
+ preserve_unknown_sections ||= !updating_major && (Bundler.frozen_bundle? || !(unlocking? || @unlocking_bundler))
+
+ if file_exists?(file) && lockfiles_equal?(@lockfile_contents, contents, preserve_unknown_sections)
+ return if Bundler.frozen_bundle?
+ SharedHelpers.filesystem_access(file) { FileUtils.touch(file) }
+ return
+ end
+
+ if Bundler.frozen_bundle?
+ Bundler.ui.error "Cannot write a changed lockfile while frozen."
+ return
+ end
+
+ SharedHelpers.filesystem_access(file) do |p|
+ File.open(p, "wb") {|f| f.puts(contents) }
+ end
end
def resolver
@@ -518,8 +562,10 @@ module Bundler
@resolution_packages ||= begin
last_resolve = converge_locked_specs
remove_invalid_platforms!(current_dependencies)
- packages = Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, :locked_specs => @originally_locked_specs, :unlock => @unlock[:gems], :prerelease => gem_version_promoter.pre?)
- additional_base_requirements_for_resolve(packages, last_resolve)
+ packages = Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: @gems_to_unlock, prerelease: gem_version_promoter.pre?)
+ packages = additional_base_requirements_to_prevent_downgrades(packages, last_resolve)
+ packages = additional_base_requirements_to_force_updates(packages)
+ packages
end
end
@@ -534,7 +580,7 @@ module Bundler
if missing_specs.any?
missing_specs.each do |s|
locked_gem = @locked_specs[s.name].last
- next if locked_gem.nil? || locked_gem.version != s.version || !@remote
+ next if locked_gem.nil? || locked_gem.version != s.version || sources.local_mode?
raise GemNotFound, "Your bundle is locked to #{locked_gem} from #{locked_gem.source}, but that version can " \
"no longer be found in that source. That means the author of #{locked_gem} has removed it. " \
"You'll need to update your bundle to a version other than #{locked_gem} that hasn't been " \
@@ -553,7 +599,7 @@ module Bundler
break if incomplete_specs.empty?
Bundler.ui.debug("The lockfile does not have all gems needed for the current platform though, Bundler will still re-resolve dependencies")
- setup_sources_for_resolve
+ sources.remote!
resolution_packages.delete(incomplete_specs)
@resolve = start_resolution
specs = resolve.materialize(dependencies)
@@ -578,7 +624,9 @@ module Bundler
result = SpecSet.new(resolver.start)
@resolved_bundler_version = result.find {|spec| spec.name == "bundler" }&.version
- @platforms = result.complete_platforms!(platforms) if should_complete_platforms?
+ @platforms = result.add_extra_platforms!(platforms) if should_add_extra_platforms?
+
+ result.complete_platforms!(platforms)
SpecSet.new(result.for(dependencies, false, @platforms))
end
@@ -621,14 +669,18 @@ module Bundler
def change_reason
if unlocking?
- unlock_reason = @unlock.reject {|_k, v| Array(v).empty? }.map do |k, v|
- if v == true
- k.to_s
- else
- v = Array(v)
- "#{k}: (#{v.join(", ")})"
- end
- end.join(", ")
+ unlock_targets = if @gems_to_unlock.any?
+ ["gems", @gems_to_unlock]
+ elsif @sources_to_unlock.any?
+ ["sources", @sources_to_unlock]
+ end
+
+ unlock_reason = if unlock_targets
+ "#{unlock_targets.first}: (#{unlock_targets.last.join(", ")})"
+ else
+ @unlock[:ruby] ? "ruby" : ""
+ end
+
return "bundler is unlocking #{unlock_reason}"
end
[
@@ -639,7 +691,8 @@ module Bundler
[@local_changes, "the gemspecs for git local gems changed"],
[@missing_lockfile_dep, "your lock file is missing \"#{@missing_lockfile_dep}\""],
[@unlocking_bundler, "an update to the version of Bundler itself was requested"],
- [@invalid_lockfile_dep, "your lock file has an invalid dependency \"#{@invalid_lockfile_dep}\""],
+ [@locked_spec_with_missing_deps, "your lock file includes \"#{@locked_spec_with_missing_deps}\" but not some of its dependencies"],
+ [@locked_spec_with_invalid_deps, "your lockfile does not satisfy dependencies of \"#{@locked_spec_with_invalid_deps}\""],
].select(&:first).map(&:last).join(", ")
end
@@ -682,7 +735,7 @@ module Bundler
spec = @dependencies.find {|s| s.name == k }
source = spec&.source
if source&.respond_to?(:local_override!)
- source.unlock! if @unlock[:gems].include?(spec.name)
+ source.unlock! if @gems_to_unlock.include?(spec.name)
locals << [source, source.local_override!(v)]
end
end
@@ -690,30 +743,29 @@ module Bundler
sources_with_changes = locals.select do |source, changed|
changed || specs_changed?(source)
end.map(&:first)
- !sources_with_changes.each {|source| @unlock[:sources] << source.name }.empty?
+ !sources_with_changes.each {|source| @sources_to_unlock << source.name }.empty?
end
def check_lockfile
- @invalid_lockfile_dep = nil
@missing_lockfile_dep = nil
- locked_names = @locked_specs.map(&:name)
+ @locked_spec_with_invalid_deps = nil
+ @locked_spec_with_missing_deps = nil
+
missing = []
invalid = []
@locked_specs.each do |s|
- s.dependencies.each do |dep|
- next if dep.name == "bundler"
+ validation = @locked_specs.validate_deps(s)
- missing << s unless locked_names.include?(dep.name)
- invalid << s if @locked_specs.none? {|spec| dep.matches_spec?(spec) }
- end
+ missing << s if validation == :missing
+ invalid << s if validation == :invalid
end
if missing.any?
@locked_specs.delete(missing)
- @missing_lockfile_dep = missing.first.name
+ @locked_spec_with_missing_deps = missing.first.name
elsif !@dependency_changes
@missing_lockfile_dep = current_dependencies.find do |d|
@locked_specs[d.name].empty? && d.name != "bundler"
@@ -723,7 +775,7 @@ module Bundler
if invalid.any?
@locked_specs.delete(invalid)
- @invalid_lockfile_dep = invalid.first.name
+ @locked_spec_with_invalid_deps = invalid.first.name
end
end
@@ -760,7 +812,7 @@ module Bundler
sources.all_sources.each do |source|
# has to be done separately, because we want to keep the locked checksum
# store for a source, even when doing a full update
- if @locked_gems && locked_source = @locked_gems.sources.find {|s| s == source && !s.equal?(source) }
+ if @locked_checksums && @locked_gems && locked_source = @locked_gems.sources.find {|s| s == source && !s.equal?(source) }
source.checksum_store.merge!(locked_source.checksum_store)
end
# If the source is unlockable and the current command allows an unlock of
@@ -768,7 +820,7 @@ module Bundler
# gem), unlock it. For git sources, this means to unlock the revision, which
# will cause the `ref` used to be the most recent for the branch (or master) if
# an explicit `ref` is not used.
- if source.respond_to?(:unlock!) && @unlock[:sources].include?(source.name)
+ if source.respond_to?(:unlock!) && @sources_to_unlock.include?(source.name)
source.unlock!
changes = true
end
@@ -785,9 +837,7 @@ module Bundler
dep.source = sources.get(dep.source)
end
- next if unlocking?
-
- unless locked_dep = @locked_deps[dep.name]
+ unless locked_dep = @originally_locked_deps[dep.name]
changes = true
next
end
@@ -814,7 +864,7 @@ module Bundler
def converge_locked_specs
converged = converge_specs(@locked_specs)
- resolve = SpecSet.new(converged.reject {|s| @unlock[:gems].include?(s.name) })
+ resolve = SpecSet.new(converged.reject {|s| @gems_to_unlock.include?(s.name) })
diff = nil
@@ -847,7 +897,7 @@ module Bundler
@specs_that_changed_sources << s if gemfile_source != lockfile_source
deps << dep if !dep.source || lockfile_source.include?(dep.source)
- @unlock[:gems] << name if lockfile_source.include?(dep.source) && lockfile_source != gemfile_source
+ @gems_to_unlock << name if lockfile_source.include?(dep.source) && lockfile_source != gemfile_source
# Replace the locked dependency's source with the equivalent source from the Gemfile
s.source = gemfile_source
@@ -856,7 +906,7 @@ module Bundler
s.source = default_source unless sources.get(lockfile_source)
end
- next if @unlock[:sources].include?(s.source.name)
+ next if @sources_to_unlock.include?(s.source.name)
# Path sources have special logic
if s.source.instance_of?(Source::Path) || s.source.instance_of?(Source::Gemspec)
@@ -878,12 +928,12 @@ module Bundler
else
# If the spec is no longer in the path source, unlock it. This
# commonly happens if the version changed in the gemspec
- @unlock[:gems] << name
+ @gems_to_unlock << name
end
end
if dep.nil? && requested_dependencies.find {|d| name == d.name }
- @unlock[:gems] << s.name
+ @gems_to_unlock << s.name
else
converged << s
end
@@ -906,11 +956,11 @@ module Bundler
source_requirements = if precompute_source_requirements_for_indirect_dependencies?
all_requirements = source_map.all_requirements
all_requirements = pin_locally_available_names(all_requirements) if @prefer_local
- { :default => default_source }.merge(all_requirements)
+ { default: default_source }.merge(all_requirements)
else
- { :default => Source::RubygemsAggregate.new(sources, source_map) }.merge(source_map.direct_requirements)
+ { default: Source::RubygemsAggregate.new(sources, source_map) }.merge(source_map.direct_requirements)
end
- source_requirements.merge!(source_map.locked_requirements) unless @remote
+ source_requirements.merge!(source_map.locked_requirements) if nothing_changed?
metadata_dependencies.each do |dep|
source_requirements[dep.name] = sources.metadata_source
end
@@ -960,7 +1010,7 @@ module Bundler
current == proposed
end
- def additional_base_requirements_for_resolve(resolution_packages, last_resolve)
+ def additional_base_requirements_to_prevent_downgrades(resolution_packages, last_resolve)
return resolution_packages unless @locked_gems && !sources.expired_sources?(@locked_gems.sources)
converge_specs(@originally_locked_specs - last_resolve).each do |locked_spec|
next if locked_spec.source.is_a?(Source::Path)
@@ -969,10 +1019,30 @@ module Bundler
resolution_packages
end
+ def additional_base_requirements_to_force_updates(resolution_packages)
+ return resolution_packages if @explicit_unlocks.empty?
+ full_update = dup_for_full_unlock.resolve
+ @explicit_unlocks.each do |name|
+ version = full_update[name].first&.version
+ resolution_packages.base_requirements[name] = Gem::Requirement.new("= #{version}") if version
+ end
+ resolution_packages
+ end
+
+ def dup_for_full_unlock
+ unlocked_definition = self.class.new(@lockfile, @dependencies, @sources, true, @ruby_version, @optional_groups, @gemfiles)
+ unlocked_definition.gem_version_promoter.tap do |gvp|
+ gvp.level = gem_version_promoter.level
+ gvp.strict = gem_version_promoter.strict
+ gvp.pre = gem_version_promoter.pre
+ end
+ unlocked_definition
+ end
+
def remove_invalid_platforms!(dependencies)
return if Bundler.frozen_bundle?
- platforms.each do |platform|
+ platforms.reverse_each do |platform|
next if local_platform == platform ||
(@new_platform && platforms.last == platform) ||
@path_changes ||
diff --git a/lib/bundler/dependency.rb b/lib/bundler/dependency.rb
index 21a4564dcc..2a4f72fe55 100644
--- a/lib/bundler/dependency.rb
+++ b/lib/bundler/dependency.rb
@@ -7,21 +7,21 @@ require_relative "rubygems_ext"
module Bundler
class Dependency < Gem::Dependency
attr_reader :autorequire
- attr_reader :groups, :platforms, :gemfile, :path, :git, :github, :branch, :ref
+ attr_reader :groups, :platforms, :gemfile, :path, :git, :github, :branch, :ref, :glob
- ALL_RUBY_VERSIONS = ((18..27).to_a + (30..33).to_a).freeze
+ ALL_RUBY_VERSIONS = (18..27).to_a.concat((30..34).to_a).freeze
PLATFORM_MAP = {
- :ruby => [Gem::Platform::RUBY, ALL_RUBY_VERSIONS],
- :mri => [Gem::Platform::RUBY, ALL_RUBY_VERSIONS],
- :rbx => [Gem::Platform::RUBY],
- :truffleruby => [Gem::Platform::RUBY],
- :jruby => [Gem::Platform::JAVA, [18, 19]],
- :windows => [Gem::Platform::WINDOWS, ALL_RUBY_VERSIONS],
+ ruby: [Gem::Platform::RUBY, ALL_RUBY_VERSIONS],
+ mri: [Gem::Platform::RUBY, ALL_RUBY_VERSIONS],
+ rbx: [Gem::Platform::RUBY],
+ truffleruby: [Gem::Platform::RUBY],
+ jruby: [Gem::Platform::JAVA, [18, 19]],
+ windows: [Gem::Platform::WINDOWS, ALL_RUBY_VERSIONS],
# deprecated
- :mswin => [Gem::Platform::MSWIN, ALL_RUBY_VERSIONS],
- :mswin64 => [Gem::Platform::MSWIN64, ALL_RUBY_VERSIONS - [18]],
- :mingw => [Gem::Platform::MINGW, ALL_RUBY_VERSIONS],
- :x64_mingw => [Gem::Platform::X64_MINGW, ALL_RUBY_VERSIONS - [18, 19]],
+ mswin: [Gem::Platform::MSWIN, ALL_RUBY_VERSIONS],
+ mswin64: [Gem::Platform::MSWIN64, ALL_RUBY_VERSIONS - [18]],
+ mingw: [Gem::Platform::MINGW, ALL_RUBY_VERSIONS],
+ x64_mingw: [Gem::Platform::X64_MINGW, ALL_RUBY_VERSIONS - [18, 19]],
}.each_with_object({}) do |(platform, spec), hash|
hash[platform] = spec[0]
spec[1]&.each {|version| hash[:"#{platform}_#{version}"] = spec[0] }
@@ -39,6 +39,7 @@ module Bundler
@github = options["github"]
@branch = options["branch"]
@ref = options["ref"]
+ @glob = options["glob"]
@platforms = Array(options["platforms"])
@env = options["env"]
@should_include = options.fetch("should_include", true)
@@ -48,10 +49,13 @@ module Bundler
@autorequire = Array(options["require"] || []) if options.key?("require")
end
+ RUBY_PLATFORM_ARRAY = [Gem::Platform::RUBY].freeze
+ private_constant :RUBY_PLATFORM_ARRAY
+
# Returns the platforms this dependency is valid for, in the same order as
# passed in the `valid_platforms` parameter
def gem_platforms(valid_platforms)
- return [Gem::Platform::RUBY] if force_ruby_platform
+ return RUBY_PLATFORM_ARRAY if force_ruby_platform
return valid_platforms if @platforms.empty?
valid_platforms.select {|p| expanded_platforms.include?(GemHelpers.generic(p)) }
@@ -65,6 +69,10 @@ module Bundler
@should_include && current_env? && current_platform?
end
+ def gemspec_dev_dep?
+ type == :development
+ end
+
def current_env?
return true unless @env
if @env.is_a?(Hash)
diff --git a/lib/bundler/digest.rb b/lib/bundler/digest.rb
index 148e9f7788..2c6d971f1b 100644
--- a/lib/bundler/digest.rb
+++ b/lib/bundler/digest.rb
@@ -50,7 +50,7 @@ module Bundler
words.map!.with_index {|word, index| SHA1_MASK & (word + mutated[index]) }
end
- words.pack("N*").unpack("H*").first
+ words.pack("N*").unpack1("H*")
end
private
diff --git a/lib/bundler/dsl.rb b/lib/bundler/dsl.rb
index db59e1a372..6af80fb31f 100644
--- a/lib/bundler/dsl.rb
+++ b/lib/bundler/dsl.rb
@@ -19,8 +19,9 @@ module Bundler
platform platforms type source install_if gemfile force_ruby_platform].freeze
GITHUB_PULL_REQUEST_URL = %r{\Ahttps://github\.com/([A-Za-z0-9_\-\.]+/[A-Za-z0-9_\-\.]+)/pull/(\d+)\z}
+ GITLAB_MERGE_REQUEST_URL = %r{\Ahttps://gitlab\.com/([A-Za-z0-9_\-\./]+)/-/merge_requests/(\d+)\z}
- attr_reader :gemspecs
+ attr_reader :gemspecs, :gemfile
attr_accessor :dependencies
def initialize
@@ -46,7 +47,7 @@ module Bundler
@gemfile = expanded_gemfile_path
@gemfiles << expanded_gemfile_path
contents ||= Bundler.read_file(@gemfile.to_s)
- instance_eval(contents, gemfile.to_s, 1)
+ instance_eval(contents, @gemfile.to_s, 1)
rescue Exception => e # rubocop:disable Lint/RescueException
message = "There was an error " \
"#{e.is_a?(GemfileEvalError) ? "evaluating" : "parsing"} " \
@@ -76,11 +77,11 @@ module Bundler
@gemspecs << spec
- gem spec.name, :name => spec.name, :path => path, :glob => glob
+ gem spec.name, name: spec.name, path: path, glob: glob
group(development_group) do
spec.development_dependencies.each do |dep|
- gem dep.name, *(dep.requirement.as_list + [:type => :development])
+ gem dep.name, *(dep.requirement.as_list + [type: :development])
end
end
when 0
@@ -105,12 +106,13 @@ module Bundler
if current.requirement != dep.requirement
current_requirement_open = current.requirements_list.include?(">= 0")
- if current.type == :development
- @dependencies.delete(current)
+ gemspec_dep = [dep, current].find(&:gemspec_dev_dep?)
+ if gemspec_dep
+ gemfile_dep = [dep, current].find(&:runtime?)
- unless current_requirement_open || dep.type == :development
- Bundler.ui.warn "A gemspec development dependency (#{dep.name}, #{current.requirement}) is being overridden by a Gemfile dependency (#{dep.name}, #{dep.requirement}).\n" \
- "This behaviour may change in the future. Please remove either of them, or make sure they both have the same requirement\n" \
+ unless current_requirement_open
+ Bundler.ui.warn "A gemspec development dependency (#{gemspec_dep.name}, #{gemspec_dep.requirement}) is being overridden by a Gemfile dependency (#{gemfile_dep.name}, #{gemfile_dep.requirement}).\n" \
+ "This behaviour may change in the future. Please remove either of them, or make sure they both have the same requirement\n"
end
else
update_prompt = ""
@@ -129,12 +131,18 @@ module Bundler
"You specified: #{current.name} (#{current.requirement}) and #{dep.name} (#{dep.requirement})" \
"#{update_prompt}"
end
+ end
+
+ # Always prefer the dependency from the Gemfile
+ if current.gemspec_dev_dep?
+ @dependencies.delete(current)
+ elsif dep.gemspec_dev_dep?
+ return
elsif current.source != dep.source
- return if dep.type == :development
raise GemfileError, "You cannot specify the same gem twice coming from different sources.\n" \
"You specified that #{dep.name} (#{dep.requirement}) should come from " \
"#{current.source || "an unspecified source"} and #{dep.source}\n"
- elsif current.type != :development && dep.type != :development
+ else
Bundler.ui.warn "Your Gemfile lists the gem #{current.name} (#{current.requirement}) more than once.\n" \
"You should probably keep only one of them.\n" \
"Remove any duplicate entries and specify the gem only once.\n" \
@@ -301,6 +309,20 @@ module Bundler
repo_name ||= user_name
"https://#{user_name}@bitbucket.org/#{user_name}/#{repo_name}.git"
end
+
+ git_source(:gitlab) do |repo_name|
+ if repo_name =~ GITLAB_MERGE_REQUEST_URL
+ {
+ "git" => "https://gitlab.com/#{$1}.git",
+ "branch" => nil,
+ "ref" => "refs/merge-requests/#{$2}/head",
+ "tag" => nil,
+ }
+ else
+ repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
+ "https://gitlab.com/#{repo_name}.git"
+ end
+ end
end
def with_source(source)
@@ -402,13 +424,11 @@ module Bundler
end
def validate_keys(command, opts, valid_keys)
- invalid_keys = opts.keys - valid_keys
-
- git_source = opts.keys & @git_sources.keys.map(&:to_s)
- if opts["branch"] && !(opts["git"] || opts["github"] || git_source.any?)
+ if opts["branch"] && !(opts["git"] || opts["github"] || (opts.keys & @git_sources.keys.map(&:to_s)).any?)
raise GemfileError, %(The `branch` option for `#{command}` is not allowed. Only gems with a git source can specify a branch)
end
+ invalid_keys = opts.keys - valid_keys
return true unless invalid_keys.any?
message = String.new
@@ -427,9 +447,13 @@ module Bundler
def normalize_source(source)
case source
when :gemcutter, :rubygems, :rubyforge
- Bundler::SharedHelpers.major_deprecation 2, "The source :#{source} is deprecated because HTTP " \
- "requests are insecure.\nPlease change your source to 'https://" \
- "rubygems.org' if possible, or 'http://rubygems.org' if not."
+ message =
+ "The source :#{source} is deprecated because HTTP requests are insecure.\n" \
+ "Please change your source to 'https://rubygems.org' if possible, or 'http://rubygems.org' if not."
+ removed_message =
+ "The source :#{source} is disallowed because HTTP requests are insecure.\n" \
+ "Please change your source to 'https://rubygems.org' if possible, or 'http://rubygems.org' if not."
+ Bundler::SharedHelpers.major_deprecation 2, message, removed_message: removed_message
"http://rubygems.org"
when String
source
@@ -474,10 +498,17 @@ module Bundler
"should come from that source"
raise GemfileEvalError, msg
else
- Bundler::SharedHelpers.major_deprecation 2, "Your Gemfile contains multiple global sources. " \
+ message =
+ "Your Gemfile contains multiple global sources. " \
"Using `source` more than once without a block is a security risk, and " \
"may result in installing unexpected gems. To resolve this warning, use " \
"a block to indicate which gems should come from the secondary source."
+ removed_message =
+ "Your Gemfile contains multiple global sources. " \
+ "Using `source` more than once without a block is a security risk, and " \
+ "may result in installing unexpected gems. To resolve this error, use " \
+ "a block to indicate which gems should come from the secondary source."
+ Bundler::SharedHelpers.major_deprecation 2, message, removed_message: removed_message
end
end
diff --git a/lib/bundler/endpoint_specification.rb b/lib/bundler/endpoint_specification.rb
index b639918f70..87cb352efa 100644
--- a/lib/bundler/endpoint_specification.rb
+++ b/lib/bundler/endpoint_specification.rb
@@ -125,7 +125,6 @@ module Bundler
next unless v
case k.to_s
when "checksum"
- next if Bundler.settings[:disable_checksum_validation]
begin
@checksum = Checksum.from_api(v.last, @spec_fetcher.uri)
rescue ArgumentError => e
diff --git a/lib/bundler/environment_preserver.rb b/lib/bundler/environment_preserver.rb
index 57013f5d50..444ab6fd37 100644
--- a/lib/bundler/environment_preserver.rb
+++ b/lib/bundler/environment_preserver.rb
@@ -19,14 +19,7 @@ module Bundler
BUNDLER_PREFIX = "BUNDLER_ORIG_"
def self.from_env
- new(env_to_hash(ENV), BUNDLER_KEYS)
- end
-
- def self.env_to_hash(env)
- to_hash = env.to_hash
- return to_hash unless Gem.win_platform?
-
- to_hash.each_with_object({}) {|(k,v), a| a[k.upcase] = v }
+ new(ENV.to_hash, BUNDLER_KEYS)
end
# @param env [Hash]
@@ -39,18 +32,7 @@ module Bundler
# Replaces `ENV` with the bundler environment variables backed up
def replace_with_backup
- unless Gem.win_platform?
- ENV.replace(backup)
- return
- end
-
- # Fallback logic for Windows below to workaround
- # https://bugs.ruby-lang.org/issues/16798. Can be dropped once all
- # supported rubies include the fix for that.
-
- ENV.clear
-
- backup.each {|k, v| ENV[k] = v }
+ ENV.replace(backup)
end
# @return [Hash]
@@ -58,9 +40,9 @@ module Bundler
env = @original.clone
@keys.each do |key|
value = env[key]
- if !value.nil? && !value.empty?
+ if !value.nil?
env[@prefix + key] ||= value
- elsif value.nil?
+ else
env[@prefix + key] ||= INTENTIONALLY_NIL
end
end
@@ -72,7 +54,7 @@ module Bundler
env = @original.clone
@keys.each do |key|
value_original = env[@prefix + key]
- next if value_original.nil? || value_original.empty?
+ next if value_original.nil?
if value_original == INTENTIONALLY_NIL
env.delete(key)
else
diff --git a/lib/bundler/errors.rb b/lib/bundler/errors.rb
index eec72b1692..c29b1bfed8 100644
--- a/lib/bundler/errors.rb
+++ b/lib/bundler/errors.rb
@@ -53,8 +53,8 @@ module Bundler
class MarshalError < StandardError; end
class ChecksumMismatchError < SecurityError
- def initialize(name_tuple, existing, checksum)
- @name_tuple = name_tuple
+ def initialize(lock_name, existing, checksum)
+ @lock_name = lock_name
@existing = existing
@checksum = checksum
end
@@ -62,9 +62,9 @@ module Bundler
def message
<<~MESSAGE
Bundler found mismatched checksums. This is a potential security risk.
- #{@name_tuple.lock_name} #{@existing.to_lock}
+ #{@lock_name} #{@existing.to_lock}
from #{@existing.sources.join("\n and ")}
- #{@name_tuple.lock_name} #{@checksum.to_lock}
+ #{@lock_name} #{@checksum.to_lock}
from #{@checksum.sources.join("\n and ")}
#{mismatch_resolution_instructions}
@@ -230,4 +230,18 @@ module Bundler
status_code(38)
end
+
+ class CorruptBundlerInstallError < BundlerError
+ def initialize(loaded_spec)
+ @loaded_spec = loaded_spec
+ end
+
+ def message
+ "The running version of Bundler (#{Bundler::VERSION}) does not match the version of the specification installed for it (#{@loaded_spec.version}). " \
+ "This can be caused by reinstalling Ruby without removing previous installation, leaving around an upgraded default version of Bundler. " \
+ "Reinstalling Ruby from scratch should fix the problem."
+ end
+
+ status_code(39)
+ end
end
diff --git a/lib/bundler/fetcher.rb b/lib/bundler/fetcher.rb
index e5384c5679..6288b22dcd 100644
--- a/lib/bundler/fetcher.rb
+++ b/lib/bundler/fetcher.rb
@@ -1,10 +1,10 @@
# frozen_string_literal: true
require_relative "vendored_persistent"
+require_relative "vendored_timeout"
require "cgi"
require "securerandom"
require "zlib"
-require "rubygems/request"
module Bundler
# Handles all the fetching with the rubygems server
@@ -83,7 +83,7 @@ module Bundler
FAIL_ERRORS = begin
fail_errors = [AuthenticationRequiredError, BadAuthenticationError, AuthenticationForbiddenError, FallbackError, SecurityError]
fail_errors << Gem::Requirement::BadRequirementError
- fail_errors.concat(NET_ERRORS.map {|e| Net.const_get(e) })
+ fail_errors.concat(NET_ERRORS.map {|e| Gem::Net.const_get(e) })
end.freeze
class << self
@@ -95,6 +95,7 @@ module Bundler
self.max_retries = Bundler.settings[:retry] # How many retries for the API call
def initialize(remote)
+ @cis = nil
@remote = remote
Socket.do_not_reverse_lookup = true
@@ -110,9 +111,9 @@ module Bundler
spec -= [nil, "ruby", ""]
spec_file_name = "#{spec.join "-"}.gemspec"
- uri = Bundler::URI.parse("#{remote_uri}#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}.rz")
+ uri = Gem::URI.parse("#{remote_uri}#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}.rz")
spec = if uri.scheme == "file"
- path = Bundler.rubygems.correct_for_windows_path(uri.path)
+ path = Gem::Util.correct_for_windows_path(uri.path)
Bundler.safe_load_marshal Bundler.rubygems.inflate(Gem.read_binary(path))
elsif cached_spec_path = gemspec_cached_path(spec_file_name)
Bundler.load_gemspec(cached_spec_path)
@@ -204,6 +205,16 @@ module Bundler
fetchers.first.api_fetcher?
end
+ def gem_remote_fetcher
+ @gem_remote_fetcher ||= begin
+ require_relative "fetcher/gem_remote_fetcher"
+ fetcher = GemRemoteFetcher.new Gem.configuration[:http_proxy]
+ fetcher.headers["User-Agent"] = user_agent
+ fetcher.headers["X-Gemfile-Source"] = @remote.original_uri.to_s if @remote.original_uri
+ fetcher
+ end
+ end
+
private
def available_fetchers
@@ -218,7 +229,7 @@ module Bundler
end
def fetchers
- @fetchers ||= available_fetchers.map {|f| f.new(downloader, @remote, uri) }.drop_while {|f| !f.available? }
+ @fetchers ||= available_fetchers.map {|f| f.new(downloader, @remote, uri, gem_remote_fetcher) }.drop_while {|f| !f.available? }
end
def fetch_specs(gem_names)
@@ -232,20 +243,7 @@ module Bundler
end
def cis
- env_cis = {
- "TRAVIS" => "travis",
- "CIRCLECI" => "circle",
- "SEMAPHORE" => "semaphore",
- "JENKINS_URL" => "jenkins",
- "BUILDBOX" => "buildbox",
- "GO_SERVER_URL" => "go",
- "SNAP_CI" => "snap",
- "GITLAB_CI" => "gitlab",
- "GITHUB_ACTIONS" => "github",
- "CI_NAME" => ENV["CI_NAME"],
- "CI" => "ci",
- }
- env_cis.find_all {|env, _| ENV[env] }.map {|_, ci| ci }
+ @cis ||= Bundler::CIDetector.ci_strings
end
def connection
@@ -255,9 +253,9 @@ module Bundler
Bundler.settings[:ssl_client_cert]
raise SSLError if needs_ssl && !defined?(OpenSSL::SSL)
- con = PersistentHTTP.new :name => "bundler", :proxy => :ENV
+ con = Gem::Net::HTTP::Persistent.new name: "bundler", proxy: :ENV
if gem_proxy = Gem.configuration[:http_proxy]
- con.proxy = Bundler::URI.parse(gem_proxy) if gem_proxy != :no_proxy
+ con.proxy = Gem::URI.parse(gem_proxy) if gem_proxy != :no_proxy
end
if remote_uri.scheme == "https"
@@ -290,10 +288,10 @@ module Bundler
end
HTTP_ERRORS = [
- Timeout::Error, EOFError, SocketError, Errno::ENETDOWN, Errno::ENETUNREACH,
+ Gem::Timeout::Error, EOFError, SocketError, Errno::ENETDOWN, Errno::ENETUNREACH,
Errno::EINVAL, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::EAGAIN,
- Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError,
- PersistentHTTP::Error, Zlib::BufError, Errno::EHOSTUNREACH
+ Gem::Net::HTTPBadResponse, Gem::Net::HTTPHeaderSyntaxError, Gem::Net::ProtocolError,
+ Gem::Net::HTTP::Persistent::Error, Zlib::BufError, Errno::EHOSTUNREACH
].freeze
def bundler_cert_store
@@ -309,6 +307,7 @@ module Bundler
end
else
store.set_default_paths
+ require "rubygems/request"
Gem::Request.get_cert_files.each {|c| store.add_file c }
end
store
diff --git a/lib/bundler/fetcher/base.rb b/lib/bundler/fetcher/base.rb
index 99c6343c9a..cfec2f8e94 100644
--- a/lib/bundler/fetcher/base.rb
+++ b/lib/bundler/fetcher/base.rb
@@ -6,12 +6,14 @@ module Bundler
attr_reader :downloader
attr_reader :display_uri
attr_reader :remote
+ attr_reader :gem_remote_fetcher
- def initialize(downloader, remote, display_uri)
+ def initialize(downloader, remote, display_uri, gem_remote_fetcher)
raise "Abstract class" if self.class == Base
@downloader = downloader
@remote = remote
@display_uri = display_uri
+ @gem_remote_fetcher = gem_remote_fetcher
end
def remote_uri
diff --git a/lib/bundler/fetcher/compact_index.rb b/lib/bundler/fetcher/compact_index.rb
index dc30443e27..6e5656d26a 100644
--- a/lib/bundler/fetcher/compact_index.rb
+++ b/lib/bundler/fetcher/compact_index.rb
@@ -4,8 +4,6 @@ require_relative "base"
require_relative "../worker"
module Bundler
- autoload :CompactIndexClient, File.expand_path("../compact_index_client", __dir__)
-
class Fetcher
class CompactIndex < Base
def self.compact_index_request(method_name)
@@ -13,7 +11,7 @@ module Bundler
undef_method(method_name)
define_method(method_name) do |*args, &blk|
method.bind(self).call(*args, &blk)
- rescue NetworkDownError, CompactIndexClient::Updater::MisMatchedChecksumError => e
+ rescue NetworkDownError, CompactIndexClient::Updater::MismatchedChecksumError => e
raise HTTPError, e.message
rescue AuthenticationRequiredError, BadAuthenticationError
# Fail since we got a 401 from the server.
@@ -36,15 +34,8 @@ module Bundler
until remaining_gems.empty?
log_specs { "Looking up gems #{remaining_gems.inspect}" }
-
- deps = begin
- parallel_compact_index_client.dependencies(remaining_gems)
- rescue TooManyRequestsError
- @bundle_worker&.stop
- @bundle_worker = nil # reset it. Not sure if necessary
- serial_compact_index_client.dependencies(remaining_gems)
- end
- next_gems = deps.flat_map {|d| d[3].flat_map(&:first) }.uniq
+ deps = fetch_gem_infos(remaining_gems).flatten(1)
+ next_gems = deps.flat_map {|d| d[CompactIndexClient::INFO_DEPS].flat_map(&:first) }.uniq
deps.each {|dep| gem_info << dep }
complete_gems.concat(deps.map(&:first)).uniq!
remaining_gems = next_gems - complete_gems
@@ -61,8 +52,8 @@ module Bundler
return nil
end
# Read info file checksums out of /versions, so we can know if gems are up to date
- compact_index_client.update_and_parse_checksums!
- rescue CompactIndexClient::Updater::MisMatchedChecksumError => e
+ compact_index_client.available?
+ rescue CompactIndexClient::Updater::MismatchedChecksumError => e
Bundler.ui.debug(e.message)
nil
end
@@ -81,20 +72,20 @@ module Bundler
end
end
- def parallel_compact_index_client
- compact_index_client.execution_mode = lambda do |inputs, &blk|
- func = lambda {|object, _index| blk.call(object) }
- worker = bundle_worker(func)
- inputs.each {|input| worker.enq(input) }
- inputs.map { worker.deq }
- end
-
- compact_index_client
+ def fetch_gem_infos(names)
+ in_parallel(names) {|name| compact_index_client.info(name) }
+ rescue TooManyRequestsError # rubygems.org is rate limiting us, slow down.
+ @bundle_worker&.stop
+ @bundle_worker = nil # reset it. Not sure if necessary
+ compact_index_client.reset!
+ names.map {|name| compact_index_client.info(name) }
end
- def serial_compact_index_client
- compact_index_client.sequential_execution_mode!
- compact_index_client
+ def in_parallel(inputs, &blk)
+ func = lambda {|object, _index| blk.call(object) }
+ worker = bundle_worker(func)
+ inputs.each {|input| worker.enq(input) }
+ inputs.map { worker.deq }
end
def bundle_worker(func = nil)
@@ -121,7 +112,7 @@ module Bundler
rescue NetworkDownError => e
raise unless Bundler.feature_flag.allow_offline_install? && headers["If-None-Match"]
ui.warn "Using the cached data for the new index because of a network error: #{e}"
- Net::HTTPNotModified.new(nil, nil, nil)
+ Gem::Net::HTTPNotModified.new(nil, nil, nil)
end
end
end
diff --git a/lib/bundler/fetcher/downloader.rb b/lib/bundler/fetcher/downloader.rb
index 3062899e0e..868b39b959 100644
--- a/lib/bundler/fetcher/downloader.rb
+++ b/lib/bundler/fetcher/downloader.rb
@@ -20,33 +20,35 @@ module Bundler
Bundler.ui.debug("HTTP #{response.code} #{response.message} #{filtered_uri}")
case response
- when Net::HTTPSuccess, Net::HTTPNotModified
+ when Gem::Net::HTTPSuccess, Gem::Net::HTTPNotModified
response
- when Net::HTTPRedirection
- new_uri = Bundler::URI.parse(response["location"])
+ when Gem::Net::HTTPRedirection
+ new_uri = Gem::URI.parse(response["location"])
if new_uri.host == uri.host
new_uri.user = uri.user
new_uri.password = uri.password
end
fetch(new_uri, headers, counter + 1)
- when Net::HTTPRequestedRangeNotSatisfiable
+ when Gem::Net::HTTPRequestedRangeNotSatisfiable
new_headers = headers.dup
new_headers.delete("Range")
new_headers["Accept-Encoding"] = "gzip"
fetch(uri, new_headers)
- when Net::HTTPRequestEntityTooLarge
+ when Gem::Net::HTTPRequestEntityTooLarge
raise FallbackError, response.body
- when Net::HTTPTooManyRequests
+ when Gem::Net::HTTPTooManyRequests
raise TooManyRequestsError, response.body
- when Net::HTTPUnauthorized
+ when Gem::Net::HTTPUnauthorized
raise BadAuthenticationError, uri.host if uri.userinfo
raise AuthenticationRequiredError, uri.host
- when Net::HTTPForbidden
+ when Gem::Net::HTTPForbidden
raise AuthenticationForbiddenError, uri.host
- when Net::HTTPNotFound
- raise FallbackError, "Net::HTTPNotFound: #{filtered_uri}"
+ when Gem::Net::HTTPNotFound
+ raise FallbackError, "Gem::Net::HTTPNotFound: #{filtered_uri}"
else
- raise HTTPError, "#{response.class}#{": #{response.body}" unless response.body.empty?}"
+ message = "Gem::#{response.class.name.gsub(/\AGem::/, "")}"
+ message += ": #{response.body}" unless response.body.empty?
+ raise HTTPError, message
end
end
@@ -56,7 +58,7 @@ module Bundler
filtered_uri = URICredentialsFilter.credential_filtered_uri(uri)
Bundler.ui.debug "HTTP GET #{filtered_uri}"
- req = Net::HTTP::Get.new uri.request_uri, headers
+ req = Gem::Net::HTTP::Get.new uri.request_uri, headers
if uri.user
user = CGI.unescape(uri.user)
password = uri.password ? CGI.unescape(uri.password) : nil
diff --git a/lib/bundler/fetcher/gem_remote_fetcher.rb b/lib/bundler/fetcher/gem_remote_fetcher.rb
new file mode 100644
index 0000000000..3fc7b68263
--- /dev/null
+++ b/lib/bundler/fetcher/gem_remote_fetcher.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require "rubygems/remote_fetcher"
+
+module Bundler
+ class Fetcher
+ class GemRemoteFetcher < Gem::RemoteFetcher
+ def request(*args)
+ super do |req|
+ req.delete("User-Agent") if headers["User-Agent"]
+ yield req if block_given?
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bundler/fetcher/index.rb b/lib/bundler/fetcher/index.rb
index c623647f01..6e37e1e5d1 100644
--- a/lib/bundler/fetcher/index.rb
+++ b/lib/bundler/fetcher/index.rb
@@ -6,7 +6,7 @@ module Bundler
class Fetcher
class Index < Base
def specs(_gem_names)
- Bundler.rubygems.fetch_all_remote_specs(remote)
+ Bundler.rubygems.fetch_all_remote_specs(remote, gem_remote_fetcher)
rescue Gem::RemoteFetcher::FetchError => e
case e.message
when /certificate verify failed/
diff --git a/lib/bundler/friendly_errors.rb b/lib/bundler/friendly_errors.rb
index b66a046d37..e61ed64450 100644
--- a/lib/bundler/friendly_errors.rb
+++ b/lib/bundler/friendly_errors.rb
@@ -32,7 +32,7 @@ module Bundler
if Bundler.ui.debug?
Bundler.ui.trace error
else
- Bundler.ui.error error.message, :wrap => true
+ Bundler.ui.error error.message, wrap: true
end
when Thor::Error
Bundler.ui.error error.message
@@ -40,7 +40,7 @@ module Bundler
Bundler.ui.error "\nQuitting..."
Bundler.ui.trace error
when Gem::InvalidSpecificationException
- Bundler.ui.error error.message, :wrap => true
+ Bundler.ui.error error.message, wrap: true
when SystemExit
when *[defined?(Java::JavaLang::OutOfMemoryError) && Java::JavaLang::OutOfMemoryError].compact
Bundler.ui.error "\nYour JVM has run out of memory, and Bundler cannot continue. " \
diff --git a/lib/bundler/gem_helper.rb b/lib/bundler/gem_helper.rb
index dcf759cded..5ce0ef6280 100644
--- a/lib/bundler/gem_helper.rb
+++ b/lib/bundler/gem_helper.rb
@@ -47,7 +47,7 @@ module Bundler
built_gem_path = build_gem
end
- desc "Generate SHA512 checksum if #{name}-#{version}.gem into the checksums directory."
+ desc "Generate SHA512 checksum of #{name}-#{version}.gem into the checksums directory."
task "build:checksum" => "build" do
build_checksum(built_gem_path)
end
@@ -215,7 +215,7 @@ module Bundler
def sh_with_status(cmd, &block)
Bundler.ui.debug(cmd)
SharedHelpers.chdir(base) do
- outbuf = IO.popen(cmd, :err => [:child, :out], &:read)
+ outbuf = IO.popen(cmd, err: [:child, :out], &:read)
status = $?
block&.call(outbuf) if status.success?
[outbuf, status]
diff --git a/lib/bundler/gem_version_promoter.rb b/lib/bundler/gem_version_promoter.rb
index c7eacd1930..ecc65b4956 100644
--- a/lib/bundler/gem_version_promoter.rb
+++ b/lib/bundler/gem_version_promoter.rb
@@ -45,17 +45,37 @@ module Bundler
# Given a Resolver::Package and an Array of Specifications of available
# versions for a gem, this method will return the Array of Specifications
- # sorted (and possibly truncated if strict is true) in an order to give
- # preference to the current level (:major, :minor or :patch) when resolution
- # is deciding what versions best resolve all dependencies in the bundle.
+ # sorted in an order to give preference to the current level (:major, :minor
+ # or :patch) when resolution is deciding what versions best resolve all
+ # dependencies in the bundle.
# @param package [Resolver::Package] The package being resolved.
# @param specs [Specification] An array of Specifications for the package.
- # @return [Specification] A new instance of the Specification Array sorted and
- # possibly filtered.
+ # @return [Specification] A new instance of the Specification Array sorted.
def sort_versions(package, specs)
- specs = filter_dep_specs(specs, package) if strict
+ locked_version = package.locked_version
- sort_dep_specs(specs, package)
+ result = specs.sort do |a, b|
+ unless package.prerelease_specified? || pre?
+ a_pre = a.prerelease?
+ b_pre = b.prerelease?
+
+ next 1 if a_pre && !b_pre
+ next -1 if b_pre && !a_pre
+ end
+
+ if major? || locked_version.nil?
+ b <=> a
+ elsif either_version_older_than_locked?(a, b, locked_version)
+ b <=> a
+ elsif segments_do_not_match?(a, b, :major)
+ a <=> b
+ elsif !minor? && segments_do_not_match?(a, b, :minor)
+ a <=> b
+ else
+ b <=> a
+ end
+ end
+ post_sort(result, package.unlock?, locked_version)
end
# @return [bool] Convenience method for testing value of level variable.
@@ -73,9 +93,18 @@ module Bundler
pre == true
end
- private
+ # Given a Resolver::Package and an Array of Specifications of available
+ # versions for a gem, this method will truncate the Array if strict
+ # is true. That means filtering out downgrades from the version currently
+ # locked, and filtering out upgrades that go past the selected level (major,
+ # minor, or patch).
+ # @param package [Resolver::Package] The package being resolved.
+ # @param specs [Specification] An array of Specifications for the package.
+ # @return [Specification] A new instance of the Specification Array
+ # truncated.
+ def filter_versions(package, specs)
+ return specs unless strict
- def filter_dep_specs(specs, package)
locked_version = package.locked_version
return specs if locked_version.nil? || major?
@@ -89,32 +118,7 @@ module Bundler
end
end
- def sort_dep_specs(specs, package)
- locked_version = package.locked_version
-
- result = specs.sort do |a, b|
- unless package.prerelease_specified? || pre?
- a_pre = a.prerelease?
- b_pre = b.prerelease?
-
- next -1 if a_pre && !b_pre
- next 1 if b_pre && !a_pre
- end
-
- if major? || locked_version.nil?
- a <=> b
- elsif either_version_older_than_locked?(a, b, locked_version)
- a <=> b
- elsif segments_do_not_match?(a, b, :major)
- b <=> a
- elsif !minor? && segments_do_not_match?(a, b, :minor)
- b <=> a
- else
- a <=> b
- end
- end
- post_sort(result, package.unlock?, locked_version)
- end
+ private
def either_version_older_than_locked?(a, b, locked_version)
a.version < locked_version || b.version < locked_version
@@ -133,13 +137,13 @@ module Bundler
if unlock || locked_version.nil?
result
else
- move_version_to_end(result, locked_version)
+ move_version_to_beginning(result, locked_version)
end
end
- def move_version_to_end(result, version)
+ def move_version_to_beginning(result, version)
move, keep = result.partition {|s| s.version.to_s == version.to_s }
- keep.concat(move)
+ move.concat(keep)
end
end
end
diff --git a/lib/bundler/graph.rb b/lib/bundler/graph.rb
index 3c008e63e3..b22b17a453 100644
--- a/lib/bundler/graph.rb
+++ b/lib/bundler/graph.rb
@@ -84,7 +84,7 @@ module Bundler
else
raise ArgumentError, "2nd argument is invalid"
end
- label.nil? ? {} : { :label => label }
+ label.nil? ? {} : { label: label }
end
def spec_for_dependency(dependency)
@@ -103,7 +103,7 @@ module Bundler
end
def g
- @g ||= ::GraphViz.digraph(@graph_name, :concentrate => true, :normalize => true, :nodesep => 0.55) do |g|
+ @g ||= ::GraphViz.digraph(@graph_name, concentrate: true, normalize: true, nodesep: 0.55) do |g|
g.edge[:weight] = 2
g.edge[:fontname] = g.node[:fontname] = "Arial, Helvetica, SansSerif"
g.edge[:fontsize] = 12
@@ -114,10 +114,10 @@ module Bundler
@groups.each do |group|
g.add_nodes(
group, {
- :style => "filled",
- :fillcolor => "#B9B9D5",
- :shape => "box3d",
- :fontsize => 16,
+ style: "filled",
+ fillcolor: "#B9B9D5",
+ shape: "box3d",
+ fontsize: 16,
}.merge(@node_options[group])
)
end
@@ -125,8 +125,8 @@ module Bundler
@relations.each do |parent, children|
children.each do |child|
if @groups.include?(parent)
- g.add_nodes(child, { :style => "filled", :fillcolor => "#B9B9D5" }.merge(@node_options[child]))
- g.add_edges(parent, child, { :constraint => false }.merge(@edge_options["#{parent}_#{child}"]))
+ g.add_nodes(child, { style: "filled", fillcolor: "#B9B9D5" }.merge(@node_options[child]))
+ g.add_edges(parent, child, { constraint: false }.merge(@edge_options["#{parent}_#{child}"]))
else
g.add_nodes(child, @node_options[child])
g.add_edges(parent, child, @edge_options["#{parent}_#{child}"])
@@ -135,7 +135,7 @@ module Bundler
end
if @output_format.to_s == "debug"
- $stdout.puts g.output :none => String
+ $stdout.puts g.output none: String
Bundler.ui.info "debugging bundle viz..."
else
begin
diff --git a/lib/bundler/injector.rb b/lib/bundler/injector.rb
index a738992068..879b481339 100644
--- a/lib/bundler/injector.rb
+++ b/lib/bundler/injector.rb
@@ -29,7 +29,7 @@ module Bundler
end
# temporarily unfreeze
- Bundler.settings.temporary(:deployment => false, :frozen => false) do
+ Bundler.settings.temporary(deployment: false, frozen: false) do
# evaluate the Gemfile we have now
builder = Dsl.new
builder.eval_gemfile(gemfile_path)
@@ -50,7 +50,7 @@ module Bundler
append_to(gemfile_path, build_gem_lines(@options[:conservative_versioning])) if @deps.any?
# since we resolved successfully, write out the lockfile
- @definition.lock(Bundler.default_lockfile)
+ @definition.lock
# invalidate the cached Bundler.definition
Bundler.reset_paths!
@@ -120,9 +120,10 @@ module Bundler
github = ", :github => \"#{d.github}\"" unless d.github.nil?
branch = ", :branch => \"#{d.branch}\"" unless d.branch.nil?
ref = ", :ref => \"#{d.ref}\"" unless d.ref.nil?
+ glob = ", :glob => \"#{d.glob}\"" unless d.glob.nil?
require_path = ", :require => #{convert_autorequire(d.autorequire)}" unless d.autorequire.nil?
- %(gem #{name}#{requirement}#{group}#{source}#{path}#{git}#{github}#{branch}#{ref}#{require_path})
+ %(gem #{name}#{requirement}#{group}#{source}#{path}#{git}#{github}#{branch}#{ref}#{glob}#{require_path})
end.join("\n")
end
diff --git a/lib/bundler/inline.rb b/lib/bundler/inline.rb
index 5c184f67a1..ae4ccf2138 100644
--- a/lib/bundler/inline.rb
+++ b/lib/bundler/inline.rb
@@ -48,14 +48,14 @@ def gemfile(install = false, options = {}, &gemfile)
builder.instance_eval(&gemfile)
builder.check_primary_source_safety
- Bundler.settings.temporary(:deployment => false, :frozen => false) do
+ Bundler.settings.temporary(deployment: false, frozen: false) do
definition = builder.to_definition(nil, true)
def definition.lock(*); end
definition.validate_runtime!
if install || definition.missing_specs?
- Bundler.settings.temporary(:inline => true, :no_install => false) do
- installer = Bundler::Installer.install(Bundler.root, definition, :system => true)
+ Bundler.settings.temporary(inline: true, no_install: false) do
+ installer = Bundler::Installer.install(Bundler.root, definition, system: true)
installer.post_install_messages.each do |name, message|
Bundler.ui.info "Post-install message from #{name}:\n#{message}"
end
diff --git a/lib/bundler/installer.rb b/lib/bundler/installer.rb
index 59b6a6ad22..256f0be348 100644
--- a/lib/bundler/installer.rb
+++ b/lib/bundler/installer.rb
@@ -81,7 +81,7 @@ module Bundler
if resolve_if_needed(options)
ensure_specs_are_compatible!
- load_plugins
+ Bundler.load_plugins(@definition)
options.delete(:jobs)
else
options[:jobs] = 1 # to avoid the overhead of Bundler::Worker
@@ -136,12 +136,12 @@ module Bundler
mode = Gem.win_platform? ? "wb:UTF-8" : "w"
require "erb"
- content = ERB.new(template, :trim_mode => "-").result(binding)
+ content = ERB.new(template, trim_mode: "-").result(binding)
- File.write(binstub_path, content, :mode => mode, :perm => 0o777 & ~File.umask)
+ File.write(binstub_path, content, mode: mode, perm: 0o777 & ~File.umask)
if Gem.win_platform? || options[:all_platforms]
prefix = "@ruby -x \"%~f0\" %*\n@exit /b %ERRORLEVEL%\n\n"
- File.write("#{binstub_path}.cmd", prefix + content, :mode => mode)
+ File.write("#{binstub_path}.cmd", prefix + content, mode: mode)
end
end
@@ -179,12 +179,12 @@ module Bundler
mode = Gem.win_platform? ? "wb:UTF-8" : "w"
require "erb"
- content = ERB.new(template, :trim_mode => "-").result(binding)
+ content = ERB.new(template, trim_mode: "-").result(binding)
- File.write("#{bin_path}/#{executable}", content, :mode => mode, :perm => 0o755)
+ File.write("#{bin_path}/#{executable}", content, mode: mode, perm: 0o755)
if Gem.win_platform? || options[:all_platforms]
prefix = "@ruby -x \"%~f0\" %*\n@exit /b %ERRORLEVEL%\n\n"
- File.write("#{bin_path}/#{executable}.cmd", prefix + content, :mode => mode)
+ File.write("#{bin_path}/#{executable}.cmd", prefix + content, mode: mode)
end
end
end
@@ -213,20 +213,6 @@ module Bundler
Bundler.settings.processor_count
end
- def load_plugins
- Bundler.rubygems.load_plugins
-
- requested_path_gems = @definition.requested_specs.select {|s| s.source.is_a?(Source::Path) }
- path_plugin_files = requested_path_gems.map do |spec|
- Bundler.rubygems.spec_matches_for_glob(spec, "rubygems_plugin#{Bundler.rubygems.suffix_pattern}")
- rescue TypeError
- error_message = "#{spec.name} #{spec.version} has an invalid gemspec"
- raise Gem::InvalidSpecificationException, error_message
- end.flatten
- Bundler.rubygems.load_plugin_files(path_plugin_files)
- Bundler.rubygems.load_env_plugins
- end
-
def ensure_specs_are_compatible!
@definition.specs.each do |spec|
unless spec.matches_current_ruby?
@@ -249,19 +235,19 @@ module Bundler
# returns whether or not a re-resolve was needed
def resolve_if_needed(options)
- @definition.resolution_mode = options
-
- if !@definition.unlocking? && !options["force"] && !Bundler.settings[:inline] && Bundler.default_lockfile.file?
- return false if @definition.nothing_changed? && !@definition.missing_specs?
+ @definition.prefer_local! if options["prefer-local"]
+
+ if options["local"] || (@definition.no_resolve_needed? && !@definition.missing_specs?)
+ @definition.resolve_with_cache!
+ false
+ else
+ @definition.resolve_remotely!
+ true
end
-
- @definition.setup_sources_for_resolve
-
- true
end
- def lock(opts = {})
- @definition.lock(Bundler.default_lockfile, opts[:preserve_unknown_sections])
+ def lock
+ @definition.lock
end
end
end
diff --git a/lib/bundler/installer/gem_installer.rb b/lib/bundler/installer/gem_installer.rb
index b6065c24d0..a7770eb7e0 100644
--- a/lib/bundler/installer/gem_installer.rb
+++ b/lib/bundler/installer/gem_installer.rb
@@ -53,10 +53,9 @@ module Bundler
def install
spec.source.install(
spec,
- :force => force,
- :ensure_builtin_gems_cached => standalone,
- :build_args => Array(spec_settings),
- :previous_spec => previous_spec,
+ force: force,
+ build_args: Array(spec_settings),
+ previous_spec: previous_spec,
)
end
@@ -77,7 +76,7 @@ module Bundler
if Bundler.settings[:bin] && standalone
installer.generate_standalone_bundler_executable_stubs(spec)
elsif Bundler.settings[:bin]
- installer.generate_bundler_executable_stubs(spec, :force => true)
+ installer.generate_bundler_executable_stubs(spec, force: true)
end
end
end
diff --git a/lib/bundler/installer/parallel_installer.rb b/lib/bundler/installer/parallel_installer.rb
index 11a90b36cb..e745088f81 100644
--- a/lib/bundler/installer/parallel_installer.rb
+++ b/lib/bundler/installer/parallel_installer.rb
@@ -42,8 +42,7 @@ module Bundler
# Checks installed dependencies against spec's dependencies to make
# sure needed dependencies have been installed.
- def dependencies_installed?(all_specs)
- installed_specs = all_specs.select(&:installed?).map(&:name)
+ def dependencies_installed?(installed_specs)
dependencies.all? {|d| installed_specs.include? d.name }
end
@@ -63,20 +62,23 @@ module Bundler
end
end
- def self.call(*args)
- new(*args).call
+ def self.call(*args, **kwargs)
+ new(*args, **kwargs).call
end
attr_reader :size
- def initialize(installer, all_specs, size, standalone, force)
+ def initialize(installer, all_specs, size, standalone, force, skip: nil)
@installer = installer
@size = size
@standalone = standalone
@force = force
@specs = all_specs.map {|s| SpecInstallation.new(s) }
+ @specs.each do |spec_install|
+ spec_install.state = :installed if skip.include?(spec_install.name)
+ end if skip
@spec_set = all_specs
- @rake = @specs.find {|s| s.name == "rake" }
+ @rake = @specs.find {|s| s.name == "rake" unless s.installed? }
end
def call
@@ -183,8 +185,14 @@ module Bundler
# previously installed specifications. We continue until all specs
# are installed.
def enqueue_specs
- @specs.select(&:ready_to_enqueue?).each do |spec|
- if spec.dependencies_installed? @specs
+ installed_specs = {}
+ @specs.each do |spec|
+ next unless spec.installed?
+ installed_specs[spec.name] = true
+ end
+
+ @specs.each do |spec|
+ if spec.ready_to_enqueue? && spec.dependencies_installed?(installed_specs)
spec.state = :enqueued
worker_pool.enq spec
end
diff --git a/lib/bundler/installer/standalone.rb b/lib/bundler/installer/standalone.rb
index 2cdada44d6..5331df2e95 100644
--- a/lib/bundler/installer/standalone.rb
+++ b/lib/bundler/installer/standalone.rb
@@ -56,7 +56,7 @@ module Bundler
if spec.source.instance_of?(Source::Path) && spec.source.path.absolute?
full_path
else
- SharedHelpers.relative_path_to(full_path, :from => Bundler.root.join(bundler_path))
+ SharedHelpers.relative_path_to(full_path, from: Bundler.root.join(bundler_path))
end
rescue TypeError
error_message = "#{spec.name} #{spec.version} has an invalid gemspec"
diff --git a/lib/bundler/lazy_specification.rb b/lib/bundler/lazy_specification.rb
index fdd3efb443..8669e021c2 100644
--- a/lib/bundler/lazy_specification.rb
+++ b/lib/bundler/lazy_specification.rb
@@ -4,12 +4,15 @@ require_relative "force_platform"
module Bundler
class LazySpecification
+ include MatchMetadata
include MatchPlatform
include ForcePlatform
attr_reader :name, :version, :platform
attr_accessor :source, :remote, :force_ruby_platform, :dependencies, :required_ruby_version, :required_rubygems_version
+ alias_method :runtime_dependencies, :dependencies
+
def self.from_spec(s)
lazy_spec = new(s.name, s.version, s.platform, s.source)
lazy_spec.dependencies = s.dependencies
@@ -102,7 +105,7 @@ module Bundler
installable_candidates = GemHelpers.select_best_platform_match(matching_specs, target_platform)
- specification = __materialize__(installable_candidates, :fallback_to_non_installable => false)
+ specification = __materialize__(installable_candidates, fallback_to_non_installable: false)
return specification unless specification.nil?
if target_platform != platform
@@ -122,9 +125,7 @@ module Bundler
# bad gem.
def __materialize__(candidates, fallback_to_non_installable: Bundler.frozen_bundle?)
search = candidates.reverse.find do |spec|
- spec.is_a?(StubSpecification) ||
- (spec.matches_current_ruby? &&
- spec.matches_current_rubygems?)
+ spec.is_a?(StubSpecification) || spec.matches_current_metadata?
end
if search.nil? && fallback_to_non_installable
search = candidates.last
diff --git a/lib/bundler/lockfile_generator.rb b/lib/bundler/lockfile_generator.rb
index 4d2a968d7e..a646d00ee1 100644
--- a/lib/bundler/lockfile_generator.rb
+++ b/lib/bundler/lockfile_generator.rb
@@ -67,6 +67,7 @@ module Bundler
end
def add_checksums
+ return unless definition.locked_checksums
checksums = definition.resolve.map do |spec|
spec.source.checksum_store.to_lock(spec)
end
diff --git a/lib/bundler/lockfile_parser.rb b/lib/bundler/lockfile_parser.rb
index 942f051052..1e11621e55 100644
--- a/lib/bundler/lockfile_parser.rb
+++ b/lib/bundler/lockfile_parser.rb
@@ -24,7 +24,15 @@ module Bundler
end
end
- attr_reader :sources, :dependencies, :specs, :platforms, :bundler_version, :ruby_version, :checksums
+ attr_reader(
+ :sources,
+ :dependencies,
+ :specs,
+ :platforms,
+ :bundler_version,
+ :ruby_version,
+ :checksums,
+ )
BUNDLED = "BUNDLED WITH"
DEPENDENCIES = "DEPENDENCIES"
@@ -111,6 +119,9 @@ module Bundler
elsif line == DEPENDENCIES
@parse_method = :parse_dependency
elsif line == CHECKSUMS
+ # This is a temporary solution to make this feature disabled by default
+ # for all gemfiles that don't already explicitly include the feature.
+ @checksums = true
@parse_method = :parse_checksum
elsif line == PLATFORMS
@parse_method = :parse_platform
@@ -228,8 +239,6 @@ module Bundler
version = Gem::Version.new(version)
platform = platform ? Gem::Platform.new(platform) : Gem::Platform::RUBY
full_name = Gem::NameTuple.new(name, version, platform).full_name
- # Don't raise exception if there's a checksum for a gem that's not in the lockfile,
- # we prefer to heal invalid lockfiles
return unless spec = @specs[full_name]
checksums.split(",") do |lock_checksum|
diff --git a/lib/bundler/man/bundle-add.1 b/lib/bundler/man/bundle-add.1
index 17f03fc290..56a3b6f85c 100644
--- a/lib/bundler/man/bundle-add.1
+++ b/lib/bundler/man/bundle-add.1
@@ -1,81 +1,58 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-ADD" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-ADD" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install
-.
.SH "SYNOPSIS"
\fBbundle add\fR \fIGEM_NAME\fR [\-\-group=GROUP] [\-\-version=VERSION] [\-\-source=SOURCE] [\-\-path=PATH] [\-\-git=GIT] [\-\-github=GITHUB] [\-\-branch=BRANCH] [\-\-ref=REF] [\-\-skip\-install] [\-\-strict] [\-\-optimistic]
-.
.SH "DESCRIPTION"
Adds the named gem to the Gemfile and run \fBbundle install\fR\. \fBbundle install\fR can be avoided by using the flag \fB\-\-skip\-install\fR\.
-.
.P
Example:
-.
.P
bundle add rails
-.
.P
bundle add rails \-\-version "< 3\.0, > 1\.1"
-.
.P
bundle add rails \-\-version "~> 5\.0\.0" \-\-source "https://gems\.example\.com" \-\-group "development"
-.
.P
bundle add rails \-\-skip\-install
-.
.P
bundle add rails \-\-group "development, test"
-.
.SH "OPTIONS"
-.
.TP
\fB\-\-version\fR, \fB\-v\fR
Specify version requirements(s) for the added gem\.
-.
.TP
\fB\-\-group\fR, \fB\-g\fR
Specify the group(s) for the added gem\. Multiple groups should be separated by commas\.
-.
.TP
\fB\-\-source\fR, \fB\-s\fR
Specify the source for the added gem\.
-.
.TP
\fB\-\-require\fR, \fB\-r\fR
Adds require path to gem\. Provide false, or a path as a string\.
-.
.TP
\fB\-\-path\fR
Specify the file system path for the added gem\.
-.
.TP
\fB\-\-git\fR
Specify the git source for the added gem\.
-.
.TP
\fB\-\-github\fR
Specify the github source for the added gem\.
-.
.TP
\fB\-\-branch\fR
Specify the git branch for the added gem\.
-.
.TP
\fB\-\-ref\fR
Specify the git ref for the added gem\.
-.
.TP
\fB\-\-skip\-install\fR
Adds the gem to the Gemfile but does not install it\.
-.
.TP
\fB\-\-optimistic\fR
Adds optimistic declaration of version\.
-.
.TP
\fB\-\-strict\fR
Adds strict declaration of version\.
diff --git a/lib/bundler/man/bundle-binstubs.1 b/lib/bundler/man/bundle-binstubs.1
index 00cbda104a..4ec301951f 100644
--- a/lib/bundler/man/bundle-binstubs.1
+++ b/lib/bundler/man/bundle-binstubs.1
@@ -1,41 +1,29 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-BINSTUBS" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-BINSTUBS" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-binstubs\fR \- Install the binstubs of the listed gems
-.
.SH "SYNOPSIS"
\fBbundle binstubs\fR \fIGEM_NAME\fR [\-\-force] [\-\-path PATH] [\-\-standalone]
-.
.SH "DESCRIPTION"
Binstubs are scripts that wrap around executables\. Bundler creates a small Ruby file (a binstub) that loads Bundler, runs the command, and puts it into \fBbin/\fR\. Binstubs are a shortcut\-or alternative\- to always using \fBbundle exec\fR\. This gives you a file that can be run directly, and one that will always run the correct gem version used by the application\.
-.
.P
For example, if you run \fBbundle binstubs rspec\-core\fR, Bundler will create the file \fBbin/rspec\fR\. That file will contain enough code to load Bundler, tell it to load the bundled gems, and then run rspec\.
-.
.P
This command generates binstubs for executables in \fBGEM_NAME\fR\. Binstubs are put into \fBbin\fR, or the \fB\-\-path\fR directory if one has been set\. Calling binstubs with [GEM [GEM]] will create binstubs for all given gems\.
-.
.SH "OPTIONS"
-.
.TP
\fB\-\-force\fR
Overwrite existing binstubs if they exist\.
-.
.TP
\fB\-\-path\fR
The location to install the specified binstubs to\. This defaults to \fBbin\fR\.
-.
.TP
\fB\-\-standalone\fR
Makes binstubs that can work without depending on Rubygems or Bundler at runtime\.
-.
.TP
\fB\-\-shebang\fR
-Specify a different shebang executable name than the default (default \'ruby\')
-.
+Specify a different shebang executable name than the default (default 'ruby')
.TP
\fB\-\-all\fR
Create binstubs for all gems in the bundle\.
diff --git a/lib/bundler/man/bundle-cache.1 b/lib/bundler/man/bundle-cache.1
index 14250e589a..e2da1269e6 100644
--- a/lib/bundler/man/bundle-cache.1
+++ b/lib/bundler/man/bundle-cache.1
@@ -1,61 +1,40 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-CACHE" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-CACHE" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-cache\fR \- Package your needed \fB\.gem\fR files into your application
-.
.SH "SYNOPSIS"
\fBbundle cache\fR
-.
.P
alias: \fBpackage\fR, \fBpack\fR
-.
.SH "DESCRIPTION"
Copy all of the \fB\.gem\fR files needed to run the application into the \fBvendor/cache\fR directory\. In the future, when running \fBbundle install(1)\fR \fIbundle\-install\.1\.html\fR, use the gems in the cache in preference to the ones on \fBrubygems\.org\fR\.
-.
.SH "GIT AND PATH GEMS"
The \fBbundle cache\fR command can also package \fB:git\fR and \fB:path\fR dependencies besides \.gem files\. This needs to be explicitly enabled via the \fB\-\-all\fR option\. Once used, the \fB\-\-all\fR option will be remembered\.
-.
.SH "SUPPORT FOR MULTIPLE PLATFORMS"
When using gems that have different packages for different platforms, Bundler supports caching of gems for other platforms where the Gemfile has been resolved (i\.e\. present in the lockfile) in \fBvendor/cache\fR\. This needs to be enabled via the \fB\-\-all\-platforms\fR option\. This setting will be remembered in your local bundler configuration\.
-.
.SH "REMOTE FETCHING"
By default, if you run \fBbundle install(1)\fR \fIbundle\-install\.1\.html\fR after running bundle cache(1) \fIbundle\-cache\.1\.html\fR, bundler will still connect to \fBrubygems\.org\fR to check whether a platform\-specific gem exists for any of the gems in \fBvendor/cache\fR\.
-.
.P
For instance, consider this Gemfile(5):
-.
.IP "" 4
-.
.nf
-
source "https://rubygems\.org"
gem "nokogiri"
-.
.fi
-.
.IP "" 0
-.
.P
If you run \fBbundle cache\fR under C Ruby, bundler will retrieve the version of \fBnokogiri\fR for the \fB"ruby"\fR platform\. If you deploy to JRuby and run \fBbundle install\fR, bundler is forced to check to see whether a \fB"java"\fR platformed \fBnokogiri\fR exists\.
-.
.P
Even though the \fBnokogiri\fR gem for the Ruby platform is \fItechnically\fR acceptable on JRuby, it has a C extension that does not run on JRuby\. As a result, bundler will, by default, still connect to \fBrubygems\.org\fR to check whether it has a version of one of your gems more specific to your platform\.
-.
.P
This problem is also not limited to the \fB"java"\fR platform\. A similar (common) problem can happen when developing on Windows and deploying to Linux, or even when developing on OSX and deploying to Linux\.
-.
.P
If you know for sure that the gems packaged in \fBvendor/cache\fR are appropriate for the platform you are on, you can run \fBbundle install \-\-local\fR to skip checking for more appropriate gems, and use the ones in \fBvendor/cache\fR\.
-.
.P
One way to be sure that you have the right platformed versions of all your gems is to run \fBbundle cache\fR on an identical machine and check in the gems\. For instance, you can run \fBbundle cache\fR on an identical staging box during your staging process, and check in the \fBvendor/cache\fR before deploying to production\.
-.
.P
By default, bundle cache(1) \fIbundle\-cache\.1\.html\fR fetches and also installs the gems to the default location\. To package the dependencies to \fBvendor/cache\fR without installing them to the local install location, you can run \fBbundle cache \-\-no\-install\fR\.
-.
.SH "HISTORY"
In Bundler 2\.1, \fBcache\fR took in the functionalities of \fBpackage\fR and now \fBpackage\fR and \fBpack\fR are aliases of \fBcache\fR\.
diff --git a/lib/bundler/man/bundle-check.1 b/lib/bundler/man/bundle-check.1
index cb70661591..dee1af1326 100644
--- a/lib/bundler/man/bundle-check.1
+++ b/lib/bundler/man/bundle-check.1
@@ -1,30 +1,23 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-CHECK" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-CHECK" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-check\fR \- Verifies if dependencies are satisfied by installed gems
-.
.SH "SYNOPSIS"
\fBbundle check\fR [\-\-dry\-run] [\-\-gemfile=FILE] [\-\-path=PATH]
-.
.SH "DESCRIPTION"
\fBcheck\fR searches the local machine for each of the gems requested in the Gemfile\. If all gems are found, Bundler prints a success message and exits with a status of 0\.
-.
.P
If not, the first missing gem is listed and Bundler exits status 1\.
-.
+.P
+If the lockfile needs to be updated then it will be resolved using the gems installed on the local machine, if they satisfy the requirements\.
.SH "OPTIONS"
-.
.TP
\fB\-\-dry\-run\fR
Locks the [\fBGemfile(5)\fR][Gemfile(5)] before running the command\.
-.
.TP
\fB\-\-gemfile\fR
Use the specified gemfile instead of the [\fBGemfile(5)\fR][Gemfile(5)]\.
-.
.TP
\fB\-\-path\fR
Specify a different path than the system default (\fB$BUNDLE_PATH\fR or \fB$GEM_HOME\fR)\. Bundler will remember this value for future installs on this machine\.
diff --git a/lib/bundler/man/bundle-check.1.ronn b/lib/bundler/man/bundle-check.1.ronn
index f2846b8ff2..eb3ff1daf9 100644
--- a/lib/bundler/man/bundle-check.1.ronn
+++ b/lib/bundler/man/bundle-check.1.ronn
@@ -15,6 +15,9 @@ a status of 0.
If not, the first missing gem is listed and Bundler exits status 1.
+If the lockfile needs to be updated then it will be resolved using the gems
+installed on the local machine, if they satisfy the requirements.
+
## OPTIONS
* `--dry-run`:
diff --git a/lib/bundler/man/bundle-clean.1 b/lib/bundler/man/bundle-clean.1
index 76450a35dc..7c7f9b5c77 100644
--- a/lib/bundler/man/bundle-clean.1
+++ b/lib/bundler/man/bundle-clean.1
@@ -1,23 +1,16 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-CLEAN" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-CLEAN" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-clean\fR \- Cleans up unused gems in your bundler directory
-.
.SH "SYNOPSIS"
\fBbundle clean\fR [\-\-dry\-run] [\-\-force]
-.
.SH "DESCRIPTION"
This command will remove all unused gems in your bundler directory\. This is useful when you have made many changes to your gem dependencies\.
-.
.SH "OPTIONS"
-.
.TP
\fB\-\-dry\-run\fR
Print the changes, but do not clean the unused gems\.
-.
.TP
\fB\-\-force\fR
Forces cleaning up unused gems even if Bundler is configured to use globally installed gems\. As a consequence, removes all system gems except for the ones in the current application\.
diff --git a/lib/bundler/man/bundle-config.1 b/lib/bundler/man/bundle-config.1
index 34654301b2..2de52ee375 100644
--- a/lib/bundler/man/bundle-config.1
+++ b/lib/bundler/man/bundle-config.1
@@ -1,515 +1,319 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-CONFIG" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-CONFIG" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-config\fR \- Set bundler configuration options
-.
.SH "SYNOPSIS"
\fBbundle config\fR list
-.
.br
\fBbundle config\fR [get] NAME
-.
.br
\fBbundle config\fR [set] NAME VALUE
-.
.br
\fBbundle config\fR unset NAME
-.
.SH "DESCRIPTION"
-This command allows you to interact with Bundler\'s configuration system\.
-.
+This command allows you to interact with Bundler's configuration system\.
.P
Bundler loads configuration settings in this order:
-.
.IP "1." 4
Local config (\fB<project_root>/\.bundle/config\fR or \fB$BUNDLE_APP_CONFIG/config\fR)
-.
.IP "2." 4
Environmental variables (\fBENV\fR)
-.
.IP "3." 4
Global config (\fB~/\.bundle/config\fR)
-.
.IP "4." 4
Bundler default config
-.
.IP "" 0
-.
.P
Executing \fBbundle config list\fR will print a list of all bundler configuration for the current bundle, and where that configuration was set\.
-.
.P
Executing \fBbundle config get <name>\fR will print the value of that configuration setting, and where it was set\.
-.
.P
Executing \fBbundle config set <name> <value>\fR defaults to setting \fBlocal\fR configuration if executing from within a local application, otherwise it will set \fBglobal\fR configuration\. See \fB\-\-local\fR and \fB\-\-global\fR options below\.
-.
.P
Executing \fBbundle config set \-\-local <name> <value>\fR will set that configuration in the directory for the local application\. The configuration will be stored in \fB<project_root>/\.bundle/config\fR\. If \fBBUNDLE_APP_CONFIG\fR is set, the configuration will be stored in \fB$BUNDLE_APP_CONFIG/config\fR\.
-.
.P
Executing \fBbundle config set \-\-global <name> <value>\fR will set that configuration to the value specified for all bundles executed as the current user\. The configuration will be stored in \fB~/\.bundle/config\fR\. If \fIname\fR already is set, \fIname\fR will be overridden and user will be warned\.
-.
.P
Executing \fBbundle config unset <name>\fR will delete the configuration in both local and global sources\.
-.
.P
Executing \fBbundle config unset \-\-global <name>\fR will delete the configuration only from the user configuration\.
-.
.P
Executing \fBbundle config unset \-\-local <name>\fR will delete the configuration only from the local application\.
-.
.P
Executing bundle with the \fBBUNDLE_IGNORE_CONFIG\fR environment variable set will cause it to ignore all configuration\.
-.
.SH "REMEMBERING OPTIONS"
-Flags passed to \fBbundle install\fR or the Bundler runtime, such as \fB\-\-path foo\fR or \fB\-\-without production\fR, are remembered between commands and saved to your local application\'s configuration (normally, \fB\./\.bundle/config\fR)\.
-.
+Flags passed to \fBbundle install\fR or the Bundler runtime, such as \fB\-\-path foo\fR or \fB\-\-without production\fR, are remembered between commands and saved to your local application's configuration (normally, \fB\./\.bundle/config\fR)\.
.P
-However, this will be changed in bundler 3, so it\'s better not to rely on this behavior\. If these options must be remembered, it\'s better to set them using \fBbundle config\fR (e\.g\., \fBbundle config set \-\-local path foo\fR)\.
-.
+However, this will be changed in bundler 3, so it's better not to rely on this behavior\. If these options must be remembered, it's better to set them using \fBbundle config\fR (e\.g\., \fBbundle config set \-\-local path foo\fR)\.
.P
The options that can be configured are:
-.
.TP
\fBbin\fR
-Creates a directory (defaults to \fB~/bin\fR) and place any executables from the gem there\. These executables run in Bundler\'s context\. If used, you might add this directory to your environment\'s \fBPATH\fR variable\. For instance, if the \fBrails\fR gem comes with a \fBrails\fR executable, this flag will create a \fBbin/rails\fR executable that ensures that all referred dependencies will be resolved using the bundled gems\.
-.
+Creates a directory (defaults to \fB~/bin\fR) and place any executables from the gem there\. These executables run in Bundler's context\. If used, you might add this directory to your environment's \fBPATH\fR variable\. For instance, if the \fBrails\fR gem comes with a \fBrails\fR executable, this flag will create a \fBbin/rails\fR executable that ensures that all referred dependencies will be resolved using the bundled gems\.
.TP
\fBdeployment\fR
-In deployment mode, Bundler will \'roll\-out\' the bundle for \fBproduction\fR use\. Please check carefully if you want to have this option enabled in \fBdevelopment\fR or \fBtest\fR environments\.
-.
+In deployment mode, Bundler will 'roll\-out' the bundle for \fBproduction\fR use\. Please check carefully if you want to have this option enabled in \fBdevelopment\fR or \fBtest\fR environments\.
.TP
\fBonly\fR
A space\-separated list of groups to install only gems of the specified groups\.
-.
.TP
\fBpath\fR
-The location to install the specified gems to\. This defaults to Rubygems\' setting\. Bundler shares this location with Rubygems, \fBgem install \.\.\.\fR will have gem installed there, too\. Therefore, gems installed without a \fB\-\-path \.\.\.\fR setting will show up by calling \fBgem list\fR\. Accordingly, gems installed to other locations will not get listed\.
-.
+The location to install the specified gems to\. This defaults to Rubygems' setting\. Bundler shares this location with Rubygems, \fBgem install \|\.\|\.\|\.\fR will have gem installed there, too\. Therefore, gems installed without a \fB\-\-path \|\.\|\.\|\.\fR setting will show up by calling \fBgem list\fR\. Accordingly, gems installed to other locations will not get listed\.
.TP
\fBwithout\fR
A space\-separated list of groups referencing gems to skip during installation\.
-.
.TP
\fBwith\fR
A space\-separated list of \fBoptional\fR groups referencing gems to include during installation\.
-.
.SH "BUILD OPTIONS"
You can use \fBbundle config\fR to give Bundler the flags to pass to the gem installer every time bundler tries to install a particular gem\.
-.
.P
A very common example, the \fBmysql\fR gem, requires Snow Leopard users to pass configuration flags to \fBgem install\fR to specify where to find the \fBmysql_config\fR executable\.
-.
.IP "" 4
-.
.nf
-
gem install mysql \-\- \-\-with\-mysql\-config=/usr/local/mysql/bin/mysql_config
-.
.fi
-.
.IP "" 0
-.
.P
Since the specific location of that executable can change from machine to machine, you can specify these flags on a per\-machine basis\.
-.
.IP "" 4
-.
.nf
-
bundle config set \-\-global build\.mysql \-\-with\-mysql\-config=/usr/local/mysql/bin/mysql_config
-.
.fi
-.
.IP "" 0
-.
.P
After running this command, every time bundler needs to install the \fBmysql\fR gem, it will pass along the flags you specified\.
-.
.SH "CONFIGURATION KEYS"
Configuration keys in bundler have two forms: the canonical form and the environment variable form\.
-.
.P
-For instance, passing the \fB\-\-without\fR flag to bundle install(1) \fIbundle\-install\.1\.html\fR prevents Bundler from installing certain groups specified in the Gemfile(5)\. Bundler persists this value in \fBapp/\.bundle/config\fR so that calls to \fBBundler\.setup\fR do not try to find gems from the \fBGemfile\fR that you didn\'t install\. Additionally, subsequent calls to bundle install(1) \fIbundle\-install\.1\.html\fR remember this setting and skip those groups\.
-.
+For instance, passing the \fB\-\-without\fR flag to bundle install(1) \fIbundle\-install\.1\.html\fR prevents Bundler from installing certain groups specified in the Gemfile(5)\. Bundler persists this value in \fBapp/\.bundle/config\fR so that calls to \fBBundler\.setup\fR do not try to find gems from the \fBGemfile\fR that you didn't install\. Additionally, subsequent calls to bundle install(1) \fIbundle\-install\.1\.html\fR remember this setting and skip those groups\.
.P
The canonical form of this configuration is \fB"without"\fR\. To convert the canonical form to the environment variable form, capitalize it, and prepend \fBBUNDLE_\fR\. The environment variable form of \fB"without"\fR is \fBBUNDLE_WITHOUT\fR\.
-.
.P
Any periods in the configuration keys must be replaced with two underscores when setting it via environment variables\. The configuration key \fBlocal\.rack\fR becomes the environment variable \fBBUNDLE_LOCAL__RACK\fR\.
-.
.SH "LIST OF AVAILABLE KEYS"
The following is a list of all configuration keys and their purpose\. You can learn more about their operation in bundle install(1) \fIbundle\-install\.1\.html\fR\.
-.
-.IP "\(bu" 4
-\fBallow_deployment_source_credential_changes\fR (\fBBUNDLE_ALLOW_DEPLOYMENT_SOURCE_CREDENTIAL_CHANGES\fR): When in deployment mode, allow changing the credentials to a gem\'s source\. Ex: \fBhttps://some\.host\.com/gems/path/\fR \-> \fBhttps://user_name:password@some\.host\.com/gems/path\fR
-.
.IP "\(bu" 4
\fBallow_offline_install\fR (\fBBUNDLE_ALLOW_OFFLINE_INSTALL\fR): Allow Bundler to use cached data when installing without network access\.
-.
.IP "\(bu" 4
\fBauto_clean_without_path\fR (\fBBUNDLE_AUTO_CLEAN_WITHOUT_PATH\fR): Automatically run \fBbundle clean\fR after installing when an explicit \fBpath\fR has not been set and Bundler is not installing into the system gems\.
-.
.IP "\(bu" 4
\fBauto_install\fR (\fBBUNDLE_AUTO_INSTALL\fR): Automatically run \fBbundle install\fR when gems are missing\.
-.
.IP "\(bu" 4
\fBbin\fR (\fBBUNDLE_BIN\fR): Install executables from gems in the bundle to the specified directory\. Defaults to \fBfalse\fR\.
-.
.IP "\(bu" 4
\fBcache_all\fR (\fBBUNDLE_CACHE_ALL\fR): Cache all gems, including path and git gems\. This needs to be explicitly configured on bundler 1 and bundler 2, but will be the default on bundler 3\.
-.
.IP "\(bu" 4
\fBcache_all_platforms\fR (\fBBUNDLE_CACHE_ALL_PLATFORMS\fR): Cache gems for all platforms\.
-.
.IP "\(bu" 4
\fBcache_path\fR (\fBBUNDLE_CACHE_PATH\fR): The directory that bundler will place cached gems in when running \fBbundle package\fR, and that bundler will look in when installing gems\. Defaults to \fBvendor/cache\fR\.
-.
.IP "\(bu" 4
\fBclean\fR (\fBBUNDLE_CLEAN\fR): Whether Bundler should run \fBbundle clean\fR automatically after \fBbundle install\fR\.
-.
.IP "\(bu" 4
\fBconsole\fR (\fBBUNDLE_CONSOLE\fR): The console that \fBbundle console\fR starts\. Defaults to \fBirb\fR\.
-.
.IP "\(bu" 4
\fBdefault_install_uses_path\fR (\fBBUNDLE_DEFAULT_INSTALL_USES_PATH\fR): Whether a \fBbundle install\fR without an explicit \fB\-\-path\fR argument defaults to installing gems in \fB\.bundle\fR\.
-.
.IP "\(bu" 4
\fBdeployment\fR (\fBBUNDLE_DEPLOYMENT\fR): Disallow changes to the \fBGemfile\fR\. When the \fBGemfile\fR is changed and the lockfile has not been updated, running Bundler commands will be blocked\.
-.
.IP "\(bu" 4
\fBdisable_checksum_validation\fR (\fBBUNDLE_DISABLE_CHECKSUM_VALIDATION\fR): Allow installing gems even if they do not match the checksum provided by RubyGems\.
-.
.IP "\(bu" 4
\fBdisable_exec_load\fR (\fBBUNDLE_DISABLE_EXEC_LOAD\fR): Stop Bundler from using \fBload\fR to launch an executable in\-process in \fBbundle exec\fR\.
-.
.IP "\(bu" 4
\fBdisable_local_branch_check\fR (\fBBUNDLE_DISABLE_LOCAL_BRANCH_CHECK\fR): Allow Bundler to use a local git override without a branch specified in the Gemfile\.
-.
.IP "\(bu" 4
\fBdisable_local_revision_check\fR (\fBBUNDLE_DISABLE_LOCAL_REVISION_CHECK\fR): Allow Bundler to use a local git override without checking if the revision present in the lockfile is present in the repository\.
-.
.IP "\(bu" 4
-\fBdisable_shared_gems\fR (\fBBUNDLE_DISABLE_SHARED_GEMS\fR): Stop Bundler from accessing gems installed to RubyGems\' normal location\.
-.
+\fBdisable_shared_gems\fR (\fBBUNDLE_DISABLE_SHARED_GEMS\fR): Stop Bundler from accessing gems installed to RubyGems' normal location\.
.IP "\(bu" 4
\fBdisable_version_check\fR (\fBBUNDLE_DISABLE_VERSION_CHECK\fR): Stop Bundler from checking if a newer Bundler version is available on rubygems\.org\.
-.
.IP "\(bu" 4
-\fBforce_ruby_platform\fR (\fBBUNDLE_FORCE_RUBY_PLATFORM\fR): Ignore the current machine\'s platform and install only \fBruby\fR platform gems\. As a result, gems with native extensions will be compiled from source\.
-.
+\fBforce_ruby_platform\fR (\fBBUNDLE_FORCE_RUBY_PLATFORM\fR): Ignore the current machine's platform and install only \fBruby\fR platform gems\. As a result, gems with native extensions will be compiled from source\.
.IP "\(bu" 4
\fBfrozen\fR (\fBBUNDLE_FROZEN\fR): Disallow changes to the \fBGemfile\fR\. When the \fBGemfile\fR is changed and the lockfile has not been updated, running Bundler commands will be blocked\. Defaults to \fBtrue\fR when \fB\-\-deployment\fR is used\.
-.
.IP "\(bu" 4
\fBgem\.github_username\fR (\fBBUNDLE_GEM__GITHUB_USERNAME\fR): Sets a GitHub username or organization to be used in \fBREADME\fR file when you create a new gem via \fBbundle gem\fR command\. It can be overridden by passing an explicit \fB\-\-github\-username\fR flag to \fBbundle gem\fR\.
-.
.IP "\(bu" 4
\fBgem\.push_key\fR (\fBBUNDLE_GEM__PUSH_KEY\fR): Sets the \fB\-\-key\fR parameter for \fBgem push\fR when using the \fBrake release\fR command with a private gemstash server\.
-.
.IP "\(bu" 4
\fBgemfile\fR (\fBBUNDLE_GEMFILE\fR): The name of the file that bundler should use as the \fBGemfile\fR\. This location of this file also sets the root of the project, which is used to resolve relative paths in the \fBGemfile\fR, among other things\. By default, bundler will search up from the current working directory until it finds a \fBGemfile\fR\.
-.
.IP "\(bu" 4
\fBglobal_gem_cache\fR (\fBBUNDLE_GLOBAL_GEM_CACHE\fR): Whether Bundler should cache all gems globally, rather than locally to the installing Ruby installation\.
-.
.IP "\(bu" 4
\fBignore_funding_requests\fR (\fBBUNDLE_IGNORE_FUNDING_REQUESTS\fR): When set, no funding requests will be printed\.
-.
.IP "\(bu" 4
\fBignore_messages\fR (\fBBUNDLE_IGNORE_MESSAGES\fR): When set, no post install messages will be printed\. To silence a single gem, use dot notation like \fBignore_messages\.httparty true\fR\.
-.
.IP "\(bu" 4
\fBinit_gems_rb\fR (\fBBUNDLE_INIT_GEMS_RB\fR): Generate a \fBgems\.rb\fR instead of a \fBGemfile\fR when running \fBbundle init\fR\.
-.
.IP "\(bu" 4
\fBjobs\fR (\fBBUNDLE_JOBS\fR): The number of gems Bundler can install in parallel\. Defaults to the number of available processors\.
-.
.IP "\(bu" 4
\fBno_install\fR (\fBBUNDLE_NO_INSTALL\fR): Whether \fBbundle package\fR should skip installing gems\.
-.
.IP "\(bu" 4
\fBno_prune\fR (\fBBUNDLE_NO_PRUNE\fR): Whether Bundler should leave outdated gems unpruned when caching\.
-.
.IP "\(bu" 4
\fBonly\fR (\fBBUNDLE_ONLY\fR): A space\-separated list of groups to install only gems of the specified groups\.
-.
.IP "\(bu" 4
\fBpath\fR (\fBBUNDLE_PATH\fR): The location on disk where all gems in your bundle will be located regardless of \fB$GEM_HOME\fR or \fB$GEM_PATH\fR values\. Bundle gems not found in this location will be installed by \fBbundle install\fR\. Defaults to \fBGem\.dir\fR\. When \-\-deployment is used, defaults to vendor/bundle\.
-.
.IP "\(bu" 4
\fBpath\.system\fR (\fBBUNDLE_PATH__SYSTEM\fR): Whether Bundler will install gems into the default system path (\fBGem\.dir\fR)\.
-.
.IP "\(bu" 4
\fBpath_relative_to_cwd\fR (\fBBUNDLE_PATH_RELATIVE_TO_CWD\fR) Makes \fB\-\-path\fR relative to the CWD instead of the \fBGemfile\fR\.
-.
.IP "\(bu" 4
-\fBplugins\fR (\fBBUNDLE_PLUGINS\fR): Enable Bundler\'s experimental plugin system\.
-.
+\fBplugins\fR (\fBBUNDLE_PLUGINS\fR): Enable Bundler's experimental plugin system\.
.IP "\(bu" 4
\fBprefer_patch\fR (BUNDLE_PREFER_PATCH): Prefer updating only to next patch version during updates\. Makes \fBbundle update\fR calls equivalent to \fBbundler update \-\-patch\fR\.
-.
.IP "\(bu" 4
\fBprint_only_version_number\fR (\fBBUNDLE_PRINT_ONLY_VERSION_NUMBER\fR): Print only version number from \fBbundler \-\-version\fR\.
-.
.IP "\(bu" 4
\fBredirect\fR (\fBBUNDLE_REDIRECT\fR): The number of redirects allowed for network requests\. Defaults to \fB5\fR\.
-.
.IP "\(bu" 4
\fBretry\fR (\fBBUNDLE_RETRY\fR): The number of times to retry failed network requests\. Defaults to \fB3\fR\.
-.
.IP "\(bu" 4
\fBsetup_makes_kernel_gem_public\fR (\fBBUNDLE_SETUP_MAKES_KERNEL_GEM_PUBLIC\fR): Have \fBBundler\.setup\fR make the \fBKernel#gem\fR method public, even though RubyGems declares it as private\.
-.
.IP "\(bu" 4
\fBshebang\fR (\fBBUNDLE_SHEBANG\fR): The program name that should be invoked for generated binstubs\. Defaults to the ruby install name used to generate the binstub\.
-.
.IP "\(bu" 4
\fBsilence_deprecations\fR (\fBBUNDLE_SILENCE_DEPRECATIONS\fR): Whether Bundler should silence deprecation warnings for behavior that will be changed in the next major version\.
-.
.IP "\(bu" 4
\fBsilence_root_warning\fR (\fBBUNDLE_SILENCE_ROOT_WARNING\fR): Silence the warning Bundler prints when installing gems as root\.
-.
.IP "\(bu" 4
\fBssl_ca_cert\fR (\fBBUNDLE_SSL_CA_CERT\fR): Path to a designated CA certificate file or folder containing multiple certificates for trusted CAs in PEM format\.
-.
.IP "\(bu" 4
\fBssl_client_cert\fR (\fBBUNDLE_SSL_CLIENT_CERT\fR): Path to a designated file containing a X\.509 client certificate and key in PEM format\.
-.
.IP "\(bu" 4
\fBssl_verify_mode\fR (\fBBUNDLE_SSL_VERIFY_MODE\fR): The SSL verification mode Bundler uses when making HTTPS requests\. Defaults to verify peer\.
-.
.IP "\(bu" 4
\fBsystem_bindir\fR (\fBBUNDLE_SYSTEM_BINDIR\fR): The location where RubyGems installs binstubs\. Defaults to \fBGem\.bindir\fR\.
-.
.IP "\(bu" 4
\fBtimeout\fR (\fBBUNDLE_TIMEOUT\fR): The seconds allowed before timing out for network requests\. Defaults to \fB10\fR\.
-.
.IP "\(bu" 4
\fBupdate_requires_all_flag\fR (\fBBUNDLE_UPDATE_REQUIRES_ALL_FLAG\fR): Require passing \fB\-\-all\fR to \fBbundle update\fR when everything should be updated, and disallow passing no options to \fBbundle update\fR\.
-.
.IP "\(bu" 4
\fBuser_agent\fR (\fBBUNDLE_USER_AGENT\fR): The custom user agent fragment Bundler includes in API requests\.
-.
.IP "\(bu" 4
\fBversion\fR (\fBBUNDLE_VERSION\fR): The version of Bundler to use when running under Bundler environment\. Defaults to \fBlockfile\fR\. You can also specify \fBsystem\fR or \fBx\.y\.z\fR\. \fBlockfile\fR will use the Bundler version specified in the \fBGemfile\.lock\fR, \fBsystem\fR will use the system version of Bundler, and \fBx\.y\.z\fR will use the specified version of Bundler\.
-.
.IP "\(bu" 4
\fBwith\fR (\fBBUNDLE_WITH\fR): A \fB:\fR\-separated list of groups whose gems bundler should install\.
-.
.IP "\(bu" 4
\fBwithout\fR (\fBBUNDLE_WITHOUT\fR): A \fB:\fR\-separated list of groups whose gems bundler should not install\.
-.
.IP "" 0
-.
.P
In general, you should set these settings per\-application by using the applicable flag to the bundle install(1) \fIbundle\-install\.1\.html\fR or bundle cache(1) \fIbundle\-cache\.1\.html\fR command\.
-.
.P
You can set them globally either via environment variables or \fBbundle config\fR, whichever is preferable for your setup\. If you use both, environment variables will take preference over global settings\.
-.
.SH "LOCAL GIT REPOS"
Bundler also allows you to work against a git repository locally instead of using the remote version\. This can be achieved by setting up a local override:
-.
.IP "" 4
-.
.nf
-
bundle config set \-\-local local\.GEM_NAME /path/to/local/git/repository
-.
.fi
-.
.IP "" 0
-.
.P
For example, in order to use a local Rack repository, a developer could call:
-.
.IP "" 4
-.
.nf
-
bundle config set \-\-local local\.rack ~/Work/git/rack
-.
.fi
-.
.IP "" 0
-.
.P
-Now instead of checking out the remote git repository, the local override will be used\. Similar to a path source, every time the local git repository change, changes will be automatically picked up by Bundler\. This means a commit in the local git repo will update the revision in the \fBGemfile\.lock\fR to the local git repo revision\. This requires the same attention as git submodules\. Before pushing to the remote, you need to ensure the local override was pushed, otherwise you may point to a commit that only exists in your local machine\. You\'ll also need to CGI escape your usernames and passwords as well\.
-.
+Now instead of checking out the remote git repository, the local override will be used\. Similar to a path source, every time the local git repository change, changes will be automatically picked up by Bundler\. This means a commit in the local git repo will update the revision in the \fBGemfile\.lock\fR to the local git repo revision\. This requires the same attention as git submodules\. Before pushing to the remote, you need to ensure the local override was pushed, otherwise you may point to a commit that only exists in your local machine\. You'll also need to CGI escape your usernames and passwords as well\.
.P
-Bundler does many checks to ensure a developer won\'t work with invalid references\. Particularly, we force a developer to specify a branch in the \fBGemfile\fR in order to use this feature\. If the branch specified in the \fBGemfile\fR and the current branch in the local git repository do not match, Bundler will abort\. This ensures that a developer is always working against the correct branches, and prevents accidental locking to a different branch\.
-.
+Bundler does many checks to ensure a developer won't work with invalid references\. Particularly, we force a developer to specify a branch in the \fBGemfile\fR in order to use this feature\. If the branch specified in the \fBGemfile\fR and the current branch in the local git repository do not match, Bundler will abort\. This ensures that a developer is always working against the correct branches, and prevents accidental locking to a different branch\.
.P
Finally, Bundler also ensures that the current revision in the \fBGemfile\.lock\fR exists in the local git repository\. By doing this, Bundler forces you to fetch the latest changes in the remotes\.
-.
.SH "MIRRORS OF GEM SOURCES"
Bundler supports overriding gem sources with mirrors\. This allows you to configure rubygems\.org as the gem source in your Gemfile while still using your mirror to fetch gems\.
-.
.IP "" 4
-.
.nf
-
bundle config set \-\-global mirror\.SOURCE_URL MIRROR_URL
-.
.fi
-.
.IP "" 0
-.
.P
For example, to use a mirror of https://rubygems\.org hosted at https://example\.org:
-.
.IP "" 4
-.
.nf
-
bundle config set \-\-global mirror\.https://rubygems\.org https://example\.org
-.
.fi
-.
.IP "" 0
-.
.P
Each mirror also provides a fallback timeout setting\. If the mirror does not respond within the fallback timeout, Bundler will try to use the original server instead of the mirror\.
-.
.IP "" 4
-.
.nf
-
bundle config set \-\-global mirror\.SOURCE_URL\.fallback_timeout TIMEOUT
-.
.fi
-.
.IP "" 0
-.
.P
For example, to fall back to rubygems\.org after 3 seconds:
-.
.IP "" 4
-.
.nf
-
bundle config set \-\-global mirror\.https://rubygems\.org\.fallback_timeout 3
-.
.fi
-.
.IP "" 0
-.
.P
The default fallback timeout is 0\.1 seconds, but the setting can currently only accept whole seconds (for example, 1, 15, or 30)\.
-.
.SH "CREDENTIALS FOR GEM SOURCES"
Bundler allows you to configure credentials for any gem source, which allows you to avoid putting secrets into your Gemfile\.
-.
.IP "" 4
-.
.nf
-
bundle config set \-\-global SOURCE_HOSTNAME USERNAME:PASSWORD
-.
.fi
-.
.IP "" 0
-.
.P
For example, to save the credentials of user \fBclaudette\fR for the gem source at \fBgems\.longerous\.com\fR, you would run:
-.
.IP "" 4
-.
.nf
-
bundle config set \-\-global gems\.longerous\.com claudette:s00pers3krit
-.
.fi
-.
.IP "" 0
-.
.P
Or you can set the credentials as an environment variable like this:
-.
.IP "" 4
-.
.nf
-
export BUNDLE_GEMS__LONGEROUS__COM="claudette:s00pers3krit"
-.
.fi
-.
.IP "" 0
-.
.P
For gems with a git source with HTTP(S) URL you can specify credentials like so:
-.
.IP "" 4
-.
.nf
-
bundle config set \-\-global https://github\.com/rubygems/rubygems\.git username:password
-.
.fi
-.
.IP "" 0
-.
.P
Or you can set the credentials as an environment variable like so:
-.
.IP "" 4
-.
.nf
-
export BUNDLE_GITHUB__COM=username:password
-.
.fi
-.
.IP "" 0
-.
.P
This is especially useful for private repositories on hosts such as GitHub, where you can use personal OAuth tokens:
-.
.IP "" 4
-.
.nf
-
export BUNDLE_GITHUB__COM=abcd0123generatedtoken:x\-oauth\-basic
-.
.fi
-.
.IP "" 0
-.
.P
Note that any configured credentials will be redacted by informative commands such as \fBbundle config list\fR or \fBbundle config get\fR, unless you use the \fB\-\-parseable\fR flag\. This is to avoid unintentionally leaking credentials when copy\-pasting bundler output\.
-.
.P
Also note that to guarantee a sane mapping between valid environment variable names and valid host names, bundler makes the following transformations:
-.
.IP "\(bu" 4
-Any \fB\-\fR characters in a host name are mapped to a triple dash (\fB___\fR) in the corresponding environment variable\.
-.
+Any \fB\-\fR characters in a host name are mapped to a triple underscore (\fB___\fR) in the corresponding environment variable\.
.IP "\(bu" 4
-Any \fB\.\fR characters in a host name are mapped to a double dash (\fB__\fR) in the corresponding environment variable\.
-.
+Any \fB\.\fR characters in a host name are mapped to a double underscore (\fB__\fR) in the corresponding environment variable\.
.IP "" 0
-.
.P
-This means that if you have a gem server named \fBmy\.gem\-host\.com\fR, you\'ll need to use the \fBBUNDLE_MY__GEM___HOST__COM\fR variable to configure credentials for it through ENV\.
-.
+This means that if you have a gem server named \fBmy\.gem\-host\.com\fR, you'll need to use the \fBBUNDLE_MY__GEM___HOST__COM\fR variable to configure credentials for it through ENV\.
.SH "CONFIGURE BUNDLER DIRECTORIES"
-Bundler\'s home, config, cache and plugin directories are able to be configured through environment variables\. The default location for Bundler\'s home directory is \fB~/\.bundle\fR, which all directories inherit from by default\. The following outlines the available environment variables and their default values
-.
+Bundler's home, cache and plugin directories and config file can be configured through environment variables\. The default location for Bundler's home directory is \fB~/\.bundle\fR, which all directories inherit from by default\. The following outlines the available environment variables and their default values
.IP "" 4
-.
.nf
-
BUNDLE_USER_HOME : $HOME/\.bundle
BUNDLE_USER_CACHE : $BUNDLE_USER_HOME/cache
BUNDLE_USER_CONFIG : $BUNDLE_USER_HOME/config
BUNDLE_USER_PLUGIN : $BUNDLE_USER_HOME/plugin
-.
.fi
-.
.IP "" 0
diff --git a/lib/bundler/man/bundle-config.1.ronn b/lib/bundler/man/bundle-config.1.ronn
index b935329b4e..1a0ec2a5dc 100644
--- a/lib/bundler/man/bundle-config.1.ronn
+++ b/lib/bundler/man/bundle-config.1.ronn
@@ -137,9 +137,6 @@ the environment variable `BUNDLE_LOCAL__RACK`.
The following is a list of all configuration keys and their purpose. You can
learn more about their operation in [bundle install(1)](bundle-install.1.html).
-* `allow_deployment_source_credential_changes` (`BUNDLE_ALLOW_DEPLOYMENT_SOURCE_CREDENTIAL_CHANGES`):
- When in deployment mode, allow changing the credentials to a gem's source.
- Ex: `https://some.host.com/gems/path/` -> `https://user_name:password@some.host.com/gems/path`
* `allow_offline_install` (`BUNDLE_ALLOW_OFFLINE_INSTALL`):
Allow Bundler to use cached data when installing without network access.
* `auto_clean_without_path` (`BUNDLE_AUTO_CLEAN_WITHOUT_PATH`):
@@ -388,10 +385,10 @@ copy-pasting bundler output.
Also note that to guarantee a sane mapping between valid environment variable
names and valid host names, bundler makes the following transformations:
-* Any `-` characters in a host name are mapped to a triple dash (`___`) in the
+* Any `-` characters in a host name are mapped to a triple underscore (`___`) in the
corresponding environment variable.
-* Any `.` characters in a host name are mapped to a double dash (`__`) in the
+* Any `.` characters in a host name are mapped to a double underscore (`__`) in the
corresponding environment variable.
This means that if you have a gem server named `my.gem-host.com`, you'll need to
@@ -400,7 +397,7 @@ through ENV.
## CONFIGURE BUNDLER DIRECTORIES
-Bundler's home, config, cache and plugin directories are able to be configured
+Bundler's home, cache and plugin directories and config file can be configured
through environment variables. The default location for Bundler's home directory is
`~/.bundle`, which all directories inherit from by default. The following
outlines the available environment variables and their default values
diff --git a/lib/bundler/man/bundle-console.1 b/lib/bundler/man/bundle-console.1
index a223558c68..dca18ec43d 100644
--- a/lib/bundler/man/bundle-console.1
+++ b/lib/bundler/man/bundle-console.1
@@ -1,53 +1,35 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-CONSOLE" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-CONSOLE" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-console\fR \- Deprecated way to open an IRB session with the bundle pre\-loaded
-.
.SH "SYNOPSIS"
\fBbundle console\fR [GROUP]
-.
.SH "DESCRIPTION"
Starts an interactive Ruby console session in the context of the current bundle\.
-.
.P
If no \fBGROUP\fR is specified, all gems in the \fBdefault\fR group in the Gemfile(5) \fIhttps://bundler\.io/man/gemfile\.5\.html\fR are preliminarily loaded\.
-.
.P
If \fBGROUP\fR is specified, all gems in the given group in the Gemfile in addition to the gems in \fBdefault\fR group are loaded\. Even if the given group does not exist in the Gemfile, IRB console starts without any warning or error\.
-.
.P
The environment variable \fBBUNDLE_CONSOLE\fR or \fBbundle config set console\fR can be used to change the shell from the following:
-.
.IP "\(bu" 4
\fBirb\fR (default)
-.
.IP "\(bu" 4
\fBpry\fR (https://github\.com/pry/pry)
-.
.IP "\(bu" 4
\fBripl\fR (https://github\.com/cldwalker/ripl)
-.
.IP "" 0
-.
.P
\fBbundle console\fR uses irb by default\. An alternative Pry or Ripl can be used with \fBbundle console\fR by adjusting the \fBconsole\fR Bundler setting\. Also make sure that \fBpry\fR or \fBripl\fR is in your Gemfile\.
-.
.SH "EXAMPLE"
-.
.nf
-
$ bundle config set console pry
$ bundle console
-Resolving dependencies\.\.\.
+Resolving dependencies\|\.\|\.\|\.
[1] pry(main)>
-.
.fi
-.
.SH "NOTES"
This command was deprecated in Bundler 2\.1 and will be removed in 3\.0\. Use \fBbin/console\fR script, which can be generated by \fBbundle gem <NAME>\fR\.
-.
.SH "SEE ALSO"
Gemfile(5) \fIhttps://bundler\.io/man/gemfile\.5\.html\fR
diff --git a/lib/bundler/man/bundle-doctor.1 b/lib/bundler/man/bundle-doctor.1
index 143d9b700f..6489cc07f7 100644
--- a/lib/bundler/man/bundle-doctor.1
+++ b/lib/bundler/man/bundle-doctor.1
@@ -1,44 +1,30 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-DOCTOR" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-DOCTOR" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-doctor\fR \- Checks the bundle for common problems
-.
.SH "SYNOPSIS"
\fBbundle doctor\fR [\-\-quiet] [\-\-gemfile=GEMFILE]
-.
.SH "DESCRIPTION"
Checks your Gemfile and gem environment for common problems\. If issues are detected, Bundler prints them and exits status 1\. Otherwise, Bundler prints a success message and exits status 0\.
-.
.P
Examples of common problems caught by bundle\-doctor include:
-.
.IP "\(bu" 4
Invalid Bundler settings
-.
.IP "\(bu" 4
Mismatched Ruby versions
-.
.IP "\(bu" 4
Mismatched platforms
-.
.IP "\(bu" 4
Uninstalled gems
-.
.IP "\(bu" 4
Missing dependencies
-.
.IP "" 0
-.
.SH "OPTIONS"
-.
.TP
\fB\-\-quiet\fR
Only output warnings and errors\.
-.
.TP
\fB\-\-gemfile=<gemfile>\fR
-The location of the Gemfile(5) which Bundler should use\. This defaults to a Gemfile(5) in the current working directory\. In general, Bundler will assume that the location of the Gemfile(5) is also the project\'s root and will try to find \fBGemfile\.lock\fR and \fBvendor/cache\fR relative to this location\.
+The location of the Gemfile(5) which Bundler should use\. This defaults to a Gemfile(5) in the current working directory\. In general, Bundler will assume that the location of the Gemfile(5) is also the project's root and will try to find \fBGemfile\.lock\fR and \fBvendor/cache\fR relative to this location\.
diff --git a/lib/bundler/man/bundle-exec.1 b/lib/bundler/man/bundle-exec.1
index 91454985f2..1548d29670 100644
--- a/lib/bundler/man/bundle-exec.1
+++ b/lib/bundler/man/bundle-exec.1
@@ -1,165 +1,104 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-EXEC" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-EXEC" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-exec\fR \- Execute a command in the context of the bundle
-.
.SH "SYNOPSIS"
\fBbundle exec\fR [\-\-keep\-file\-descriptors] \fIcommand\fR
-.
.SH "DESCRIPTION"
This command executes the command, making all gems specified in the [\fBGemfile(5)\fR][Gemfile(5)] available to \fBrequire\fR in Ruby programs\.
-.
.P
Essentially, if you would normally have run something like \fBrspec spec/my_spec\.rb\fR, and you want to use the gems specified in the [\fBGemfile(5)\fR][Gemfile(5)] and installed via bundle install(1) \fIbundle\-install\.1\.html\fR, you should run \fBbundle exec rspec spec/my_spec\.rb\fR\.
-.
.P
-Note that \fBbundle exec\fR does not require that an executable is available on your shell\'s \fB$PATH\fR\.
-.
+Note that \fBbundle exec\fR does not require that an executable is available on your shell's \fB$PATH\fR\.
.SH "OPTIONS"
-.
.TP
\fB\-\-keep\-file\-descriptors\fR
Passes all file descriptors to the new processes\. Default is true from bundler version 2\.2\.26\. Setting it to false is now deprecated\.
-.
.SH "BUNDLE INSTALL \-\-BINSTUBS"
If you use the \fB\-\-binstubs\fR flag in bundle install(1) \fIbundle\-install\.1\.html\fR, Bundler will automatically create a directory (which defaults to \fBapp_root/bin\fR) containing all of the executables available from gems in the bundle\.
-.
.P
After using \fB\-\-binstubs\fR, \fBbin/rspec spec/my_spec\.rb\fR is identical to \fBbundle exec rspec spec/my_spec\.rb\fR\.
-.
.SH "ENVIRONMENT MODIFICATIONS"
\fBbundle exec\fR makes a number of changes to the shell environment, then executes the command you specify in full\.
-.
.IP "\(bu" 4
-make sure that it\'s still possible to shell out to \fBbundle\fR from inside a command invoked by \fBbundle exec\fR (using \fB$BUNDLE_BIN_PATH\fR)
-.
+make sure that it's still possible to shell out to \fBbundle\fR from inside a command invoked by \fBbundle exec\fR (using \fB$BUNDLE_BIN_PATH\fR)
.IP "\(bu" 4
put the directory containing executables (like \fBrails\fR, \fBrspec\fR, \fBrackup\fR) for your bundle on \fB$PATH\fR
-.
.IP "\(bu" 4
make sure that if bundler is invoked in the subshell, it uses the same \fBGemfile\fR (by setting \fBBUNDLE_GEMFILE\fR)
-.
.IP "\(bu" 4
add \fB\-rbundler/setup\fR to \fB$RUBYOPT\fR, which makes sure that Ruby programs invoked in the subshell can see the gems in the bundle
-.
.IP "" 0
-.
.P
It also modifies Rubygems:
-.
.IP "\(bu" 4
disallow loading additional gems not in the bundle
-.
.IP "\(bu" 4
-modify the \fBgem\fR method to be a no\-op if a gem matching the requirements is in the bundle, and to raise a \fBGem::LoadError\fR if it\'s not
-.
+modify the \fBgem\fR method to be a no\-op if a gem matching the requirements is in the bundle, and to raise a \fBGem::LoadError\fR if it's not
.IP "\(bu" 4
Define \fBGem\.refresh\fR to be a no\-op, since the source index is always frozen when using bundler, and to prevent gems from the system leaking into the environment
-.
.IP "\(bu" 4
Override \fBGem\.bin_path\fR to use the gems in the bundle, making system executables work
-.
.IP "\(bu" 4
Add all gems in the bundle into Gem\.loaded_specs
-.
.IP "" 0
-.
.P
-Finally, \fBbundle exec\fR also implicitly modifies \fBGemfile\.lock\fR if the lockfile and the Gemfile do not match\. Bundler needs the Gemfile to determine things such as a gem\'s groups, \fBautorequire\fR, and platforms, etc\., and that information isn\'t stored in the lockfile\. The Gemfile and lockfile must be synced in order to \fBbundle exec\fR successfully, so \fBbundle exec\fR updates the lockfile beforehand\.
-.
+Finally, \fBbundle exec\fR also implicitly modifies \fBGemfile\.lock\fR if the lockfile and the Gemfile do not match\. Bundler needs the Gemfile to determine things such as a gem's groups, \fBautorequire\fR, and platforms, etc\., and that information isn't stored in the lockfile\. The Gemfile and lockfile must be synced in order to \fBbundle exec\fR successfully, so \fBbundle exec\fR updates the lockfile beforehand\.
.SS "Loading"
By default, when attempting to \fBbundle exec\fR to a file with a ruby shebang, Bundler will \fBKernel\.load\fR that file instead of using \fBKernel\.exec\fR\. For the vast majority of cases, this is a performance improvement\. In a rare few cases, this could cause some subtle side\-effects (such as dependence on the exact contents of \fB$0\fR or \fB__FILE__\fR) and the optimization can be disabled by enabling the \fBdisable_exec_load\fR setting\.
-.
.SS "Shelling out"
-Any Ruby code that opens a subshell (like \fBsystem\fR, backticks, or \fB%x{}\fR) will automatically use the current Bundler environment\. If you need to shell out to a Ruby command that is not part of your current bundle, use the \fBwith_unbundled_env\fR method with a block\. Any subshells created inside the block will be given the environment present before Bundler was activated\. For example, Homebrew commands run Ruby, but don\'t work inside a bundle:
-.
+Any Ruby code that opens a subshell (like \fBsystem\fR, backticks, or \fB%x{}\fR) will automatically use the current Bundler environment\. If you need to shell out to a Ruby command that is not part of your current bundle, use the \fBwith_unbundled_env\fR method with a block\. Any subshells created inside the block will be given the environment present before Bundler was activated\. For example, Homebrew commands run Ruby, but don't work inside a bundle:
.IP "" 4
-.
.nf
-
Bundler\.with_unbundled_env do
`brew install wget`
end
-.
.fi
-.
.IP "" 0
-.
.P
Using \fBwith_unbundled_env\fR is also necessary if you are shelling out to a different bundle\. Any Bundler commands run in a subshell will inherit the current Gemfile, so commands that need to run in the context of a different bundle also need to use \fBwith_unbundled_env\fR\.
-.
.IP "" 4
-.
.nf
-
Bundler\.with_unbundled_env do
Dir\.chdir "/other/bundler/project" do
`bundle exec \./script`
end
end
-.
.fi
-.
.IP "" 0
-.
.P
Bundler provides convenience helpers that wrap \fBsystem\fR and \fBexec\fR, and they can be used like this:
-.
.IP "" 4
-.
.nf
-
-Bundler\.clean_system(\'brew install wget\')
-Bundler\.clean_exec(\'brew install wget\')
-.
+Bundler\.clean_system('brew install wget')
+Bundler\.clean_exec('brew install wget')
.fi
-.
.IP "" 0
-.
.SH "RUBYGEMS PLUGINS"
At present, the Rubygems plugin system requires all files named \fBrubygems_plugin\.rb\fR on the load path of \fIany\fR installed gem when any Ruby code requires \fBrubygems\.rb\fR\. This includes executables installed into the system, like \fBrails\fR, \fBrackup\fR, and \fBrspec\fR\.
-.
.P
Since Rubygems plugins can contain arbitrary Ruby code, they commonly end up activating themselves or their dependencies\.
-.
.P
For instance, the \fBgemcutter 0\.5\fR gem depended on \fBjson_pure\fR\. If you had that version of gemcutter installed (even if you \fIalso\fR had a newer version without this problem), Rubygems would activate \fBgemcutter 0\.5\fR and \fBjson_pure <latest>\fR\.
-.
.P
If your Gemfile(5) also contained \fBjson_pure\fR (or a gem with a dependency on \fBjson_pure\fR), the latest version on your system might conflict with the version in your Gemfile(5), or the snapshot version in your \fBGemfile\.lock\fR\.
-.
.P
If this happens, bundler will say:
-.
.IP "" 4
-.
.nf
-
You have already activated json_pure 1\.4\.6 but your Gemfile
requires json_pure 1\.4\.3\. Consider using bundle exec\.
-.
.fi
-.
.IP "" 0
-.
.P
In this situation, you almost certainly want to remove the underlying gem with the problematic gem plugin\. In general, the authors of these plugins (in this case, the \fBgemcutter\fR gem) have released newer versions that are more careful in their plugins\.
-.
.P
You can find a list of all the gems containing gem plugins by running
-.
.IP "" 4
-.
.nf
-
-ruby \-e "puts Gem\.find_files(\'rubygems_plugin\.rb\')"
-.
+ruby \-e "puts Gem\.find_files('rubygems_plugin\.rb')"
.fi
-.
.IP "" 0
-.
.P
-At the very least, you should remove all but the newest version of each gem plugin, and also remove all gem plugins that you aren\'t using (\fBgem uninstall gem_name\fR)\.
+At the very least, you should remove all but the newest version of each gem plugin, and also remove all gem plugins that you aren't using (\fBgem uninstall gem_name\fR)\.
diff --git a/lib/bundler/man/bundle-gem.1 b/lib/bundler/man/bundle-gem.1
index 825c46fd47..5df7b0ef2f 100644
--- a/lib/bundler/man/bundle-gem.1
+++ b/lib/bundler/man/bundle-gem.1
@@ -1,105 +1,69 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-GEM" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-GEM" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-gem\fR \- Generate a project skeleton for creating a rubygem
-.
.SH "SYNOPSIS"
\fBbundle gem\fR \fIGEM_NAME\fR \fIOPTIONS\fR
-.
.SH "DESCRIPTION"
Generates a directory named \fBGEM_NAME\fR with a \fBRakefile\fR, \fBGEM_NAME\.gemspec\fR, and other supporting files and directories that can be used to develop a rubygem with that name\.
-.
.P
Run \fBrake \-T\fR in the resulting project for a list of Rake tasks that can be used to test and publish the gem to rubygems\.org\.
-.
.P
-The generated project skeleton can be customized with OPTIONS, as explained below\. Note that these options can also be specified via Bundler\'s global configuration file using the following names:
-.
+The generated project skeleton can be customized with OPTIONS, as explained below\. Note that these options can also be specified via Bundler's global configuration file using the following names:
.IP "\(bu" 4
\fBgem\.coc\fR
-.
.IP "\(bu" 4
\fBgem\.mit\fR
-.
.IP "\(bu" 4
\fBgem\.test\fR
-.
.IP "" 0
-.
.SH "OPTIONS"
-.
.IP "\(bu" 4
\fB\-\-exe\fR or \fB\-b\fR or \fB\-\-bin\fR: Specify that Bundler should create a binary executable (as \fBexe/GEM_NAME\fR) in the generated rubygem project\. This binary will also be added to the \fBGEM_NAME\.gemspec\fR manifest\. This behavior is disabled by default\.
-.
.IP "\(bu" 4
\fB\-\-no\-exe\fR: Do not create a binary (overrides \fB\-\-exe\fR specified in the global config)\.
-.
.IP "\(bu" 4
-\fB\-\-coc\fR: Add a \fBCODE_OF_CONDUCT\.md\fR file to the root of the generated project\. If this option is unspecified, an interactive prompt will be displayed and the answer will be saved in Bundler\'s global config for future \fBbundle gem\fR use\.
-.
+\fB\-\-coc\fR: Add a \fBCODE_OF_CONDUCT\.md\fR file to the root of the generated project\. If this option is unspecified, an interactive prompt will be displayed and the answer will be saved in Bundler's global config for future \fBbundle gem\fR use\.
.IP "\(bu" 4
\fB\-\-no\-coc\fR: Do not create a \fBCODE_OF_CONDUCT\.md\fR (overrides \fB\-\-coc\fR specified in the global config)\.
-.
.IP "\(bu" 4
\fB\-\-ext=c\fR, \fB\-\-ext=rust\fR Add boilerplate for C or Rust (currently magnus \fIhttps://docs\.rs/magnus\fR based) extension code to the generated project\. This behavior is disabled by default\.
-.
.IP "\(bu" 4
\fB\-\-no\-ext\fR: Do not add extension code (overrides \fB\-\-ext\fR specified in the global config)\.
-.
.IP "\(bu" 4
-\fB\-\-mit\fR: Add an MIT license to a \fBLICENSE\.txt\fR file in the root of the generated project\. Your name from the global git config is used for the copyright statement\. If this option is unspecified, an interactive prompt will be displayed and the answer will be saved in Bundler\'s global config for future \fBbundle gem\fR use\.
-.
+\fB\-\-mit\fR: Add an MIT license to a \fBLICENSE\.txt\fR file in the root of the generated project\. Your name from the global git config is used for the copyright statement\. If this option is unspecified, an interactive prompt will be displayed and the answer will be saved in Bundler's global config for future \fBbundle gem\fR use\.
.IP "\(bu" 4
\fB\-\-no\-mit\fR: Do not create a \fBLICENSE\.txt\fR (overrides \fB\-\-mit\fR specified in the global config)\.
-.
.IP "\(bu" 4
\fB\-t\fR, \fB\-\-test=minitest\fR, \fB\-\-test=rspec\fR, \fB\-\-test=test\-unit\fR: Specify the test framework that Bundler should use when generating the project\. Acceptable values are \fBminitest\fR, \fBrspec\fR and \fBtest\-unit\fR\. The \fBGEM_NAME\.gemspec\fR will be configured and a skeleton test/spec directory will be created based on this option\. Given no option is specified:
-.
.IP
-When Bundler is configured to generate tests, this defaults to Bundler\'s global config setting \fBgem\.test\fR\.
-.
+When Bundler is configured to generate tests, this defaults to Bundler's global config setting \fBgem\.test\fR\.
.IP
When Bundler is configured to not generate tests, an interactive prompt will be displayed and the answer will be used for the current rubygem project\.
-.
.IP
-When Bundler is unconfigured, an interactive prompt will be displayed and the answer will be saved in Bundler\'s global config for future \fBbundle gem\fR use\.
-.
+When Bundler is unconfigured, an interactive prompt will be displayed and the answer will be saved in Bundler's global config for future \fBbundle gem\fR use\.
.IP "\(bu" 4
\fB\-\-ci\fR, \fB\-\-ci=github\fR, \fB\-\-ci=gitlab\fR, \fB\-\-ci=circle\fR: Specify the continuous integration service that Bundler should use when generating the project\. Acceptable values are \fBgithub\fR, \fBgitlab\fR and \fBcircle\fR\. A configuration file will be generated in the project directory\. Given no option is specified:
-.
.IP
-When Bundler is configured to generate CI files, this defaults to Bundler\'s global config setting \fBgem\.ci\fR\.
-.
+When Bundler is configured to generate CI files, this defaults to Bundler's global config setting \fBgem\.ci\fR\.
.IP
When Bundler is configured to not generate CI files, an interactive prompt will be displayed and the answer will be used for the current rubygem project\.
-.
.IP
-When Bundler is unconfigured, an interactive prompt will be displayed and the answer will be saved in Bundler\'s global config for future \fBbundle gem\fR use\.
-.
+When Bundler is unconfigured, an interactive prompt will be displayed and the answer will be saved in Bundler's global config for future \fBbundle gem\fR use\.
.IP "\(bu" 4
-\fB\-\-linter\fR, \fB\-\-linter=rubocop\fR, \fB\-\-linter=standard\fR: Specify the linter and code formatter that Bundler should add to the project\'s development dependencies\. Acceptable values are \fBrubocop\fR and \fBstandard\fR\. A configuration file will be generated in the project directory\. Given no option is specified:
-.
+\fB\-\-linter\fR, \fB\-\-linter=rubocop\fR, \fB\-\-linter=standard\fR: Specify the linter and code formatter that Bundler should add to the project's development dependencies\. Acceptable values are \fBrubocop\fR and \fBstandard\fR\. A configuration file will be generated in the project directory\. Given no option is specified:
.IP
-When Bundler is configured to add a linter, this defaults to Bundler\'s global config setting \fBgem\.linter\fR\.
-.
+When Bundler is configured to add a linter, this defaults to Bundler's global config setting \fBgem\.linter\fR\.
.IP
When Bundler is configured not to add a linter, an interactive prompt will be displayed and the answer will be used for the current rubygem project\.
-.
.IP
-When Bundler is unconfigured, an interactive prompt will be displayed and the answer will be saved in Bundler\'s global config for future \fBbundle gem\fR use\.
-.
+When Bundler is unconfigured, an interactive prompt will be displayed and the answer will be saved in Bundler's global config for future \fBbundle gem\fR use\.
.IP "\(bu" 4
\fB\-e\fR, \fB\-\-edit[=EDITOR]\fR: Open the resulting GEM_NAME\.gemspec in EDITOR, or the default editor if not specified\. The default is \fB$BUNDLER_EDITOR\fR, \fB$VISUAL\fR, or \fB$EDITOR\fR\.
-.
.IP "" 0
-.
.SH "SEE ALSO"
-.
.IP "\(bu" 4
bundle config(1) \fIbundle\-config\.1\.html\fR
-.
.IP "" 0
diff --git a/lib/bundler/man/bundle-help.1 b/lib/bundler/man/bundle-help.1
index 26309a2e68..a3e7c7770d 100644
--- a/lib/bundler/man/bundle-help.1
+++ b/lib/bundler/man/bundle-help.1
@@ -1,13 +1,9 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-HELP" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-HELP" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-help\fR \- Displays detailed help for each subcommand
-.
.SH "SYNOPSIS"
\fBbundle help\fR [COMMAND]
-.
.SH "DESCRIPTION"
Displays detailed help for the given subcommand\. You can specify a single \fBCOMMAND\fR at the same time\. When \fBCOMMAND\fR is omitted, help for \fBhelp\fR command will be displayed\.
diff --git a/lib/bundler/man/bundle-info.1 b/lib/bundler/man/bundle-info.1
index d6049aa667..a3d7ff0988 100644
--- a/lib/bundler/man/bundle-info.1
+++ b/lib/bundler/man/bundle-info.1
@@ -1,19 +1,13 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-INFO" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-INFO" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-info\fR \- Show information for the given gem in your bundle
-.
.SH "SYNOPSIS"
\fBbundle info\fR [GEM_NAME] [\-\-path]
-.
.SH "DESCRIPTION"
Given a gem name present in your bundle, print the basic information about it such as homepage, version, path and summary\.
-.
.SH "OPTIONS"
-.
.TP
\fB\-\-path\fR
Print the path of the given gem
diff --git a/lib/bundler/man/bundle-init.1 b/lib/bundler/man/bundle-init.1
index 3514ae40e1..a0edaaa18f 100644
--- a/lib/bundler/man/bundle-init.1
+++ b/lib/bundler/man/bundle-init.1
@@ -1,29 +1,20 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-INIT" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-INIT" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-init\fR \- Generates a Gemfile into the current working directory
-.
.SH "SYNOPSIS"
\fBbundle init\fR [\-\-gemspec=FILE]
-.
.SH "DESCRIPTION"
Init generates a default [\fBGemfile(5)\fR][Gemfile(5)] in the current working directory\. When adding a [\fBGemfile(5)\fR][Gemfile(5)] to a gem with a gemspec, the \fB\-\-gemspec\fR option will automatically add each dependency listed in the gemspec file to the newly created [\fBGemfile(5)\fR][Gemfile(5)]\.
-.
.SH "OPTIONS"
-.
.TP
\fB\-\-gemspec\fR
Use the specified \.gemspec to create the [\fBGemfile(5)\fR][Gemfile(5)]
-.
.TP
\fB\-\-gemfile\fR
Use the specified name for the gemfile instead of \fBGemfile\fR
-.
.SH "FILES"
Included in the default [\fBGemfile(5)\fR][Gemfile(5)] generated is the line \fB# frozen_string_literal: true\fR\. This is a magic comment supported for the first time in Ruby 2\.3\. The presence of this line results in all string literals in the file being implicitly frozen\.
-.
.SH "SEE ALSO"
Gemfile(5) \fIhttps://bundler\.io/man/gemfile\.5\.html\fR
diff --git a/lib/bundler/man/bundle-inject.1 b/lib/bundler/man/bundle-inject.1
index 21fb8734fe..7a1038206e 100644
--- a/lib/bundler/man/bundle-inject.1
+++ b/lib/bundler/man/bundle-inject.1
@@ -1,36 +1,23 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-INJECT" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-INJECT" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-inject\fR \- Add named gem(s) with version requirements to Gemfile
-.
.SH "SYNOPSIS"
\fBbundle inject\fR [GEM] [VERSION]
-.
.SH "DESCRIPTION"
Adds the named gem(s) with their version requirements to the resolved [\fBGemfile(5)\fR][Gemfile(5)]\.
-.
.P
-This command will add the gem to both your [\fBGemfile(5)\fR][Gemfile(5)] and Gemfile\.lock if it isn\'t listed yet\.
-.
+This command will add the gem to both your [\fBGemfile(5)\fR][Gemfile(5)] and Gemfile\.lock if it isn't listed yet\.
.P
Example:
-.
.IP "" 4
-.
.nf
-
bundle install
-bundle inject \'rack\' \'> 0\'
-.
+bundle inject 'rack' '> 0'
.fi
-.
.IP "" 0
-.
.P
-This will inject the \'rack\' gem with a version greater than 0 in your [\fBGemfile(5)\fR][Gemfile(5)] and Gemfile\.lock\.
-.
+This will inject the 'rack' gem with a version greater than 0 in your [\fBGemfile(5)\fR][Gemfile(5)] and Gemfile\.lock\.
.P
The \fBbundle inject\fR command was deprecated in Bundler 2\.1 and will be removed in Bundler 3\.0\.
diff --git a/lib/bundler/man/bundle-install.1 b/lib/bundler/man/bundle-install.1
index 70dccc6078..cc46a03b7f 100644
--- a/lib/bundler/man/bundle-install.1
+++ b/lib/bundler/man/bundle-install.1
@@ -1,313 +1,215 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-INSTALL" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-INSTALL" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-install\fR \- Install the dependencies specified in your Gemfile
-.
.SH "SYNOPSIS"
-\fBbundle install\fR [\-\-binstubs[=DIRECTORY]] [\-\-clean] [\-\-deployment] [\-\-frozen] [\-\-full\-index] [\-\-gemfile=GEMFILE] [\-\-jobs=NUMBER] [\-\-local] [\-\-no\-cache] [\-\-no\-prune] [\-\-path PATH] [\-\-quiet] [\-\-redownload] [\-\-retry=NUMBER] [\-\-shebang] [\-\-standalone[=GROUP[ GROUP\.\.\.]]] [\-\-system] [\-\-trust\-policy=POLICY] [\-\-with=GROUP[ GROUP\.\.\.]] [\-\-without=GROUP[ GROUP\.\.\.]]
-.
+\fBbundle install\fR [\-\-binstubs[=DIRECTORY]] [\-\-clean] [\-\-deployment] [\-\-frozen] [\-\-full\-index] [\-\-gemfile=GEMFILE] [\-\-jobs=NUMBER] [\-\-local] [\-\-no\-cache] [\-\-no\-prune] [\-\-path PATH] [\-\-prefer\-local] [\-\-quiet] [\-\-redownload] [\-\-retry=NUMBER] [\-\-shebang] [\-\-standalone[=GROUP[ GROUP\|\.\|\.\|\.]]] [\-\-system] [\-\-trust\-policy=POLICY] [\-\-with=GROUP[ GROUP\|\.\|\.\|\.]] [\-\-without=GROUP[ GROUP\|\.\|\.\|\.]]
.SH "DESCRIPTION"
Install the gems specified in your Gemfile(5)\. If this is the first time you run bundle install (and a \fBGemfile\.lock\fR does not exist), Bundler will fetch all remote sources, resolve dependencies and install all needed gems\.
-.
.P
If a \fBGemfile\.lock\fR does exist, and you have not updated your Gemfile(5), Bundler will fetch all remote sources, but use the dependencies specified in the \fBGemfile\.lock\fR instead of resolving dependencies\.
-.
.P
If a \fBGemfile\.lock\fR does exist, and you have updated your Gemfile(5), Bundler will use the dependencies in the \fBGemfile\.lock\fR for all gems that you did not update, but will re\-resolve the dependencies of gems that you did update\. You can find more information about this update process below under \fICONSERVATIVE UPDATING\fR\.
-.
.SH "OPTIONS"
The \fB\-\-clean\fR, \fB\-\-deployment\fR, \fB\-\-frozen\fR, \fB\-\-no\-prune\fR, \fB\-\-path\fR, \fB\-\-shebang\fR, \fB\-\-system\fR, \fB\-\-without\fR and \fB\-\-with\fR options are deprecated because they only make sense if they are applied to every subsequent \fBbundle install\fR run automatically and that requires \fBbundler\fR to silently remember them\. Since \fBbundler\fR will no longer remember CLI flags in future versions, \fBbundle config\fR (see bundle\-config(1)) should be used to apply them permanently\.
-.
.TP
\fB\-\-binstubs[=<directory>]\fR
Binstubs are scripts that wrap around executables\. Bundler creates a small Ruby file (a binstub) that loads Bundler, runs the command, and puts it in \fBbin/\fR\. This lets you link the binstub inside of an application to the exact gem version the application needs\.
-.
.IP
-Creates a directory (defaults to \fB~/bin\fR) and places any executables from the gem there\. These executables run in Bundler\'s context\. If used, you might add this directory to your environment\'s \fBPATH\fR variable\. For instance, if the \fBrails\fR gem comes with a \fBrails\fR executable, this flag will create a \fBbin/rails\fR executable that ensures that all referred dependencies will be resolved using the bundled gems\.
-.
+Creates a directory (defaults to \fB~/bin\fR) and places any executables from the gem there\. These executables run in Bundler's context\. If used, you might add this directory to your environment's \fBPATH\fR variable\. For instance, if the \fBrails\fR gem comes with a \fBrails\fR executable, this flag will create a \fBbin/rails\fR executable that ensures that all referred dependencies will be resolved using the bundled gems\.
.TP
\fB\-\-clean\fR
-On finishing the installation Bundler is going to remove any gems not present in the current Gemfile(5)\. Don\'t worry, gems currently in use will not be removed\.
-.
+On finishing the installation Bundler is going to remove any gems not present in the current Gemfile(5)\. Don't worry, gems currently in use will not be removed\.
.IP
This option is deprecated in favor of the \fBclean\fR setting\.
-.
.TP
\fB\-\-deployment\fR
-In \fIdeployment mode\fR, Bundler will \'roll\-out\' the bundle for production or CI use\. Please check carefully if you want to have this option enabled in your development environment\.
-.
+In \fIdeployment mode\fR, Bundler will 'roll\-out' the bundle for production or CI use\. Please check carefully if you want to have this option enabled in your development environment\.
.IP
This option is deprecated in favor of the \fBdeployment\fR setting\.
-.
.TP
\fB\-\-redownload\fR
Force download every gem, even if the required versions are already available locally\.
-.
.TP
\fB\-\-frozen\fR
Do not allow the Gemfile\.lock to be updated after this install\. Exits non\-zero if there are going to be changes to the Gemfile\.lock\.
-.
.IP
This option is deprecated in favor of the \fBfrozen\fR setting\.
-.
.TP
\fB\-\-full\-index\fR
-Bundler will not call Rubygems\' API endpoint (default) but download and cache a (currently big) index file of all gems\. Performance can be improved for large bundles that seldom change by enabling this option\.
-.
+Bundler will not call Rubygems' API endpoint (default) but download and cache a (currently big) index file of all gems\. Performance can be improved for large bundles that seldom change by enabling this option\.
.TP
\fB\-\-gemfile=<gemfile>\fR
-The location of the Gemfile(5) which Bundler should use\. This defaults to a Gemfile(5) in the current working directory\. In general, Bundler will assume that the location of the Gemfile(5) is also the project\'s root and will try to find \fBGemfile\.lock\fR and \fBvendor/cache\fR relative to this location\.
-.
+The location of the Gemfile(5) which Bundler should use\. This defaults to a Gemfile(5) in the current working directory\. In general, Bundler will assume that the location of the Gemfile(5) is also the project's root and will try to find \fBGemfile\.lock\fR and \fBvendor/cache\fR relative to this location\.
.TP
\fB\-\-jobs=[<number>]\fR, \fB\-j[<number>]\fR
The maximum number of parallel download and install jobs\. The default is the number of available processors\.
-.
.TP
\fB\-\-local\fR
-Do not attempt to connect to \fBrubygems\.org\fR\. Instead, Bundler will use the gems already present in Rubygems\' cache or in \fBvendor/cache\fR\. Note that if an appropriate platform\-specific gem exists on \fBrubygems\.org\fR it will not be found\.
-.
+Do not attempt to connect to \fBrubygems\.org\fR\. Instead, Bundler will use the gems already present in Rubygems' cache or in \fBvendor/cache\fR\. Note that if an appropriate platform\-specific gem exists on \fBrubygems\.org\fR it will not be found\.
.TP
\fB\-\-prefer\-local\fR
-Force using locally installed gems, or gems already present in Rubygems\' cache or in \fBvendor/cache\fR, when resolving, even if newer versions are available remotely\. Only attempt to connect to \fBrubygems\.org\fR for gems that are not present locally\.
-.
+Force using locally installed gems, or gems already present in Rubygems' cache or in \fBvendor/cache\fR, when resolving, even if newer versions are available remotely\. Only attempt to connect to \fBrubygems\.org\fR for gems that are not present locally\.
.TP
\fB\-\-no\-cache\fR
Do not update the cache in \fBvendor/cache\fR with the newly bundled gems\. This does not remove any gems in the cache but keeps the newly bundled gems from being cached during the install\.
-.
.TP
\fB\-\-no\-prune\fR
-Don\'t remove stale gems from the cache when the installation finishes\.
-.
+Don't remove stale gems from the cache when the installation finishes\.
.IP
This option is deprecated in favor of the \fBno_prune\fR setting\.
-.
.TP
\fB\-\-path=<path>\fR
-The location to install the specified gems to\. This defaults to Rubygems\' setting\. Bundler shares this location with Rubygems, \fBgem install \.\.\.\fR will have gem installed there, too\. Therefore, gems installed without a \fB\-\-path \.\.\.\fR setting will show up by calling \fBgem list\fR\. Accordingly, gems installed to other locations will not get listed\.
-.
+The location to install the specified gems to\. This defaults to Rubygems' setting\. Bundler shares this location with Rubygems, \fBgem install \|\.\|\.\|\.\fR will have gem installed there, too\. Therefore, gems installed without a \fB\-\-path \|\.\|\.\|\.\fR setting will show up by calling \fBgem list\fR\. Accordingly, gems installed to other locations will not get listed\.
.IP
This option is deprecated in favor of the \fBpath\fR setting\.
-.
.TP
\fB\-\-quiet\fR
Do not print progress information to the standard output\. Instead, Bundler will exit using a status code (\fB$?\fR)\.
-.
.TP
\fB\-\-retry=[<number>]\fR
Retry failed network or git requests for \fInumber\fR times\.
-.
.TP
\fB\-\-shebang=<ruby\-executable>\fR
Uses the specified ruby executable (usually \fBruby\fR) to execute the scripts created with \fB\-\-binstubs\fR\. In addition, if you use \fB\-\-binstubs\fR together with \fB\-\-shebang jruby\fR these executables will be changed to execute \fBjruby\fR instead\.
-.
.IP
This option is deprecated in favor of the \fBshebang\fR setting\.
-.
.TP
\fB\-\-standalone[=<list>]\fR
-Makes a bundle that can work without depending on Rubygems or Bundler at runtime\. A space separated list of groups to install has to be specified\. Bundler creates a directory named \fBbundle\fR and installs the bundle there\. It also generates a \fBbundle/bundler/setup\.rb\fR file to replace Bundler\'s own setup in the manner required\. Using this option implicitly sets \fBpath\fR, which is a [remembered option][REMEMBERED OPTIONS]\.
-.
+Makes a bundle that can work without depending on Rubygems or Bundler at runtime\. A space separated list of groups to install has to be specified\. Bundler creates a directory named \fBbundle\fR and installs the bundle there\. It also generates a \fBbundle/bundler/setup\.rb\fR file to replace Bundler's own setup in the manner required\. Using this option implicitly sets \fBpath\fR, which is a [remembered option][REMEMBERED OPTIONS]\.
.TP
\fB\-\-system\fR
-Installs the gems specified in the bundle to the system\'s Rubygems location\. This overrides any previous configuration of \fB\-\-path\fR\.
-.
+Installs the gems specified in the bundle to the system's Rubygems location\. This overrides any previous configuration of \fB\-\-path\fR\.
.IP
This option is deprecated in favor of the \fBsystem\fR setting\.
-.
.TP
\fB\-\-trust\-policy=[<policy>]\fR
Apply the Rubygems security policy \fIpolicy\fR, where policy is one of \fBHighSecurity\fR, \fBMediumSecurity\fR, \fBLowSecurity\fR, \fBAlmostNoSecurity\fR, or \fBNoSecurity\fR\. For more details, please see the Rubygems signing documentation linked below in \fISEE ALSO\fR\.
-.
.TP
\fB\-\-with=<list>\fR
A space\-separated list of groups referencing gems to install\. If an optional group is given it is installed\. If a group is given that is in the remembered list of groups given to \-\-without, it is removed from that list\.
-.
.IP
This option is deprecated in favor of the \fBwith\fR setting\.
-.
.TP
\fB\-\-without=<list>\fR
A space\-separated list of groups referencing gems to skip during installation\. If a group is given that is in the remembered list of groups given to \-\-with, it is removed from that list\.
-.
.IP
This option is deprecated in favor of the \fBwithout\fR setting\.
-.
.SH "DEPLOYMENT MODE"
-Bundler\'s defaults are optimized for development\. To switch to defaults optimized for deployment and for CI, use the \fB\-\-deployment\fR flag\. Do not activate deployment mode on development machines, as it will cause an error when the Gemfile(5) is modified\.
-.
+Bundler's defaults are optimized for development\. To switch to defaults optimized for deployment and for CI, use the \fB\-\-deployment\fR flag\. Do not activate deployment mode on development machines, as it will cause an error when the Gemfile(5) is modified\.
.IP "1." 4
A \fBGemfile\.lock\fR is required\.
-.
.IP
To ensure that the same versions of the gems you developed with and tested with are also used in deployments, a \fBGemfile\.lock\fR is required\.
-.
.IP
This is mainly to ensure that you remember to check your \fBGemfile\.lock\fR into version control\.
-.
.IP "2." 4
The \fBGemfile\.lock\fR must be up to date
-.
.IP
In development, you can modify your Gemfile(5) and re\-run \fBbundle install\fR to \fIconservatively update\fR your \fBGemfile\.lock\fR snapshot\.
-.
.IP
In deployment, your \fBGemfile\.lock\fR should be up\-to\-date with changes made in your Gemfile(5)\.
-.
.IP "3." 4
Gems are installed to \fBvendor/bundle\fR not your default system location
-.
.IP
-In development, it\'s convenient to share the gems used in your application with other applications and other scripts that run on the system\.
-.
+In development, it's convenient to share the gems used in your application with other applications and other scripts that run on the system\.
.IP
In deployment, isolation is a more important default\. In addition, the user deploying the application may not have permission to install gems to the system, or the web server may not have permission to read them\.
-.
.IP
As a result, \fBbundle install \-\-deployment\fR installs gems to the \fBvendor/bundle\fR directory in the application\. This may be overridden using the \fB\-\-path\fR option\.
-.
.IP "" 0
-.
.SH "INSTALLING GROUPS"
By default, \fBbundle install\fR will install all gems in all groups in your Gemfile(5), except those declared for a different platform\.
-.
.P
However, you can explicitly tell Bundler to skip installing certain groups with the \fB\-\-without\fR option\. This option takes a space\-separated list of groups\.
-.
.P
While the \fB\-\-without\fR option will skip \fIinstalling\fR the gems in the specified groups, it will still \fIdownload\fR those gems and use them to resolve the dependencies of every gem in your Gemfile(5)\.
-.
.P
This is so that installing a different set of groups on another machine (such as a production server) will not change the gems and versions that you have already developed and tested against\.
-.
.P
\fBBundler offers a rock\-solid guarantee that the third\-party code you are running in development and testing is also the third\-party code you are running in production\. You can choose to exclude some of that code in different environments, but you will never be caught flat\-footed by different versions of third\-party code being used in different environments\.\fR
-.
.P
For a simple illustration, consider the following Gemfile(5):
-.
.IP "" 4
-.
.nf
+source 'https://rubygems\.org'
-source \'https://rubygems\.org\'
-
-gem \'sinatra\'
+gem 'sinatra'
group :production do
- gem \'rack\-perftools\-profiler\'
+ gem 'rack\-perftools\-profiler'
end
-.
.fi
-.
.IP "" 0
-.
.P
In this case, \fBsinatra\fR depends on any version of Rack (\fB>= 1\.0\fR), while \fBrack\-perftools\-profiler\fR depends on 1\.x (\fB~> 1\.0\fR)\.
-.
.P
When you run \fBbundle install \-\-without production\fR in development, we look at the dependencies of \fBrack\-perftools\-profiler\fR as well\. That way, you do not spend all your time developing against Rack 2\.0, using new APIs unavailable in Rack 1\.x, only to have Bundler switch to Rack 1\.2 when the \fBproduction\fR group \fIis\fR used\.
-.
.P
This should not cause any problems in practice, because we do not attempt to \fBinstall\fR the gems in the excluded groups, and only evaluate as part of the dependency resolution process\.
-.
.P
This also means that you cannot include different versions of the same gem in different groups, because doing so would result in different sets of dependencies used in development and production\. Because of the vagaries of the dependency resolution process, this usually affects more than the gems you list in your Gemfile(5), and can (surprisingly) radically change the gems you are using\.
-.
.SH "THE GEMFILE\.LOCK"
When you run \fBbundle install\fR, Bundler will persist the full names and versions of all gems that you used (including dependencies of the gems specified in the Gemfile(5)) into a file called \fBGemfile\.lock\fR\.
-.
.P
Bundler uses this file in all subsequent calls to \fBbundle install\fR, which guarantees that you always use the same exact code, even as your application moves across machines\.
-.
.P
Because of the way dependency resolution works, even a seemingly small change (for instance, an update to a point\-release of a dependency of a gem in your Gemfile(5)) can result in radically different gems being needed to satisfy all dependencies\.
-.
.P
As a result, you \fBSHOULD\fR check your \fBGemfile\.lock\fR into version control, in both applications and gems\. If you do not, every machine that checks out your repository (including your production server) will resolve all dependencies again, which will result in different versions of third\-party code being used if \fBany\fR of the gems in the Gemfile(5) or any of their dependencies have been updated\.
-.
.P
When Bundler first shipped, the \fBGemfile\.lock\fR was included in the \fB\.gitignore\fR file included with generated gems\. Over time, however, it became clear that this practice forces the pain of broken dependencies onto new contributors, while leaving existing contributors potentially unaware of the problem\. Since \fBbundle install\fR is usually the first step towards a contribution, the pain of broken dependencies would discourage new contributors from contributing\. As a result, we have revised our guidance for gem authors to now recommend checking in the lock for gems\.
-.
.SH "CONSERVATIVE UPDATING"
When you make a change to the Gemfile(5) and then run \fBbundle install\fR, Bundler will update only the gems that you modified\.
-.
.P
In other words, if a gem that you \fBdid not modify\fR worked before you called \fBbundle install\fR, it will continue to use the exact same versions of all dependencies as it used before the update\.
-.
.P
-Let\'s take a look at an example\. Here\'s your original Gemfile(5):
-.
+Let's take a look at an example\. Here's your original Gemfile(5):
.IP "" 4
-.
.nf
+source 'https://rubygems\.org'
-source \'https://rubygems\.org\'
-
-gem \'actionpack\', \'2\.3\.8\'
-gem \'activemerchant\'
-.
+gem 'actionpack', '2\.3\.8'
+gem 'activemerchant'
.fi
-.
.IP "" 0
-.
.P
In this case, both \fBactionpack\fR and \fBactivemerchant\fR depend on \fBactivesupport\fR\. The \fBactionpack\fR gem depends on \fBactivesupport 2\.3\.8\fR and \fBrack ~> 1\.1\.0\fR, while the \fBactivemerchant\fR gem depends on \fBactivesupport >= 2\.3\.2\fR, \fBbraintree >= 2\.0\.0\fR, and \fBbuilder >= 2\.0\.0\fR\.
-.
.P
When the dependencies are first resolved, Bundler will select \fBactivesupport 2\.3\.8\fR, which satisfies the requirements of both gems in your Gemfile(5)\.
-.
.P
Next, you modify your Gemfile(5) to:
-.
.IP "" 4
-.
.nf
+source 'https://rubygems\.org'
-source \'https://rubygems\.org\'
-
-gem \'actionpack\', \'3\.0\.0\.rc\'
-gem \'activemerchant\'
-.
+gem 'actionpack', '3\.0\.0\.rc'
+gem 'activemerchant'
.fi
-.
.IP "" 0
-.
.P
The \fBactionpack 3\.0\.0\.rc\fR gem has a number of new dependencies, and updates the \fBactivesupport\fR dependency to \fB= 3\.0\.0\.rc\fR and the \fBrack\fR dependency to \fB~> 1\.2\.1\fR\.
-.
.P
When you run \fBbundle install\fR, Bundler notices that you changed the \fBactionpack\fR gem, but not the \fBactivemerchant\fR gem\. It evaluates the gems currently being used to satisfy its requirements:
-.
.TP
\fBactivesupport 2\.3\.8\fR
also used to satisfy a dependency in \fBactivemerchant\fR, which is not being updated
-.
.TP
\fBrack ~> 1\.1\.0\fR
not currently being used to satisfy another dependency
-.
.P
Because you did not explicitly ask to update \fBactivemerchant\fR, you would not expect it to suddenly stop working after updating \fBactionpack\fR\. However, satisfying the new \fBactivesupport 3\.0\.0\.rc\fR dependency of actionpack requires updating one of its dependencies\.
-.
.P
Even though \fBactivemerchant\fR declares a very loose dependency that theoretically matches \fBactivesupport 3\.0\.0\.rc\fR, Bundler treats gems in your Gemfile(5) that have not changed as an atomic unit together with their dependencies\. In this case, the \fBactivemerchant\fR dependency is treated as \fBactivemerchant 1\.7\.1 + activesupport 2\.3\.8\fR, so \fBbundle install\fR will report that it cannot update \fBactionpack\fR\.
-.
.P
To explicitly update \fBactionpack\fR, including its dependencies which other gems in the Gemfile(5) still depend on, run \fBbundle update actionpack\fR (see \fBbundle update(1)\fR)\.
-.
.P
\fBSummary\fR: In general, after making a change to the Gemfile(5) , you should first try to run \fBbundle install\fR, which will guarantee that no other gem in the Gemfile(5) is impacted by the change\. If that does not work, run bundle update(1) \fIbundle\-update\.1\.html\fR\.
-.
.SH "SEE ALSO"
-.
.IP "\(bu" 4
-Gem install docs \fIhttp://guides\.rubygems\.org/rubygems\-basics/#installing\-gems\fR
-.
+Gem install docs \fIhttps://guides\.rubygems\.org/rubygems\-basics/#installing\-gems\fR
.IP "\(bu" 4
-Rubygems signing docs \fIhttp://guides\.rubygems\.org/security/\fR
-.
+Rubygems signing docs \fIhttps://guides\.rubygems\.org/security/\fR
.IP "" 0
diff --git a/lib/bundler/man/bundle-install.1.ronn b/lib/bundler/man/bundle-install.1.ronn
index be9ed0f974..ed8169de05 100644
--- a/lib/bundler/man/bundle-install.1.ronn
+++ b/lib/bundler/man/bundle-install.1.ronn
@@ -14,6 +14,7 @@ bundle-install(1) -- Install the dependencies specified in your Gemfile
[--no-cache]
[--no-prune]
[--path PATH]
+ [--prefer-local]
[--quiet]
[--redownload]
[--retry=NUMBER]
@@ -378,5 +379,5 @@ does not work, run [bundle update(1)](bundle-update.1.html).
## SEE ALSO
-* [Gem install docs](http://guides.rubygems.org/rubygems-basics/#installing-gems)
-* [Rubygems signing docs](http://guides.rubygems.org/security/)
+* [Gem install docs](https://guides.rubygems.org/rubygems-basics/#installing-gems)
+* [Rubygems signing docs](https://guides.rubygems.org/security/)
diff --git a/lib/bundler/man/bundle-list.1 b/lib/bundler/man/bundle-list.1
index f66755b19a..21723608cc 100644
--- a/lib/bundler/man/bundle-list.1
+++ b/lib/bundler/man/bundle-list.1
@@ -1,49 +1,34 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-LIST" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-LIST" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-list\fR \- List all the gems in the bundle
-.
.SH "SYNOPSIS"
-\fBbundle list\fR [\-\-name\-only] [\-\-paths] [\-\-without\-group=GROUP[ GROUP\.\.\.]] [\-\-only\-group=GROUP[ GROUP\.\.\.]]
-.
+\fBbundle list\fR [\-\-name\-only] [\-\-paths] [\-\-without\-group=GROUP[ GROUP\|\.\|\.\|\.]] [\-\-only\-group=GROUP[ GROUP\|\.\|\.\|\.]]
.SH "DESCRIPTION"
Prints a list of all the gems in the bundle including their version\.
-.
.P
Example:
-.
.P
bundle list \-\-name\-only
-.
.P
bundle list \-\-paths
-.
.P
bundle list \-\-without\-group test
-.
.P
bundle list \-\-only\-group dev
-.
.P
bundle list \-\-only\-group dev test \-\-paths
-.
.SH "OPTIONS"
-.
.TP
\fB\-\-name\-only\fR
Print only the name of each gem\.
-.
.TP
\fB\-\-paths\fR
Print the path to each gem in the bundle\.
-.
.TP
\fB\-\-without\-group=<list>\fR
A space\-separated list of groups of gems to skip during printing\.
-.
.TP
\fB\-\-only\-group=<list>\fR
A space\-separated list of groups of gems to print\.
diff --git a/lib/bundler/man/bundle-lock.1 b/lib/bundler/man/bundle-lock.1
index 783e97f9f2..8b81b7732f 100644
--- a/lib/bundler/man/bundle-lock.1
+++ b/lib/bundler/man/bundle-lock.1
@@ -1,84 +1,60 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-LOCK" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-LOCK" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-lock\fR \- Creates / Updates a lockfile without installing
-.
.SH "SYNOPSIS"
\fBbundle lock\fR [\-\-update] [\-\-local] [\-\-print] [\-\-lockfile=PATH] [\-\-full\-index] [\-\-add\-platform] [\-\-remove\-platform] [\-\-patch] [\-\-minor] [\-\-major] [\-\-strict] [\-\-conservative]
-.
.SH "DESCRIPTION"
Lock the gems specified in Gemfile\.
-.
.SH "OPTIONS"
-.
.TP
\fB\-\-update=<*gems>\fR
Ignores the existing lockfile\. Resolve then updates lockfile\. Taking a list of gems or updating all gems if no list is given\.
-.
.TP
\fB\-\-local\fR
-Do not attempt to connect to \fBrubygems\.org\fR\. Instead, Bundler will use the gems already present in Rubygems\' cache or in \fBvendor/cache\fR\. Note that if a appropriate platform\-specific gem exists on \fBrubygems\.org\fR it will not be found\.
-.
+Do not attempt to connect to \fBrubygems\.org\fR\. Instead, Bundler will use the gems already present in Rubygems' cache or in \fBvendor/cache\fR\. Note that if a appropriate platform\-specific gem exists on \fBrubygems\.org\fR it will not be found\.
.TP
\fB\-\-print\fR
Prints the lockfile to STDOUT instead of writing to the file system\.
-.
.TP
\fB\-\-lockfile=<path>\fR
The path where the lockfile should be written to\.
-.
.TP
\fB\-\-full\-index\fR
Fall back to using the single\-file index of all gems\.
-.
.TP
\fB\-\-add\-platform\fR
Add a new platform to the lockfile, re\-resolving for the addition of that platform\.
-.
.TP
\fB\-\-remove\-platform\fR
Remove a platform from the lockfile\.
-.
.TP
\fB\-\-patch\fR
If updating, prefer updating only to next patch version\.
-.
.TP
\fB\-\-minor\fR
If updating, prefer updating only to next minor version\.
-.
.TP
\fB\-\-major\fR
If updating, prefer updating to next major version (default)\.
-.
.TP
\fB\-\-strict\fR
If updating, do not allow any gem to be updated past latest \-\-patch | \-\-minor | \-\-major\.
-.
.TP
\fB\-\-conservative\fR
If updating, use bundle install conservative update behavior and do not allow shared dependencies to be updated\.
-.
.SH "UPDATING ALL GEMS"
If you run \fBbundle lock\fR with \fB\-\-update\fR option without list of gems, bundler will ignore any previously installed gems and resolve all dependencies again based on the latest versions of all gems available in the sources\.
-.
.SH "UPDATING A LIST OF GEMS"
Sometimes, you want to update a single gem in the Gemfile(5), and leave the rest of the gems that you specified locked to the versions in the \fBGemfile\.lock\fR\.
-.
.P
For instance, you only want to update \fBnokogiri\fR, run \fBbundle lock \-\-update nokogiri\fR\.
-.
.P
Bundler will update \fBnokogiri\fR and any of its dependencies, but leave the rest of the gems that you specified locked to the versions in the \fBGemfile\.lock\fR\.
-.
.SH "SUPPORTING OTHER PLATFORMS"
-If you want your bundle to support platforms other than the one you\'re running locally, you can run \fBbundle lock \-\-add\-platform PLATFORM\fR to add PLATFORM to the lockfile, force bundler to re\-resolve and consider the new platform when picking gems, all without needing to have a machine that matches PLATFORM handy to install those platform\-specific gems on\.
-.
+If you want your bundle to support platforms other than the one you're running locally, you can run \fBbundle lock \-\-add\-platform PLATFORM\fR to add PLATFORM to the lockfile, force bundler to re\-resolve and consider the new platform when picking gems, all without needing to have a machine that matches PLATFORM handy to install those platform\-specific gems on\.
.P
For a full explanation of gem platforms, see \fBgem help platform\fR\.
-.
.SH "PATCH LEVEL OPTIONS"
See bundle update(1) \fIbundle\-update\.1\.html\fR for details\.
diff --git a/lib/bundler/man/bundle-open.1 b/lib/bundler/man/bundle-open.1
index 8fb26f9862..41a8804a09 100644
--- a/lib/bundler/man/bundle-open.1
+++ b/lib/bundler/man/bundle-open.1
@@ -1,51 +1,31 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-OPEN" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-OPEN" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-open\fR \- Opens the source directory for a gem in your bundle
-.
.SH "SYNOPSIS"
\fBbundle open\fR [GEM] [\-\-path=PATH]
-.
.SH "DESCRIPTION"
Opens the source directory of the provided GEM in your editor\.
-.
.P
For this to work the \fBEDITOR\fR or \fBBUNDLER_EDITOR\fR environment variable has to be set\.
-.
.P
Example:
-.
.IP "" 4
-.
.nf
-
-bundle open \'rack\'
-.
+bundle open 'rack'
.fi
-.
.IP "" 0
-.
.P
-Will open the source directory for the \'rack\' gem in your bundle\.
-.
+Will open the source directory for the 'rack' gem in your bundle\.
.IP "" 4
-.
.nf
-
-bundle open \'rack\' \-\-path \'README\.md\'
-.
+bundle open 'rack' \-\-path 'README\.md'
.fi
-.
.IP "" 0
-.
.P
-Will open the README\.md file of the \'rack\' gem source in your bundle\.
-.
+Will open the README\.md file of the 'rack' gem source in your bundle\.
.SH "OPTIONS"
-.
.TP
\fB\-\-path\fR
Specify GEM source relative path to open\.
diff --git a/lib/bundler/man/bundle-outdated.1 b/lib/bundler/man/bundle-outdated.1
index a8afc5cc74..838fce45cd 100644
--- a/lib/bundler/man/bundle-outdated.1
+++ b/lib/bundler/man/bundle-outdated.1
@@ -1,152 +1,100 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-OUTDATED" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-OUTDATED" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-outdated\fR \- List installed gems with newer versions available
-.
.SH "SYNOPSIS"
\fBbundle outdated\fR [GEM] [\-\-local] [\-\-pre] [\-\-source] [\-\-strict] [\-\-parseable | \-\-porcelain] [\-\-group=GROUP] [\-\-groups] [\-\-patch|\-\-minor|\-\-major] [\-\-filter\-major] [\-\-filter\-minor] [\-\-filter\-patch] [\-\-only\-explicit]
-.
.SH "DESCRIPTION"
Outdated lists the names and versions of gems that have a newer version available in the given source\. Calling outdated with [GEM [GEM]] will only check for newer versions of the given gems\. Prerelease gems are ignored by default\. If your gems are up to date, Bundler will exit with a status of 0\. Otherwise, it will exit 1\.
-.
.SH "OPTIONS"
-.
.TP
\fB\-\-local\fR
Do not attempt to fetch gems remotely and use the gem cache instead\.
-.
.TP
\fB\-\-pre\fR
Check for newer pre\-release gems\.
-.
.TP
\fB\-\-source\fR
Check against a specific source\.
-.
.TP
\fB\-\-strict\fR
Only list newer versions allowed by your Gemfile requirements, also respecting conservative update flags (\-\-patch, \-\-minor, \-\-major)\.
-.
.TP
\fB\-\-parseable\fR, \fB\-\-porcelain\fR
Use minimal formatting for more parseable output\.
-.
.TP
\fB\-\-group\fR
List gems from a specific group\.
-.
.TP
\fB\-\-groups\fR
List gems organized by groups\.
-.
.TP
\fB\-\-minor\fR
Prefer updating only to next minor version\.
-.
.TP
\fB\-\-major\fR
Prefer updating to next major version (default)\.
-.
.TP
\fB\-\-patch\fR
Prefer updating only to next patch version\.
-.
.TP
\fB\-\-filter\-major\fR
Only list major newer versions\.
-.
.TP
\fB\-\-filter\-minor\fR
Only list minor newer versions\.
-.
.TP
\fB\-\-filter\-patch\fR
Only list patch newer versions\.
-.
.TP
\fB\-\-only\-explicit\fR
Only list gems specified in your Gemfile, not their dependencies\.
-.
.SH "PATCH LEVEL OPTIONS"
See bundle update(1) \fIbundle\-update\.1\.html\fR for details\.
-.
.SH "FILTERING OUTPUT"
The 3 filtering options do not affect the resolution of versions, merely what versions are shown in the output\.
-.
.P
If the regular output shows the following:
-.
.IP "" 4
-.
.nf
-
* Gem Current Latest Requested Groups
* faker 1\.6\.5 1\.6\.6 ~> 1\.4 development, test
* hashie 1\.2\.0 3\.4\.6 = 1\.2\.0 default
* headless 2\.2\.3 2\.3\.1 = 2\.2\.3 test
-.
.fi
-.
.IP "" 0
-.
.P
\fB\-\-filter\-major\fR would only show:
-.
.IP "" 4
-.
.nf
-
* Gem Current Latest Requested Groups
* hashie 1\.2\.0 3\.4\.6 = 1\.2\.0 default
-.
.fi
-.
.IP "" 0
-.
.P
\fB\-\-filter\-minor\fR would only show:
-.
.IP "" 4
-.
.nf
-
* Gem Current Latest Requested Groups
* headless 2\.2\.3 2\.3\.1 = 2\.2\.3 test
-.
.fi
-.
.IP "" 0
-.
.P
\fB\-\-filter\-patch\fR would only show:
-.
.IP "" 4
-.
.nf
-
* Gem Current Latest Requested Groups
* faker 1\.6\.5 1\.6\.6 ~> 1\.4 development, test
-.
.fi
-.
.IP "" 0
-.
.P
Filter options can be combined\. \fB\-\-filter\-minor\fR and \fB\-\-filter\-patch\fR would show:
-.
.IP "" 4
-.
.nf
-
* Gem Current Latest Requested Groups
* faker 1\.6\.5 1\.6\.6 ~> 1\.4 development, test
-.
.fi
-.
.IP "" 0
-.
.P
Combining all three \fBfilter\fR options would be the same result as providing none of them\.
diff --git a/lib/bundler/man/bundle-outdated.1.ronn b/lib/bundler/man/bundle-outdated.1.ronn
index 27bf21ab9d..4ac65d0532 100644
--- a/lib/bundler/man/bundle-outdated.1.ronn
+++ b/lib/bundler/man/bundle-outdated.1.ronn
@@ -102,4 +102,5 @@ Filter options can be combined. `--filter-minor` and `--filter-patch` would show
* Gem Current Latest Requested Groups
* faker 1.6.5 1.6.6 ~> 1.4 development, test
+
Combining all three `filter` options would be the same result as providing none of them.
diff --git a/lib/bundler/man/bundle-platform.1 b/lib/bundler/man/bundle-platform.1
index 6c0451ebac..0dbce7a7a4 100644
--- a/lib/bundler/man/bundle-platform.1
+++ b/lib/bundler/man/bundle-platform.1
@@ -1,41 +1,27 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-PLATFORM" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-PLATFORM" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-platform\fR \- Displays platform compatibility information
-.
.SH "SYNOPSIS"
\fBbundle platform\fR [\-\-ruby]
-.
.SH "DESCRIPTION"
\fBplatform\fR displays information from your Gemfile, Gemfile\.lock, and Ruby VM about your platform\.
-.
.P
For instance, using this Gemfile(5):
-.
.IP "" 4
-.
.nf
-
source "https://rubygems\.org"
ruby "3\.1\.2"
gem "rack"
-.
.fi
-.
.IP "" 0
-.
.P
If you run \fBbundle platform\fR on Ruby 3\.1\.2, it displays the following output:
-.
.IP "" 4
-.
.nf
-
Your platform is: x86_64\-linux
Your app has gems that work on these platforms:
@@ -48,24 +34,16 @@ Your Gemfile specifies a Ruby version requirement:
* ruby 3\.1\.2
Your current platform satisfies the Ruby version requirement\.
-.
.fi
-.
.IP "" 0
-.
.P
-\fBplatform\fR lists all the platforms in your \fBGemfile\.lock\fR as well as the \fBruby\fR directive if applicable from your Gemfile(5)\. It also lets you know if the \fBruby\fR directive requirement has been met\. If \fBruby\fR directive doesn\'t match the running Ruby VM, it tells you what part does not\.
-.
+\fBplatform\fR lists all the platforms in your \fBGemfile\.lock\fR as well as the \fBruby\fR directive if applicable from your Gemfile(5)\. It also lets you know if the \fBruby\fR directive requirement has been met\. If \fBruby\fR directive doesn't match the running Ruby VM, it tells you what part does not\.
.SH "OPTIONS"
-.
.TP
\fB\-\-ruby\fR
-It will display the ruby directive information, so you don\'t have to parse it from the Gemfile(5)\.
-.
+It will display the ruby directive information, so you don't have to parse it from the Gemfile(5)\.
.SH "SEE ALSO"
-.
.IP "\(bu" 4
bundle\-lock(1) \fIbundle\-lock\.1\.html\fR
-.
.IP "" 0
diff --git a/lib/bundler/man/bundle-plugin.1 b/lib/bundler/man/bundle-plugin.1
index e295c30622..1290abb3ba 100644
--- a/lib/bundler/man/bundle-plugin.1
+++ b/lib/bundler/man/bundle-plugin.1
@@ -1,81 +1,58 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-PLUGIN" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-PLUGIN" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-plugin\fR \- Manage Bundler plugins
-.
.SH "SYNOPSIS"
-\fBbundle plugin\fR install PLUGINS [\-\-source=\fISOURCE\fR] [\-\-version=\fIversion\fR] [\-\-git|\-\-local_git=\fIgit\-url\fR] [\-\-branch=\fIbranch\fR|\-\-ref=\fIrev\fR]
-.
+\fBbundle plugin\fR install PLUGINS [\-\-source=\fISOURCE\fR] [\-\-version=\fIversion\fR] [\-\-git=\fIgit\-url\fR] [\-\-branch=\fIbranch\fR|\-\-ref=\fIrev\fR] [\-\-path=\fIpath\fR]
.br
\fBbundle plugin\fR uninstall PLUGINS
-.
.br
\fBbundle plugin\fR list
-.
.br
\fBbundle plugin\fR help [COMMAND]
-.
.SH "DESCRIPTION"
You can install, uninstall, and list plugin(s) with this command to extend functionalities of Bundler\.
-.
.SH "SUB\-COMMANDS"
-.
.SS "install"
Install the given plugin(s)\.
-.
.TP
\fBbundle plugin install bundler\-graph\fR
Install bundler\-graph gem from globally configured sources (defaults to RubyGems\.org)\. The global source, specified in source in Gemfile is ignored\.
-.
.TP
\fBbundle plugin install bundler\-graph \-\-source https://example\.com\fR
Install bundler\-graph gem from example\.com\. The global source, specified in source in Gemfile is not considered\.
-.
.TP
\fBbundle plugin install bundler\-graph \-\-version 0\.2\.1\fR
You can specify the version of the gem via \fB\-\-version\fR\.
-.
.TP
\fBbundle plugin install bundler\-graph \-\-git https://github\.com/rubygems/bundler\-graph\fR
-Install bundler\-graph gem from Git repository\. \fB\-\-git\fR can be replaced with \fB\-\-local\-git\fR\. You cannot use both \fB\-\-git\fR and \fB\-\-local\-git\fR\. You can use standard Git URLs like:
-.
+Install bundler\-graph gem from Git repository\. You can use standard Git URLs like:
.IP
\fBssh://[user@]host\.xz[:port]/path/to/repo\.git\fR
-.
.br
\fBhttp[s]://host\.xz[:port]/path/to/repo\.git\fR
-.
.br
\fB/path/to/repo\fR
-.
.br
\fBfile:///path/to/repo\fR
-.
.IP
-When you specify \fB\-\-git\fR/\fB\-\-local\-git\fR, you can use \fB\-\-branch\fR or \fB\-\-ref\fR to specify any branch, tag, or commit hash (revision) to use\. When you specify both, only the latter is used\.
-.
+When you specify \fB\-\-git\fR, you can use \fB\-\-branch\fR or \fB\-\-ref\fR to specify any branch, tag, or commit hash (revision) to use\.
+.TP
+\fBbundle plugin install bundler\-graph \-\-path \.\./bundler\-graph\fR
+Install bundler\-graph gem from a local path\.
.SS "uninstall"
Uninstall the plugin(s) specified in PLUGINS\.
-.
.SS "list"
List the installed plugins and available commands\.
-.
.P
No options\.
-.
.SS "help"
Describe subcommands or one specific subcommand\.
-.
.P
No options\.
-.
.SH "SEE ALSO"
-.
.IP "\(bu" 4
How to write a Bundler plugin \fIhttps://bundler\.io/guides/bundler_plugins\.html\fR
-.
.IP "" 0
diff --git a/lib/bundler/man/bundle-plugin.1.ronn b/lib/bundler/man/bundle-plugin.1.ronn
index a11df4c162..b0a34660ea 100644
--- a/lib/bundler/man/bundle-plugin.1.ronn
+++ b/lib/bundler/man/bundle-plugin.1.ronn
@@ -4,7 +4,8 @@ bundle-plugin(1) -- Manage Bundler plugins
## SYNOPSIS
`bundle plugin` install PLUGINS [--source=<SOURCE>] [--version=<version>]
- [--git|--local_git=<git-url>] [--branch=<branch>|--ref=<rev>]<br>
+ [--git=<git-url>] [--branch=<branch>|--ref=<rev>]
+ [--path=<path>]<br>
`bundle plugin` uninstall PLUGINS<br>
`bundle plugin` list<br>
`bundle plugin` help [COMMAND]
@@ -29,14 +30,17 @@ Install the given plugin(s).
You can specify the version of the gem via `--version`.
* `bundle plugin install bundler-graph --git https://github.com/rubygems/bundler-graph`:
- Install bundler-graph gem from Git repository. `--git` can be replaced with `--local-git`. You cannot use both `--git` and `--local-git`. You can use standard Git URLs like:
+ Install bundler-graph gem from Git repository. You can use standard Git URLs like:
`ssh://[user@]host.xz[:port]/path/to/repo.git`<br>
`http[s]://host.xz[:port]/path/to/repo.git`<br>
`/path/to/repo`<br>
`file:///path/to/repo`
- When you specify `--git`/`--local-git`, you can use `--branch` or `--ref` to specify any branch, tag, or commit hash (revision) to use. When you specify both, only the latter is used.
+ When you specify `--git`, you can use `--branch` or `--ref` to specify any branch, tag, or commit hash (revision) to use.
+
+* `bundle plugin install bundler-graph --path ../bundler-graph`:
+ Install bundler-graph gem from a local path.
### uninstall
diff --git a/lib/bundler/man/bundle-pristine.1 b/lib/bundler/man/bundle-pristine.1
index 6422ea9517..bf4a7cd323 100644
--- a/lib/bundler/man/bundle-pristine.1
+++ b/lib/bundler/man/bundle-pristine.1
@@ -1,34 +1,23 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-PRISTINE" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-PRISTINE" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-pristine\fR \- Restores installed gems to their pristine condition
-.
.SH "SYNOPSIS"
\fBbundle pristine\fR
-.
.SH "DESCRIPTION"
\fBpristine\fR restores the installed gems in the bundle to their pristine condition using the local gem cache from RubyGems\. For git gems, a forced checkout will be performed\.
-.
.P
-For further explanation, \fBbundle pristine\fR ignores unpacked files on disk\. In other words, this command utilizes the local \fB\.gem\fR cache or the gem\'s git repository as if one were installing from scratch\.
-.
+For further explanation, \fBbundle pristine\fR ignores unpacked files on disk\. In other words, this command utilizes the local \fB\.gem\fR cache or the gem's git repository as if one were installing from scratch\.
.P
-Note: the Bundler gem cannot be restored to its original state with \fBpristine\fR\. One also cannot use \fBbundle pristine\fR on gems with a \'path\' option in the Gemfile, because bundler has no original copy it can restore from\.
-.
+Note: the Bundler gem cannot be restored to its original state with \fBpristine\fR\. One also cannot use \fBbundle pristine\fR on gems with a 'path' option in the Gemfile, because bundler has no original copy it can restore from\.
.P
When is it practical to use \fBbundle pristine\fR?
-.
.P
It comes in handy when a developer is debugging a gem\. \fBbundle pristine\fR is a great way to get rid of experimental changes to a gem that one may not want\.
-.
.P
Why use \fBbundle pristine\fR over \fBgem pristine \-\-all\fR?
-.
.P
Both commands are very similar\. For context: \fBbundle pristine\fR, without arguments, cleans all gems from the lockfile\. Meanwhile, \fBgem pristine \-\-all\fR cleans all installed gems for that Ruby version\.
-.
.P
If a developer forgets which gems in their project they might have been debugging, the Rubygems \fBgem pristine [GEMNAME]\fR command may be inconvenient\. One can avoid waiting for \fBgem pristine \-\-all\fR, and instead run \fBbundle pristine\fR\.
diff --git a/lib/bundler/man/bundle-remove.1 b/lib/bundler/man/bundle-remove.1
index ebfb17ffb1..c3c96b416d 100644
--- a/lib/bundler/man/bundle-remove.1
+++ b/lib/bundler/man/bundle-remove.1
@@ -1,31 +1,21 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-REMOVE" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-REMOVE" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-remove\fR \- Removes gems from the Gemfile
-.
.SH "SYNOPSIS"
-\fBbundle remove [GEM [GEM \.\.\.]] [\-\-install]\fR
-.
+\fBbundle remove [GEM [GEM \|\.\|\.\|\.]] [\-\-install]\fR
.SH "DESCRIPTION"
Removes the given gems from the Gemfile while ensuring that the resulting Gemfile is still valid\. If a gem cannot be removed, a warning is printed\. If a gem is already absent from the Gemfile, and error is raised\.
-.
.SH "OPTIONS"
-.
.TP
\fB\-\-install\fR
Runs \fBbundle install\fR after the given gems have been removed from the Gemfile, which ensures that both the lockfile and the installed gems on disk are also updated to remove the given gem(s)\.
-.
.P
Example:
-.
.P
bundle remove rails
-.
.P
bundle remove rails rack
-.
.P
bundle remove rails rack \-\-install
diff --git a/lib/bundler/man/bundle-show.1 b/lib/bundler/man/bundle-show.1
index ac64aee6b6..c054875efd 100644
--- a/lib/bundler/man/bundle-show.1
+++ b/lib/bundler/man/bundle-show.1
@@ -1,22 +1,15 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-SHOW" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-SHOW" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-show\fR \- Shows all the gems in your bundle, or the path to a gem
-.
.SH "SYNOPSIS"
\fBbundle show\fR [GEM] [\-\-paths]
-.
.SH "DESCRIPTION"
Without the [GEM] option, \fBshow\fR will print a list of the names and versions of all gems that are required by your [\fBGemfile(5)\fR][Gemfile(5)], sorted by name\.
-.
.P
Calling show with [GEM] will list the exact location of that gem on your machine\.
-.
.SH "OPTIONS"
-.
.TP
\fB\-\-paths\fR
List the paths of all gems that are required by your [\fBGemfile(5)\fR][Gemfile(5)], sorted by gem name\.
diff --git a/lib/bundler/man/bundle-update.1 b/lib/bundler/man/bundle-update.1
index 37a289ddf9..acd80ec75c 100644
--- a/lib/bundler/man/bundle-update.1
+++ b/lib/bundler/man/bundle-update.1
@@ -1,114 +1,81 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-UPDATE" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-UPDATE" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-update\fR \- Update your gems to the latest available versions
-.
.SH "SYNOPSIS"
\fBbundle update\fR \fI*gems\fR [\-\-all] [\-\-group=NAME] [\-\-source=NAME] [\-\-local] [\-\-ruby] [\-\-bundler[=VERSION]] [\-\-full\-index] [\-\-jobs=JOBS] [\-\-quiet] [\-\-patch|\-\-minor|\-\-major] [\-\-redownload] [\-\-strict] [\-\-conservative]
-.
.SH "DESCRIPTION"
Update the gems specified (all gems, if \fB\-\-all\fR flag is used), ignoring the previously installed gems specified in the \fBGemfile\.lock\fR\. In general, you should use bundle install(1) \fIbundle\-install\.1\.html\fR to install the same exact gems and versions across machines\.
-.
.P
You would use \fBbundle update\fR to explicitly update the version of a gem\.
-.
.SH "OPTIONS"
-.
.TP
\fB\-\-all\fR
Update all gems specified in Gemfile\.
-.
.TP
\fB\-\-group=<name>\fR, \fB\-g=[<name>]\fR
Only update the gems in the specified group\. For instance, you can update all gems in the development group with \fBbundle update \-\-group development\fR\. You can also call \fBbundle update rails \-\-group test\fR to update the rails gem and all gems in the test group, for example\.
-.
.TP
\fB\-\-source=<name>\fR
The name of a \fB:git\fR or \fB:path\fR source used in the Gemfile(5)\. For instance, with a \fB:git\fR source of \fBhttp://github\.com/rails/rails\.git\fR, you would call \fBbundle update \-\-source rails\fR
-.
.TP
\fB\-\-local\fR
Do not attempt to fetch gems remotely and use the gem cache instead\.
-.
.TP
\fB\-\-ruby\fR
Update the locked version of Ruby to the current version of Ruby\.
-.
.TP
\fB\-\-bundler\fR
Update the locked version of bundler to the invoked bundler version\.
-.
.TP
\fB\-\-full\-index\fR
Fall back to using the single\-file index of all gems\.
-.
.TP
\fB\-\-jobs=[<number>]\fR, \fB\-j[<number>]\fR
Specify the number of jobs to run in parallel\. The default is the number of available processors\.
-.
.TP
\fB\-\-retry=[<number>]\fR
Retry failed network or git requests for \fInumber\fR times\.
-.
.TP
\fB\-\-quiet\fR
Only output warnings and errors\.
-.
.TP
\fB\-\-redownload\fR
Force downloading every gem\.
-.
.TP
\fB\-\-patch\fR
Prefer updating only to next patch version\.
-.
.TP
\fB\-\-minor\fR
Prefer updating only to next minor version\.
-.
.TP
\fB\-\-major\fR
Prefer updating to next major version (default)\.
-.
.TP
\fB\-\-strict\fR
Do not allow any gem to be updated past latest \fB\-\-patch\fR | \fB\-\-minor\fR | \fB\-\-major\fR\.
-.
.TP
\fB\-\-conservative\fR
Use bundle install conservative update behavior and do not allow indirect dependencies to be updated\.
-.
.SH "UPDATING ALL GEMS"
If you run \fBbundle update \-\-all\fR, bundler will ignore any previously installed gems and resolve all dependencies again based on the latest versions of all gems available in the sources\.
-.
.P
Consider the following Gemfile(5):
-.
.IP "" 4
-.
.nf
-
source "https://rubygems\.org"
gem "rails", "3\.0\.0\.rc"
gem "nokogiri"
-.
.fi
-.
.IP "" 0
-.
.P
When you run bundle install(1) \fIbundle\-install\.1\.html\fR the first time, bundler will resolve all of the dependencies, all the way down, and install what you need:
-.
.IP "" 4
-.
.nf
-
-Fetching gem metadata from https://rubygems\.org/\.\.\.\.\.\.\.\.\.
-Resolving dependencies\.\.\.
+Fetching gem metadata from https://rubygems\.org/\|\.\|\.\|\.\|\.\|\.\|\.\|\.\|\.\|\.
+Resolving dependencies\|\.\|\.\|\.
Installing builder 2\.1\.2
Installing abstract 1\.0\.0
Installing rack 1\.2\.8
@@ -138,55 +105,36 @@ Installing nokogiri 1\.6\.5
Bundle complete! 2 Gemfile dependencies, 26 gems total\.
Use `bundle show [gemname]` to see where a bundled gem is installed\.
-.
.fi
-.
.IP "" 0
-.
.P
As you can see, even though you have two gems in the Gemfile(5), your application needs 26 different gems in order to run\. Bundler remembers the exact versions it installed in \fBGemfile\.lock\fR\. The next time you run bundle install(1) \fIbundle\-install\.1\.html\fR, bundler skips the dependency resolution and installs the same gems as it installed last time\.
-.
.P
-After checking in the \fBGemfile\.lock\fR into version control and cloning it on another machine, running bundle install(1) \fIbundle\-install\.1\.html\fR will \fIstill\fR install the gems that you installed last time\. You don\'t need to worry that a new release of \fBerubis\fR or \fBmail\fR changes the gems you use\.
-.
+After checking in the \fBGemfile\.lock\fR into version control and cloning it on another machine, running bundle install(1) \fIbundle\-install\.1\.html\fR will \fIstill\fR install the gems that you installed last time\. You don't need to worry that a new release of \fBerubis\fR or \fBmail\fR changes the gems you use\.
.P
However, from time to time, you might want to update the gems you are using to the newest versions that still match the gems in your Gemfile(5)\.
-.
.P
To do this, run \fBbundle update \-\-all\fR, which will ignore the \fBGemfile\.lock\fR, and resolve all the dependencies again\. Keep in mind that this process can result in a significantly different set of the 25 gems, based on the requirements of new gems that the gem authors released since the last time you ran \fBbundle update \-\-all\fR\.
-.
.SH "UPDATING A LIST OF GEMS"
Sometimes, you want to update a single gem in the Gemfile(5), and leave the rest of the gems that you specified locked to the versions in the \fBGemfile\.lock\fR\.
-.
.P
For instance, in the scenario above, imagine that \fBnokogiri\fR releases version \fB1\.4\.4\fR, and you want to update it \fIwithout\fR updating Rails and all of its dependencies\. To do this, run \fBbundle update nokogiri\fR\.
-.
.P
Bundler will update \fBnokogiri\fR and any of its dependencies, but leave alone Rails and its dependencies\.
-.
.SH "OVERLAPPING DEPENDENCIES"
Sometimes, multiple gems declared in your Gemfile(5) are satisfied by the same second\-level dependency\. For instance, consider the case of \fBthin\fR and \fBrack\-perftools\-profiler\fR\.
-.
.IP "" 4
-.
.nf
-
source "https://rubygems\.org"
gem "thin"
gem "rack\-perftools\-profiler"
-.
.fi
-.
.IP "" 0
-.
.P
The \fBthin\fR gem depends on \fBrack >= 1\.0\fR, while \fBrack\-perftools\-profiler\fR depends on \fBrack ~> 1\.0\fR\. If you run bundle install, you get:
-.
.IP "" 4
-.
.nf
-
Fetching source index for https://rubygems\.org/
Installing daemons (1\.1\.0)
Installing eventmachine (0\.12\.10) with native extensions
@@ -196,199 +144,132 @@ Installing rack (1\.2\.1)
Installing rack\-perftools_profiler (0\.0\.2)
Installing thin (1\.2\.7) with native extensions
Using bundler (1\.0\.0\.rc\.3)
-.
.fi
-.
.IP "" 0
-.
.P
-In this case, the two gems have their own set of dependencies, but they share \fBrack\fR in common\. If you run \fBbundle update thin\fR, bundler will update \fBdaemons\fR, \fBeventmachine\fR and \fBrack\fR, which are dependencies of \fBthin\fR, but not \fBopen4\fR or \fBperftools\.rb\fR, which are dependencies of \fBrack\-perftools_profiler\fR\. Note that \fBbundle update thin\fR will update \fBrack\fR even though it\'s \fIalso\fR a dependency of \fBrack\-perftools_profiler\fR\.
-.
+In this case, the two gems have their own set of dependencies, but they share \fBrack\fR in common\. If you run \fBbundle update thin\fR, bundler will update \fBdaemons\fR, \fBeventmachine\fR and \fBrack\fR, which are dependencies of \fBthin\fR, but not \fBopen4\fR or \fBperftools\.rb\fR, which are dependencies of \fBrack\-perftools_profiler\fR\. Note that \fBbundle update thin\fR will update \fBrack\fR even though it's \fIalso\fR a dependency of \fBrack\-perftools_profiler\fR\.
.P
In short, by default, when you update a gem using \fBbundle update\fR, bundler will update all dependencies of that gem, including those that are also dependencies of another gem\.
-.
.P
To prevent updating indirect dependencies, prior to version 1\.14 the only option was the \fBCONSERVATIVE UPDATING\fR behavior in bundle install(1) \fIbundle\-install\.1\.html\fR:
-.
.P
In this scenario, updating the \fBthin\fR version manually in the Gemfile(5), and then running bundle install(1) \fIbundle\-install\.1\.html\fR will only update \fBdaemons\fR and \fBeventmachine\fR, but not \fBrack\fR\. For more information, see the \fBCONSERVATIVE UPDATING\fR section of bundle install(1) \fIbundle\-install\.1\.html\fR\.
-.
.P
Starting with 1\.14, specifying the \fB\-\-conservative\fR option will also prevent indirect dependencies from being updated\.
-.
.SH "PATCH LEVEL OPTIONS"
Version 1\.14 introduced 4 patch\-level options that will influence how gem versions are resolved\. One of the following options can be used: \fB\-\-patch\fR, \fB\-\-minor\fR or \fB\-\-major\fR\. \fB\-\-strict\fR can be added to further influence resolution\.
-.
.TP
\fB\-\-patch\fR
Prefer updating only to next patch version\.
-.
.TP
\fB\-\-minor\fR
Prefer updating only to next minor version\.
-.
.TP
\fB\-\-major\fR
Prefer updating to next major version (default)\.
-.
.TP
\fB\-\-strict\fR
Do not allow any gem to be updated past latest \fB\-\-patch\fR | \fB\-\-minor\fR | \fB\-\-major\fR\.
-.
.P
-When Bundler is resolving what versions to use to satisfy declared requirements in the Gemfile or in parent gems, it looks up all available versions, filters out any versions that don\'t satisfy the requirement, and then, by default, sorts them from newest to oldest, considering them in that order\.
-.
+When Bundler is resolving what versions to use to satisfy declared requirements in the Gemfile or in parent gems, it looks up all available versions, filters out any versions that don't satisfy the requirement, and then, by default, sorts them from newest to oldest, considering them in that order\.
.P
Providing one of the patch level options (e\.g\. \fB\-\-patch\fR) changes the sort order of the satisfying versions, causing Bundler to consider the latest \fB\-\-patch\fR or \fB\-\-minor\fR version available before other versions\. Note that versions outside the stated patch level could still be resolved to if necessary to find a suitable dependency graph\.
-.
.P
-For example, if gem \'foo\' is locked at 1\.0\.2, with no gem requirement defined in the Gemfile, and versions 1\.0\.3, 1\.0\.4, 1\.1\.0, 1\.1\.1, 2\.0\.0 all exist, the default order of preference by default (\fB\-\-major\fR) will be "2\.0\.0, 1\.1\.1, 1\.1\.0, 1\.0\.4, 1\.0\.3, 1\.0\.2"\.
-.
+For example, if gem 'foo' is locked at 1\.0\.2, with no gem requirement defined in the Gemfile, and versions 1\.0\.3, 1\.0\.4, 1\.1\.0, 1\.1\.1, 2\.0\.0 all exist, the default order of preference by default (\fB\-\-major\fR) will be "2\.0\.0, 1\.1\.1, 1\.1\.0, 1\.0\.4, 1\.0\.3, 1\.0\.2"\.
.P
If the \fB\-\-patch\fR option is used, the order of preference will change to "1\.0\.4, 1\.0\.3, 1\.0\.2, 1\.1\.1, 1\.1\.0, 2\.0\.0"\.
-.
.P
If the \fB\-\-minor\fR option is used, the order of preference will change to "1\.1\.1, 1\.1\.0, 1\.0\.4, 1\.0\.3, 1\.0\.2, 2\.0\.0"\.
-.
.P
Combining the \fB\-\-strict\fR option with any of the patch level options will remove any versions beyond the scope of the patch level option, to ensure that no gem is updated that far\.
-.
.P
To continue the previous example, if both \fB\-\-patch\fR and \fB\-\-strict\fR options are used, the available versions for resolution would be "1\.0\.4, 1\.0\.3, 1\.0\.2"\. If \fB\-\-minor\fR and \fB\-\-strict\fR are used, it would be "1\.1\.1, 1\.1\.0, 1\.0\.4, 1\.0\.3, 1\.0\.2"\.
-.
.P
-Gem requirements as defined in the Gemfile will still be the first determining factor for what versions are available\. If the gem requirement for \fBfoo\fR in the Gemfile is \'~> 1\.0\', that will accomplish the same thing as providing the \fB\-\-minor\fR and \fB\-\-strict\fR options\.
-.
+Gem requirements as defined in the Gemfile will still be the first determining factor for what versions are available\. If the gem requirement for \fBfoo\fR in the Gemfile is '~> 1\.0', that will accomplish the same thing as providing the \fB\-\-minor\fR and \fB\-\-strict\fR options\.
.SH "PATCH LEVEL EXAMPLES"
Given the following gem specifications:
-.
.IP "" 4
-.
.nf
-
foo 1\.4\.3, requires: ~> bar 2\.0
foo 1\.4\.4, requires: ~> bar 2\.0
foo 1\.4\.5, requires: ~> bar 2\.1
foo 1\.5\.0, requires: ~> bar 2\.1
foo 1\.5\.1, requires: ~> bar 3\.0
bar with versions 2\.0\.3, 2\.0\.4, 2\.1\.0, 2\.1\.1, 3\.0\.0
-.
.fi
-.
.IP "" 0
-.
.P
Gemfile:
-.
.IP "" 4
-.
.nf
-
-gem \'foo\'
-.
+gem 'foo'
.fi
-.
.IP "" 0
-.
.P
Gemfile\.lock:
-.
.IP "" 4
-.
.nf
-
foo (1\.4\.3)
bar (~> 2\.0)
bar (2\.0\.3)
-.
.fi
-.
.IP "" 0
-.
.P
Cases:
-.
.IP "" 4
-.
.nf
-
# Command Line Result
\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
-1 bundle update \-\-patch \'foo 1\.4\.5\', \'bar 2\.1\.1\'
-2 bundle update \-\-patch foo \'foo 1\.4\.5\', \'bar 2\.1\.1\'
-3 bundle update \-\-minor \'foo 1\.5\.1\', \'bar 3\.0\.0\'
-4 bundle update \-\-minor \-\-strict \'foo 1\.5\.0\', \'bar 2\.1\.1\'
-5 bundle update \-\-patch \-\-strict \'foo 1\.4\.4\', \'bar 2\.0\.4\'
-.
+1 bundle update \-\-patch 'foo 1\.4\.5', 'bar 2\.1\.1'
+2 bundle update \-\-patch foo 'foo 1\.4\.5', 'bar 2\.1\.1'
+3 bundle update \-\-minor 'foo 1\.5\.1', 'bar 3\.0\.0'
+4 bundle update \-\-minor \-\-strict 'foo 1\.5\.0', 'bar 2\.1\.1'
+5 bundle update \-\-patch \-\-strict 'foo 1\.4\.4', 'bar 2\.0\.4'
.fi
-.
.IP "" 0
-.
.P
In case 1, bar is upgraded to 2\.1\.1, a minor version increase, because the dependency from foo 1\.4\.5 required it\.
-.
.P
-In case 2, only foo is requested to be unlocked, but bar is also allowed to move because it\'s not a declared dependency in the Gemfile\.
-.
+In case 2, only foo is requested to be unlocked, but bar is also allowed to move because it's not a declared dependency in the Gemfile\.
.P
In case 3, bar goes up a whole major release, because a minor increase is preferred now for foo, and when it goes to 1\.5\.1, it requires 3\.0\.0 of bar\.
-.
.P
-In case 4, foo is preferred up to a minor version, but 1\.5\.1 won\'t work because the \-\-strict flag removes bar 3\.0\.0 from consideration since it\'s a major increment\.
-.
+In case 4, foo is preferred up to a minor version, but 1\.5\.1 won't work because the \-\-strict flag removes bar 3\.0\.0 from consideration since it's a major increment\.
.P
In case 5, both foo and bar have any minor or major increments removed from consideration because of the \-\-strict flag, so the most they can move is up to 1\.4\.4 and 2\.0\.4\.
-.
.SH "RECOMMENDED WORKFLOW"
In general, when working with an application managed with bundler, you should use the following workflow:
-.
.IP "\(bu" 4
After you create your Gemfile(5) for the first time, run
-.
.IP
$ bundle install
-.
.IP "\(bu" 4
Check the resulting \fBGemfile\.lock\fR into version control
-.
.IP
$ git add Gemfile\.lock
-.
.IP "\(bu" 4
When checking out this repository on another development machine, run
-.
.IP
$ bundle install
-.
.IP "\(bu" 4
When checking out this repository on a deployment machine, run
-.
.IP
$ bundle install \-\-deployment
-.
.IP "\(bu" 4
After changing the Gemfile(5) to reflect a new or update dependency, run
-.
.IP
$ bundle install
-.
.IP "\(bu" 4
Make sure to check the updated \fBGemfile\.lock\fR into version control
-.
.IP
$ git add Gemfile\.lock
-.
.IP "\(bu" 4
If bundle install(1) \fIbundle\-install\.1\.html\fR reports a conflict, manually update the specific gems that you changed in the Gemfile(5)
-.
.IP
$ bundle update rails thin
-.
.IP "\(bu" 4
If you want to update all the gems to the latest possible versions that still match the gems listed in the Gemfile(5), run
-.
.IP
$ bundle update \-\-all
-.
.IP "" 0
diff --git a/lib/bundler/man/bundle-version.1 b/lib/bundler/man/bundle-version.1
index ab29c24763..44eaf92224 100644
--- a/lib/bundler/man/bundle-version.1
+++ b/lib/bundler/man/bundle-version.1
@@ -1,35 +1,22 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-VERSION" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-VERSION" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-version\fR \- Prints Bundler version information
-.
.SH "SYNOPSIS"
\fBbundle version\fR
-.
.SH "DESCRIPTION"
Prints Bundler version information\.
-.
.SH "OPTIONS"
No options\.
-.
.SH "EXAMPLE"
Print the version of Bundler with build date and commit hash of the in the Git source\.
-.
.IP "" 4
-.
.nf
-
bundle version
-.
.fi
-.
.IP "" 0
-.
.P
shows \fBBundler version 2\.3\.21 (2022\-08\-24 commit d54be5fdd8)\fR for example\.
-.
.P
cf\. \fBbundle \-\-version\fR shows \fBBundler version 2\.3\.21\fR\.
diff --git a/lib/bundler/man/bundle-viz.1 b/lib/bundler/man/bundle-viz.1
index 3ae31a0fba..77b902214c 100644
--- a/lib/bundler/man/bundle-viz.1
+++ b/lib/bundler/man/bundle-viz.1
@@ -1,41 +1,29 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-VIZ" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE\-VIZ" "1" "May 2024" ""
.SH "NAME"
\fBbundle\-viz\fR \- Generates a visual dependency graph for your Gemfile
-.
.SH "SYNOPSIS"
\fBbundle viz\fR [\-\-file=FILE] [\-\-format=FORMAT] [\-\-requirements] [\-\-version] [\-\-without=GROUP GROUP]
-.
.SH "DESCRIPTION"
\fBviz\fR generates a PNG file of the current \fBGemfile(5)\fR as a dependency graph\. \fBviz\fR requires the ruby\-graphviz gem (and its dependencies)\.
-.
.P
The associated gems must also be installed via \fBbundle install(1)\fR \fIbundle\-install\.1\.html\fR\.
-.
.P
\fBviz\fR command was deprecated in Bundler 2\.2\. Use bundler\-graph plugin \fIhttps://github\.com/rubygems/bundler\-graph\fR instead\.
-.
.SH "OPTIONS"
-.
.TP
\fB\-\-file\fR, \fB\-f\fR
The name to use for the generated file\. See \fB\-\-format\fR option
-.
.TP
\fB\-\-format\fR, \fB\-F\fR
-This is output format option\. Supported format is png, jpg, svg, dot \.\.\.
-.
+This is output format option\. Supported format is png, jpg, svg, dot \|\.\|\.\|\.
.TP
\fB\-\-requirements\fR, \fB\-R\fR
Set to show the version of each required dependency\.
-.
.TP
\fB\-\-version\fR, \fB\-v\fR
Set to show each gem version\.
-.
.TP
\fB\-\-without\fR, \fB\-W\fR
Exclude gems that are part of the specified named group\.
diff --git a/lib/bundler/man/bundle.1 b/lib/bundler/man/bundle.1
index d89a8cb1ee..199d1ce9fd 100644
--- a/lib/bundler/man/bundle.1
+++ b/lib/bundler/man/bundle.1
@@ -1,141 +1,102 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE" "1" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "BUNDLE" "1" "May 2024" ""
.SH "NAME"
\fBbundle\fR \- Ruby Dependency Management
-.
.SH "SYNOPSIS"
\fBbundle\fR COMMAND [\-\-no\-color] [\-\-verbose] [ARGS]
-.
.SH "DESCRIPTION"
-Bundler manages an \fBapplication\'s dependencies\fR through its entire life across many machines systematically and repeatably\.
-.
+Bundler manages an \fBapplication's dependencies\fR through its entire life across many machines systematically and repeatably\.
.P
See the bundler website \fIhttps://bundler\.io\fR for information on getting started, and Gemfile(5) for more information on the \fBGemfile\fR format\.
-.
.SH "OPTIONS"
-.
.TP
\fB\-\-no\-color\fR
Print all output without color
-.
.TP
\fB\-\-retry\fR, \fB\-r\fR
Specify the number of times you wish to attempt network commands
-.
.TP
\fB\-\-verbose\fR, \fB\-V\fR
Print out additional logging information
-.
.SH "BUNDLE COMMANDS"
We divide \fBbundle\fR subcommands into primary commands and utilities:
-.
.SH "PRIMARY COMMANDS"
-.
.TP
\fBbundle install(1)\fR \fIbundle\-install\.1\.html\fR
Install the gems specified by the \fBGemfile\fR or \fBGemfile\.lock\fR
-.
.TP
\fBbundle update(1)\fR \fIbundle\-update\.1\.html\fR
Update dependencies to their latest versions
-.
.TP
\fBbundle cache(1)\fR \fIbundle\-cache\.1\.html\fR
Package the \.gem files required by your application into the \fBvendor/cache\fR directory (aliases: \fBbundle package\fR, \fBbundle pack\fR)
-.
.TP
\fBbundle exec(1)\fR \fIbundle\-exec\.1\.html\fR
Execute a script in the current bundle
-.
.TP
\fBbundle config(1)\fR \fIbundle\-config\.1\.html\fR
Specify and read configuration options for Bundler
-.
.TP
\fBbundle help(1)\fR \fIbundle\-help\.1\.html\fR
Display detailed help for each subcommand
-.
.SH "UTILITIES"
-.
.TP
\fBbundle add(1)\fR \fIbundle\-add\.1\.html\fR
Add the named gem to the Gemfile and run \fBbundle install\fR
-.
.TP
\fBbundle binstubs(1)\fR \fIbundle\-binstubs\.1\.html\fR
Generate binstubs for executables in a gem
-.
.TP
\fBbundle check(1)\fR \fIbundle\-check\.1\.html\fR
Determine whether the requirements for your application are installed and available to Bundler
-.
.TP
\fBbundle show(1)\fR \fIbundle\-show\.1\.html\fR
Show the source location of a particular gem in the bundle
-.
.TP
\fBbundle outdated(1)\fR \fIbundle\-outdated\.1\.html\fR
Show all of the outdated gems in the current bundle
-.
.TP
\fBbundle console(1)\fR (deprecated)
Start an IRB session in the current bundle
-.
.TP
\fBbundle open(1)\fR \fIbundle\-open\.1\.html\fR
Open an installed gem in the editor
-.
.TP
\fBbundle lock(1)\fR \fIbundle\-lock\.1\.html\fR
Generate a lockfile for your dependencies
-.
.TP
\fBbundle viz(1)\fR \fIbundle\-viz\.1\.html\fR (deprecated)
Generate a visual representation of your dependencies
-.
.TP
\fBbundle init(1)\fR \fIbundle\-init\.1\.html\fR
Generate a simple \fBGemfile\fR, placed in the current directory
-.
.TP
\fBbundle gem(1)\fR \fIbundle\-gem\.1\.html\fR
Create a simple gem, suitable for development with Bundler
-.
.TP
\fBbundle platform(1)\fR \fIbundle\-platform\.1\.html\fR
Display platform compatibility information
-.
.TP
\fBbundle clean(1)\fR \fIbundle\-clean\.1\.html\fR
Clean up unused gems in your Bundler directory
-.
.TP
\fBbundle doctor(1)\fR \fIbundle\-doctor\.1\.html\fR
Display warnings about common problems
-.
.TP
\fBbundle remove(1)\fR \fIbundle\-remove\.1\.html\fR
Removes gems from the Gemfile
-.
.TP
\fBbundle plugin(1)\fR \fIbundle\-plugin\.1\.html\fR
Manage Bundler plugins
-.
.TP
\fBbundle version(1)\fR \fIbundle\-version\.1\.html\fR
Prints Bundler version information
-.
.SH "PLUGINS"
-When running a command that isn\'t listed in PRIMARY COMMANDS or UTILITIES, Bundler will try to find an executable on your path named \fBbundler\-<command>\fR and execute it, passing down any extra arguments to it\.
-.
+When running a command that isn't listed in PRIMARY COMMANDS or UTILITIES, Bundler will try to find an executable on your path named \fBbundler\-<command>\fR and execute it, passing down any extra arguments to it\.
.SH "OBSOLETE"
These commands are obsolete and should no longer be used:
-.
.IP "\(bu" 4
\fBbundle inject(1)\fR
-.
.IP "" 0
diff --git a/lib/bundler/man/gemfile.5 b/lib/bundler/man/gemfile.5
index 4480bb625a..fa9e31f615 100644
--- a/lib/bundler/man/gemfile.5
+++ b/lib/bundler/man/gemfile.5
@@ -1,239 +1,143 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "GEMFILE" "5" "October 2023" "" ""
-.
+.\" generated with nRonn/v0.11.1
+.\" https://github.com/n-ronn/nronn/tree/0.11.1
+.TH "GEMFILE" "5" "May 2024" ""
.SH "NAME"
\fBGemfile\fR \- A format for describing gem dependencies for Ruby programs
-.
.SH "SYNOPSIS"
A \fBGemfile\fR describes the gem dependencies required to execute associated Ruby code\.
-.
.P
Place the \fBGemfile\fR in the root of the directory containing the associated code\. For instance, in a Rails application, place the \fBGemfile\fR in the same directory as the \fBRakefile\fR\.
-.
.SH "SYNTAX"
A \fBGemfile\fR is evaluated as Ruby code, in a context which makes available a number of methods used to describe the gem requirements\.
-.
.SH "GLOBAL SOURCE"
At the top of the \fBGemfile\fR, add a single line for the \fBRubyGems\fR source that contains the gems listed in the \fBGemfile\fR\.
-.
.IP "" 4
-.
.nf
-
source "https://rubygems\.org"
-.
.fi
-.
.IP "" 0
-.
.P
You can add only one global source\. In Bundler 1\.13, adding multiple global sources was deprecated\. The \fBsource\fR \fBMUST\fR be a valid RubyGems repository\.
-.
.P
To use more than one source of RubyGems, you should use \fI\fBsource\fR block\fR\.
-.
.P
A source is checked for gems following the heuristics described in \fISOURCE PRIORITY\fR\.
-.
.P
\fBNote about a behavior of the feature deprecated in Bundler 1\.13\fR: If a gem is found in more than one global source, Bundler will print a warning after installing the gem indicating which source was used, and listing the other sources where the gem is available\. A specific source can be selected for gems that need to use a non\-standard repository, suppressing this warning, by using the \fI\fB:source\fR option\fR or \fBsource\fR block\.
-.
.SS "CREDENTIALS"
Some gem sources require a username and password\. Use bundle config(1) \fIbundle\-config\.1\.html\fR to set the username and password for any of the sources that need it\. The command must be run once on each computer that will install the Gemfile, but this keeps the credentials from being stored in plain text in version control\.
-.
.IP "" 4
-.
.nf
-
bundle config gems\.example\.com user:password
-.
.fi
-.
.IP "" 0
-.
.P
For some sources, like a company Gemfury account, it may be easier to include the credentials in the Gemfile as part of the source URL\.
-.
.IP "" 4
-.
.nf
-
source "https://user:password@gems\.example\.com"
-.
.fi
-.
.IP "" 0
-.
.P
Credentials in the source URL will take precedence over credentials set using \fBconfig\fR\.
-.
.SH "RUBY"
If your application requires a specific Ruby version or engine, specify your requirements using the \fBruby\fR method, with the following arguments\. All parameters are \fBOPTIONAL\fR unless otherwise specified\.
-.
.SS "VERSION (required)"
The version of Ruby that your application requires\. If your application requires an alternate Ruby engine, such as JRuby, TruffleRuby, etc\., this should be the Ruby version that the engine is compatible with\.
-.
.IP "" 4
-.
.nf
-
ruby "3\.1\.2"
-.
.fi
-.
.IP "" 0
-.
.P
If you wish to derive your Ruby version from a version file (ie \.ruby\-version), you can use the \fBfile\fR option instead\.
-.
.IP "" 4
-.
.nf
-
ruby file: "\.ruby\-version"
-.
.fi
-.
.IP "" 0
-.
.P
The version file should conform to any of the following formats:
-.
.IP "\(bu" 4
\fB3\.1\.2\fR (\.ruby\-version)
-.
.IP "\(bu" 4
\fBruby 3\.1\.2\fR (\.tool\-versions, read: https://asdf\-vm\.com/manage/configuration\.html#tool\-versions)
-.
.IP "" 0
-.
.SS "ENGINE"
Each application \fImay\fR specify a Ruby engine\. If an engine is specified, an engine version \fImust\fR also be specified\.
-.
.P
-What exactly is an Engine? \- A Ruby engine is an implementation of the Ruby language\.
-.
+What exactly is an Engine?
.IP "\(bu" 4
-For background: the reference or original implementation of the Ruby programming language is called Matz\'s Ruby Interpreter \fIhttps://en\.wikipedia\.org/wiki/Ruby_MRI\fR, or MRI for short\. This is named after Ruby creator Yukihiro Matsumoto, also known as Matz\. MRI is also known as CRuby, because it is written in C\. MRI is the most widely used Ruby engine\.
-.
+A Ruby engine is an implementation of the Ruby language\.
.IP "\(bu" 4
-Other implementations \fIhttps://www\.ruby\-lang\.org/en/about/\fR of Ruby exist\. Some of the more well\-known implementations include JRuby \fIhttp://jruby\.org/\fR and TruffleRuby \fIhttps://www\.graalvm\.org/ruby/\fR\. Rubinius is an alternative implementation of Ruby written in Ruby\. JRuby is an implementation of Ruby on the JVM, short for Java Virtual Machine\. TruffleRuby is a Ruby implementation on the GraalVM, a language toolkit built on the JVM\.
-.
+For background: the reference or original implementation of the Ruby programming language is called Matz's Ruby Interpreter \fIhttps://en\.wikipedia\.org/wiki/Ruby_MRI\fR, or MRI for short\. This is named after Ruby creator Yukihiro Matsumoto, also known as Matz\. MRI is also known as CRuby, because it is written in C\. MRI is the most widely used Ruby engine\.
+.IP "\(bu" 4
+Other implementations \fIhttps://www\.ruby\-lang\.org/en/about/\fR of Ruby exist\. Some of the more well\-known implementations include JRuby \fIhttps://www\.jruby\.org/\fR and TruffleRuby \fIhttps://www\.graalvm\.org/ruby/\fR\. Rubinius is an alternative implementation of Ruby written in Ruby\. JRuby is an implementation of Ruby on the JVM, short for Java Virtual Machine\. TruffleRuby is a Ruby implementation on the GraalVM, a language toolkit built on the JVM\.
.IP "" 0
-.
.SS "ENGINE VERSION"
Each application \fImay\fR specify a Ruby engine version\. If an engine version is specified, an engine \fImust\fR also be specified\. If the engine is "ruby" the engine version specified \fImust\fR match the Ruby version\.
-.
.IP "" 4
-.
.nf
-
ruby "2\.6\.8", engine: "jruby", engine_version: "9\.3\.8\.0"
-.
.fi
-.
.IP "" 0
-.
.SS "PATCHLEVEL"
Each application \fImay\fR specify a Ruby patchlevel\. Specifying the patchlevel has been meaningless since Ruby 2\.1\.0 was released as the patchlevel is now uniquely determined by a combination of major, minor, and teeny version numbers\.
-.
.P
This option was implemented in Bundler 1\.4\.0 for Ruby 2\.0 or earlier\.
-.
.IP "" 4
-.
.nf
-
ruby "3\.1\.2", patchlevel: "20"
-.
.fi
-.
.IP "" 0
-.
.SH "GEMS"
Specify gem requirements using the \fBgem\fR method, with the following arguments\. All parameters are \fBOPTIONAL\fR unless otherwise specified\.
-.
.SS "NAME (required)"
For each gem requirement, list a single \fIgem\fR line\.
-.
.IP "" 4
-.
.nf
-
gem "nokogiri"
-.
.fi
-.
.IP "" 0
-.
.SS "VERSION"
Each \fIgem\fR \fBMAY\fR have one or more version specifiers\.
-.
.IP "" 4
-.
.nf
-
gem "nokogiri", ">= 1\.4\.2"
gem "RedCloth", ">= 4\.1\.0", "< 4\.2\.0"
-.
.fi
-.
.IP "" 0
-.
.SS "REQUIRE AS"
Each \fIgem\fR \fBMAY\fR specify files that should be used when autorequiring via \fBBundler\.require\fR\. You may pass an array with multiple files or \fBtrue\fR if the file you want \fBrequired\fR has the same name as \fIgem\fR or \fBfalse\fR to prevent any file from being autorequired\.
-.
.IP "" 4
-.
.nf
-
gem "redis", require: ["redis/connection/hiredis", "redis"]
gem "webmock", require: false
gem "byebug", require: true
-.
.fi
-.
.IP "" 0
-.
.P
The argument defaults to the name of the gem\. For example, these are identical:
-.
.IP "" 4
-.
.nf
-
gem "nokogiri"
gem "nokogiri", require: "nokogiri"
gem "nokogiri", require: true
-.
.fi
-.
.IP "" 0
-.
.SS "GROUPS"
Each \fIgem\fR \fBMAY\fR specify membership in one or more groups\. Any \fIgem\fR that does not specify membership in any group is placed in the \fBdefault\fR group\.
-.
.IP "" 4
-.
.nf
-
gem "rspec", group: :test
gem "wirble", groups: [:development, :test]
-.
.fi
-.
.IP "" 0
-.
.P
The Bundler runtime allows its two main methods, \fBBundler\.setup\fR and \fBBundler\.require\fR, to limit their impact to particular groups\.
-.
.IP "" 4
-.
.nf
-
-# setup adds gems to Ruby\'s load path
+# setup adds gems to Ruby's load path
Bundler\.setup # defaults to all groups
require "bundler/setup" # same as Bundler\.setup
Bundler\.setup(:default) # only set up the _default_ group
@@ -245,437 +149,269 @@ Bundler\.require # defaults to the _default_ group
Bundler\.require(:default) # identical
Bundler\.require(:default, :test) # requires the _default_ and _test_ groups
Bundler\.require(:test) # requires the _test_ group
-.
.fi
-.
.IP "" 0
-.
.P
The Bundler CLI allows you to specify a list of groups whose gems \fBbundle install\fR should not install with the \fBwithout\fR configuration\.
-.
.P
To specify multiple groups to ignore, specify a list of groups separated by spaces\.
-.
.IP "" 4
-.
.nf
-
bundle config set \-\-local without test
bundle config set \-\-local without development test
-.
.fi
-.
.IP "" 0
-.
.P
Also, calling \fBBundler\.setup\fR with no parameters, or calling \fBrequire "bundler/setup"\fR will setup all groups except for the ones you excluded via \fB\-\-without\fR (since they are not available)\.
-.
.P
Note that on \fBbundle install\fR, bundler downloads and evaluates all gems, in order to create a single canonical list of all of the required gems and their dependencies\. This means that you cannot list different versions of the same gems in different groups\. For more details, see Understanding Bundler \fIhttps://bundler\.io/rationale\.html\fR\.
-.
.SS "PLATFORMS"
If a gem should only be used in a particular platform or set of platforms, you can specify them\. Platforms are essentially identical to groups, except that you do not need to use the \fB\-\-without\fR install\-time flag to exclude groups of gems for other platforms\.
-.
.P
There are a number of \fBGemfile\fR platforms:
-.
.TP
\fBruby\fR
C Ruby (MRI), Rubinius, or TruffleRuby, but not Windows
-.
.TP
\fBmri\fR
C Ruby (MRI) only, but not Windows
-.
.TP
\fBwindows\fR
Windows C Ruby (MRI), including RubyInstaller 32\-bit and 64\-bit versions
-.
.TP
\fBmswin\fR
Windows C Ruby (MRI), including RubyInstaller 32\-bit versions
-.
.TP
\fBmswin64\fR
Windows C Ruby (MRI), including RubyInstaller 64\-bit versions
-.
.TP
\fBrbx\fR
Rubinius
-.
.TP
\fBjruby\fR
JRuby
-.
.TP
\fBtruffleruby\fR
TruffleRuby
-.
.P
On platforms \fBruby\fR, \fBmri\fR, \fBmswin\fR, \fBmswin64\fR, and \fBwindows\fR, you may additionally specify a version by appending the major and minor version numbers without a delimiter\. For example, to specify that a gem should only be used on platform \fBruby\fR version 3\.1, use:
-.
.IP "" 4
-.
.nf
-
ruby_31
-.
.fi
-.
.IP "" 0
-.
.P
As with groups (above), you may specify one or more platforms:
-.
.IP "" 4
-.
.nf
-
gem "weakling", platforms: :jruby
gem "ruby\-debug", platforms: :mri_31
gem "nokogiri", platforms: [:windows_31, :jruby]
-.
.fi
-.
.IP "" 0
-.
.P
All operations involving groups (\fBbundle install\fR \fIbundle\-install\.1\.html\fR, \fBBundler\.setup\fR, \fBBundler\.require\fR) behave exactly the same as if any groups not matching the current platform were explicitly excluded\.
-.
.P
The following platform values are deprecated and should be replaced with \fBwindows\fR:
-.
.IP "\(bu" 4
\fBmswin\fR, \fBmswin64\fR, \fBmingw32\fR, \fBx64_mingw\fR
-.
.IP "" 0
-.
.SS "FORCE_RUBY_PLATFORM"
If you always want the pure ruby variant of a gem to be chosen over platform specific variants, you can use the \fBforce_ruby_platform\fR option:
-.
.IP "" 4
-.
.nf
-
gem "ffi", force_ruby_platform: true
-.
.fi
-.
.IP "" 0
-.
.P
This can be handy (assuming the pure ruby variant works fine) when:
-.
.IP "\(bu" 4
-You\'re having issues with the platform specific variant\.
-.
+You're having issues with the platform specific variant\.
.IP "\(bu" 4
The platform specific variant does not yet support a newer ruby (and thus has a \fBrequired_ruby_version\fR upper bound), but you still want your Gemfile{\.lock} files to resolve under that ruby\.
-.
.IP "" 0
-.
.SS "SOURCE"
-You can select an alternate RubyGems repository for a gem using the \':source\' option\.
-.
+You can select an alternate RubyGems repository for a gem using the ':source' option\.
.IP "" 4
-.
.nf
-
gem "some_internal_gem", source: "https://gems\.example\.com"
-.
.fi
-.
.IP "" 0
-.
.P
This forces the gem to be loaded from this source and ignores the global source declared at the top level of the file\. If the gem does not exist in this source, it will not be installed\.
-.
.P
Bundler will search for child dependencies of this gem by first looking in the source selected for the parent, but if they are not found there, it will fall back on the global source\.
-.
.P
\fBNote about a behavior of the feature deprecated in Bundler 1\.13\fR: Selecting a specific source repository this way also suppresses the ambiguous gem warning described above in \fIGLOBAL SOURCE\fR\.
-.
.P
Using the \fB:source\fR option for an individual gem will also make that source available as a possible global source for any other gems which do not specify explicit sources\. Thus, when adding gems with explicit sources, it is recommended that you also ensure all other gems in the Gemfile are using explicit sources\.
-.
.SS "GIT"
If necessary, you can specify that a gem is located at a particular git repository using the \fB:git\fR parameter\. The repository can be accessed via several protocols:
-.
.TP
\fBHTTP(S)\fR
gem "rails", git: "https://github\.com/rails/rails\.git"
-.
.TP
\fBSSH\fR
gem "rails", git: "git@github\.com:rails/rails\.git"
-.
.TP
\fBgit\fR
gem "rails", git: "git://github\.com/rails/rails\.git"
-.
.P
If using SSH, the user that you use to run \fBbundle install\fR \fBMUST\fR have the appropriate keys available in their \fB$HOME/\.ssh\fR\.
-.
.P
\fBNOTE\fR: \fBhttp://\fR and \fBgit://\fR URLs should be avoided if at all possible\. These protocols are unauthenticated, so a man\-in\-the\-middle attacker can deliver malicious code and compromise your system\. HTTPS and SSH are strongly preferred\.
-.
.P
The \fBgroup\fR, \fBplatforms\fR, and \fBrequire\fR options are available and behave exactly the same as they would for a normal gem\.
-.
.P
A git repository \fBSHOULD\fR have at least one file, at the root of the directory containing the gem, with the extension \fB\.gemspec\fR\. This file \fBMUST\fR contain a valid gem specification, as expected by the \fBgem build\fR command\.
-.
.P
If a git repository does not have a \fB\.gemspec\fR, bundler will attempt to create one, but it will not contain any dependencies, executables, or C extension compilation instructions\. As a result, it may fail to properly integrate into your application\.
-.
.P
If a git repository does have a \fB\.gemspec\fR for the gem you attached it to, a version specifier, if provided, means that the git repository is only valid if the \fB\.gemspec\fR specifies a version matching the version specifier\. If not, bundler will print a warning\.
-.
.IP "" 4
-.
.nf
-
gem "rails", "2\.3\.8", git: "https://github\.com/rails/rails\.git"
# bundle install will fail, because the \.gemspec in the rails
-# repository\'s master branch specifies version 3\.0\.0
-.
+# repository's master branch specifies version 3\.0\.0
.fi
-.
.IP "" 0
-.
.P
If a git repository does \fBnot\fR have a \fB\.gemspec\fR for the gem you attached it to, a version specifier \fBMUST\fR be provided\. Bundler will use this version in the simple \fB\.gemspec\fR it creates\.
-.
.P
Git repositories support a number of additional options\.
-.
.TP
\fBbranch\fR, \fBtag\fR, and \fBref\fR
You \fBMUST\fR only specify at most one of these options\. The default is \fBbranch: "master"\fR\. For example:
-.
.IP
gem "rails", git: "https://github\.com/rails/rails\.git", branch: "5\-0\-stable"
-.
.IP
gem "rails", git: "https://github\.com/rails/rails\.git", tag: "v5\.0\.0"
-.
.IP
gem "rails", git: "https://github\.com/rails/rails\.git", ref: "4aded"
-.
.TP
\fBsubmodules\fR
For reference, a git submodule \fIhttps://git\-scm\.com/book/en/v2/Git\-Tools\-Submodules\fR lets you have another git repository within a subfolder of your repository\. Specify \fBsubmodules: true\fR to cause bundler to expand any submodules included in the git repository
-.
.P
If a git repository contains multiple \fB\.gemspecs\fR, each \fB\.gemspec\fR represents a gem located at the same place in the file system as the \fB\.gemspec\fR\.
-.
.IP "" 4
-.
.nf
-
|~rails [git root]
| |\-rails\.gemspec [rails gem located here]
|~actionpack
| |\-actionpack\.gemspec [actionpack gem located here]
|~activesupport
| |\-activesupport\.gemspec [activesupport gem located here]
-|\.\.\.
-.
+|\|\.\|\.\|\.
.fi
-.
.IP "" 0
-.
.P
To install a gem located in a git repository, bundler changes to the directory containing the gemspec, runs \fBgem build name\.gemspec\fR and then installs the resulting gem\. The \fBgem build\fR command, which comes standard with Rubygems, evaluates the \fB\.gemspec\fR in the context of the directory in which it is located\.
-.
.SS "GIT SOURCE"
-A custom git source can be defined via the \fBgit_source\fR method\. Provide the source\'s name as an argument, and a block which receives a single argument and interpolates it into a string to return the full repo address:
-.
+A custom git source can be defined via the \fBgit_source\fR method\. Provide the source's name as an argument, and a block which receives a single argument and interpolates it into a string to return the full repo address:
.IP "" 4
-.
.nf
-
git_source(:stash){ |repo_name| "https://stash\.corp\.acme\.pl/#{repo_name}\.git" }
-gem \'rails\', stash: \'forks/rails\'
-.
+gem 'rails', stash: 'forks/rails'
.fi
-.
.IP "" 0
-.
.P
In addition, if you wish to choose a specific branch:
-.
.IP "" 4
-.
.nf
-
gem "rails", stash: "forks/rails", branch: "branch_name"
-.
.fi
-.
.IP "" 0
-.
.SS "GITHUB"
\fBNOTE\fR: This shorthand should be avoided until Bundler 2\.0, since it currently expands to an insecure \fBgit://\fR URL\. This allows a man\-in\-the\-middle attacker to compromise your system\.
-.
.P
If the git repository you want to use is hosted on GitHub and is public, you can use the :github shorthand to specify the github username and repository name (without the trailing "\.git"), separated by a slash\. If both the username and repository name are the same, you can omit one\.
-.
.IP "" 4
-.
.nf
-
gem "rails", github: "rails/rails"
gem "rails", github: "rails"
-.
.fi
-.
.IP "" 0
-.
.P
Are both equivalent to
-.
.IP "" 4
-.
.nf
-
gem "rails", git: "https://github\.com/rails/rails\.git"
-.
.fi
-.
.IP "" 0
-.
.P
Since the \fBgithub\fR method is a specialization of \fBgit_source\fR, it accepts a \fB:branch\fR named argument\.
-.
.P
You can also directly pass a pull request URL:
-.
.IP "" 4
-.
.nf
-
gem "rails", github: "https://github\.com/rails/rails/pull/43753"
-.
.fi
-.
.IP "" 0
-.
.P
Which is equivalent to:
-.
.IP "" 4
-.
.nf
-
gem "rails", github: "rails/rails", branch: "refs/pull/43753/head"
-.
.fi
-.
.IP "" 0
-.
.SS "GIST"
If the git repository you want to use is hosted as a GitHub Gist and is public, you can use the :gist shorthand to specify the gist identifier (without the trailing "\.git")\.
-.
.IP "" 4
-.
.nf
-
gem "the_hatch", gist: "4815162342"
-.
.fi
-.
.IP "" 0
-.
.P
Is equivalent to:
-.
.IP "" 4
-.
.nf
-
gem "the_hatch", git: "https://gist\.github\.com/4815162342\.git"
-.
.fi
-.
.IP "" 0
-.
.P
Since the \fBgist\fR method is a specialization of \fBgit_source\fR, it accepts a \fB:branch\fR named argument\.
-.
.SS "BITBUCKET"
If the git repository you want to use is hosted on Bitbucket and is public, you can use the :bitbucket shorthand to specify the bitbucket username and repository name (without the trailing "\.git"), separated by a slash\. If both the username and repository name are the same, you can omit one\.
-.
.IP "" 4
-.
.nf
-
gem "rails", bitbucket: "rails/rails"
gem "rails", bitbucket: "rails"
-.
.fi
-.
.IP "" 0
-.
.P
Are both equivalent to
-.
.IP "" 4
-.
.nf
-
gem "rails", git: "https://rails@bitbucket\.org/rails/rails\.git"
-.
.fi
-.
.IP "" 0
-.
.P
Since the \fBbitbucket\fR method is a specialization of \fBgit_source\fR, it accepts a \fB:branch\fR named argument\.
-.
.SS "PATH"
You can specify that a gem is located in a particular location on the file system\. Relative paths are resolved relative to the directory containing the \fBGemfile\fR\.
-.
.P
Similar to the semantics of the \fB:git\fR option, the \fB:path\fR option requires that the directory in question either contains a \fB\.gemspec\fR for the gem, or that you specify an explicit version that bundler should use\.
-.
.P
Unlike \fB:git\fR, bundler does not compile C extensions for gems specified as paths\.
-.
.IP "" 4
-.
.nf
-
gem "rails", path: "vendor/rails"
-.
.fi
-.
.IP "" 0
-.
.P
-If you would like to use multiple local gems directly from the filesystem, you can set a global \fBpath\fR option to the path containing the gem\'s files\. This will automatically load gemspec files from subdirectories\.
-.
+If you would like to use multiple local gems directly from the filesystem, you can set a global \fBpath\fR option to the path containing the gem's files\. This will automatically load gemspec files from subdirectories\.
.IP "" 4
-.
.nf
-
-path \'components\' do
- gem \'admin_ui\'
- gem \'public_ui\'
+path 'components' do
+ gem 'admin_ui'
+ gem 'public_ui'
end
-.
.fi
-.
.IP "" 0
-.
.SH "BLOCK FORM OF SOURCE, GIT, PATH, GROUP and PLATFORMS"
The \fB:source\fR, \fB:git\fR, \fB:path\fR, \fB:group\fR, and \fB:platforms\fR options may be applied to a group of gems by using block form\.
-.
.IP "" 4
-.
.nf
-
source "https://gems\.example\.com" do
gem "some_internal_gem"
gem "another_internal_gem"
@@ -695,61 +431,40 @@ group :development, optional: true do
gem "wirble"
gem "faker"
end
-.
.fi
-.
.IP "" 0
-.
.P
In the case of the group block form the :optional option can be given to prevent a group from being installed unless listed in the \fB\-\-with\fR option given to the \fBbundle install\fR command\.
-.
.P
In the case of the \fBgit\fR block form, the \fB:ref\fR, \fB:branch\fR, \fB:tag\fR, and \fB:submodules\fR options may be passed to the \fBgit\fR method, and all gems in the block will inherit those options\.
-.
.P
The presence of a \fBsource\fR block in a Gemfile also makes that source available as a possible global source for any other gems which do not specify explicit sources\. Thus, when defining source blocks, it is recommended that you also ensure all other gems in the Gemfile are using explicit sources, either via source blocks or \fB:source\fR directives on individual gems\.
-.
.SH "INSTALL_IF"
The \fBinstall_if\fR method allows gems to be installed based on a proc or lambda\. This is especially useful for optional gems that can only be used if certain software is installed or some other conditions are met\.
-.
.IP "" 4
-.
.nf
-
install_if \-> { RUBY_PLATFORM =~ /darwin/ } do
gem "pasteboard"
end
-.
.fi
-.
.IP "" 0
-.
.SH "GEMSPEC"
-The \fB\.gemspec\fR \fIhttp://guides\.rubygems\.org/specification\-reference/\fR file is where you provide metadata about your gem to Rubygems\. Some required Gemspec attributes include the name, description, and homepage of your gem\. This is also where you specify the dependencies your gem needs to run\.
-.
+The \fB\.gemspec\fR \fIhttps://guides\.rubygems\.org/specification\-reference/\fR file is where you provide metadata about your gem to Rubygems\. Some required Gemspec attributes include the name, description, and homepage of your gem\. This is also where you specify the dependencies your gem needs to run\.
.P
If you wish to use Bundler to help install dependencies for a gem while it is being developed, use the \fBgemspec\fR method to pull in the dependencies listed in the \fB\.gemspec\fR file\.
-.
.P
-The \fBgemspec\fR method adds any runtime dependencies as gem requirements in the default group\. It also adds development dependencies as gem requirements in the \fBdevelopment\fR group\. Finally, it adds a gem requirement on your project (\fBpath: \'\.\'\fR)\. In conjunction with \fBBundler\.setup\fR, this allows you to require project files in your test code as you would if the project were installed as a gem; you need not manipulate the load path manually or require project files via relative paths\.
-.
+The \fBgemspec\fR method adds any runtime dependencies as gem requirements in the default group\. It also adds development dependencies as gem requirements in the \fBdevelopment\fR group\. Finally, it adds a gem requirement on your project (\fBpath: '\.'\fR)\. In conjunction with \fBBundler\.setup\fR, this allows you to require project files in your test code as you would if the project were installed as a gem; you need not manipulate the load path manually or require project files via relative paths\.
.P
The \fBgemspec\fR method supports optional \fB:path\fR, \fB:glob\fR, \fB:name\fR, and \fB:development_group\fR options, which control where bundler looks for the \fB\.gemspec\fR, the glob it uses to look for the gemspec (defaults to: \fB{,*,*/*}\.gemspec\fR), what named \fB\.gemspec\fR it uses (if more than one is present), and which group development dependencies are included in\.
-.
.P
When a \fBgemspec\fR dependency encounters version conflicts during resolution, the local version under development will always be selected \-\- even if there are remote versions that better match other requirements for the \fBgemspec\fR gem\.
-.
.SH "SOURCE PRIORITY"
When attempting to locate a gem to satisfy a gem requirement, bundler uses the following priority order:
-.
.IP "1." 4
The source explicitly attached to the gem (using \fB:source\fR, \fB:path\fR, or \fB:git\fR)
-.
.IP "2." 4
For implicit gems (dependencies of explicit gems), any source, git, or path repository declared on the parent\. This results in bundler prioritizing the ActiveSupport gem from the Rails git repository over ones from \fBrubygems\.org\fR
-.
.IP "3." 4
If neither of the above conditions are met, the global source will be used\. If multiple global sources are specified, they will be prioritized from last to first, but this is deprecated since Bundler 1\.13, so Bundler prints a warning and will abort with an error in the future\.
-.
.IP "" 0
diff --git a/lib/bundler/man/gemfile.5.ronn b/lib/bundler/man/gemfile.5.ronn
index e8a1f8b79e..7c1e00d13a 100644
--- a/lib/bundler/man/gemfile.5.ronn
+++ b/lib/bundler/man/gemfile.5.ronn
@@ -96,7 +96,7 @@ What exactly is an Engine?
- [Other implementations](https://www.ruby-lang.org/en/about/) of Ruby exist.
Some of the more well-known implementations include
- [JRuby](http://jruby.org/) and [TruffleRuby](https://www.graalvm.org/ruby/).
+ [JRuby](https://www.jruby.org/) and [TruffleRuby](https://www.graalvm.org/ruby/).
Rubinius is an alternative implementation of Ruby written in Ruby.
JRuby is an implementation of Ruby on the JVM, short for Java Virtual Machine.
TruffleRuby is a Ruby implementation on the GraalVM, a language toolkit built on the JVM.
@@ -509,7 +509,7 @@ software is installed or some other conditions are met.
## GEMSPEC
-The [`.gemspec`](http://guides.rubygems.org/specification-reference/) file is where
+The [`.gemspec`](https://guides.rubygems.org/specification-reference/) file is where
you provide metadata about your gem to Rubygems. Some required Gemspec
attributes include the name, description, and homepage of your gem. This is
also where you specify the dependencies your gem needs to run.
diff --git a/lib/bundler/match_metadata.rb b/lib/bundler/match_metadata.rb
index 499036ca93..f6cc27df32 100644
--- a/lib/bundler/match_metadata.rb
+++ b/lib/bundler/match_metadata.rb
@@ -2,6 +2,10 @@
module Bundler
module MatchMetadata
+ def matches_current_metadata?
+ matches_current_ruby? && matches_current_rubygems?
+ end
+
def matches_current_ruby?
@required_ruby_version.satisfied_by?(Gem.ruby_version)
end
diff --git a/lib/bundler/mirror.rb b/lib/bundler/mirror.rb
index 9d437a0951..494a6d6aef 100644
--- a/lib/bundler/mirror.rb
+++ b/lib/bundler/mirror.rb
@@ -47,7 +47,7 @@ module Bundler
def fetch_valid_mirror_for(uri)
downcased = uri.to_s.downcase
- mirror = @mirrors[downcased] || @mirrors[Bundler::URI(downcased).host] || Mirror.new(uri)
+ mirror = @mirrors[downcased] || @mirrors[Gem::URI(downcased).host] || Mirror.new(uri)
mirror.validate!(@prober)
mirror = Mirror.new(uri) unless mirror.valid?
mirror
@@ -74,7 +74,7 @@ module Bundler
@uri = if uri.nil?
nil
else
- Bundler::URI(uri.to_s)
+ Gem::URI(uri.to_s)
end
@valid = nil
end
@@ -126,7 +126,7 @@ module Bundler
if uri == "all"
@all = true
else
- @uri = Bundler::URI(uri).absolute? ? Settings.normalize_uri(uri) : uri
+ @uri = Gem::URI(uri).absolute? ? Settings.normalize_uri(uri) : uri
end
@value = value
end
diff --git a/lib/bundler/plugin.rb b/lib/bundler/plugin.rb
index e3f698ec43..588fa79be8 100644
--- a/lib/bundler/plugin.rb
+++ b/lib/bundler/plugin.rb
@@ -101,7 +101,7 @@ module Bundler
# @param [Pathname] gemfile path
# @param [Proc] block that can be evaluated for (inline) Gemfile
def gemfile_install(gemfile = nil, &inline)
- Bundler.settings.temporary(:frozen => false, :deployment => false) do
+ Bundler.settings.temporary(frozen: false, deployment: false) do
builder = DSL.new
if block_given?
builder.instance_eval(&inline)
@@ -307,7 +307,7 @@ module Bundler
@hooks_by_event = Hash.new {|h, k| h[k] = [] }
load_paths = spec.load_paths
- Bundler.rubygems.add_to_load_path(load_paths)
+ Gem.add_to_load_path(*load_paths)
path = Pathname.new spec.full_gem_path
begin
@@ -342,7 +342,7 @@ module Bundler
# done to avoid conflicts
path = index.plugin_path(name)
- Bundler.rubygems.add_to_load_path(index.load_paths(name))
+ Gem.add_to_load_path(*index.load_paths(name))
load path.join(PLUGIN_FILE_NAME)
diff --git a/lib/bundler/plugin/api/source.rb b/lib/bundler/plugin/api/source.rb
index 57d4eb64ad..8563ee358a 100644
--- a/lib/bundler/plugin/api/source.rb
+++ b/lib/bundler/plugin/api/source.rb
@@ -96,7 +96,7 @@ module Bundler
#
# Note: Do not override if you don't know what you are doing.
def post_install(spec, disable_exts = false)
- opts = { :env_shebang => false, :disable_extensions => disable_exts }
+ opts = { env_shebang: false, disable_extensions: disable_exts }
installer = Bundler::Source::Path::Installer.new(spec, opts)
installer.post_install
end
@@ -107,7 +107,7 @@ module Bundler
def install_path
@install_path ||=
begin
- base_name = File.basename(Bundler::URI.parse(uri).normalize.path)
+ base_name = File.basename(Gem::URI.parse(uri).normalize.path)
gem_install_dir.join("#{base_name}-#{uri_hash[0..11]}")
end
@@ -176,7 +176,7 @@ module Bundler
#
# This is used by `app_cache_path`
def app_cache_dirname
- base_name = File.basename(Bundler::URI.parse(uri).normalize.path)
+ base_name = File.basename(Gem::URI.parse(uri).normalize.path)
"#{base_name}-#{uri_hash}"
end
diff --git a/lib/bundler/plugin/events.rb b/lib/bundler/plugin/events.rb
index bc037d1af5..29c05098ae 100644
--- a/lib/bundler/plugin/events.rb
+++ b/lib/bundler/plugin/events.rb
@@ -56,6 +56,30 @@ module Bundler
# Includes an Array of Bundler::Dependency objects
# GEM_AFTER_INSTALL_ALL = "after-install-all"
define :GEM_AFTER_INSTALL_ALL, "after-install-all"
+
+ # @!parse
+ # A hook called before each individual gem is required
+ # Includes a Bundler::Dependency.
+ # GEM_BEFORE_REQUIRE = "before-require"
+ define :GEM_BEFORE_REQUIRE, "before-require"
+
+ # @!parse
+ # A hook called after each individual gem is required
+ # Includes a Bundler::Dependency.
+ # GEM_AFTER_REQUIRE = "after-require"
+ define :GEM_AFTER_REQUIRE, "after-require"
+
+ # @!parse
+ # A hook called before any gems require
+ # Includes an Array of Bundler::Dependency objects.
+ # GEM_BEFORE_REQUIRE_ALL = "before-require-all"
+ define :GEM_BEFORE_REQUIRE_ALL, "before-require-all"
+
+ # @!parse
+ # A hook called after all gems required
+ # Includes an Array of Bundler::Dependency objects.
+ # GEM_AFTER_REQUIRE_ALL = "after-require-all"
+ define :GEM_AFTER_REQUIRE_ALL, "after-require-all"
end
end
end
diff --git a/lib/bundler/plugin/installer.rb b/lib/bundler/plugin/installer.rb
index c9ff12ce4b..4f60862bb4 100644
--- a/lib/bundler/plugin/installer.rb
+++ b/lib/bundler/plugin/installer.rb
@@ -10,6 +10,7 @@ module Bundler
class Installer
autoload :Rubygems, File.expand_path("installer/rubygems", __dir__)
autoload :Git, File.expand_path("installer/git", __dir__)
+ autoload :Path, File.expand_path("installer/path", __dir__)
def install(names, options)
check_sources_consistency!(options)
@@ -18,8 +19,8 @@ module Bundler
if options[:git]
install_git(names, version, options)
- elsif options[:local_git]
- install_local_git(names, version, options)
+ elsif options[:path]
+ install_path(names, version, options[:path])
else
sources = options[:source] || Gem.sources
install_rubygems(names, version, sources)
@@ -45,20 +46,40 @@ module Bundler
if options.key?(:git) && options.key?(:local_git)
raise InvalidOption, "Remote and local plugin git sources can't be both specified"
end
+
+ # back-compat; local_git is an alias for git
+ if options.key?(:local_git)
+ Bundler::SharedHelpers.major_deprecation(2, "--local_git is deprecated, use --git")
+ options[:git] = options.delete(:local_git)
+ end
+
+ if (options.keys & [:source, :git, :path]).length > 1
+ raise InvalidOption, "Only one of --source, --git, or --path may be specified"
+ end
+
+ if (options.key?(:branch) || options.key?(:ref)) && !options.key?(:git)
+ raise InvalidOption, "--#{options.key?(:branch) ? "branch" : "ref"} can only be used with git sources"
+ end
+
+ if options.key?(:branch) && options.key?(:ref)
+ raise InvalidOption, "--branch and --ref can't be both specified"
+ end
end
def install_git(names, version, options)
- uri = options.delete(:git)
- options["uri"] = uri
+ source_list = SourceList.new
+ source = source_list.add_git_source({ "uri" => options[:git],
+ "branch" => options[:branch],
+ "ref" => options[:ref] })
- install_all_sources(names, version, options, options[:source])
+ install_all_sources(names, version, source_list, source)
end
- def install_local_git(names, version, options)
- uri = options.delete(:local_git)
- options["uri"] = uri
+ def install_path(names, version, path)
+ source_list = SourceList.new
+ source = source_list.add_path_source({ "path" => path, "root_path" => SharedHelpers.pwd })
- install_all_sources(names, version, options, options[:source])
+ install_all_sources(names, version, source_list, source)
end
# Installs the plugin from rubygems source and returns the path where the
@@ -70,20 +91,19 @@ module Bundler
#
# @return [Hash] map of names to the specs of plugins installed
def install_rubygems(names, version, sources)
- install_all_sources(names, version, nil, sources)
- end
-
- def install_all_sources(names, version, git_source_options, rubygems_source)
source_list = SourceList.new
- source_list.add_git_source(git_source_options) if git_source_options
- Array(rubygems_source).each {|remote| source_list.add_global_rubygems_remote(remote) } if rubygems_source
+ Array(sources).each {|remote| source_list.add_global_rubygems_remote(remote) }
+
+ install_all_sources(names, version, source_list)
+ end
- deps = names.map {|name| Dependency.new name, version }
+ def install_all_sources(names, version, source_list, source = nil)
+ deps = names.map {|name| Dependency.new(name, version, { "source" => source }) }
Bundler.configure_gem_home_and_path(Plugin.root)
- Bundler.settings.temporary(:deployment => false, :frozen => false) do
+ Bundler.settings.temporary(deployment: false, frozen: false) do
definition = Definition.new(nil, deps, source_list, true)
install_definition(definition)
diff --git a/lib/bundler/plugin/installer/path.rb b/lib/bundler/plugin/installer/path.rb
new file mode 100644
index 0000000000..58a8fa7426
--- /dev/null
+++ b/lib/bundler/plugin/installer/path.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Bundler
+ module Plugin
+ class Installer
+ class Path < Bundler::Source::Path
+ def root
+ SharedHelpers.in_bundle? ? Bundler.root : Plugin.root
+ end
+
+ def generate_bin(spec, disable_extensions = false)
+ # Need to find a way without code duplication
+ # For now, we can ignore this
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bundler/plugin/source_list.rb b/lib/bundler/plugin/source_list.rb
index 547661cf2f..746996de55 100644
--- a/lib/bundler/plugin/source_list.rb
+++ b/lib/bundler/plugin/source_list.rb
@@ -9,6 +9,10 @@ module Bundler
add_source_to_list Plugin::Installer::Git.new(options), git_sources
end
+ def add_path_source(options = {})
+ add_source_to_list Plugin::Installer::Path.new(options), path_sources
+ end
+
def add_rubygems_source(options = {})
add_source_to_list Plugin::Installer::Rubygems.new(options), @rubygems_sources
end
@@ -17,10 +21,6 @@ module Bundler
path_sources + git_sources + rubygems_sources + [metadata_source]
end
- def default_source
- git_sources.first || global_rubygems_source
- end
-
private
def rubygems_aggregate_class
diff --git a/lib/bundler/remote_specification.rb b/lib/bundler/remote_specification.rb
index f626a3218e..9d237f3fa0 100644
--- a/lib/bundler/remote_specification.rb
+++ b/lib/bundler/remote_specification.rb
@@ -88,6 +88,10 @@ module Bundler
end
end
+ def runtime_dependencies
+ dependencies.select(&:runtime?)
+ end
+
def git_version
return unless loaded_from && source.is_a?(Bundler::Source::Git)
" #{source.revision[0..6]}"
diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb
index 9ec39d5a35..1a6711ea6f 100644
--- a/lib/bundler/resolver.rb
+++ b/lib/bundler/resolver.rb
@@ -29,7 +29,7 @@ module Bundler
Bundler.ui.info "Resolving dependencies...", true
- solve_versions(:root => root, :logger => logger)
+ solve_versions(root: root, logger: logger)
end
def setup_solver
@@ -50,26 +50,26 @@ module Bundler
specs[name] = matches.sort_by {|s| [s.version, s.platform.to_s] }
end
+ @all_versions = Hash.new do |candidates, package|
+ candidates[package] = all_versions_for(package)
+ end
+
@sorted_versions = Hash.new do |candidates, package|
- candidates[package] = if package.root?
- [root_version]
- else
- all_versions_for(package).sort
- end
+ candidates[package] = filtered_versions_for(package).sort
end
+ @sorted_versions[root] = [root_version]
+
root_dependencies = prepare_dependencies(@requirements, @packages)
@cached_dependencies = Hash.new do |dependencies, package|
- dependencies[package] = if package.root?
- { root_version => root_dependencies }
- else
- Hash.new do |versions, version|
- versions[version] = to_dependency_hash(version.dependencies.reject {|d| d.name == package.name }, @packages)
- end
+ dependencies[package] = Hash.new do |versions, version|
+ versions[version] = to_dependency_hash(version.dependencies.reject {|d| d.name == package.name }, @packages)
end
end
+ @cached_dependencies[root] = { root_version => root_dependencies }
+
logger = Bundler::UI::Shell.new
logger.level = debug? ? "debug" : "warn"
@@ -77,7 +77,7 @@ module Bundler
end
def solve_versions(root:, logger:)
- solver = PubGrub::VersionSolver.new(:source => self, :root => root, :logger => logger)
+ solver = PubGrub::VersionSolver.new(source: self, root: root, logger: logger)
result = solver.solve
result.map {|package, version| version.to_specs(package) }.flatten.uniq
rescue PubGrub::SolveFailure => e
@@ -152,13 +152,19 @@ module Bundler
requirement_to_range(dependency)
end
- PubGrub::VersionConstraint.new(package, :range => range)
+ PubGrub::VersionConstraint.new(package, range: range)
end
def versions_for(package, range=VersionRange.any)
- versions = range.select_versions(@sorted_versions[package])
+ versions = select_sorted_versions(package, range)
- sort_versions(package, versions)
+ # Conditional avoids (among other things) calling
+ # sort_versions_by_preferred with the root package
+ if versions.size > 1
+ sort_versions_by_preferred(package, versions)
+ else
+ versions
+ end
end
def no_versions_incompatibility_for(package, unsatisfied_term)
@@ -181,7 +187,7 @@ module Bundler
extended_explanation = other_specs_matching_message(specs_matching_other_platforms, label) if specs_matching_other_platforms.any?
end
- Incompatibility.new([unsatisfied_term], :cause => cause, :custom_explanation => custom_explanation, :extended_explanation => extended_explanation)
+ Incompatibility.new([unsatisfied_term], cause: cause, custom_explanation: custom_explanation, extended_explanation: extended_explanation)
end
def debug?
@@ -220,9 +226,9 @@ module Bundler
sorted_versions[high]
end
- range = PubGrub::VersionRange.new(:min => low, :max => high, :include_min => true)
+ range = PubGrub::VersionRange.new(min: low, max: high, include_min: true)
- self_constraint = PubGrub::VersionConstraint.new(package, :range => range)
+ self_constraint = PubGrub::VersionConstraint.new(package, range: range)
dep_term = PubGrub::Term.new(dep_constraint, false)
self_term = PubGrub::Term.new(self_constraint, true)
@@ -231,7 +237,7 @@ module Bundler
"current #{dep_package} version is #{dep_constraint.constraint_string}"
end
- PubGrub::Incompatibility.new([self_term, dep_term], :cause => :dependency, :custom_explanation => custom_explanation)
+ PubGrub::Incompatibility.new([self_term, dep_term], cause: :dependency, custom_explanation: custom_explanation)
end
end
@@ -247,7 +253,7 @@ module Bundler
locked_requirement = base_requirements[name]
results = filter_matching_specs(results, locked_requirement) if locked_requirement
- versions = results.group_by(&:version).reduce([]) do |groups, (version, specs)|
+ results.group_by(&:version).reduce([]) do |groups, (version, specs)|
platform_specs = package.platforms.map {|platform| select_best_platform_match(specs, platform) }
# If package is a top-level dependency,
@@ -266,16 +272,14 @@ module Bundler
platform_specs.flatten!
ruby_specs = select_best_platform_match(specs, Gem::Platform::RUBY)
- groups << Resolver::Candidate.new(version, :specs => ruby_specs) if ruby_specs.any?
+ groups << Resolver::Candidate.new(version, specs: ruby_specs) if ruby_specs.any?
next groups if platform_specs == ruby_specs || package.force_ruby_platform?
- groups << Resolver::Candidate.new(version, :specs => platform_specs)
+ groups << Resolver::Candidate.new(version, specs: platform_specs)
groups
end
-
- sort_versions(package, versions)
end
def source_for(name)
@@ -334,6 +338,21 @@ module Bundler
private
+ def filtered_versions_for(package)
+ @gem_version_promoter.filter_versions(package, @all_versions[package])
+ end
+
+ def raise_all_versions_filtered_out!(package)
+ level = @gem_version_promoter.level
+ name = package.name
+ locked_version = package.locked_version
+ requirement = package.dependency
+
+ raise GemNotFound,
+ "#{name} is locked to #{locked_version}, while Gemfile is requesting #{requirement}. " \
+ "--strict --#{level} was specified, but there are no #{level} level upgrades from #{locked_version} satisfying #{requirement}, so version solving has failed"
+ end
+
def filter_matching_specs(specs, requirements)
Array(requirements).flat_map do |requirement|
specs.select {| spec| requirement_satisfied_by?(requirement, spec) }
@@ -357,12 +376,8 @@ module Bundler
requirement.satisfied_by?(spec.version) || spec.source.is_a?(Source::Gemspec)
end
- def sort_versions(package, versions)
- if versions.size > 1
- @gem_version_promoter.sort_versions(package, versions).reverse
- else
- versions
- end
+ def sort_versions_by_preferred(package, versions)
+ @gem_version_promoter.sort_versions(package, versions)
end
def repository_for(package)
@@ -379,12 +394,19 @@ module Bundler
next [dep_package, dep_constraint] if name == "bundler"
- versions = versions_for(dep_package, dep_constraint.range)
+ dep_range = dep_constraint.range
+ versions = select_sorted_versions(dep_package, dep_range)
if versions.empty? && dep_package.ignores_prereleases?
+ @all_versions.delete(dep_package)
@sorted_versions.delete(dep_package)
dep_package.consider_prereleases!
- versions = versions_for(dep_package, dep_constraint.range)
+ versions = select_sorted_versions(dep_package, dep_range)
end
+
+ if versions.empty? && select_all_versions(dep_package, dep_range).any?
+ raise_all_versions_filtered_out!(dep_package)
+ end
+
next [dep_package, dep_constraint] unless versions.empty?
next unless dep_package.current_platform?
@@ -393,6 +415,14 @@ module Bundler
end.compact.to_h
end
+ def select_sorted_versions(package, range)
+ range.select_versions(@sorted_versions[package])
+ end
+
+ def select_all_versions(package, range)
+ range.select_versions(@all_versions[package])
+ end
+
def other_specs_matching_message(specs, requirement)
message = String.new("The source contains the following gems matching '#{requirement}':\n")
message << specs.map {|s| " * #{s.full_name}" }.join("\n")
@@ -408,19 +438,19 @@ module Bundler
when "~>"
name = "~> #{ver}"
bump = Resolver::Candidate.new(version.bump.to_s + ".A")
- PubGrub::VersionRange.new(:name => name, :min => ver, :max => bump, :include_min => true)
+ PubGrub::VersionRange.new(name: name, min: ver, max: bump, include_min: true)
when ">"
- PubGrub::VersionRange.new(:min => platform_ver)
+ PubGrub::VersionRange.new(min: platform_ver)
when ">="
- PubGrub::VersionRange.new(:min => ver, :include_min => true)
+ PubGrub::VersionRange.new(min: ver, include_min: true)
when "<"
- PubGrub::VersionRange.new(:max => ver)
+ PubGrub::VersionRange.new(max: ver)
when "<="
- PubGrub::VersionRange.new(:max => platform_ver, :include_max => true)
+ PubGrub::VersionRange.new(max: platform_ver, include_max: true)
when "="
- PubGrub::VersionRange.new(:min => ver, :max => platform_ver, :include_min => true, :include_max => true)
+ PubGrub::VersionRange.new(min: ver, max: platform_ver, include_min: true, include_max: true)
when "!="
- PubGrub::VersionRange.new(:min => ver, :max => platform_ver, :include_min => true, :include_max => true).invert
+ PubGrub::VersionRange.new(min: ver, max: platform_ver, include_min: true, include_max: true).invert
else
raise "bad version specifier: #{op}"
end
diff --git a/lib/bundler/resolver/base.rb b/lib/bundler/resolver/base.rb
index e5c3763c3f..ad19eeb3f4 100644
--- a/lib/bundler/resolver/base.rb
+++ b/lib/bundler/resolver/base.rb
@@ -24,7 +24,7 @@ module Bundler
name = dep.name
- @packages[name] = Package.new(name, dep_platforms, **options.merge(:dependency => dep))
+ @packages[name] = Package.new(name, dep_platforms, **options.merge(dependency: dep))
dep
end.compact
diff --git a/lib/bundler/resolver/candidate.rb b/lib/bundler/resolver/candidate.rb
index e695ef08ee..9e8b913335 100644
--- a/lib/bundler/resolver/candidate.rb
+++ b/lib/bundler/resolver/candidate.rb
@@ -15,7 +15,7 @@ module Bundler
# considered separately.
#
# Some candidates may also keep some information explicitly about the
- # package the refer to. These candidates are referred to as "canonical" and
+ # package they refer to. These candidates are referred to as "canonical" and
# are used when materializing resolution results back into RubyGems
# specifications that can be installed, written to lock files, and so on.
#
diff --git a/lib/bundler/resolver/incompatibility.rb b/lib/bundler/resolver/incompatibility.rb
index c61151fbeb..4ac1b2e1ea 100644
--- a/lib/bundler/resolver/incompatibility.rb
+++ b/lib/bundler/resolver/incompatibility.rb
@@ -8,7 +8,7 @@ module Bundler
def initialize(terms, cause:, custom_explanation: nil, extended_explanation: nil)
@extended_explanation = extended_explanation
- super(terms, :cause => cause, :custom_explanation => custom_explanation)
+ super(terms, cause: cause, custom_explanation: custom_explanation)
end
end
end
diff --git a/lib/bundler/ruby_dsl.rb b/lib/bundler/ruby_dsl.rb
index 95151898ff..fb4b79c4df 100644
--- a/lib/bundler/ruby_dsl.rb
+++ b/lib/bundler/ruby_dsl.rb
@@ -3,22 +3,28 @@
module Bundler
module RubyDsl
def ruby(*ruby_version)
- options = ruby_version.last.is_a?(Hash) ? ruby_version.pop : {}
+ options = ruby_version.pop if ruby_version.last.is_a?(Hash)
ruby_version.flatten!
- raise GemfileError, "Please define :engine_version" if options[:engine] && options[:engine_version].nil?
- raise GemfileError, "Please define :engine" if options[:engine_version] && options[:engine].nil?
+ if options
+ patchlevel = options[:patchlevel]
+ engine = options[:engine]
+ engine_version = options[:engine_version]
- if options[:file]
- raise GemfileError, "Do not pass version argument when using :file option" unless ruby_version.empty?
- ruby_version << normalize_ruby_file(options[:file])
- end
+ raise GemfileError, "Please define :engine_version" if engine && engine_version.nil?
+ raise GemfileError, "Please define :engine" if engine_version && engine.nil?
+
+ if options[:file]
+ raise GemfileError, "Do not pass version argument when using :file option" unless ruby_version.empty?
+ ruby_version << normalize_ruby_file(options[:file])
+ end
- if options[:engine] == "ruby" && options[:engine_version] &&
- ruby_version != Array(options[:engine_version])
- raise GemfileEvalError, "ruby_version must match the :engine_version for MRI"
+ if engine == "ruby" && engine_version && ruby_version != Array(engine_version)
+ raise GemfileEvalError, "ruby_version must match the :engine_version for MRI"
+ end
end
- @ruby_version = RubyVersion.new(ruby_version, options[:patchlevel], options[:engine], options[:engine_version])
+
+ @ruby_version = RubyVersion.new(ruby_version, patchlevel, engine, engine_version)
end
# Support the various file formats found in .ruby-version files.
@@ -32,8 +38,10 @@ module Bundler
# ruby 2.5.1# close comment and extra spaces doesn't confuse
#
# Intentionally does not support `3.2.1@gemset` since rvm recommends using .ruby-gemset instead
+ #
+ # Loads the file relative to the dirname of the Gemfile itself.
def normalize_ruby_file(filename)
- file_content = Bundler.read_file(Bundler.root.join(filename))
+ file_content = Bundler.read_file(gemfile.dirname.join(filename))
# match "ruby-3.2.2" or "ruby 3.2.2" capturing version string up to the first space or comment
if /^ruby(-|\s+)([^\s#]+)/.match(file_content)
$2
diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb
index 1d5a42cbbe..18180a81a1 100644
--- a/lib/bundler/rubygems_ext.rb
+++ b/lib/bundler/rubygems_ext.rb
@@ -1,11 +1,7 @@
# frozen_string_literal: true
-require "pathname"
-
require "rubygems" unless defined?(Gem)
-require "rubygems/specification"
-
# We can't let `Gem::Source` be autoloaded in the `Gem::Specification#source`
# redefinition below, so we need to load it upfront. The reason is that if
# Bundler monkeypatches are loaded before RubyGems activates an executable (for
@@ -17,10 +13,6 @@ require "rubygems/specification"
# `Gem::Source` from the redefined `Gem::Specification#source`.
require "rubygems/source"
-require_relative "match_metadata"
-require_relative "force_platform"
-require_relative "match_platform"
-
# Cherry-pick fixes to `Gem.ruby_version` to be useful for modern Bundler
# versions and ignore patchlevels
# (https://github.com/rubygems/rubygems/pull/5472,
@@ -31,7 +23,19 @@ unless Gem.ruby_version.to_s == RUBY_VERSION || RUBY_PATCHLEVEL == -1
end
module Gem
+ # Can be removed once RubyGems 3.5.11 support is dropped
+ unless Gem.respond_to?(:freebsd_platform?)
+ def self.freebsd_platform?
+ RbConfig::CONFIG["host_os"].to_s.include?("bsd")
+ end
+ end
+
+ require "rubygems/specification"
+
class Specification
+ require_relative "match_metadata"
+ require_relative "match_platform"
+
include ::Bundler::MatchMetadata
include ::Bundler::MatchPlatform
@@ -48,7 +52,7 @@ module Gem
def full_gem_path
if source.respond_to?(:root)
- Pathname.new(loaded_from).dirname.expand_path(source.root).to_s
+ File.expand_path(File.dirname(loaded_from), source.root)
else
rg_full_gem_path
end
@@ -78,24 +82,6 @@ module Gem
end
end
- alias_method :rg_missing_extensions?, :missing_extensions?
- def missing_extensions?
- # When we use this methods with local gemspec, we don't handle
- # build status of extension correctly. So We need to find extension
- # files in require_paths.
- # TODO: Gem::Specification couldn't access extension name from extconf.rb
- # so we find them with heuristic way. We should improve it.
- if source.respond_to?(:root)
- return false if raw_require_paths.any? do |path|
- ext_dir = File.join(full_gem_path, path)
- File.exist?(File.join(ext_dir, "#{name}.#{RbConfig::CONFIG["DLEXT"]}")) ||
- !Dir.glob(File.join(ext_dir, name, "*.#{RbConfig::CONFIG["DLEXT"]}")).empty?
- end
- end
-
- rg_missing_extensions?
- end
-
remove_method :gem_dir
def gem_dir
full_gem_path
@@ -164,7 +150,23 @@ module Gem
end
end
+ module BetterPermissionError
+ def data
+ super
+ rescue Errno::EACCES
+ raise Bundler::PermissionError.new(loaded_from, :read)
+ end
+ end
+
+ require "rubygems/stub_specification"
+
+ class StubSpecification
+ prepend BetterPermissionError
+ end
+
class Dependency
+ require_relative "force_platform"
+
include ::Bundler::ForcePlatform
attr_accessor :source, :groups
@@ -197,37 +199,7 @@ module Gem
end
end
- # comparison is done order independently since rubygems 3.2.0.rc.2
- unless Gem::Requirement.new("> 1", "< 2") == Gem::Requirement.new("< 2", "> 1")
- class Requirement
- module OrderIndependentComparison
- def ==(other)
- return unless Gem::Requirement === other
-
- if _requirements_sorted? && other._requirements_sorted?
- super
- else
- _with_sorted_requirements == other._with_sorted_requirements
- end
- end
-
- protected
-
- def _requirements_sorted?
- return @_requirements_sorted if defined?(@_requirements_sorted)
- strings = as_list
- @_requirements_sorted = strings == strings.sort
- end
-
- def _with_sorted_requirements
- @_with_sorted_requirements ||= _requirements_sorted? ? self : self.class.new(as_list.sort)
- end
- end
-
- prepend OrderIndependentComparison
- end
- end
-
+ # Requirements using lambda operator differentiate trailing zeros since rubygems 3.2.6
if Gem::Requirement.new("~> 2.0").hash == Gem::Requirement.new("~> 2.0.0").hash
class Requirement
module CorrectHashForLambdaOperator
@@ -352,31 +324,25 @@ module Gem
require "rubygems/name_tuple"
class NameTuple
- def self.new(name, version, platform="ruby")
- if Gem::Platform === platform
- super(name, version, platform.to_s)
- else
- super
- end
- end
+ # Versions of RubyGems before about 3.5.0 don't to_s the platform.
+ unless Gem::NameTuple.new("a", Gem::Version.new("1"), Gem::Platform.new("x86_64-linux")).platform.is_a?(String)
+ alias_method :initialize_with_platform, :initialize
- def lock_name
- @lock_name ||=
- if platform == Gem::Platform::RUBY
- "#{name} (#{version})"
+ def initialize(name, version, platform=Gem::Platform::RUBY)
+ if Gem::Platform === platform
+ initialize_with_platform(name, version, platform.to_s)
else
- "#{name} (#{version}-#{platform})"
+ initialize_with_platform(name, version, platform)
end
+ end
end
- end
-
- require "rubygems/util"
-
- Util.singleton_class.module_eval do
- remove_method :glob_files_in_dir
- def glob_files_in_dir(glob, base_path)
- Dir.glob(glob, :base => base_path).map! {|f| File.expand_path(f, base_path) }
+ def lock_name
+ if platform == Gem::Platform::RUBY
+ "#{name} (#{version})"
+ else
+ "#{name} (#{version}-#{platform})"
+ end
end
end
end
diff --git a/lib/bundler/rubygems_gem_installer.rb b/lib/bundler/rubygems_gem_installer.rb
index d04ef62e8e..d563868cd2 100644
--- a/lib/bundler/rubygems_gem_installer.rb
+++ b/lib/bundler/rubygems_gem_installer.rb
@@ -20,7 +20,7 @@ module Bundler
strict_rm_rf spec.extension_dir
SharedHelpers.filesystem_access(gem_dir, :create) do
- FileUtils.mkdir_p gem_dir, :mode => 0o755
+ FileUtils.mkdir_p gem_dir, mode: 0o755
end
extract_files
@@ -103,15 +103,7 @@ module Bundler
end
def gem_checksum
- return nil if Bundler.settings[:disable_checksum_validation]
- return nil unless source = @package.instance_variable_get(:@gem)
- return nil unless source.respond_to?(:with_read_io)
-
- source.with_read_io do |io|
- Checksum.from_gem(io, source.path)
- ensure
- io.rewind
- end
+ Checksum.from_gem_package(@package)
end
private
diff --git a/lib/bundler/rubygems_integration.rb b/lib/bundler/rubygems_integration.rb
index f420934ceb..b841462263 100644
--- a/lib/bundler/rubygems_integration.rb
+++ b/lib/bundler/rubygems_integration.rb
@@ -4,17 +4,12 @@ require "rubygems" unless defined?(Gem)
module Bundler
class RubygemsIntegration
- if defined?(Gem::Ext::Builder::CHDIR_MONITOR)
- EXT_LOCK = Gem::Ext::Builder::CHDIR_MONITOR
- else
- require "monitor"
+ require "monitor"
- EXT_LOCK = Monitor.new
- end
+ EXT_LOCK = Monitor.new
def initialize
@replaced_methods = {}
- backport_ext_builder_monitor
end
def version
@@ -43,18 +38,6 @@ module Bundler
Gem.loaded_specs[name]
end
- def add_to_load_path(paths)
- return Gem.add_to_load_path(*paths) if Gem.respond_to?(:add_to_load_path)
-
- if insert_index = Gem.load_path_insert_index
- # Gem directories must come after -I and ENV['RUBYLIB']
- $LOAD_PATH.insert(insert_index, *paths)
- else
- # We are probably testing in core, -I and RUBYLIB don't apply
- $LOAD_PATH.unshift(*paths)
- end
- end
-
def mark_loaded(spec)
if spec.respond_to?(:activated=)
current = Gem.loaded_specs[spec.name]
@@ -116,16 +99,6 @@ module Bundler
Gem::Util.inflate(obj)
end
- def correct_for_windows_path(path)
- if Gem::Util.respond_to?(:correct_for_windows_path)
- Gem::Util.correct_for_windows_path(path)
- elsif path[0].chr == "/" && path[1].chr =~ /[a-z]/i && path[2].chr == ":"
- path[1..-1]
- else
- path
- end
- end
-
def gem_dir
Gem.dir
end
@@ -161,7 +134,7 @@ module Bundler
def spec_cache_dirs
@spec_cache_dirs ||= begin
dirs = gem_path.map {|dir| File.join(dir, "specifications") }
- dirs << Gem.spec_cache_dir if Gem.respond_to?(:spec_cache_dir) # Not in RubyGems 2.0.3 or earlier
+ dirs << Gem.spec_cache_dir
dirs.uniq.select {|dir| File.directory? dir }
end
end
@@ -184,15 +157,15 @@ module Bundler
end
def load_plugins
- Gem.load_plugins if Gem.respond_to?(:load_plugins)
+ Gem.load_plugins
end
- def load_plugin_files(files)
- Gem.load_plugin_files(files) if Gem.respond_to?(:load_plugin_files)
+ def load_plugin_files(plugin_files)
+ Gem.load_plugin_files(plugin_files)
end
def load_env_plugins
- Gem.load_env_plugins if Gem.respond_to?(:load_env_plugins)
+ Gem.load_env_plugins
end
def ui=(obj)
@@ -238,25 +211,6 @@ module Bundler
end
end
- def replace_require(specs)
- return if [::Kernel.singleton_class, ::Kernel].any? {|klass| klass.respond_to?(:no_warning_require) }
-
- [::Kernel.singleton_class, ::Kernel].each do |kernel_class|
- kernel_class.send(:alias_method, :no_warning_require, :require)
- kernel_class.send(:define_method, :require) do |name|
- if message = ::Gem::BUNDLED_GEMS.warning?(name, specs: specs) # rubocop:disable Style/HashSyntax
- warn message, :uplevel => 1
- end
- kernel_class.send(:no_warning_require, name)
- end
- if kernel_class == ::Kernel
- kernel_class.send(:private, :require)
- else
- kernel_class.send(:public, :require)
- end
- end
- end
-
def replace_gem(specs, specs_by_name)
executables = nil
@@ -373,10 +327,13 @@ module Bundler
def replace_entrypoints(specs)
specs_by_name = add_default_gems_to(specs)
- if defined?(::Gem::BUNDLED_GEMS)
- replace_require(specs)
+ reverse_rubygems_kernel_mixin
+ begin
+ # bundled_gems only provide with Ruby 3.3 or later
+ require "bundled_gems"
+ rescue LoadError
else
- reverse_rubygems_kernel_mixin
+ Gem::BUNDLED_GEMS.replace_require(specs) if Gem::BUNDLED_GEMS.respond_to?(:replace_require)
end
replace_gem(specs, specs_by_name)
stub_rubygems(specs)
@@ -467,11 +424,9 @@ module Bundler
Gem::Specification.all = specs
end
- def fetch_specs(remote, name)
+ def fetch_specs(remote, name, fetcher)
require "rubygems/remote_fetcher"
path = remote.uri.to_s + "#{name}.#{Gem.marshal_version}.gz"
- fetcher = gem_remote_fetcher
- fetcher.headers = { "X-Gemfile-Source" => remote.original_uri.to_s } if remote.original_uri
string = fetcher.fetch_path(path)
specs = Bundler.safe_load_marshal(string)
raise MarshalError, "Specs #{name} from #{remote} is expected to be an Array but was unexpected class #{specs.class}" unless specs.is_a?(Array)
@@ -481,18 +436,16 @@ module Bundler
raise unless name == "prerelease_specs"
end
- def fetch_all_remote_specs(remote)
- specs = fetch_specs(remote, "specs")
- pres = fetch_specs(remote, "prerelease_specs") || []
+ def fetch_all_remote_specs(remote, gem_remote_fetcher)
+ specs = fetch_specs(remote, "specs", gem_remote_fetcher)
+ pres = fetch_specs(remote, "prerelease_specs", gem_remote_fetcher) || []
specs.concat(pres)
end
- def download_gem(spec, uri, cache_dir)
+ def download_gem(spec, uri, cache_dir, fetcher)
require "rubygems/remote_fetcher"
uri = Bundler.settings.mirror_for(uri)
- fetcher = gem_remote_fetcher
- fetcher.headers = { "X-Gemfile-Source" => spec.remote.original_uri.to_s } if spec.remote.original_uri
Bundler::Retry.new("download gem from #{uri}").attempts do
gem_file_name = spec.file_name
local_gem_path = File.join cache_dir, gem_file_name
@@ -500,7 +453,6 @@ module Bundler
begin
remote_gem_path = uri + "gems/#{gem_file_name}"
- remote_gem_path = remote_gem_path.to_s if provides?("< 3.2.0.rc.1")
SharedHelpers.filesystem_access(local_gem_path) do
fetcher.cache_update_path remote_gem_path, local_gem_path
@@ -519,11 +471,6 @@ module Bundler
raise Bundler::HTTPError, "Could not download gem from #{uri} due to underlying error <#{e.message}>"
end
- def gem_remote_fetcher
- require "rubygems/remote_fetcher"
- Gem::RemoteFetcher.fetcher
- end
-
def build(spec, skip_validation = false)
require "rubygems/package"
Gem::Package.build(spec, skip_validation)
@@ -534,27 +481,22 @@ module Bundler
end
def all_specs
+ SharedHelpers.major_deprecation 2, "Bundler.rubygems.all_specs has been removed in favor of Bundler.rubygems.installed_specs"
+
Gem::Specification.stubs.map do |stub|
StubSpecification.from_stub(stub)
end
end
- def backport_ext_builder_monitor
- # So we can avoid requiring "rubygems/ext" in its entirety
- Gem.module_eval <<-RUBY, __FILE__, __LINE__ + 1
- module Ext
- end
- RUBY
-
- require "rubygems/ext/builder"
-
- Gem::Ext::Builder.class_eval do
- unless const_defined?(:CHDIR_MONITOR)
- const_set(:CHDIR_MONITOR, EXT_LOCK)
- end
+ def installed_specs
+ Gem::Specification.stubs.reject(&:default_gem?).map do |stub|
+ StubSpecification.from_stub(stub)
+ end
+ end
- remove_const(:CHDIR_MUTEX) if const_defined?(:CHDIR_MUTEX)
- const_set(:CHDIR_MUTEX, const_get(:CHDIR_MONITOR))
+ def default_specs
+ Gem::Specification.default_stubs.map do |stub|
+ StubSpecification.from_stub(stub)
end
end
@@ -566,14 +508,8 @@ module Bundler
Gem::Specification.stubs_for(name).map(&:to_spec)
end
- if Gem::Specification.respond_to?(:default_stubs)
- def default_stubs
- Gem::Specification.default_stubs("*.gemspec")
- end
- else
- def default_stubs
- Gem::Specification.send(:default_stubs, "*.gemspec")
- end
+ def default_stubs
+ Gem::Specification.default_stubs("*.gemspec")
end
end
diff --git a/lib/bundler/runtime.rb b/lib/bundler/runtime.rb
index 95cf78dd41..54aa30ce0b 100644
--- a/lib/bundler/runtime.rb
+++ b/lib/bundler/runtime.rb
@@ -28,11 +28,11 @@ module Bundler
spec.load_paths.reject {|path| $LOAD_PATH.include?(path) }
end.reverse.flatten
- Bundler.rubygems.add_to_load_path(load_paths)
+ Gem.add_to_load_path(*load_paths)
setup_manpath
- lock(:preserve_unknown_sections => true)
+ lock(preserve_unknown_sections: true)
self
end
@@ -41,12 +41,17 @@ module Bundler
groups.map!(&:to_sym)
groups = [:default] if groups.empty?
- @definition.dependencies.each do |dep|
- # Skip the dependency if it is not in any of the requested groups, or
- # not for the current platform, or doesn't match the gem constraints.
- next unless (dep.groups & groups).any? && dep.should_include?
+ dependencies = @definition.dependencies.select do |dep|
+ # Select the dependency if it is in any of the requested groups, and
+ # for the current platform, and matches the gem constraints.
+ (dep.groups & groups).any? && dep.should_include?
+ end
+
+ Plugin.hook(Plugin::Events::GEM_BEFORE_REQUIRE_ALL, dependencies)
+ dependencies.each do |dep|
required_file = nil
+ Plugin.hook(Plugin::Events::GEM_BEFORE_REQUIRE, dep)
begin
# Loop through all the specified autorequires for the
@@ -76,7 +81,13 @@ module Bundler
end
end
end
+
+ Plugin.hook(Plugin::Events::GEM_AFTER_REQUIRE, dep)
end
+
+ Plugin.hook(Plugin::Events::GEM_AFTER_REQUIRE_ALL, dependencies)
+
+ dependencies
end
def self.definition_method(meth)
@@ -95,7 +106,7 @@ module Bundler
def lock(opts = {})
return if @definition.no_resolve_needed?
- @definition.lock(Bundler.default_lockfile, opts[:preserve_unknown_sections])
+ @definition.lock(opts[:preserve_unknown_sections])
end
alias_method :gems, :specs
diff --git a/lib/bundler/self_manager.rb b/lib/bundler/self_manager.rb
index 1925a266d9..5accda4bcb 100644
--- a/lib/bundler/self_manager.rb
+++ b/lib/bundler/self_manager.rb
@@ -121,7 +121,7 @@ module Bundler
source = Bundler::Source::Rubygems.new("remotes" => "https://rubygems.org")
source.remote!
source.add_dependency_names("bundler")
- source.specs
+ source.specs.select(&:matches_current_metadata?)
end
end
diff --git a/lib/bundler/settings.rb b/lib/bundler/settings.rb
index 0dd92b1ad9..878747a53b 100644
--- a/lib/bundler/settings.rb
+++ b/lib/bundler/settings.rb
@@ -7,7 +7,6 @@ module Bundler
autoload :Validator, File.expand_path("settings/validator", __dir__)
BOOL_KEYS = %w[
- allow_deployment_source_credential_changes
allow_offline_install
auto_clean_without_path
auto_install
@@ -46,6 +45,20 @@ module Bundler
update_requires_all_flag
].freeze
+ REMEMBERED_KEYS = %w[
+ bin
+ cache_all
+ clean
+ deployment
+ frozen
+ no_prune
+ path
+ shebang
+ path.system
+ without
+ with
+ ].freeze
+
NUMBER_KEYS = %w[
jobs
redirect
@@ -90,6 +103,7 @@ module Bundler
def initialize(root = nil)
@root = root
@local_config = load_config(local_config_file)
+ @local_root = root || Pathname.new(".bundle").expand_path
@env_config = ENV.to_h
@env_config.select! {|key, _value| key.start_with?("BUNDLE_") }
@@ -115,7 +129,7 @@ module Bundler
end
def set_command_option(key, value)
- if Bundler.feature_flag.forget_cli_options?
+ if !is_remembered(key) || Bundler.feature_flag.forget_cli_options?
temporary(key => value)
value
else
@@ -129,7 +143,7 @@ module Bundler
end
def set_local(key, value)
- local_config_file || raise(GemfileNotFound, "Could not locate Gemfile")
+ local_config_file = @local_root.join("config")
set_key(key, value, @local_config, local_config_file)
end
@@ -175,7 +189,7 @@ module Bundler
def mirror_for(uri)
if uri.is_a?(String)
require_relative "vendored_uri"
- uri = Bundler::URI(uri)
+ uri = Gem::URI(uri)
end
gem_mirrors.for(uri.to_s).uri
@@ -321,11 +335,11 @@ module Bundler
def configs
@configs ||= {
- :temporary => @temporary,
- :local => @local_config,
- :env => @env_config,
- :global => @global_config,
- :default => DEFAULT_CONFIG,
+ temporary: @temporary,
+ local: @local_config,
+ env: @env_config,
+ global: @global_config,
+ default: DEFAULT_CONFIG,
}
end
@@ -374,6 +388,10 @@ module Bundler
ARRAY_KEYS.include?(self.class.key_to_s(key))
end
+ def is_remembered(key)
+ REMEMBERED_KEYS.include?(self.class.key_to_s(key))
+ end
+
def is_credential(key)
key == "gem.push_key"
end
@@ -474,16 +492,23 @@ module Bundler
valid_file = file.exist? && !file.size.zero?
return {} unless valid_file
serializer_class.load(file.read).inject({}) do |config, (k, v)|
- if k.include?("-")
- Bundler.ui.warn "Your #{file} config includes `#{k}`, which contains the dash character (`-`).\n" \
- "This is deprecated, because configuration through `ENV` should be possible, but `ENV` keys cannot include dashes.\n" \
- "Please edit #{file} and replace any dashes in configuration keys with a triple underscore (`___`)."
+ k = k.dup
+ k << "/" if /https?:/i.match?(k) && !k.end_with?("/", "__#{FALLBACK_TIMEOUT_URI_OPTION.upcase}")
+ k.gsub!(".", "__")
+
+ unless k.start_with?("#")
+ if k.include?("-")
+ Bundler.ui.warn "Your #{file} config includes `#{k}`, which contains the dash character (`-`).\n" \
+ "This is deprecated, because configuration through `ENV` should be possible, but `ENV` keys cannot include dashes.\n" \
+ "Please edit #{file} and replace any dashes in configuration keys with a triple underscore (`___`)."
- # string hash keys are frozen
- k = k.gsub("-", "___")
+ # string hash keys are frozen
+ k = k.gsub("-", "___")
+ end
+
+ config[k] = v
end
- config[k] = v
config
end
end
@@ -498,26 +523,25 @@ module Bundler
YAMLSerializer
end
- PER_URI_OPTIONS = %w[
- fallback_timeout
- ].freeze
+ FALLBACK_TIMEOUT_URI_OPTION = "fallback_timeout"
NORMALIZE_URI_OPTIONS_PATTERN =
/
\A
(\w+\.)? # optional prefix key
(https?.*?) # URI
- (\.#{Regexp.union(PER_URI_OPTIONS)})? # optional suffix key
+ (\.#{FALLBACK_TIMEOUT_URI_OPTION})? # optional suffix key
\z
/ix
def self.key_for(key)
- key = normalize_uri(key).to_s if key.is_a?(String) && key.start_with?("http", "mirror.http")
- key = key_to_s(key).gsub(".", "__")
+ key = key_to_s(key)
+ key = normalize_uri(key) if key.start_with?("http", "mirror.http")
+ key = key.gsub(".", "__")
key.gsub!("-", "___")
key.upcase!
- key.prepend("BUNDLE_")
+ key.gsub(/\A([ #]*)/, '\1BUNDLE_')
end
# TODO: duplicates Rubygems#normalize_uri
@@ -531,7 +555,7 @@ module Bundler
end
uri = URINormalizer.normalize_suffix(uri)
require_relative "vendored_uri"
- uri = Bundler::URI(uri)
+ uri = Gem::URI(uri)
unless uri.absolute?
raise ArgumentError, format("Gem sources must be absolute. You provided '%s'.", uri)
end
@@ -546,7 +570,7 @@ module Bundler
key
when Symbol
key.name
- when Bundler::URI::HTTP
+ when Gem::URI::HTTP
key.to_s
else
raise ArgumentError, "Invalid key: #{key.inspect}"
@@ -559,7 +583,7 @@ module Bundler
key
when Symbol
key.to_s
- when Bundler::URI::HTTP
+ when Gem::URI::HTTP
key.to_s
else
raise ArgumentError, "Invalid key: #{key.inspect}"
diff --git a/lib/bundler/setup.rb b/lib/bundler/setup.rb
index 801fd5312a..6010d66742 100644
--- a/lib/bundler/setup.rb
+++ b/lib/bundler/setup.rb
@@ -5,6 +5,9 @@ require_relative "shared_helpers"
if Bundler::SharedHelpers.in_bundle?
require_relative "../bundler"
+ # try to auto_install first before we get to the `Bundler.ui.silence`, so user knows what is happening
+ Bundler.auto_install
+
if STDOUT.tty? || ENV["BUNDLER_FORCE_TTY"]
begin
Bundler.ui.silence { Bundler.setup }
@@ -12,7 +15,10 @@ if Bundler::SharedHelpers.in_bundle?
Bundler.ui.error e.message
Bundler.ui.warn e.backtrace.join("\n") if ENV["DEBUG"]
if e.is_a?(Bundler::GemNotFound)
- suggested_cmd = "bundle install"
+ default_bundle = Gem.bin_path("bundler", "bundle")
+ current_bundle = Bundler::SharedHelpers.bundle_bin_path
+ suggested_bundle = default_bundle == current_bundle ? "bundle" : current_bundle
+ suggested_cmd = "#{suggested_bundle} install"
original_gemfile = Bundler.original_env["BUNDLE_GEMFILE"]
suggested_cmd += " --gemfile #{original_gemfile}" if original_gemfile
Bundler.ui.warn "Run `#{suggested_cmd}` to install missing gems."
diff --git a/lib/bundler/shared_helpers.rb b/lib/bundler/shared_helpers.rb
index cccc2b63d9..e55632b89f 100644
--- a/lib/bundler/shared_helpers.rb
+++ b/lib/bundler/shared_helpers.rb
@@ -1,14 +1,16 @@
# frozen_string_literal: true
-require "pathname"
-require "rbconfig"
-
require_relative "version"
-require_relative "constants"
require_relative "rubygems_integration"
require_relative "current_ruby"
+autoload :Pathname, "pathname"
+
module Bundler
+ autoload :WINDOWS, File.expand_path("constants", __dir__)
+ autoload :FREEBSD, File.expand_path("constants", __dir__)
+ autoload :NULL, File.expand_path("constants", __dir__)
+
module SharedHelpers
def root
gemfile = find_gemfile
@@ -117,16 +119,18 @@ module Bundler
raise GenericSystemCallError.new(e, "There was an error accessing `#{path}`.")
end
- def major_deprecation(major_version, message, print_caller_location: false)
+ def major_deprecation(major_version, message, removed_message: nil, print_caller_location: false)
if print_caller_location
caller_location = caller_locations(2, 2).first
- message = "#{message} (called at #{caller_location.path}:#{caller_location.lineno})"
+ suffix = " (called at #{caller_location.path}:#{caller_location.lineno})"
+ message += suffix
+ removed_message += suffix if removed_message
end
bundler_major_version = Bundler.bundler_major_version
if bundler_major_version > major_version
require_relative "errors"
- raise DeprecatedError, "[REMOVED] #{message}"
+ raise DeprecatedError, "[REMOVED] #{removed_message || message}"
end
return unless bundler_major_version >= major_version && prints_major_deprecations?
@@ -193,6 +197,21 @@ module Bundler
Digest(name)
end
+ def checksum_for_file(path, digest)
+ return unless path.file?
+ # This must use File.read instead of Digest.file().hexdigest
+ # because we need to preserve \n line endings on windows when calculating
+ # the checksum
+ SharedHelpers.filesystem_access(path, :read) do
+ File.open(path, "rb") do |f|
+ digest = SharedHelpers.digest(digest).new
+ buf = String.new(capacity: 16_384, encoding: Encoding::BINARY)
+ digest << buf while f.read(16_384, buf)
+ digest.hexdigest
+ end
+ end
+ end
+
def write_to_gemfile(gemfile_path, contents)
filesystem_access(gemfile_path) {|g| File.open(g, "w") {|file| file.puts contents } }
end
@@ -287,6 +306,13 @@ module Bundler
public :set_env
def set_bundle_variables
+ Bundler::SharedHelpers.set_env "BUNDLE_BIN_PATH", bundle_bin_path
+ Bundler::SharedHelpers.set_env "BUNDLE_GEMFILE", find_gemfile.to_s
+ Bundler::SharedHelpers.set_env "BUNDLER_VERSION", Bundler::VERSION
+ Bundler::SharedHelpers.set_env "BUNDLER_SETUP", File.expand_path("setup", __dir__)
+ end
+
+ def bundle_bin_path
# bundler exe & lib folders have same root folder, typical gem installation
exe_file = File.expand_path("../../exe/bundle", __dir__)
@@ -296,11 +322,9 @@ module Bundler
# bundler is a default gem, exe path is separate
exe_file = Bundler.rubygems.bin_path("bundler", "bundle", VERSION) unless File.exist?(exe_file)
- Bundler::SharedHelpers.set_env "BUNDLE_BIN_PATH", exe_file
- Bundler::SharedHelpers.set_env "BUNDLE_GEMFILE", find_gemfile.to_s
- Bundler::SharedHelpers.set_env "BUNDLER_VERSION", Bundler::VERSION
- Bundler::SharedHelpers.set_env "BUNDLER_SETUP", File.expand_path("setup", __dir__)
+ exe_file
end
+ public :bundle_bin_path
def set_path
validate_bundle_path
@@ -312,7 +336,7 @@ module Bundler
def set_rubyopt
rubyopt = [ENV["RUBYOPT"]].compact
setup_require = "-r#{File.expand_path("setup", __dir__)}"
- return if !rubyopt.empty? && rubyopt.first =~ /#{Regexp.escape(setup_require)}/
+ return if !rubyopt.empty? && rubyopt.first.include?(setup_require)
rubyopt.unshift setup_require
Bundler::SharedHelpers.set_env "RUBYOPT", rubyopt.join(" ")
end
diff --git a/lib/bundler/source/git.rb b/lib/bundler/source/git.rb
index 1d77c39f77..198e335bb6 100644
--- a/lib/bundler/source/git.rb
+++ b/lib/bundler/source/git.rb
@@ -20,7 +20,7 @@ module Bundler
# Stringify options that could be set as symbols
%w[ref branch tag revision].each {|k| options[k] = options[k].to_s if options[k] }
- @uri = URINormalizer.normalize_suffix(options["uri"] || "", :trailing_slash => false)
+ @uri = URINormalizer.normalize_suffix(options["uri"] || "", trailing_slash: false)
@safe_uri = URICredentialsFilter.credential_filtered_uri(@uri)
@branch = options["branch"]
@ref = options["ref"] || options["branch"] || options["tag"]
@@ -198,7 +198,7 @@ module Bundler
@copied = true
end
- generate_bin_options = { :disable_extensions => !Bundler.rubygems.spec_missing_extensions?(spec), :build_args => options[:build_args] }
+ generate_bin_options = { disable_extensions: !Bundler.rubygems.spec_missing_extensions?(spec), build_args: options[:build_args] }
generate_bin(spec, generate_bin_options)
requires_checkout? ? spec.post_install_message : nil
@@ -326,7 +326,7 @@ module Bundler
if %r{^\w+://(\w+@)?}.match?(uri)
# Downcase the domain component of the URI
# and strip off a trailing slash, if one is present
- input = Bundler::URI.parse(uri).normalize.to_s.sub(%r{/$}, "")
+ input = Gem::URI.parse(uri).normalize.to_s.sub(%r{/$}, "")
else
# If there is no URI scheme, assume it is an ssh/git URI
input = uri
diff --git a/lib/bundler/source/git/git_proxy.rb b/lib/bundler/source/git/git_proxy.rb
index 0b507abc76..2fc9c6535f 100644
--- a/lib/bundler/source/git/git_proxy.rb
+++ b/lib/bundler/source/git/git_proxy.rb
@@ -80,14 +80,14 @@ module Bundler
def current_branch
@current_branch ||= with_path do
- git_local("rev-parse", "--abbrev-ref", "HEAD", :dir => path).strip
+ git_local("rev-parse", "--abbrev-ref", "HEAD", dir: path).strip
end
end
def contains?(commit)
allowed_with_path do
- result, status = git_null("branch", "--contains", commit, :dir => path)
- status.success? && result =~ /^\* (.*)$/
+ result, status = git_null("branch", "--contains", commit, dir: path)
+ status.success? && result.match?(/^\* (.*)$/)
end
end
@@ -132,18 +132,18 @@ module Bundler
ref = @commit_ref || (locked_to_full_sha? && @revision)
if ref
- git "config", "uploadpack.allowAnySHA1InWant", "true", :dir => path.to_s if @commit_ref.nil? && needs_allow_any_sha1_in_want?
+ git "config", "uploadpack.allowAnySHA1InWant", "true", dir: path.to_s if @commit_ref.nil? && needs_allow_any_sha1_in_want?
- git "fetch", "--force", "--quiet", *extra_fetch_args(ref), :dir => destination
+ git "fetch", "--force", "--quiet", *extra_fetch_args(ref), dir: destination
end
- git "reset", "--hard", @revision, :dir => destination
+ git "reset", "--hard", @revision, dir: destination
if submodules
- git_retry "submodule", "update", "--init", "--recursive", :dir => destination
+ git_retry "submodule", "update", "--init", "--recursive", dir: destination
elsif Gem::Version.create(version) >= Gem::Version.create("2.9.0")
inner_command = "git -C $toplevel submodule deinit --force $sm_path"
- git_retry "submodule", "foreach", "--quiet", inner_command, :dir => destination
+ git_retry "submodule", "foreach", "--quiet", inner_command, dir: destination
end
end
@@ -182,6 +182,14 @@ module Bundler
if err.include?("Could not find remote branch")
raise MissingGitRevisionError.new(command_with_no_credentials, nil, explicit_ref, credential_filtered_uri)
else
+ idx = command.index("--depth")
+ if idx
+ command.delete_at(idx)
+ command.delete_at(idx)
+ command_with_no_credentials = check_allowed(command)
+
+ err += "Retrying without --depth argument."
+ end
raise GitCommandError.new(command_with_no_credentials, path, err)
end
end
@@ -266,32 +274,32 @@ module Bundler
def git_null(*command, dir: nil)
check_allowed(command)
- capture(command, dir, :ignore_err => true)
+ capture(command, dir, ignore_err: true)
end
def git_retry(*command, dir: nil)
command_with_no_credentials = check_allowed(command)
Bundler::Retry.new("`#{command_with_no_credentials}` at #{dir || SharedHelpers.pwd}").attempts do
- git(*command, :dir => dir)
+ git(*command, dir: dir)
end
end
def git(*command, dir: nil)
- run_command(*command, :dir => dir) do |unredacted_command|
+ run_command(*command, dir: dir) do |unredacted_command|
check_allowed(unredacted_command)
end
end
def git_local(*command, dir: nil)
- run_command(*command, :dir => dir) do |unredacted_command|
+ run_command(*command, dir: dir) do |unredacted_command|
redact_and_check_presence(unredacted_command)
end
end
def has_revision_cached?
return unless @revision && path.exist?
- git("cat-file", "-e", @revision, :dir => path)
+ git("cat-file", "-e", @revision, dir: path)
true
rescue GitError
false
@@ -314,13 +322,13 @@ module Bundler
end
def verify(reference)
- git("rev-parse", "--verify", reference, :dir => path).strip
+ git("rev-parse", "--verify", reference, dir: path).strip
end
# Adds credentials to the URI
def configured_uri
if /https?:/.match?(uri)
- remote = Bundler::URI(uri)
+ remote = Gem::URI(uri)
config_auth = Bundler.settings[remote.to_s] || Bundler.settings[remote.host]
remote.userinfo ||= config_auth
remote.to_s
@@ -398,7 +406,7 @@ module Bundler
if Bundler.feature_flag.bundler_3_mode? || supports_minus_c?
["git", "-C", dir.to_s, *cmd]
else
- ["git", *cmd, { :chdir => dir.to_s }]
+ ["git", *cmd, { chdir: dir.to_s }]
end
end
diff --git a/lib/bundler/source/metadata.rb b/lib/bundler/source/metadata.rb
index 4d27761365..6b05e17727 100644
--- a/lib/bundler/source/metadata.rb
+++ b/lib/bundler/source/metadata.rb
@@ -11,6 +11,8 @@ module Bundler
end
if local_spec = Gem.loaded_specs["bundler"]
+ raise CorruptBundlerInstallError.new(local_spec) if local_spec.version.to_s != Bundler::VERSION
+
idx << local_spec
else
idx << Gem::Specification.new do |s|
diff --git a/lib/bundler/source/path.rb b/lib/bundler/source/path.rb
index cdf871250a..978b0b2c9f 100644
--- a/lib/bundler/source/path.rb
+++ b/lib/bundler/source/path.rb
@@ -86,7 +86,7 @@ module Bundler
using_message = "Using #{version_message(spec, options[:previous_spec])} from #{self}"
using_message += " and installing its executables" unless spec.executables.empty?
print_using_message using_message
- generate_bin(spec, :disable_extensions => true)
+ generate_bin(spec, disable_extensions: true)
nil # no post-install message
end
@@ -226,7 +226,7 @@ module Bundler
# Some gem authors put absolute paths in their gemspec
# and we have to save them from themselves
spec.files = spec.files.map do |path|
- next path unless /\A#{Pathname::SEPARATOR_PAT}/.match?(path)
+ next path unless /\A#{Pathname::SEPARATOR_PAT}/o.match?(path)
next if File.directory?(path)
begin
Pathname.new(path).relative_path_from(gem_dir).to_s
@@ -237,10 +237,10 @@ module Bundler
installer = Path::Installer.new(
spec,
- :env_shebang => false,
- :disable_extensions => options[:disable_extensions],
- :build_args => options[:build_args],
- :bundler_extension_cache_path => extension_cache_path(spec)
+ env_shebang: false,
+ disable_extensions: options[:disable_extensions],
+ build_args: options[:build_args],
+ bundler_extension_cache_path: extension_cache_path(spec)
)
installer.post_install
rescue Gem::InvalidSpecificationException => e
diff --git a/lib/bundler/source/rubygems.rb b/lib/bundler/source/rubygems.rb
index 6d6f36e298..dafc674f9d 100644
--- a/lib/bundler/source/rubygems.rb
+++ b/lib/bundler/source/rubygems.rb
@@ -10,7 +10,7 @@ module Bundler
# Ask for X gems per API request
API_REQUEST_SIZE = 50
- attr_reader :remotes
+ attr_accessor :remotes
def initialize(options = {})
@options = options
@@ -50,10 +50,11 @@ module Bundler
end
def cached!
+ return unless File.exist?(cache_path)
+
return if @allow_cached
@specs = nil
- @allow_local = true
@allow_cached = true
end
@@ -96,7 +97,7 @@ module Bundler
def to_lock
out = String.new("GEM\n")
remotes.reverse_each do |remote|
- out << " remote: #{suppress_configured_credentials remote}\n"
+ out << " remote: #{remove_auth remote}\n"
end
out << " specs:\n"
end
@@ -133,22 +134,19 @@ module Bundler
# sources, and large_idx.merge! small_idx is way faster than
# small_idx.merge! large_idx.
index = @allow_remote ? remote_specs.dup : Index.new
- index.merge!(cached_specs) if @allow_cached || @allow_remote
+ index.merge!(cached_specs) if @allow_cached
index.merge!(installed_specs) if @allow_local
+
+ # complete with default specs, only if not already available in the
+ # index through remote, cached, or installed specs
+ index.use(default_specs) if @allow_local
+
index
end
end
def install(spec, options = {})
- force = options[:force]
- ensure_builtin_gems_cached = options[:ensure_builtin_gems_cached]
-
- if ensure_builtin_gems_cached && spec.default_gem? && !cached_path(spec)
- cached_built_in_gem(spec) unless spec.remote
- force = true
- end
-
- if installed?(spec) && !force
+ if (spec.default_gem? && !cached_built_in_gem(spec)) || (installed?(spec) && !options[:force])
print_using_message "Using #{version_message(spec, options[:previous_spec])}"
return nil # no post-install message
end
@@ -171,14 +169,14 @@ module Bundler
installer = Bundler::RubyGemsGemInstaller.at(
path,
- :security_policy => Bundler.rubygems.security_policies[Bundler.settings["trust-policy"]],
- :install_dir => install_path.to_s,
- :bin_dir => bin_path.to_s,
- :ignore_dependencies => true,
- :wrappers => true,
- :env_shebang => true,
- :build_args => options[:build_args],
- :bundler_extension_cache_path => extension_cache_path(spec)
+ security_policy: Bundler.rubygems.security_policies[Bundler.settings["trust-policy"]],
+ install_dir: install_path.to_s,
+ bin_dir: bin_path.to_s,
+ ignore_dependencies: true,
+ wrappers: true,
+ env_shebang: true,
+ build_args: options[:build_args],
+ bundler_extension_cache_path: extension_cache_path(spec)
)
if spec.remote
@@ -255,11 +253,15 @@ module Bundler
end
end
- def fetchers
- @fetchers ||= remotes.map do |uri|
+ def remote_fetchers
+ @remote_fetchers ||= remotes.to_h do |uri|
remote = Source::Rubygems::Remote.new(uri)
- Bundler::Fetcher.new(remote)
- end
+ [remote, Bundler::Fetcher.new(remote)]
+ end.freeze
+ end
+
+ def fetchers
+ @fetchers ||= remote_fetchers.values.freeze
end
def double_check_for(unmet_dependency_names)
@@ -308,11 +310,7 @@ module Bundler
end
def credless_remotes
- if Bundler.settings[:allow_deployment_source_credential_changes]
- remotes.map(&method(:remove_auth))
- else
- remotes.map(&method(:suppress_configured_credentials))
- end
+ remotes.map(&method(:remove_auth))
end
def remotes_for_spec(spec)
@@ -345,21 +343,12 @@ module Bundler
def normalize_uri(uri)
uri = URINormalizer.normalize_suffix(uri.to_s)
require_relative "../vendored_uri"
- uri = Bundler::URI(uri)
+ uri = Gem::URI(uri)
raise ArgumentError, "The source must be an absolute URI. For example:\n" \
- "source 'https://rubygems.org'" if !uri.absolute? || (uri.is_a?(Bundler::URI::HTTP) && uri.host.nil?)
+ "source 'https://rubygems.org'" if !uri.absolute? || (uri.is_a?(Gem::URI::HTTP) && uri.host.nil?)
uri
end
- def suppress_configured_credentials(remote)
- remote_nouser = remove_auth(remote)
- if remote.userinfo && remote.userinfo == Bundler.settings[remote_nouser]
- remote_nouser
- else
- remote
- end
- end
-
def remove_auth(remote)
if remote.user || remote.password
remote.dup.tap {|uri| uri.user = uri.password = nil }.to_s
@@ -370,7 +359,7 @@ module Bundler
def installed_specs
@installed_specs ||= Index.build do |idx|
- Bundler.rubygems.all_specs.reverse_each do |spec|
+ Bundler.rubygems.installed_specs.reverse_each do |spec|
spec.source = self
if Bundler.rubygems.spec_missing_extensions?(spec, false)
Bundler.ui.debug "Source #{self} is ignoring #{spec} because it is missing extensions"
@@ -381,6 +370,15 @@ module Bundler
end
end
+ def default_specs
+ @default_specs ||= Index.build do |idx|
+ Bundler.rubygems.default_specs.each do |spec|
+ spec.source = self
+ idx << spec
+ end
+ end
+ end
+
def cached_specs
@cached_specs ||= begin
idx = Index.new
@@ -480,7 +478,8 @@ module Bundler
def download_gem(spec, download_cache_path, previous_spec = nil)
uri = spec.remote.uri
Bundler.ui.confirm("Fetching #{version_message(spec, previous_spec)}")
- Bundler.rubygems.download_gem(spec, uri, download_cache_path)
+ gem_remote_fetcher = remote_fetchers.fetch(spec.remote).gem_remote_fetcher
+ Bundler.rubygems.download_gem(spec, uri, download_cache_path, gem_remote_fetcher)
end
# Returns the global cache path of the calling Rubygems::Source object.
diff --git a/lib/bundler/source/rubygems/remote.rb b/lib/bundler/source/rubygems/remote.rb
index 82c850ffbb..9c5c06de24 100644
--- a/lib/bundler/source/rubygems/remote.rb
+++ b/lib/bundler/source/rubygems/remote.rb
@@ -48,7 +48,7 @@ module Bundler
end
uri
- rescue Bundler::URI::InvalidComponentError
+ rescue Gem::URI::InvalidComponentError
error_message = "Please CGI escape your usernames and passwords before " \
"setting them for authentication."
raise HTTPError.new(error_message)
diff --git a/lib/bundler/source_list.rb b/lib/bundler/source_list.rb
index 4419695b7f..5f9dd68f17 100644
--- a/lib/bundler/source_list.rb
+++ b/lib/bundler/source_list.rb
@@ -22,6 +22,7 @@ module Bundler
@metadata_source = Source::Metadata.new
@merged_gem_lockfile_sections = false
+ @local_mode = true
end
def merged_gem_lockfile_sections?
@@ -73,6 +74,10 @@ module Bundler
global_rubygems_source
end
+ def local_mode?
+ @local_mode
+ end
+
def default_source
global_path_source || global_rubygems_source
end
@@ -140,11 +145,17 @@ module Bundler
all_sources.each(&:local_only!)
end
+ def local!
+ all_sources.each(&:local!)
+ end
+
def cached!
all_sources.each(&:cached!)
end
def remote!
+ @local_mode = false
+
all_sources.each(&:remote!)
end
@@ -157,7 +168,11 @@ module Bundler
end
def map_sources(replacement_sources)
- rubygems, git, plugin = [@rubygems_sources, @git_sources, @plugin_sources].map do |sources|
+ rubygems = @rubygems_sources.map do |source|
+ replace_rubygems_source(replacement_sources, source) || source
+ end
+
+ git, plugin = [@git_sources, @plugin_sources].map do |sources|
sources.map do |source|
replacement_sources.find {|s| s == source } || source
end
@@ -171,13 +186,22 @@ module Bundler
end
def global_replacement_source(replacement_sources)
- replacement_source = replacement_sources.find {|s| s == global_rubygems_source }
+ replacement_source = replace_rubygems_source(replacement_sources, global_rubygems_source)
return global_rubygems_source unless replacement_source
replacement_source.local!
replacement_source
end
+ def replace_rubygems_source(replacement_sources, gemfile_source)
+ replacement_source = replacement_sources.find {|s| s == gemfile_source }
+ return unless replacement_source
+
+ # locked sources never include credentials so always prefer remotes from the gemfile
+ replacement_source.remotes = gemfile_source.remotes
+ replacement_source
+ end
+
def different_sources?(lock_sources, replacement_sources)
!equivalent_sources?(lock_sources, replacement_sources)
end
diff --git a/lib/bundler/spec_set.rb b/lib/bundler/spec_set.rb
index f4fc005ef2..2933d28450 100644
--- a/lib/bundler/spec_set.rb
+++ b/lib/bundler/spec_set.rb
@@ -37,7 +37,7 @@ module Bundler
specs_for_dep.first.dependencies.each do |d|
next if d.type == :development
- incomplete = true if d.name != "bundler" && lookup[d.name].empty?
+ incomplete = true if d.name != "bundler" && lookup[d.name].nil?
deps << [d, dep[1]]
end
else
@@ -45,66 +45,64 @@ module Bundler
end
if incomplete && check
- @incomplete_specs += lookup[name].any? ? lookup[name] : [LazySpecification.new(name, nil, nil)]
+ @incomplete_specs += lookup[name] || [LazySpecification.new(name, nil, nil)]
end
end
specs.uniq
end
- def complete_platforms!(platforms)
+ def add_extra_platforms!(platforms)
return platforms.concat([Gem::Platform::RUBY]).uniq if @specs.empty?
- new_platforms = @specs.flat_map {|spec| spec.source.specs.search([spec.name, spec.version]).map(&:platform) }.uniq.select do |platform|
+ new_platforms = all_platforms.select do |platform|
next if platforms.include?(platform)
next unless GemHelpers.generic(platform) == Gem::Platform::RUBY
- new_specs = []
-
- valid_platform = lookup.all? do |_, specs|
- spec = specs.first
- matching_specs = spec.source.specs.search([spec.name, spec.version])
- platform_spec = GemHelpers.select_best_platform_match(matching_specs, platform).first
-
- if platform_spec
- new_specs << LazySpecification.from_spec(platform_spec)
- true
- else
- false
- end
- end
- next unless valid_platform
-
- @specs.concat(new_specs.uniq)
+ complete_platform(platform)
end
return platforms if new_platforms.empty?
platforms.concat(new_platforms)
- less_specific_platform = new_platforms.find {|platform| platform != Gem::Platform::RUBY && platform === Bundler.local_platform }
+ less_specific_platform = new_platforms.find {|platform| platform != Gem::Platform::RUBY && Bundler.local_platform === platform && platform === Bundler.local_platform }
platforms.delete(Bundler.local_platform) if less_specific_platform
- @sorted = nil
- @lookup = nil
-
platforms
end
+ def complete_platforms!(platforms)
+ platforms.each do |platform|
+ complete_platform(platform)
+ end
+ end
+
+ def validate_deps(s)
+ s.runtime_dependencies.each do |dep|
+ next if dep.name == "bundler"
+
+ return :missing unless names.include?(dep.name)
+ return :invalid if none? {|spec| dep.matches_spec?(spec) }
+ end
+
+ :valid
+ end
+
def [](key)
key = key.name if key.respond_to?(:name)
- lookup[key].reverse
+ lookup[key]&.reverse || []
end
def []=(key, value)
@specs << value
- @lookup = nil
- @sorted = nil
+
+ reset!
end
def delete(specs)
specs.each {|spec| @specs.delete(spec) }
- @lookup = nil
- @sorted = nil
+
+ reset!
end
def sort!
@@ -162,12 +160,12 @@ module Bundler
def delete_by_name(name)
@specs.reject! {|spec| spec.name == name }
- @lookup = nil
- @sorted = nil
+
+ reset!
end
def what_required(spec)
- unless req = find {|s| s.dependencies.any? {|d| d.type == :runtime && d.name == spec.name } }
+ unless req = find {|s| s.runtime_dependencies.any? {|d| d.name == spec.name } }
return [spec]
end
what_required(req) << spec
@@ -193,8 +191,52 @@ module Bundler
sorted.each(&b)
end
+ def names
+ lookup.keys
+ end
+
private
+ def reset!
+ @sorted = nil
+ @lookup = nil
+ end
+
+ def complete_platform(platform)
+ new_specs = []
+
+ valid_platform = lookup.all? do |_, specs|
+ spec = specs.first
+ matching_specs = spec.source.specs.search([spec.name, spec.version])
+ platform_spec = GemHelpers.select_best_platform_match(matching_specs, platform).find do |s|
+ s.matches_current_metadata? && valid_dependencies?(s)
+ end
+
+ if platform_spec
+ new_specs << LazySpecification.from_spec(platform_spec) unless specs.include?(platform_spec)
+ true
+ else
+ false
+ end
+ end
+
+ if valid_platform && new_specs.any?
+ @specs.concat(new_specs)
+
+ reset!
+ end
+
+ valid_platform
+ end
+
+ def all_platforms
+ @specs.flat_map {|spec| spec.source.specs.search([spec.name, spec.version]).map(&:platform) }.uniq
+ end
+
+ def valid_dependencies?(s)
+ validate_deps(s) == :valid
+ end
+
def sorted
rake = @specs.find {|s| s.name == "rake" }
begin
@@ -213,8 +255,9 @@ module Bundler
def lookup
@lookup ||= begin
- lookup = Hash.new {|h, k| h[k] = [] }
+ lookup = {}
@specs.each do |s|
+ lookup[s.name] ||= []
lookup[s.name] << s
end
lookup
@@ -228,6 +271,8 @@ module Bundler
def specs_for_dependency(dep, platform)
specs_for_name = lookup[dep.name]
+ return [] unless specs_for_name
+
matching_specs = if dep.force_ruby_platform
GemHelpers.force_ruby_platform(specs_for_name)
else
@@ -240,7 +285,11 @@ module Bundler
def tsort_each_child(s)
s.dependencies.sort_by(&:name).each do |d|
next if d.type == :development
- lookup[d.name].each {|s2| yield s2 }
+
+ specs_for_name = lookup[d.name]
+ next unless specs_for_name
+
+ specs_for_name.each {|s2| yield s2 }
end
end
end
diff --git a/lib/bundler/templates/Executable.bundler b/lib/bundler/templates/Executable.bundler
index e290fe91eb..caa2021701 100644
--- a/lib/bundler/templates/Executable.bundler
+++ b/lib/bundler/templates/Executable.bundler
@@ -27,7 +27,7 @@ m = Module.new do
bundler_version = nil
update_index = nil
ARGV.each_with_index do |a, i|
- if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
+ if update_index && update_index.succ == i && a.match?(Gem::Version::ANCHORED_VERSION_PATTERN)
bundler_version = a
end
next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
diff --git a/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt b/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt
index 175b821a62..67fe8cee79 100644
--- a/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt
+++ b/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt
@@ -2,83 +2,131 @@
## Our Pledge
-We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
+We as members, contributors, and leaders pledge to make participation in our
+community a harassment-free experience for everyone, regardless of age, body
+size, visible or invisible disability, ethnicity, sex characteristics, gender
+identity and expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, caste, color, religion, or sexual
+identity and orientation.
-We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
+We pledge to act and interact in ways that contribute to an open, welcoming,
+diverse, inclusive, and healthy community.
## Our Standards
-Examples of behavior that contributes to a positive environment for our community include:
+Examples of behavior that contributes to a positive environment for our
+community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
-* Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
-* Focusing on what is best not just for us as individuals, but for the overall community
+* Accepting responsibility and apologizing to those affected by our mistakes,
+ and learning from the experience
+* Focusing on what is best not just for us as individuals, but for the overall
+ community
Examples of unacceptable behavior include:
-* The use of sexualized language or imagery, and sexual attention or
- advances of any kind
+* The use of sexualized language or imagery, and sexual attention or advances of
+ any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
-* Publishing others' private information, such as a physical or email
- address, without their explicit permission
+* Publishing others' private information, such as a physical or email address,
+ without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
-Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
+Community leaders are responsible for clarifying and enforcing our standards of
+acceptable behavior and will take appropriate and fair corrective action in
+response to any behavior that they deem inappropriate, threatening, offensive,
+or harmful.
-Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
+Community leaders have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, and will communicate reasons for moderation
+decisions when appropriate.
## Scope
-This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
+This Code of Conduct applies within all community spaces, and also applies when
+an individual is officially representing the community in public spaces.
+Examples of representing our community include using an official email address,
+posting via an official social media account, or acting as an appointed
+representative at an online or offline event.
## Enforcement
-Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at <%= config[:email] %>. All complaints will be reviewed and investigated promptly and fairly.
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported to the community leaders responsible for enforcement at
+[INSERT CONTACT METHOD].
+All complaints will be reviewed and investigated promptly and fairly.
-All community leaders are obligated to respect the privacy and security of the reporter of any incident.
+All community leaders are obligated to respect the privacy and security of the
+reporter of any incident.
## Enforcement Guidelines
-Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
+Community leaders will follow these Community Impact Guidelines in determining
+the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
-**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
+**Community Impact**: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
-**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
+**Consequence**: A private, written warning from community leaders, providing
+clarity around the nature of the violation and an explanation of why the
+behavior was inappropriate. A public apology may be requested.
### 2. Warning
-**Community Impact**: A violation through a single incident or series of actions.
+**Community Impact**: A violation through a single incident or series of
+actions.
-**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
+**Consequence**: A warning with consequences for continued behavior. No
+interaction with the people involved, including unsolicited interaction with
+those enforcing the Code of Conduct, for a specified period of time. This
+includes avoiding interactions in community spaces as well as external channels
+like social media. Violating these terms may lead to a temporary or permanent
+ban.
### 3. Temporary Ban
-**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
+**Community Impact**: A serious violation of community standards, including
+sustained inappropriate behavior.
-**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
+**Consequence**: A temporary ban from any sort of interaction or public
+communication with the community for a specified period of time. No public or
+private interaction with the people involved, including unsolicited interaction
+with those enforcing the Code of Conduct, is allowed during this period.
+Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
-**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
+**Community Impact**: Demonstrating a pattern of violation of community
+standards, including sustained inappropriate behavior, harassment of an
+individual, or aggression toward or disparagement of classes of individuals.
-**Consequence**: A permanent ban from any sort of public interaction within the community.
+**Consequence**: A permanent ban from any sort of public interaction within the
+community.
## Attribution
-This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0,
-available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 2.1, available at
+[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
-Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
-
-[homepage]: https://www.contributor-covenant.org
+Community Impact Guidelines were inspired by
+[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
For answers to common questions about this code of conduct, see the FAQ at
-https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.
+[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
+[https://www.contributor-covenant.org/translations][translations].
+
+[homepage]: https://www.contributor-covenant.org
+[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
+[Mozilla CoC]: https://github.com/mozilla/diversity
+[FAQ]: https://www.contributor-covenant.org/faq
+[translations]: https://www.contributor-covenant.org/translations
diff --git a/lib/bundler/templates/newgem/Rakefile.tt b/lib/bundler/templates/newgem/Rakefile.tt
index 77f8a02530..172183d4b4 100644
--- a/lib/bundler/templates/newgem/Rakefile.tt
+++ b/lib/bundler/templates/newgem/Rakefile.tt
@@ -4,13 +4,9 @@ require "bundler/gem_tasks"
<% default_task_names = [config[:test_task]].compact -%>
<% case config[:test] -%>
<% when "minitest" -%>
-require "rake/testtask"
+require "minitest/test_task"
-Rake::TestTask.new(:test) do |t|
- t.libs << "test"
- t.libs << "lib"
- t.test_files = FileList["test/**/test_*.rb"]
-end
+Minitest::TestTask.create
<% when "test-unit" -%>
require "rake/testtask"
diff --git a/lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt b/lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt
index c64385486e..0ebce0e4a0 100644
--- a/lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt
+++ b/lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt
@@ -12,4 +12,4 @@ publish = false
crate-type = ["cdylib"]
[dependencies]
-magnus = { version = "0.6" }
+magnus = { version = "0.6.2" }
diff --git a/lib/bundler/templates/newgem/newgem.gemspec.tt b/lib/bundler/templates/newgem/newgem.gemspec.tt
index 51f19a5be9..6e88f4dab1 100644
--- a/lib/bundler/templates/newgem/newgem.gemspec.tt
+++ b/lib/bundler/templates/newgem/newgem.gemspec.tt
@@ -27,9 +27,10 @@ Gem::Specification.new do |spec|
# Specify which files should be added to the gem when it is released.
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
- spec.files = Dir.chdir(__dir__) do
- `git ls-files -z`.split("\x0").reject do |f|
- (File.expand_path(f) == __FILE__) ||
+ gemspec = File.basename(__FILE__)
+ spec.files = IO.popen(%w[git ls-files -z], chdir: __dir__, err: IO::NULL) do |ls|
+ ls.readlines("\x0", chomp: true).reject do |f|
+ (f == gemspec) ||
f.start_with?(*%w[bin/ test/ spec/ features/ .git <%= config[:ci_config_path] %>appveyor Gemfile])
end
end
diff --git a/lib/bundler/templates/newgem/rubocop.yml.tt b/lib/bundler/templates/newgem/rubocop.yml.tt
index 9ecec78807..3d1c4ee7b2 100644
--- a/lib/bundler/templates/newgem/rubocop.yml.tt
+++ b/lib/bundler/templates/newgem/rubocop.yml.tt
@@ -2,12 +2,7 @@ AllCops:
TargetRubyVersion: <%= ::Gem::Version.new(config[:required_ruby_version]).segments[0..1].join(".") %>
Style/StringLiterals:
- Enabled: true
EnforcedStyle: double_quotes
Style/StringLiteralsInInterpolation:
- Enabled: true
EnforcedStyle: double_quotes
-
-Layout/LineLength:
- Max: 120
diff --git a/lib/bundler/ui/shell.rb b/lib/bundler/ui/shell.rb
index a9053f2852..4555612dbb 100644
--- a/lib/bundler/ui/shell.rb
+++ b/lib/bundler/ui/shell.rb
@@ -130,7 +130,7 @@ module Bundler
def tell_err(message, color = nil, newline = nil)
return if @shell.send(:stderr).closed?
- newline ||= message.to_s !~ /( |\t)\Z/
+ newline ||= !message.to_s.match?(/( |\t)\Z/)
message = word_wrap(message) if newline.is_a?(Hash) && newline[:wrap]
color = nil if color && !$stderr.tty?
diff --git a/lib/bundler/uri_credentials_filter.rb b/lib/bundler/uri_credentials_filter.rb
index ccfaf0bc5d..a83f5304e2 100644
--- a/lib/bundler/uri_credentials_filter.rb
+++ b/lib/bundler/uri_credentials_filter.rb
@@ -11,7 +11,7 @@ module Bundler
return uri if File.exist?(uri)
require_relative "vendored_uri"
- uri = Bundler::URI(uri)
+ uri = Gem::URI(uri)
end
if uri.userinfo
@@ -25,7 +25,7 @@ module Bundler
end
return uri.to_s if uri_to_anonymize.is_a?(String)
uri
- rescue Bundler::URI::InvalidURIError # uri is not canonical uri scheme
+ rescue Gem::URI::InvalidURIError # uri is not canonical uri scheme
uri
end
diff --git a/lib/rubygems/optparse/.document b/lib/bundler/vendor/connection_pool/.document
index 0c43bbd6b3..0c43bbd6b3 100644
--- a/lib/rubygems/optparse/.document
+++ b/lib/bundler/vendor/connection_pool/.document
diff --git a/lib/bundler/vendor/connection_pool/lib/connection_pool.rb b/lib/bundler/vendor/connection_pool/lib/connection_pool.rb
index 455319efe3..317088a866 100644
--- a/lib/bundler/vendor/connection_pool/lib/connection_pool.rb
+++ b/lib/bundler/vendor/connection_pool/lib/connection_pool.rb
@@ -1,4 +1,4 @@
-require "timeout"
+require_relative "../../../vendored_timeout"
require_relative "connection_pool/version"
class Bundler::ConnectionPool
@@ -6,7 +6,7 @@ class Bundler::ConnectionPool
class PoolShuttingDownError < ::Bundler::ConnectionPool::Error; end
- class TimeoutError < ::Timeout::Error; end
+ class TimeoutError < ::Gem::Timeout::Error; end
end
# Generic connection pool class for sharing a limited number of objects or network connections
@@ -36,14 +36,57 @@ end
# Accepts the following options:
# - :size - number of connections to pool, defaults to 5
# - :timeout - amount of time to wait for a connection if none currently available, defaults to 5 seconds
+# - :auto_reload_after_fork - automatically drop all connections after fork, defaults to true
#
class Bundler::ConnectionPool
- DEFAULTS = {size: 5, timeout: 5}
+ DEFAULTS = {size: 5, timeout: 5, auto_reload_after_fork: true}
def self.wrap(options, &block)
Wrapper.new(options, &block)
end
+ if Process.respond_to?(:fork)
+ INSTANCES = ObjectSpace::WeakMap.new
+ private_constant :INSTANCES
+
+ def self.after_fork
+ INSTANCES.values.each do |pool|
+ next unless pool.auto_reload_after_fork
+
+ # We're on after fork, so we know all other threads are dead.
+ # All we need to do is to ensure the main thread doesn't have a
+ # checked out connection
+ pool.checkin(force: true)
+ pool.reload do |connection|
+ # Unfortunately we don't know what method to call to close the connection,
+ # so we try the most common one.
+ connection.close if connection.respond_to?(:close)
+ end
+ end
+ nil
+ end
+
+ if ::Process.respond_to?(:_fork) # MRI 3.1+
+ module ForkTracker
+ def _fork
+ pid = super
+ if pid == 0
+ Bundler::ConnectionPool.after_fork
+ end
+ pid
+ end
+ end
+ Process.singleton_class.prepend(ForkTracker)
+ end
+ else
+ INSTANCES = nil
+ private_constant :INSTANCES
+
+ def self.after_fork
+ # noop
+ end
+ end
+
def initialize(options = {}, &block)
raise ArgumentError, "Connection pool requires a block" unless block
@@ -51,10 +94,12 @@ class Bundler::ConnectionPool
@size = Integer(options.fetch(:size))
@timeout = options.fetch(:timeout)
+ @auto_reload_after_fork = options.fetch(:auto_reload_after_fork)
@available = TimedStack.new(@size, &block)
@key = :"pool-#{@available.object_id}"
@key_count = :"pool-#{@available.object_id}-count"
+ INSTANCES[self] = self if INSTANCES
end
def with(options = {})
@@ -81,16 +126,16 @@ class Bundler::ConnectionPool
end
end
- def checkin
+ def checkin(force: false)
if ::Thread.current[@key]
- if ::Thread.current[@key_count] == 1
+ if ::Thread.current[@key_count] == 1 || force
@available.push(::Thread.current[@key])
::Thread.current[@key] = nil
::Thread.current[@key_count] = nil
else
::Thread.current[@key_count] -= 1
end
- else
+ elsif !force
raise Bundler::ConnectionPool::Error, "no connections are checked out"
end
@@ -117,6 +162,8 @@ class Bundler::ConnectionPool
# Size of this connection pool
attr_reader :size
+ # Automatically drop all connections after fork
+ attr_reader :auto_reload_after_fork
# Number of pool entries available for checkout at this instant.
def available
diff --git a/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb b/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb
index 56ebf69902..384d6fc977 100644
--- a/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb
+++ b/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb
@@ -1,3 +1,3 @@
class Bundler::ConnectionPool
- VERSION = "2.3.0"
+ VERSION = "2.4.1"
end
diff --git a/lib/rubygems/tsort/.document b/lib/bundler/vendor/fileutils/.document
index 0c43bbd6b3..0c43bbd6b3 100644
--- a/lib/rubygems/tsort/.document
+++ b/lib/bundler/vendor/fileutils/.document
diff --git a/lib/bundler/vendor/fileutils/lib/fileutils.rb b/lib/bundler/vendor/fileutils/lib/fileutils.rb
index 211311c069..6db19caf6f 100644
--- a/lib/bundler/vendor/fileutils/lib/fileutils.rb
+++ b/lib/bundler/vendor/fileutils/lib/fileutils.rb
@@ -180,7 +180,7 @@ end
# - {CVE-2004-0452}[https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0452].
#
module Bundler::FileUtils
- VERSION = "1.7.0"
+ VERSION = "1.7.2"
def self.private_module_function(name) #:nodoc:
module_function name
@@ -192,8 +192,6 @@ module Bundler::FileUtils
#
# Bundler::FileUtils.pwd # => "/rdoc/fileutils"
#
- # Bundler::FileUtils.getwd is an alias for Bundler::FileUtils.pwd.
- #
# Related: Bundler::FileUtils.cd.
#
def pwd
@@ -235,8 +233,6 @@ module Bundler::FileUtils
# cd ..
# cd fileutils
#
- # Bundler::FileUtils.chdir is an alias for Bundler::FileUtils.cd.
- #
# Related: Bundler::FileUtils.pwd.
#
def cd(dir, verbose: nil, &block) # :yield: dir
@@ -515,8 +511,6 @@ module Bundler::FileUtils
# Raises an exception if +dest+ is the path to an existing file
# and keyword argument +force+ is not +true+.
#
- # Bundler::FileUtils#link is an alias for Bundler::FileUtils#ln.
- #
# Related: Bundler::FileUtils.link_entry (has different options).
#
def ln(src, dest, force: nil, noop: nil, verbose: nil)
@@ -707,8 +701,6 @@ module Bundler::FileUtils
# ln -sf src2.txt dest2.txt
# ln -s srcdir3/src0.txt srcdir3/src1.txt destdir3
#
- # Bundler::FileUtils.symlink is an alias for Bundler::FileUtils.ln_s.
- #
# Related: Bundler::FileUtils.ln_sf.
#
def ln_s(src, dest, force: nil, relative: false, target_directory: true, noop: nil, verbose: nil)
@@ -876,8 +868,6 @@ module Bundler::FileUtils
#
# Raises an exception if +src+ is a directory.
#
- # Bundler::FileUtils.copy is an alias for Bundler::FileUtils.cp.
- #
# Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
#
def cp(src, dest, preserve: nil, noop: nil, verbose: nil)
@@ -1164,8 +1154,6 @@ module Bundler::FileUtils
# mv src0 dest0
# mv src1.txt src1 dest1
#
- # Bundler::FileUtils.move is an alias for Bundler::FileUtils.mv.
- #
def mv(src, dest, force: nil, noop: nil, verbose: nil, secure: nil)
fu_output_message "mv#{force ? ' -f' : ''} #{[src,dest].flatten.join ' '}" if verbose
return if noop
@@ -1223,8 +1211,6 @@ module Bundler::FileUtils
#
# rm src0.dat src0.txt
#
- # Bundler::FileUtils.remove is an alias for Bundler::FileUtils.rm.
- #
# Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
#
def rm(list, force: nil, noop: nil, verbose: nil)
@@ -1250,8 +1236,6 @@ module Bundler::FileUtils
#
# See Bundler::FileUtils.rm for keyword arguments.
#
- # Bundler::FileUtils.safe_unlink is an alias for Bundler::FileUtils.rm_f.
- #
# Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
#
def rm_f(list, noop: nil, verbose: nil)
@@ -1339,8 +1323,6 @@ module Bundler::FileUtils
#
# See Bundler::FileUtils.rm_r for keyword arguments.
#
- # Bundler::FileUtils.rmtree is an alias for Bundler::FileUtils.rm_rf.
- #
# Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
#
def rm_rf(list, noop: nil, verbose: nil, secure: nil)
@@ -1642,7 +1624,13 @@ module Bundler::FileUtils
st = File.stat(s)
unless File.exist?(d) and compare_file(s, d)
remove_file d, true
- copy_file s, d
+ if d.end_with?('/')
+ mkdir_p d
+ copy_file s, d + File.basename(s)
+ else
+ mkdir_p File.expand_path('..', d)
+ copy_file s, d
+ end
File.utime st.atime, st.mtime, d if preserve
File.chmod fu_mode(mode, st), d if mode
File.chown uid, gid, d if uid or gid
diff --git a/lib/bundler/vendor/net-http-persistent/.document b/lib/bundler/vendor/net-http-persistent/.document
new file mode 100644
index 0000000000..0c43bbd6b3
--- /dev/null
+++ b/lib/bundler/vendor/net-http-persistent/.document
@@ -0,0 +1 @@
+# Vendored files do not need to be documented
diff --git a/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb b/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb
index bd53ee757e..c15b346330 100644
--- a/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb
+++ b/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb
@@ -1,14 +1,14 @@
-require 'net/http'
-require_relative '../../../../uri/lib/uri'
+require_relative '../../../../../vendored_net_http'
+require_relative '../../../../../vendored_uri'
require 'cgi' # for escaping
require_relative '../../../../connection_pool/lib/connection_pool'
autoload :OpenSSL, 'openssl'
##
-# Persistent connections for Net::HTTP
+# Persistent connections for Gem::Net::HTTP
#
-# Bundler::Persistent::Net::HTTP::Persistent maintains persistent connections across all the
+# Gem::Net::HTTP::Persistent maintains persistent connections across all the
# servers you wish to talk to. For each host:port you communicate with a
# single persistent connection is created.
#
@@ -22,34 +22,34 @@ autoload :OpenSSL, 'openssl'
#
# require 'bundler/vendor/net-http-persistent/lib/net/http/persistent'
#
-# uri = Bundler::URI 'http://example.com/awesome/web/service'
+# uri = Gem::URI 'http://example.com/awesome/web/service'
#
-# http = Bundler::Persistent::Net::HTTP::Persistent.new
+# http = Gem::Net::HTTP::Persistent.new
#
# # perform a GET
# response = http.request uri
#
# # or
#
-# get = Net::HTTP::Get.new uri.request_uri
+# get = Gem::Net::HTTP::Get.new uri.request_uri
# response = http.request get
#
# # create a POST
# post_uri = uri + 'create'
-# post = Net::HTTP::Post.new post_uri.path
+# post = Gem::Net::HTTP::Post.new post_uri.path
# post.set_form_data 'some' => 'cool data'
#
-# # perform the POST, the Bundler::URI is always required
+# # perform the POST, the Gem::URI is always required
# response http.request post_uri, post
#
# Note that for GET, HEAD and other requests that do not have a body you want
-# to use Bundler::URI#request_uri not Bundler::URI#path. The request_uri contains the query
+# to use Gem::URI#request_uri not Gem::URI#path. The request_uri contains the query
# params which are sent in the body for other requests.
#
# == TLS/SSL
#
# TLS connections are automatically created depending upon the scheme of the
-# Bundler::URI. TLS connections are automatically verified against the default
+# Gem::URI. TLS connections are automatically verified against the default
# certificate store for your computer. You can override this by changing
# verify_mode or by specifying an alternate cert_store.
#
@@ -72,7 +72,7 @@ autoload :OpenSSL, 'openssl'
# == Proxies
#
# A proxy can be set through #proxy= or at initialization time by providing a
-# second argument to ::new. The proxy may be the Bundler::URI of the proxy server or
+# second argument to ::new. The proxy may be the Gem::URI of the proxy server or
# <code>:ENV</code> which will consult environment variables.
#
# See #proxy= and #proxy_from_env for details.
@@ -92,7 +92,7 @@ autoload :OpenSSL, 'openssl'
#
# === Segregation
#
-# Each Bundler::Persistent::Net::HTTP::Persistent instance has its own pool of connections. There
+# Each Gem::Net::HTTP::Persistent instance has its own pool of connections. There
# is no sharing with other instances (as was true in earlier versions).
#
# === Idle Timeout
@@ -131,7 +131,7 @@ autoload :OpenSSL, 'openssl'
#
# === Connection Termination
#
-# If you are done using the Bundler::Persistent::Net::HTTP::Persistent instance you may shut down
+# If you are done using the Gem::Net::HTTP::Persistent instance you may shut down
# all the connections in the current thread with #shutdown. This is not
# recommended for normal use, it should only be used when it will be several
# minutes before you make another HTTP request.
@@ -141,7 +141,7 @@ autoload :OpenSSL, 'openssl'
# Ruby will automatically garbage collect and shutdown your HTTP connections
# when the thread terminates.
-class Bundler::Persistent::Net::HTTP::Persistent
+class Gem::Net::HTTP::Persistent
##
# The beginning of Time
@@ -172,12 +172,12 @@ class Bundler::Persistent::Net::HTTP::Persistent
end
##
- # The version of Bundler::Persistent::Net::HTTP::Persistent you are using
+ # The version of Gem::Net::HTTP::Persistent you are using
VERSION = '4.0.2'
##
- # Error class for errors raised by Bundler::Persistent::Net::HTTP::Persistent. Various
+ # Error class for errors raised by Gem::Net::HTTP::Persistent. Various
# SystemCallErrors are re-raised with a human-readable message under this
# class.
@@ -197,10 +197,10 @@ class Bundler::Persistent::Net::HTTP::Persistent
# NOTE: This may not work on ruby > 1.9.
def self.detect_idle_timeout uri, max = 10
- uri = Bundler::URI uri unless Bundler::URI::Generic === uri
+ uri = Gem::URI uri unless Gem::URI::Generic === uri
uri += '/'
- req = Net::HTTP::Head.new uri.request_uri
+ req = Gem::Net::HTTP::Head.new uri.request_uri
http = new 'net-http-persistent detect_idle_timeout'
@@ -214,7 +214,7 @@ class Bundler::Persistent::Net::HTTP::Persistent
$stderr.puts "HEAD #{uri} => #{response.code}" if $DEBUG
- unless Net::HTTPOK === response then
+ unless Gem::Net::HTTPOK === response then
raise Error, "bad response code #{response.code} detecting idle timeout"
end
@@ -238,7 +238,7 @@ class Bundler::Persistent::Net::HTTP::Persistent
attr_reader :certificate
##
- # For Net::HTTP parity
+ # For Gem::Net::HTTP parity
alias cert certificate
@@ -266,7 +266,7 @@ class Bundler::Persistent::Net::HTTP::Persistent
attr_reader :ciphers
##
- # Sends debug_output to this IO via Net::HTTP#set_debug_output.
+ # Sends debug_output to this IO via Gem::Net::HTTP#set_debug_output.
#
# Never use this method in production code, it causes a serious security
# hole.
@@ -279,7 +279,7 @@ class Bundler::Persistent::Net::HTTP::Persistent
attr_reader :generation # :nodoc:
##
- # Headers that are added to every request using Net::HTTP#add_field
+ # Headers that are added to every request using Gem::Net::HTTP#add_field
attr_reader :headers
@@ -304,7 +304,7 @@ class Bundler::Persistent::Net::HTTP::Persistent
##
# Number of retries to perform if a request fails.
#
- # See also #max_retries=, Net::HTTP#max_retries=.
+ # See also #max_retries=, Gem::Net::HTTP#max_retries=.
attr_reader :max_retries
@@ -325,12 +325,12 @@ class Bundler::Persistent::Net::HTTP::Persistent
attr_reader :name
##
- # Seconds to wait until a connection is opened. See Net::HTTP#open_timeout
+ # Seconds to wait until a connection is opened. See Gem::Net::HTTP#open_timeout
attr_accessor :open_timeout
##
- # Headers that are added to every request using Net::HTTP#[]=
+ # Headers that are added to every request using Gem::Net::HTTP#[]=
attr_reader :override_headers
@@ -340,7 +340,7 @@ class Bundler::Persistent::Net::HTTP::Persistent
attr_reader :private_key
##
- # For Net::HTTP parity
+ # For Gem::Net::HTTP parity
alias key private_key
@@ -360,12 +360,12 @@ class Bundler::Persistent::Net::HTTP::Persistent
attr_reader :pool # :nodoc:
##
- # Seconds to wait until reading one block. See Net::HTTP#read_timeout
+ # Seconds to wait until reading one block. See Gem::Net::HTTP#read_timeout
attr_accessor :read_timeout
##
- # Seconds to wait until writing one block. See Net::HTTP#write_timeout
+ # Seconds to wait until writing one block. See Gem::Net::HTTP#write_timeout
attr_accessor :write_timeout
@@ -450,18 +450,18 @@ class Bundler::Persistent::Net::HTTP::Persistent
attr_reader :verify_mode
##
- # Creates a new Bundler::Persistent::Net::HTTP::Persistent.
+ # Creates a new Gem::Net::HTTP::Persistent.
#
# Set a +name+ for fun. Your library name should be good enough, but this
# otherwise has no purpose.
#
- # +proxy+ may be set to a Bundler::URI::HTTP or :ENV to pick up proxy options from
+ # +proxy+ may be set to a Gem::URI::HTTP or :ENV to pick up proxy options from
# the environment. See proxy_from_env for details.
#
- # In order to use a Bundler::URI for the proxy you may need to do some extra work
- # beyond Bundler::URI parsing if the proxy requires a password:
+ # In order to use a Gem::URI for the proxy you may need to do some extra work
+ # beyond Gem::URI parsing if the proxy requires a password:
#
- # proxy = Bundler::URI 'http://proxy.example'
+ # proxy = Gem::URI 'http://proxy.example'
# proxy.user = 'AzureDiamond'
# proxy.password = 'hunter2'
#
@@ -492,8 +492,8 @@ class Bundler::Persistent::Net::HTTP::Persistent
@socket_options << [Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1] if
Socket.const_defined? :TCP_NODELAY
- @pool = Bundler::Persistent::Net::HTTP::Persistent::Pool.new size: pool_size do |http_args|
- Bundler::Persistent::Net::HTTP::Persistent::Connection.new Net::HTTP, http_args, @ssl_generation
+ @pool = Gem::Net::HTTP::Persistent::Pool.new size: pool_size do |http_args|
+ Gem::Net::HTTP::Persistent::Connection.new Gem::Net::HTTP, http_args, @ssl_generation
end
@certificate = nil
@@ -510,7 +510,7 @@ class Bundler::Persistent::Net::HTTP::Persistent
@verify_mode = nil
@cert_store = nil
- @generation = 0 # incremented when proxy Bundler::URI changes
+ @generation = 0 # incremented when proxy Gem::URI changes
if HAVE_OPENSSL then
@verify_mode = OpenSSL::SSL::VERIFY_PEER
@@ -529,7 +529,7 @@ class Bundler::Persistent::Net::HTTP::Persistent
reconnect_ssl
end
- # For Net::HTTP parity
+ # For Gem::Net::HTTP parity
alias cert= certificate=
##
@@ -648,7 +648,7 @@ class Bundler::Persistent::Net::HTTP::Persistent
end
##
- # Starts the Net::HTTP +connection+
+ # Starts the Gem::Net::HTTP +connection+
def start http
http.set_debug_output @debug_output if @debug_output
@@ -666,7 +666,7 @@ class Bundler::Persistent::Net::HTTP::Persistent
end
##
- # Finishes the Net::HTTP +connection+
+ # Finishes the Gem::Net::HTTP +connection+
def finish connection
connection.finish
@@ -716,16 +716,16 @@ class Bundler::Persistent::Net::HTTP::Persistent
reconnect_ssl
end
- # For Net::HTTP parity
+ # For Gem::Net::HTTP parity
alias key= private_key=
##
- # Sets the proxy server. The +proxy+ may be the Bundler::URI of the proxy server,
+ # Sets the proxy server. The +proxy+ may be the Gem::URI of the proxy server,
# the symbol +:ENV+ which will read the proxy from the environment or nil to
# disable use of a proxy. See #proxy_from_env for details on setting the
# proxy from the environment.
#
- # If the proxy Bundler::URI is set after requests have been made, the next request
+ # If the proxy Gem::URI is set after requests have been made, the next request
# will shut-down and re-open all connections.
#
# The +no_proxy+ query parameter can be used to specify hosts which shouldn't
@@ -736,9 +736,9 @@ class Bundler::Persistent::Net::HTTP::Persistent
def proxy= proxy
@proxy_uri = case proxy
when :ENV then proxy_from_env
- when Bundler::URI::HTTP then proxy
+ when Gem::URI::HTTP then proxy
when nil then # ignore
- else raise ArgumentError, 'proxy must be :ENV or a Bundler::URI::HTTP'
+ else raise ArgumentError, 'proxy must be :ENV or a Gem::URI::HTTP'
end
@no_proxy.clear
@@ -763,13 +763,13 @@ class Bundler::Persistent::Net::HTTP::Persistent
end
##
- # Creates a Bundler::URI for an HTTP proxy server from ENV variables.
+ # Creates a Gem::URI for an HTTP proxy server from ENV variables.
#
# If +HTTP_PROXY+ is set a proxy will be returned.
#
- # If +HTTP_PROXY_USER+ or +HTTP_PROXY_PASS+ are set the Bundler::URI is given the
+ # If +HTTP_PROXY_USER+ or +HTTP_PROXY_PASS+ are set the Gem::URI is given the
# indicated user and password unless HTTP_PROXY contains either of these in
- # the Bundler::URI.
+ # the Gem::URI.
#
# The +NO_PROXY+ ENV variable can be used to specify hosts which shouldn't
# be reached via proxy; if set it should be a comma separated list of
@@ -785,7 +785,7 @@ class Bundler::Persistent::Net::HTTP::Persistent
return nil if env_proxy.nil? or env_proxy.empty?
- uri = Bundler::URI normalize_uri env_proxy
+ uri = Gem::URI normalize_uri env_proxy
env_no_proxy = ENV['no_proxy'] || ENV['NO_PROXY']
@@ -835,7 +835,7 @@ class Bundler::Persistent::Net::HTTP::Persistent
end
##
- # Finishes then restarts the Net::HTTP +connection+
+ # Finishes then restarts the Gem::Net::HTTP +connection+
def reset connection
http = connection.http
@@ -854,16 +854,16 @@ class Bundler::Persistent::Net::HTTP::Persistent
end
##
- # Makes a request on +uri+. If +req+ is nil a Net::HTTP::Get is performed
+ # Makes a request on +uri+. If +req+ is nil a Gem::Net::HTTP::Get is performed
# against +uri+.
#
- # If a block is passed #request behaves like Net::HTTP#request (the body of
+ # If a block is passed #request behaves like Gem::Net::HTTP#request (the body of
# the response will not have been read).
#
- # +req+ must be a Net::HTTPGenericRequest subclass (see Net::HTTP for a list).
+ # +req+ must be a Gem::Net::HTTPGenericRequest subclass (see Gem::Net::HTTP for a list).
def request uri, req = nil, &block
- uri = Bundler::URI uri
+ uri = Gem::URI uri
req = request_setup req || uri
response = nil
@@ -896,14 +896,14 @@ class Bundler::Persistent::Net::HTTP::Persistent
end
##
- # Creates a GET request if +req_or_uri+ is a Bundler::URI and adds headers to the
+ # Creates a GET request if +req_or_uri+ is a Gem::URI and adds headers to the
# request.
#
# Returns the request.
def request_setup req_or_uri # :nodoc:
req = if req_or_uri.respond_to? 'request_uri' then
- Net::HTTP::Get.new req_or_uri.request_uri
+ Gem::Net::HTTP::Get.new req_or_uri.request_uri
else
req_or_uri
end
diff --git a/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/connection.rb b/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/connection.rb
index 40f61aacea..8b9ab5cc78 100644
--- a/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/connection.rb
+++ b/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/connection.rb
@@ -1,8 +1,8 @@
##
-# A Net::HTTP connection wrapper that holds extra information for managing the
+# A Gem::Net::HTTP connection wrapper that holds extra information for managing the
# connection's lifetime.
-class Bundler::Persistent::Net::HTTP::Persistent::Connection # :nodoc:
+class Gem::Net::HTTP::Persistent::Connection # :nodoc:
attr_accessor :http
@@ -28,7 +28,7 @@ class Bundler::Persistent::Net::HTTP::Persistent::Connection # :nodoc:
alias_method :close, :finish
def reset
- @last_use = Bundler::Persistent::Net::HTTP::Persistent::EPOCH
+ @last_use = Gem::Net::HTTP::Persistent::EPOCH
@requests = 0
end
diff --git a/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/pool.rb b/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/pool.rb
index 736027863c..04a1e754bf 100644
--- a/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/pool.rb
+++ b/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/pool.rb
@@ -1,4 +1,4 @@
-class Bundler::Persistent::Net::HTTP::Persistent::Pool < Bundler::ConnectionPool # :nodoc:
+class Gem::Net::HTTP::Persistent::Pool < Bundler::ConnectionPool # :nodoc:
attr_reader :available # :nodoc:
attr_reader :key # :nodoc:
@@ -6,7 +6,7 @@ class Bundler::Persistent::Net::HTTP::Persistent::Pool < Bundler::ConnectionPool
def initialize(options = {}, &block)
super
- @available = Bundler::Persistent::Net::HTTP::Persistent::TimedStackMulti.new(@size, &block)
+ @available = Gem::Net::HTTP::Persistent::TimedStackMulti.new(@size, &block)
@key = "current-#{@available.object_id}"
end
diff --git a/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb b/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb
index 2da881c554..214804fcd9 100644
--- a/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb
+++ b/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb
@@ -1,4 +1,4 @@
-class Bundler::Persistent::Net::HTTP::Persistent::TimedStackMulti < Bundler::ConnectionPool::TimedStack # :nodoc:
+class Gem::Net::HTTP::Persistent::TimedStackMulti < Bundler::ConnectionPool::TimedStack # :nodoc:
##
# Returns a new hash that has arrays for keys
diff --git a/lib/bundler/vendor/pub_grub/.document b/lib/bundler/vendor/pub_grub/.document
new file mode 100644
index 0000000000..0c43bbd6b3
--- /dev/null
+++ b/lib/bundler/vendor/pub_grub/.document
@@ -0,0 +1 @@
+# Vendored files do not need to be documented
diff --git a/lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb b/lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb
index 4bf61461b2..36ab06254d 100644
--- a/lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb
+++ b/lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb
@@ -1,4 +1,5 @@
require_relative 'package'
+require_relative 'rubygems'
require_relative 'version_constraint'
require_relative 'incompatibility'
require_relative 'basic_package_source'
diff --git a/lib/bundler/vendor/thor/.document b/lib/bundler/vendor/thor/.document
new file mode 100644
index 0000000000..0c43bbd6b3
--- /dev/null
+++ b/lib/bundler/vendor/thor/.document
@@ -0,0 +1 @@
+# Vendored files do not need to be documented
diff --git a/lib/bundler/vendor/thor/lib/thor/shell/color.rb b/lib/bundler/vendor/thor/lib/thor/shell/color.rb
index 6a9176331c..5d708fadca 100644
--- a/lib/bundler/vendor/thor/lib/thor/shell/color.rb
+++ b/lib/bundler/vendor/thor/lib/thor/shell/color.rb
@@ -1,5 +1,4 @@
require_relative "basic"
-require_relative "lcs_diff"
class Bundler::Thor
module Shell
@@ -7,8 +6,6 @@ class Bundler::Thor
# Bundler::Thor::Shell::Basic to see all available methods.
#
class Color < Basic
- include LCSDiff
-
# Embed in a String to clear all previous ANSI sequences.
CLEAR = "\e[0m"
# The start of an ANSI bold sequence.
diff --git a/lib/bundler/vendor/thor/lib/thor/shell/html.rb b/lib/bundler/vendor/thor/lib/thor/shell/html.rb
index 6091485acb..0277b882b7 100644
--- a/lib/bundler/vendor/thor/lib/thor/shell/html.rb
+++ b/lib/bundler/vendor/thor/lib/thor/shell/html.rb
@@ -1,5 +1,4 @@
require_relative "basic"
-require_relative "lcs_diff"
class Bundler::Thor
module Shell
@@ -7,8 +6,6 @@ class Bundler::Thor
# Bundler::Thor::Shell::Basic to see all available methods.
#
class HTML < Basic
- include LCSDiff
-
# The start of an HTML bold sequence.
BOLD = "font-weight: bold"
diff --git a/lib/bundler/vendor/thor/lib/thor/shell/lcs_diff.rb b/lib/bundler/vendor/thor/lib/thor/shell/lcs_diff.rb
deleted file mode 100644
index 81268a9f02..0000000000
--- a/lib/bundler/vendor/thor/lib/thor/shell/lcs_diff.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-module LCSDiff
-protected
-
- # Overwrite show_diff to show diff with colors if Diff::LCS is
- # available.
- def show_diff(destination, content) #:nodoc:
- if diff_lcs_loaded? && ENV["THOR_DIFF"].nil? && ENV["RAILS_DIFF"].nil?
- actual = File.binread(destination).to_s.split("\n")
- content = content.to_s.split("\n")
-
- Diff::LCS.sdiff(actual, content).each do |diff|
- output_diff_line(diff)
- end
- else
- super
- end
- end
-
-private
-
- def output_diff_line(diff) #:nodoc:
- case diff.action
- when "-"
- say "- #{diff.old_element.chomp}", :red, true
- when "+"
- say "+ #{diff.new_element.chomp}", :green, true
- when "!"
- say "- #{diff.old_element.chomp}", :red, true
- say "+ #{diff.new_element.chomp}", :green, true
- else
- say " #{diff.old_element.chomp}", nil, true
- end
- end
-
- # Check if Diff::LCS is loaded. If it is, use it to create pretty output
- # for diff.
- def diff_lcs_loaded? #:nodoc:
- return true if defined?(Diff::LCS)
- return @diff_lcs_loaded unless @diff_lcs_loaded.nil?
-
- @diff_lcs_loaded = begin
- require "diff/lcs"
- true
- rescue LoadError
- false
- end
- end
-
-end
diff --git a/lib/bundler/vendor/tsort/.document b/lib/bundler/vendor/tsort/.document
new file mode 100644
index 0000000000..0c43bbd6b3
--- /dev/null
+++ b/lib/bundler/vendor/tsort/.document
@@ -0,0 +1 @@
+# Vendored files do not need to be documented
diff --git a/lib/bundler/vendor/tsort/lib/tsort.rb b/lib/bundler/vendor/tsort/lib/tsort.rb
index 4a0e1a4e25..cf8731f760 100644
--- a/lib/bundler/vendor/tsort/lib/tsort.rb
+++ b/lib/bundler/vendor/tsort/lib/tsort.rb
@@ -122,6 +122,9 @@
#
module Bundler::TSort
+
+ VERSION = "0.2.0"
+
class Cyclic < StandardError
end
diff --git a/lib/bundler/vendor/uri/.document b/lib/bundler/vendor/uri/.document
new file mode 100644
index 0000000000..0c43bbd6b3
--- /dev/null
+++ b/lib/bundler/vendor/uri/.document
@@ -0,0 +1 @@
+# Vendored files do not need to be documented
diff --git a/lib/bundler/vendor/uri/lib/uri/common.rb b/lib/bundler/vendor/uri/lib/uri/common.rb
index 914a4c7581..93f4f226ad 100644
--- a/lib/bundler/vendor/uri/lib/uri/common.rb
+++ b/lib/bundler/vendor/uri/lib/uri/common.rb
@@ -68,16 +68,32 @@ module Bundler::URI
end
private_constant :Schemes
+ # Registers the given +klass+ as the class to be instantiated
+ # when parsing a \Bundler::URI with the given +scheme+:
#
- # Register the given +klass+ to be instantiated when parsing URLs with the given +scheme+.
- # Note that currently only schemes which after .upcase are valid constant names
- # can be registered (no -/+/. allowed).
+ # Bundler::URI.register_scheme('MS_SEARCH', Bundler::URI::Generic) # => Bundler::URI::Generic
+ # Bundler::URI.scheme_list['MS_SEARCH'] # => Bundler::URI::Generic
#
+ # Note that after calling String#upcase on +scheme+, it must be a valid
+ # constant name.
def self.register_scheme(scheme, klass)
Schemes.const_set(scheme.to_s.upcase, klass)
end
- # Returns a Hash of the defined schemes.
+ # Returns a hash of the defined schemes:
+ #
+ # Bundler::URI.scheme_list
+ # # =>
+ # {"MAILTO"=>Bundler::URI::MailTo,
+ # "LDAPS"=>Bundler::URI::LDAPS,
+ # "WS"=>Bundler::URI::WS,
+ # "HTTP"=>Bundler::URI::HTTP,
+ # "HTTPS"=>Bundler::URI::HTTPS,
+ # "LDAP"=>Bundler::URI::LDAP,
+ # "FILE"=>Bundler::URI::File,
+ # "FTP"=>Bundler::URI::FTP}
+ #
+ # Related: Bundler::URI.register_scheme.
def self.scheme_list
Schemes.constants.map { |name|
[name.to_s.upcase, Schemes.const_get(name)]
@@ -88,9 +104,21 @@ module Bundler::URI
private_constant :INITIAL_SCHEMES
Ractor.make_shareable(INITIAL_SCHEMES) if defined?(Ractor)
+ # Returns a new object constructed from the given +scheme+, +arguments+,
+ # and +default+:
+ #
+ # - The new object is an instance of <tt>Bundler::URI.scheme_list[scheme.upcase]</tt>.
+ # - The object is initialized by calling the class initializer
+ # using +scheme+ and +arguments+.
+ # See Bundler::URI::Generic.new.
+ #
+ # Examples:
#
- # Construct a Bundler::URI instance, using the scheme to detect the appropriate class
- # from +Bundler::URI.scheme_list+.
+ # values = ['john.doe', 'www.example.com', '123', nil, '/forum/questions/', nil, 'tag=networking&order=newest', 'top']
+ # Bundler::URI.for('https', *values)
+ # # => #<Bundler::URI::HTTPS https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
+ # Bundler::URI.for('foo', *values, default: Bundler::URI::HTTP)
+ # # => #<Bundler::URI::HTTP foo://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
#
def self.for(scheme, *arguments, default: Generic)
const_name = scheme.to_s.upcase
@@ -121,95 +149,49 @@ module Bundler::URI
#
class BadURIError < Error; end
- #
- # == Synopsis
- #
- # Bundler::URI::split(uri)
- #
- # == Args
- #
- # +uri+::
- # String with Bundler::URI.
- #
- # == Description
- #
- # Splits the string on following parts and returns array with result:
- #
- # * Scheme
- # * Userinfo
- # * Host
- # * Port
- # * Registry
- # * Path
- # * Opaque
- # * Query
- # * Fragment
- #
- # == Usage
- #
- # require 'bundler/vendor/uri/lib/uri'
- #
- # Bundler::URI.split("http://www.ruby-lang.org/")
- # # => ["http", nil, "www.ruby-lang.org", nil, nil, "/", nil, nil, nil]
+ # Returns a 9-element array representing the parts of the \Bundler::URI
+ # formed from the string +uri+;
+ # each array element is a string or +nil+:
+ #
+ # names = %w[scheme userinfo host port registry path opaque query fragment]
+ # values = Bundler::URI.split('https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top')
+ # names.zip(values)
+ # # =>
+ # [["scheme", "https"],
+ # ["userinfo", "john.doe"],
+ # ["host", "www.example.com"],
+ # ["port", "123"],
+ # ["registry", nil],
+ # ["path", "/forum/questions/"],
+ # ["opaque", nil],
+ # ["query", "tag=networking&order=newest"],
+ # ["fragment", "top"]]
#
def self.split(uri)
RFC3986_PARSER.split(uri)
end
+ # Returns a new \Bundler::URI object constructed from the given string +uri+:
#
- # == Synopsis
- #
- # Bundler::URI::parse(uri_str)
- #
- # == Args
- #
- # +uri_str+::
- # String with Bundler::URI.
- #
- # == Description
- #
- # Creates one of the Bundler::URI's subclasses instance from the string.
- #
- # == Raises
- #
- # Bundler::URI::InvalidURIError::
- # Raised if Bundler::URI given is not a correct one.
+ # Bundler::URI.parse('https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top')
+ # # => #<Bundler::URI::HTTPS https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
+ # Bundler::URI.parse('http://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top')
+ # # => #<Bundler::URI::HTTP http://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
#
- # == Usage
- #
- # require 'bundler/vendor/uri/lib/uri'
- #
- # uri = Bundler::URI.parse("http://www.ruby-lang.org/")
- # # => #<Bundler::URI::HTTP http://www.ruby-lang.org/>
- # uri.scheme
- # # => "http"
- # uri.host
- # # => "www.ruby-lang.org"
- #
- # It's recommended to first ::escape the provided +uri_str+ if there are any
- # invalid Bundler::URI characters.
+ # It's recommended to first ::escape string +uri+
+ # if it may contain invalid Bundler::URI characters.
#
def self.parse(uri)
RFC3986_PARSER.parse(uri)
end
+ # Merges the given Bundler::URI strings +str+
+ # per {RFC 2396}[https://www.rfc-editor.org/rfc/rfc2396.html].
#
- # == Synopsis
- #
- # Bundler::URI::join(str[, str, ...])
+ # Each string in +str+ is converted to an
+ # {RFC3986 Bundler::URI}[https://www.rfc-editor.org/rfc/rfc3986.html] before being merged.
#
- # == Args
- #
- # +str+::
- # String(s) to work with, will be converted to RFC3986 URIs before merging.
- #
- # == Description
- #
- # Joins URIs.
- #
- # == Usage
- #
- # require 'bundler/vendor/uri/lib/uri'
+ # Examples:
#
# Bundler::URI.join("http://example.com/","main.rbx")
# # => #<Bundler::URI::HTTP http://example.com/main.rbx>
@@ -254,7 +236,7 @@ module Bundler::URI
# Bundler::URI.extract("text here http://foo.example.org/bla and here mailto:test@example.com and here also.")
# # => ["http://foo.example.com/bla", "mailto:test@example.com"]
#
- def self.extract(str, schemes = nil, &block)
+ def self.extract(str, schemes = nil, &block) # :nodoc:
warn "Bundler::URI.extract is obsolete", uplevel: 1 if $VERBOSE
DEFAULT_PARSER.extract(str, schemes, &block)
end
@@ -291,7 +273,7 @@ module Bundler::URI
# p $&
# end
#
- def self.regexp(schemes = nil)
+ def self.regexp(schemes = nil)# :nodoc:
warn "Bundler::URI.regexp is obsolete", uplevel: 1 if $VERBOSE
DEFAULT_PARSER.make_regexp(schemes)
end
@@ -314,40 +296,86 @@ module Bundler::URI
TBLDECWWWCOMP_['+'] = ' '
TBLDECWWWCOMP_.freeze
- # Encodes given +str+ to URL-encoded form data.
+ # Returns a URL-encoded string derived from the given string +str+.
+ #
+ # The returned string:
+ #
+ # - Preserves:
+ #
+ # - Characters <tt>'*'</tt>, <tt>'.'</tt>, <tt>'-'</tt>, and <tt>'_'</tt>.
+ # - Character in ranges <tt>'a'..'z'</tt>, <tt>'A'..'Z'</tt>,
+ # and <tt>'0'..'9'</tt>.
+ #
+ # Example:
#
- # This method doesn't convert *, -, ., 0-9, A-Z, _, a-z, but does convert SP
- # (ASCII space) to + and converts others to %XX.
+ # Bundler::URI.encode_www_form_component('*.-_azAZ09')
+ # # => "*.-_azAZ09"
#
- # If +enc+ is given, convert +str+ to the encoding before percent encoding.
+ # - Converts:
#
- # This is an implementation of
- # https://www.w3.org/TR/2013/CR-html5-20130806/forms.html#url-encoded-form-data.
+ # - Character <tt>' '</tt> to character <tt>'+'</tt>.
+ # - Any other character to "percent notation";
+ # the percent notation for character <i>c</i> is <tt>'%%%X' % c.ord</tt>.
#
- # See Bundler::URI.decode_www_form_component, Bundler::URI.encode_www_form.
+ # Example:
+ #
+ # Bundler::URI.encode_www_form_component('Here are some punctuation characters: ,;?:')
+ # # => "Here+are+some+punctuation+characters%3A+%2C%3B%3F%3A"
+ #
+ # Encoding:
+ #
+ # - If +str+ has encoding Encoding::ASCII_8BIT, argument +enc+ is ignored.
+ # - Otherwise +str+ is converted first to Encoding::UTF_8
+ # (with suitable character replacements),
+ # and then to encoding +enc+.
+ #
+ # In either case, the returned string has forced encoding Encoding::US_ASCII.
+ #
+ # Related: Bundler::URI.encode_uri_component (encodes <tt>' '</tt> as <tt>'%20'</tt>).
def self.encode_www_form_component(str, enc=nil)
_encode_uri_component(/[^*\-.0-9A-Z_a-z]/, TBLENCWWWCOMP_, str, enc)
end
- # Decodes given +str+ of URL-encoded form data.
+ # Returns a string decoded from the given \URL-encoded string +str+.
+ #
+ # The given string is first encoded as Encoding::ASCII-8BIT (using String#b),
+ # then decoded (as below), and finally force-encoded to the given encoding +enc+.
+ #
+ # The returned string:
+ #
+ # - Preserves:
+ #
+ # - Characters <tt>'*'</tt>, <tt>'.'</tt>, <tt>'-'</tt>, and <tt>'_'</tt>.
+ # - Character in ranges <tt>'a'..'z'</tt>, <tt>'A'..'Z'</tt>,
+ # and <tt>'0'..'9'</tt>.
+ #
+ # Example:
+ #
+ # Bundler::URI.decode_www_form_component('*.-_azAZ09')
+ # # => "*.-_azAZ09"
+ #
+ # - Converts:
+ #
+ # - Character <tt>'+'</tt> to character <tt>' '</tt>.
+ # - Each "percent notation" to an ASCII character.
#
- # This decodes + to SP.
+ # Example:
#
- # See Bundler::URI.encode_www_form_component, Bundler::URI.decode_www_form.
+ # Bundler::URI.decode_www_form_component('Here+are+some+punctuation+characters%3A+%2C%3B%3F%3A')
+ # # => "Here are some punctuation characters: ,;?:"
+ #
+ # Related: Bundler::URI.decode_uri_component (preserves <tt>'+'</tt>).
def self.decode_www_form_component(str, enc=Encoding::UTF_8)
_decode_uri_component(/\+|%\h\h/, str, enc)
end
- # Encodes +str+ using URL encoding
- #
- # This encodes SP to %20 instead of +.
+ # Like Bundler::URI.encode_www_form_component, except that <tt>' '</tt> (space)
+ # is encoded as <tt>'%20'</tt> (instead of <tt>'+'</tt>).
def self.encode_uri_component(str, enc=nil)
_encode_uri_component(/[^*\-.0-9A-Z_a-z]/, TBLENCURICOMP_, str, enc)
end
- # Decodes given +str+ of URL-encoded data.
- #
- # This does not decode + to SP.
+ # Like Bundler::URI.decode_www_form_component, except that <tt>'+'</tt> is preserved.
def self.decode_uri_component(str, enc=Encoding::UTF_8)
_decode_uri_component(/%\h\h/, str, enc)
end
@@ -372,33 +400,104 @@ module Bundler::URI
end
private_class_method :_decode_uri_component
- # Generates URL-encoded form data from given +enum+.
+ # Returns a URL-encoded string derived from the given
+ # {Enumerable}[rdoc-ref:Enumerable@Enumerable+in+Ruby+Classes]
+ # +enum+.
+ #
+ # The result is suitable for use as form data
+ # for an \HTTP request whose <tt>Content-Type</tt> is
+ # <tt>'application/x-www-form-urlencoded'</tt>.
+ #
+ # The returned string consists of the elements of +enum+,
+ # each converted to one or more URL-encoded strings,
+ # and all joined with character <tt>'&'</tt>.
+ #
+ # Simple examples:
+ #
+ # Bundler::URI.encode_www_form([['foo', 0], ['bar', 1], ['baz', 2]])
+ # # => "foo=0&bar=1&baz=2"
+ # Bundler::URI.encode_www_form({foo: 0, bar: 1, baz: 2})
+ # # => "foo=0&bar=1&baz=2"
+ #
+ # The returned string is formed using method Bundler::URI.encode_www_form_component,
+ # which converts certain characters:
+ #
+ # Bundler::URI.encode_www_form('f#o': '/', 'b-r': '$', 'b z': '@')
+ # # => "f%23o=%2F&b-r=%24&b+z=%40"
+ #
+ # When +enum+ is Array-like, each element +ele+ is converted to a field:
+ #
+ # - If +ele+ is an array of two or more elements,
+ # the field is formed from its first two elements
+ # (and any additional elements are ignored):
+ #
+ # name = Bundler::URI.encode_www_form_component(ele[0], enc)
+ # value = Bundler::URI.encode_www_form_component(ele[1], enc)
+ # "#{name}=#{value}"
#
- # This generates application/x-www-form-urlencoded data defined in HTML5
- # from given an Enumerable object.
+ # Examples:
#
- # This internally uses Bundler::URI.encode_www_form_component(str).
+ # Bundler::URI.encode_www_form([%w[foo bar], %w[baz bat bah]])
+ # # => "foo=bar&baz=bat"
+ # Bundler::URI.encode_www_form([['foo', 0], ['bar', :baz, 'bat']])
+ # # => "foo=0&bar=baz"
#
- # This method doesn't convert the encoding of given items, so convert them
- # before calling this method if you want to send data as other than original
- # encoding or mixed encoding data. (Strings which are encoded in an HTML5
- # ASCII incompatible encoding are converted to UTF-8.)
+ # - If +ele+ is an array of one element,
+ # the field is formed from <tt>ele[0]</tt>:
#
- # This method doesn't handle files. When you send a file, use
- # multipart/form-data.
+ # Bundler::URI.encode_www_form_component(ele[0])
#
- # This refers https://url.spec.whatwg.org/#concept-urlencoded-serializer
+ # Example:
#
- # Bundler::URI.encode_www_form([["q", "ruby"], ["lang", "en"]])
- # #=> "q=ruby&lang=en"
- # Bundler::URI.encode_www_form("q" => "ruby", "lang" => "en")
- # #=> "q=ruby&lang=en"
- # Bundler::URI.encode_www_form("q" => ["ruby", "perl"], "lang" => "en")
- # #=> "q=ruby&q=perl&lang=en"
- # Bundler::URI.encode_www_form([["q", "ruby"], ["q", "perl"], ["lang", "en"]])
- # #=> "q=ruby&q=perl&lang=en"
+ # Bundler::URI.encode_www_form([['foo'], [:bar], [0]])
+ # # => "foo&bar&0"
+ #
+ # - Otherwise the field is formed from +ele+:
+ #
+ # Bundler::URI.encode_www_form_component(ele)
+ #
+ # Example:
+ #
+ # Bundler::URI.encode_www_form(['foo', :bar, 0])
+ # # => "foo&bar&0"
+ #
+ # The elements of an Array-like +enum+ may be mixture:
+ #
+ # Bundler::URI.encode_www_form([['foo', 0], ['bar', 1, 2], ['baz'], :bat])
+ # # => "foo=0&bar=1&baz&bat"
+ #
+ # When +enum+ is Hash-like,
+ # each +key+/+value+ pair is converted to one or more fields:
+ #
+ # - If +value+ is
+ # {Array-convertible}[rdoc-ref:implicit_conversion.rdoc@Array-Convertible+Objects],
+ # each element +ele+ in +value+ is paired with +key+ to form a field:
+ #
+ # name = Bundler::URI.encode_www_form_component(key, enc)
+ # value = Bundler::URI.encode_www_form_component(ele, enc)
+ # "#{name}=#{value}"
+ #
+ # Example:
+ #
+ # Bundler::URI.encode_www_form({foo: [:bar, 1], baz: [:bat, :bam, 2]})
+ # # => "foo=bar&foo=1&baz=bat&baz=bam&baz=2"
+ #
+ # - Otherwise, +key+ and +value+ are paired to form a field:
+ #
+ # name = Bundler::URI.encode_www_form_component(key, enc)
+ # value = Bundler::URI.encode_www_form_component(value, enc)
+ # "#{name}=#{value}"
+ #
+ # Example:
+ #
+ # Bundler::URI.encode_www_form({foo: 0, bar: 1, baz: 2})
+ # # => "foo=0&bar=1&baz=2"
+ #
+ # The elements of a Hash-like +enum+ may be mixture:
+ #
+ # Bundler::URI.encode_www_form({foo: [0, 1], bar: 2})
+ # # => "foo=0&foo=1&bar=2"
#
- # See Bundler::URI.encode_www_form_component, Bundler::URI.decode_www_form.
def self.encode_www_form(enum, enc=nil)
enum.map do |k,v|
if v.nil?
@@ -419,22 +518,39 @@ module Bundler::URI
end.join('&')
end
- # Decodes URL-encoded form data from given +str+.
+ # Returns name/value pairs derived from the given string +str+,
+ # which must be an ASCII string.
+ #
+ # The method may be used to decode the body of Net::HTTPResponse object +res+
+ # for which <tt>res['Content-Type']</tt> is <tt>'application/x-www-form-urlencoded'</tt>.
+ #
+ # The returned data is an array of 2-element subarrays;
+ # each subarray is a name/value pair (both are strings).
+ # Each returned string has encoding +enc+,
+ # and has had invalid characters removed via
+ # {String#scrub}[rdoc-ref:String#scrub].
#
- # This decodes application/x-www-form-urlencoded data
- # and returns an array of key-value arrays.
+ # A simple example:
#
- # This refers http://url.spec.whatwg.org/#concept-urlencoded-parser,
- # so this supports only &-separator, and doesn't support ;-separator.
+ # Bundler::URI.decode_www_form('foo=0&bar=1&baz')
+ # # => [["foo", "0"], ["bar", "1"], ["baz", ""]]
#
- # ary = Bundler::URI.decode_www_form("a=1&a=2&b=3")
- # ary #=> [['a', '1'], ['a', '2'], ['b', '3']]
- # ary.assoc('a').last #=> '1'
- # ary.assoc('b').last #=> '3'
- # ary.rassoc('a').last #=> '2'
- # Hash[ary] #=> {"a"=>"2", "b"=>"3"}
+ # The returned strings have certain conversions,
+ # similar to those performed in Bundler::URI.decode_www_form_component:
+ #
+ # Bundler::URI.decode_www_form('f%23o=%2F&b-r=%24&b+z=%40')
+ # # => [["f#o", "/"], ["b-r", "$"], ["b z", "@"]]
+ #
+ # The given string may contain consecutive separators:
+ #
+ # Bundler::URI.decode_www_form('foo=0&&bar=1&&baz=2')
+ # # => [["foo", "0"], ["", ""], ["bar", "1"], ["", ""], ["baz", "2"]]
+ #
+ # A different separator may be specified:
+ #
+ # Bundler::URI.decode_www_form('foo=0--bar=1--baz', separator: '--')
+ # # => [["foo", "0"], ["bar", "1"], ["baz", ""]]
#
- # See Bundler::URI.decode_www_form_component, Bundler::URI.encode_www_form.
def self.decode_www_form(str, enc=Encoding::UTF_8, separator: '&', use__charset_: false, isindex: false)
raise ArgumentError, "the input of #{self.name}.#{__method__} must be ASCII only string" unless str.ascii_only?
ary = []
@@ -713,7 +829,15 @@ end # module Bundler::URI
module Bundler
#
- # Returns +uri+ converted to an Bundler::URI object.
+ # Returns a \Bundler::URI object derived from the given +uri+,
+ # which may be a \Bundler::URI string or an existing \Bundler::URI object:
+ #
+ # # Returns a new Bundler::URI.
+ # uri = Bundler::URI('http://github.com/ruby/ruby')
+ # # => #<Bundler::URI::HTTP http://github.com/ruby/ruby>
+ # # Returns the given Bundler::URI.
+ # Bundler::URI(uri)
+ # # => #<Bundler::URI::HTTP http://github.com/ruby/ruby>
#
def URI(uri)
if uri.is_a?(Bundler::URI::Generic)
diff --git a/lib/bundler/vendor/uri/lib/uri/generic.rb b/lib/bundler/vendor/uri/lib/uri/generic.rb
index 9ae6915826..762c425ac1 100644
--- a/lib/bundler/vendor/uri/lib/uri/generic.rb
+++ b/lib/bundler/vendor/uri/lib/uri/generic.rb
@@ -1376,6 +1376,7 @@ module Bundler::URI
end
str
end
+ alias to_str to_s
#
# Compares two URIs.
diff --git a/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb b/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb
index a85511c146..4c9882f595 100644
--- a/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb
+++ b/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb
@@ -1,9 +1,73 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
module Bundler::URI
class RFC3986_Parser # :nodoc:
# Bundler::URI defined in RFC3986
- RFC3986_URI = /\A(?<Bundler::URI>(?<scheme>[A-Za-z][+\-.0-9A-Za-z]*+):(?<hier-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*+)@)?(?<host>(?<IP-literal>\[(?:(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:)?\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h++\.[!$&-.0-;=A-Z_a-z~]++))\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])*+))(?::(?<port>\d*+))?)(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*+))*+)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])++)(?:\/\g<segment>)*+)?)|(?<path-rootless>\g<segment-nz>(?:\/\g<segment>)*+)|(?<path-empty>))(?:\?(?<query>[^#]*+))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*+))?)\z/
- RFC3986_relative_ref = /\A(?<relative-ref>(?<relative-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*+)@)?(?<host>(?<IP-literal>\[(?:(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:){,1}\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h++\.[!$&-.0-;=A-Z_a-z~]++))\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])++))?(?::(?<port>\d*+))?)(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*+))*+)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])++)(?:\/\g<segment>)*+)?)|(?<path-noscheme>(?<segment-nz-nc>(?:%\h\h|[!$&-.0-9;=@-Z_a-z~])++)(?:\/\g<segment>)*+)|(?<path-empty>))(?:\?(?<query>[^#]*+))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*+))?)\z/
+ HOST = %r[
+ (?<IP-literal>\[(?:
+ (?<IPv6address>
+ (?:\h{1,4}:){6}
+ (?<ls32>\h{1,4}:\h{1,4}
+ | (?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)
+ \.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>)
+ )
+ | ::(?:\h{1,4}:){5}\g<ls32>
+ | \h{1,4}?::(?:\h{1,4}:){4}\g<ls32>
+ | (?:(?:\h{1,4}:)?\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>
+ | (?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>
+ | (?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>
+ | (?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>
+ | (?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}
+ | (?:(?:\h{1,4}:){,6}\h{1,4})?::
+ )
+ | (?<IPvFuture>v\h++\.[!$&-.0-9:;=A-Z_a-z~]++)
+ )\])
+ | \g<IPv4address>
+ | (?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])*+)
+ ]x
+
+ USERINFO = /(?:%\h\h|[!$&-.0-9:;=A-Z_a-z~])*+/
+
+ SCHEME = %r[[A-Za-z][+\-.0-9A-Za-z]*+].source
+ SEG = %r[(?:%\h\h|[!$&-.0-9:;=@A-Z_a-z~/])].source
+ SEG_NC = %r[(?:%\h\h|[!$&-.0-9;=@A-Z_a-z~])].source
+ FRAGMENT = %r[(?:%\h\h|[!$&-.0-9:;=@A-Z_a-z~/?])*+].source
+
+ RFC3986_URI = %r[\A
+ (?<seg>#{SEG}){0}
+ (?<Bundler::URI>
+ (?<scheme>#{SCHEME}):
+ (?<hier-part>//
+ (?<authority>
+ (?:(?<userinfo>#{USERINFO.source})@)?
+ (?<host>#{HOST.source.delete(" \n")})
+ (?::(?<port>\d*+))?
+ )
+ (?<path-abempty>(?:/\g<seg>*+)?)
+ | (?<path-absolute>/((?!/)\g<seg>++)?)
+ | (?<path-rootless>(?!/)\g<seg>++)
+ | (?<path-empty>)
+ )
+ (?:\?(?<query>[^\#]*+))?
+ (?:\#(?<fragment>#{FRAGMENT}))?
+ )\z]x
+
+ RFC3986_relative_ref = %r[\A
+ (?<seg>#{SEG}){0}
+ (?<relative-ref>
+ (?<relative-part>//
+ (?<authority>
+ (?:(?<userinfo>#{USERINFO.source})@)?
+ (?<host>#{HOST.source.delete(" \n")}(?<!/))?
+ (?::(?<port>\d*+))?
+ )
+ (?<path-abempty>(?:/\g<seg>*+)?)
+ | (?<path-absolute>/\g<seg>*+)
+ | (?<path-noscheme>#{SEG_NC}++(?:/\g<seg>*+)?)
+ | (?<path-empty>)
+ )
+ (?:\?(?<query>[^#]*+))?
+ (?:\#(?<fragment>#{FRAGMENT}))?
+ )\z]x
attr_reader :regexp
def initialize
@@ -19,9 +83,9 @@ module Bundler::URI
uri.ascii_only? or
raise InvalidURIError, "Bundler::URI must be ascii only #{uri.dump}"
if m = RFC3986_URI.match(uri)
- query = m["query".freeze]
- scheme = m["scheme".freeze]
- opaque = m["path-rootless".freeze]
+ query = m["query"]
+ scheme = m["scheme"]
+ opaque = m["path-rootless"]
if opaque
opaque << "?#{query}" if query
[ scheme,
@@ -32,35 +96,35 @@ module Bundler::URI
nil, # path
opaque,
nil, # query
- m["fragment".freeze]
+ m["fragment"]
]
else # normal
[ scheme,
- m["userinfo".freeze],
- m["host".freeze],
- m["port".freeze],
+ m["userinfo"],
+ m["host"],
+ m["port"],
nil, # registry
- (m["path-abempty".freeze] ||
- m["path-absolute".freeze] ||
- m["path-empty".freeze]),
+ (m["path-abempty"] ||
+ m["path-absolute"] ||
+ m["path-empty"]),
nil, # opaque
query,
- m["fragment".freeze]
+ m["fragment"]
]
end
elsif m = RFC3986_relative_ref.match(uri)
[ nil, # scheme
- m["userinfo".freeze],
- m["host".freeze],
- m["port".freeze],
+ m["userinfo"],
+ m["host"],
+ m["port"],
nil, # registry,
- (m["path-abempty".freeze] ||
- m["path-absolute".freeze] ||
- m["path-noscheme".freeze] ||
- m["path-empty".freeze]),
+ (m["path-abempty"] ||
+ m["path-absolute"] ||
+ m["path-noscheme"] ||
+ m["path-empty"]),
nil, # opaque
- m["query".freeze],
- m["fragment".freeze]
+ m["query"],
+ m["fragment"]
]
else
raise InvalidURIError, "bad Bundler::URI(is not Bundler::URI?): #{uri.inspect}"
@@ -92,14 +156,14 @@ module Bundler::URI
def default_regexp # :nodoc:
{
- SCHEME: /\A[A-Za-z][A-Za-z0-9+\-.]*\z/,
- USERINFO: /\A(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*\z/,
- HOST: /\A(?:(?<IP-literal>\[(?:(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{,4}::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:)?\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h+\.[!$&-.0-;=A-Z_a-z~]+))\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])*))\z/,
- ABS_PATH: /\A\/(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*(?:\/(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*)*\z/,
- REL_PATH: /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~])+(?:\/(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*)*\z/,
- QUERY: /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*\z/,
- FRAGMENT: /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*\z/,
- OPAQUE: /\A(?:[^\/].*)?\z/,
+ SCHEME: %r[\A#{SCHEME}\z]o,
+ USERINFO: %r[\A#{USERINFO}\z]o,
+ HOST: %r[\A#{HOST}\z]o,
+ ABS_PATH: %r[\A/#{SEG}*+\z]o,
+ REL_PATH: %r[\A(?!/)#{SEG}++\z]o,
+ QUERY: %r[\A(?:%\h\h|[!$&-.0-9:;=@A-Z_a-z~/?])*+\z],
+ FRAGMENT: %r[\A#{FRAGMENT}\z]o,
+ OPAQUE: %r[\A(?:[^/].*)?\z],
PORT: /\A[\x09\x0a\x0c\x0d ]*+\d*[\x09\x0a\x0c\x0d ]*\z/,
}
end
diff --git a/lib/bundler/vendor/uri/lib/uri/version.rb b/lib/bundler/vendor/uri/lib/uri/version.rb
index 84b08eee30..1fa1c7c09a 100644
--- a/lib/bundler/vendor/uri/lib/uri/version.rb
+++ b/lib/bundler/vendor/uri/lib/uri/version.rb
@@ -1,6 +1,6 @@
module Bundler::URI
# :stopdoc:
- VERSION_CODE = '001202'.freeze
+ VERSION_CODE = '001300'.freeze
VERSION = VERSION_CODE.scan(/../).collect{|n| n.to_i}.join('.').freeze
# :startdoc:
end
diff --git a/lib/bundler/vendored_net_http.rb b/lib/bundler/vendored_net_http.rb
new file mode 100644
index 0000000000..0dcabaa7d7
--- /dev/null
+++ b/lib/bundler/vendored_net_http.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+begin
+ require "rubygems/vendored_net_http"
+rescue LoadError
+ begin
+ require "rubygems/net/http"
+ rescue LoadError
+ require "net/http"
+ Gem::Net = Net
+ end
+end
diff --git a/lib/bundler/vendored_persistent.rb b/lib/bundler/vendored_persistent.rb
index e29f27cdfd..ab985c267f 100644
--- a/lib/bundler/vendored_persistent.rb
+++ b/lib/bundler/vendored_persistent.rb
@@ -9,7 +9,3 @@ module Bundler
end
end
require_relative "vendor/net-http-persistent/lib/net/http/persistent"
-
-module Bundler
- PersistentHTTP = Persistent::Net::HTTP::Persistent
-end
diff --git a/lib/bundler/vendored_timeout.rb b/lib/bundler/vendored_timeout.rb
new file mode 100644
index 0000000000..9b2507c0cc
--- /dev/null
+++ b/lib/bundler/vendored_timeout.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+begin
+ require "rubygems/vendored_timeout"
+rescue LoadError
+ begin
+ require "rubygems/timeout"
+ rescue LoadError
+ require "timeout"
+ Gem::Timeout = Timeout
+ end
+end
diff --git a/lib/bundler/vendored_uri.rb b/lib/bundler/vendored_uri.rb
index 905e8158e8..2efddc65f9 100644
--- a/lib/bundler/vendored_uri.rb
+++ b/lib/bundler/vendored_uri.rb
@@ -1,4 +1,21 @@
# frozen_string_literal: true
module Bundler; end
-require_relative "vendor/uri/lib/uri"
+
+# Use RubyGems vendored copy when available. Otherwise fallback to Bundler
+# vendored copy. The vendored copy in Bundler can be removed once support for
+# RubyGems 3.5 is dropped.
+
+begin
+ require "rubygems/vendor/uri/lib/uri"
+rescue LoadError
+ require_relative "vendor/uri/lib/uri"
+ Gem::URI = Bundler::URI
+
+ module Gem
+ def URI(uri) # rubocop:disable Naming/MethodName
+ Bundler::URI(uri)
+ end
+ module_function :URI
+ end
+end
diff --git a/lib/bundler/version.rb b/lib/bundler/version.rb
index 7c03d8687f..f2f6236cda 100644
--- a/lib/bundler/version.rb
+++ b/lib/bundler/version.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
module Bundler
- VERSION = "2.5.0.dev".freeze
+ VERSION = "2.6.0.dev".freeze
def self.bundler_major_version
@bundler_major_version ||= VERSION.split(".").first.to_i
diff --git a/lib/bundler/vlad.rb b/lib/bundler/vlad.rb
index 538e8c3e74..6179d0e4eb 100644
--- a/lib/bundler/vlad.rb
+++ b/lib/bundler/vlad.rb
@@ -13,5 +13,5 @@ require_relative "deployment"
include Rake::DSL if defined? Rake::DSL
namespace :vlad do
- Bundler::Deployment.define_task(Rake::RemoteTask, :remote_task, :roles => :app)
+ Bundler::Deployment.define_task(Rake::RemoteTask, :remote_task, roles: :app)
end
diff --git a/lib/bundler/yaml_serializer.rb b/lib/bundler/yaml_serializer.rb
index ee01e44e82..93d08a05aa 100644
--- a/lib/bundler/yaml_serializer.rb
+++ b/lib/bundler/yaml_serializer.rb
@@ -55,10 +55,11 @@ module Bundler
stack = [res]
last_hash = nil
last_empty_key = nil
- str.split(/\r?\n/).each do |line|
+ str.split(/\r?\n/) do |line|
if match = HASH_REGEX.match(line)
indent, key, quote, val = match.captures
- convert_to_backward_compatible_key!(key)
+ val = strip_comment(val)
+
depth = indent.size / 2
if quote.empty? && val.empty?
new_hash = {}
@@ -72,6 +73,8 @@ module Bundler
end
elsif match = ARRAY_REGEX.match(line)
_, val = match.captures
+ val = strip_comment(val)
+
last_hash[last_empty_key] = [] unless last_hash[last_empty_key].is_a?(Array)
last_hash[last_empty_key].push(val)
@@ -80,14 +83,16 @@ module Bundler
res
end
- # for settings' keys
- def convert_to_backward_compatible_key!(key)
- key << "/" if /https?:/i.match?(key) && !%r{/\Z}.match?(key)
- key.gsub!(".", "__")
+ def strip_comment(val)
+ if val.include?("#") && !val.start_with?("#")
+ val.split("#", 2).first.strip
+ else
+ val
+ end
end
class << self
- private :dump_hash, :convert_to_backward_compatible_key!
+ private :dump_hash
end
end
end
diff --git a/lib/cgi.rb b/lib/cgi.rb
index faa00d0cae..7af85e7fc8 100644
--- a/lib/cgi.rb
+++ b/lib/cgi.rb
@@ -288,7 +288,7 @@
#
class CGI
- VERSION = "0.4.0"
+ VERSION = "0.4.1"
end
require 'cgi/core'
diff --git a/lib/csv.rb b/lib/csv.rb
deleted file mode 100644
index e8aa20ddd2..0000000000
--- a/lib/csv.rb
+++ /dev/null
@@ -1,2882 +0,0 @@
-# encoding: US-ASCII
-# frozen_string_literal: true
-# = csv.rb -- CSV Reading and Writing
-#
-# Created by James Edward Gray II on 2005-10-31.
-#
-# See CSV for documentation.
-#
-# == Description
-#
-# Welcome to the new and improved CSV.
-#
-# This version of the CSV library began its life as FasterCSV. FasterCSV was
-# intended as a replacement to Ruby's then standard CSV library. It was
-# designed to address concerns users of that library had and it had three
-# primary goals:
-#
-# 1. Be significantly faster than CSV while remaining a pure Ruby library.
-# 2. Use a smaller and easier to maintain code base. (FasterCSV eventually
-# grew larger, was also but considerably richer in features. The parsing
-# core remains quite small.)
-# 3. Improve on the CSV interface.
-#
-# Obviously, the last one is subjective. I did try to defer to the original
-# interface whenever I didn't have a compelling reason to change it though, so
-# hopefully this won't be too radically different.
-#
-# We must have met our goals because FasterCSV was renamed to CSV and replaced
-# the original library as of Ruby 1.9. If you are migrating code from 1.8 or
-# earlier, you may have to change your code to comply with the new interface.
-#
-# == What's the Different From the Old CSV?
-#
-# I'm sure I'll miss something, but I'll try to mention most of the major
-# differences I am aware of, to help others quickly get up to speed:
-#
-# === \CSV Parsing
-#
-# * This parser is m17n aware. See CSV for full details.
-# * This library has a stricter parser and will throw MalformedCSVErrors on
-# problematic data.
-# * This library has a less liberal idea of a line ending than CSV. What you
-# set as the <tt>:row_sep</tt> is law. It can auto-detect your line endings
-# though.
-# * The old library returned empty lines as <tt>[nil]</tt>. This library calls
-# them <tt>[]</tt>.
-# * This library has a much faster parser.
-#
-# === Interface
-#
-# * CSV now uses keyword parameters to set options.
-# * CSV no longer has generate_row() or parse_row().
-# * The old CSV's Reader and Writer classes have been dropped.
-# * CSV::open() is now more like Ruby's open().
-# * CSV objects now support most standard IO methods.
-# * CSV now has a new() method used to wrap objects like String and IO for
-# reading and writing.
-# * CSV::generate() is different from the old method.
-# * CSV no longer supports partial reads. It works line-by-line.
-# * CSV no longer allows the instance methods to override the separators for
-# performance reasons. They must be set in the constructor.
-#
-# If you use this library and find yourself missing any functionality I have
-# trimmed, please {let me know}[mailto:james@grayproductions.net].
-#
-# == Documentation
-#
-# See CSV for documentation.
-#
-# == What is CSV, really?
-#
-# CSV maintains a pretty strict definition of CSV taken directly from
-# {the RFC}[https://www.ietf.org/rfc/rfc4180.txt]. I relax the rules in only one
-# place and that is to make using this library easier. CSV will parse all valid
-# CSV.
-#
-# What you don't want to do is to feed CSV invalid data. Because of the way the
-# CSV format works, it's common for a parser to need to read until the end of
-# the file to be sure a field is invalid. This consumes a lot of time and memory.
-#
-# Luckily, when working with invalid CSV, Ruby's built-in methods will almost
-# always be superior in every way. For example, parsing non-quoted fields is as
-# easy as:
-#
-# data.split(",")
-#
-# == Questions and/or Comments
-#
-# Feel free to email {James Edward Gray II}[mailto:james@grayproductions.net]
-# with any questions.
-
-require "forwardable"
-require "date"
-require "stringio"
-
-require_relative "csv/fields_converter"
-require_relative "csv/input_record_separator"
-require_relative "csv/parser"
-require_relative "csv/row"
-require_relative "csv/table"
-require_relative "csv/writer"
-
-# == \CSV
-#
-# === \CSV Data
-#
-# \CSV (comma-separated values) data is a text representation of a table:
-# - A _row_ _separator_ delimits table rows.
-# A common row separator is the newline character <tt>"\n"</tt>.
-# - A _column_ _separator_ delimits fields in a row.
-# A common column separator is the comma character <tt>","</tt>.
-#
-# This \CSV \String, with row separator <tt>"\n"</tt>
-# and column separator <tt>","</tt>,
-# has three rows and two columns:
-# "foo,0\nbar,1\nbaz,2\n"
-#
-# Despite the name \CSV, a \CSV representation can use different separators.
-#
-# For more about tables, see the Wikipedia article
-# "{Table (information)}[https://en.wikipedia.org/wiki/Table_(information)]",
-# especially its section
-# "{Simple table}[https://en.wikipedia.org/wiki/Table_(information)#Simple_table]"
-#
-# == \Class \CSV
-#
-# Class \CSV provides methods for:
-# - Parsing \CSV data from a \String object, a \File (via its file path), or an \IO object.
-# - Generating \CSV data to a \String object.
-#
-# To make \CSV available:
-# require 'csv'
-#
-# All examples here assume that this has been done.
-#
-# == Keeping It Simple
-#
-# A \CSV object has dozens of instance methods that offer fine-grained control
-# of parsing and generating \CSV data.
-# For many needs, though, simpler approaches will do.
-#
-# This section summarizes the singleton methods in \CSV
-# that allow you to parse and generate without explicitly
-# creating \CSV objects.
-# For details, follow the links.
-#
-# === Simple Parsing
-#
-# Parsing methods commonly return either of:
-# - An \Array of Arrays of Strings:
-# - The outer \Array is the entire "table".
-# - Each inner \Array is a row.
-# - Each \String is a field.
-# - A CSV::Table object. For details, see
-# {\CSV with Headers}[#class-CSV-label-CSV+with+Headers].
-#
-# ==== Parsing a \String
-#
-# The input to be parsed can be a string:
-# string = "foo,0\nbar,1\nbaz,2\n"
-#
-# \Method CSV.parse returns the entire \CSV data:
-# CSV.parse(string) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
-#
-# \Method CSV.parse_line returns only the first row:
-# CSV.parse_line(string) # => ["foo", "0"]
-#
-# \CSV extends class \String with instance method String#parse_csv,
-# which also returns only the first row:
-# string.parse_csv # => ["foo", "0"]
-#
-# ==== Parsing Via a \File Path
-#
-# The input to be parsed can be in a file:
-# string = "foo,0\nbar,1\nbaz,2\n"
-# path = 't.csv'
-# File.write(path, string)
-#
-# \Method CSV.read returns the entire \CSV data:
-# CSV.read(path) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
-#
-# \Method CSV.foreach iterates, passing each row to the given block:
-# CSV.foreach(path) do |row|
-# p row
-# end
-# Output:
-# ["foo", "0"]
-# ["bar", "1"]
-# ["baz", "2"]
-#
-# \Method CSV.table returns the entire \CSV data as a CSV::Table object:
-# CSV.table(path) # => #<CSV::Table mode:col_or_row row_count:3>
-#
-# ==== Parsing from an Open \IO Stream
-#
-# The input to be parsed can be in an open \IO stream:
-#
-# \Method CSV.read returns the entire \CSV data:
-# File.open(path) do |file|
-# CSV.read(file)
-# end # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
-#
-# As does method CSV.parse:
-# File.open(path) do |file|
-# CSV.parse(file)
-# end # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
-#
-# \Method CSV.parse_line returns only the first row:
-# File.open(path) do |file|
-# CSV.parse_line(file)
-# end # => ["foo", "0"]
-#
-# \Method CSV.foreach iterates, passing each row to the given block:
-# File.open(path) do |file|
-# CSV.foreach(file) do |row|
-# p row
-# end
-# end
-# Output:
-# ["foo", "0"]
-# ["bar", "1"]
-# ["baz", "2"]
-#
-# \Method CSV.table returns the entire \CSV data as a CSV::Table object:
-# File.open(path) do |file|
-# CSV.table(file)
-# end # => #<CSV::Table mode:col_or_row row_count:3>
-#
-# === Simple Generating
-#
-# \Method CSV.generate returns a \String;
-# this example uses method CSV#<< to append the rows
-# that are to be generated:
-# output_string = CSV.generate do |csv|
-# csv << ['foo', 0]
-# csv << ['bar', 1]
-# csv << ['baz', 2]
-# end
-# output_string # => "foo,0\nbar,1\nbaz,2\n"
-#
-# \Method CSV.generate_line returns a \String containing the single row
-# constructed from an \Array:
-# CSV.generate_line(['foo', '0']) # => "foo,0\n"
-#
-# \CSV extends class \Array with instance method <tt>Array#to_csv</tt>,
-# which forms an \Array into a \String:
-# ['foo', '0'].to_csv # => "foo,0\n"
-#
-# === "Filtering" \CSV
-#
-# \Method CSV.filter provides a Unix-style filter for \CSV data.
-# The input data is processed to form the output data:
-# in_string = "foo,0\nbar,1\nbaz,2\n"
-# out_string = ''
-# CSV.filter(in_string, out_string) do |row|
-# row[0] = row[0].upcase
-# row[1] *= 4
-# end
-# out_string # => "FOO,0000\nBAR,1111\nBAZ,2222\n"
-#
-# == \CSV Objects
-#
-# There are three ways to create a \CSV object:
-# - \Method CSV.new returns a new \CSV object.
-# - \Method CSV.instance returns a new or cached \CSV object.
-# - \Method \CSV() also returns a new or cached \CSV object.
-#
-# === Instance Methods
-#
-# \CSV has three groups of instance methods:
-# - Its own internally defined instance methods.
-# - Methods included by module Enumerable.
-# - Methods delegated to class IO. See below.
-#
-# ==== Delegated Methods
-#
-# For convenience, a CSV object will delegate to many methods in class IO.
-# (A few have wrapper "guard code" in \CSV.) You may call:
-# * IO#binmode
-# * #binmode?
-# * IO#close
-# * IO#close_read
-# * IO#close_write
-# * IO#closed?
-# * #eof
-# * #eof?
-# * IO#external_encoding
-# * IO#fcntl
-# * IO#fileno
-# * #flock
-# * IO#flush
-# * IO#fsync
-# * IO#internal_encoding
-# * #ioctl
-# * IO#isatty
-# * #path
-# * IO#pid
-# * IO#pos
-# * IO#pos=
-# * IO#reopen
-# * #rewind
-# * IO#seek
-# * #stat
-# * IO#string
-# * IO#sync
-# * IO#sync=
-# * IO#tell
-# * #to_i
-# * #to_io
-# * IO#truncate
-# * IO#tty?
-#
-# === Options
-#
-# The default values for options are:
-# DEFAULT_OPTIONS = {
-# # For both parsing and generating.
-# col_sep: ",",
-# row_sep: :auto,
-# quote_char: '"',
-# # For parsing.
-# field_size_limit: nil,
-# converters: nil,
-# unconverted_fields: nil,
-# headers: false,
-# return_headers: false,
-# header_converters: nil,
-# skip_blanks: false,
-# skip_lines: nil,
-# liberal_parsing: false,
-# nil_value: nil,
-# empty_value: "",
-# strip: false,
-# # For generating.
-# write_headers: nil,
-# quote_empty: true,
-# force_quotes: false,
-# write_converters: nil,
-# write_nil_value: nil,
-# write_empty_value: "",
-# }
-#
-# ==== Options for Parsing
-#
-# Options for parsing, described in detail below, include:
-# - +row_sep+: Specifies the row separator; used to delimit rows.
-# - +col_sep+: Specifies the column separator; used to delimit fields.
-# - +quote_char+: Specifies the quote character; used to quote fields.
-# - +field_size_limit+: Specifies the maximum field size + 1 allowed.
-# Deprecated since 3.2.3. Use +max_field_size+ instead.
-# - +max_field_size+: Specifies the maximum field size allowed.
-# - +converters+: Specifies the field converters to be used.
-# - +unconverted_fields+: Specifies whether unconverted fields are to be available.
-# - +headers+: Specifies whether data contains headers,
-# or specifies the headers themselves.
-# - +return_headers+: Specifies whether headers are to be returned.
-# - +header_converters+: Specifies the header converters to be used.
-# - +skip_blanks+: Specifies whether blanks lines are to be ignored.
-# - +skip_lines+: Specifies how comments lines are to be recognized.
-# - +strip+: Specifies whether leading and trailing whitespace are to be
-# stripped from fields. This must be compatible with +col_sep+; if it is not,
-# then an +ArgumentError+ exception will be raised.
-# - +liberal_parsing+: Specifies whether \CSV should attempt to parse
-# non-compliant data.
-# - +nil_value+: Specifies the object that is to be substituted for each null (no-text) field.
-# - +empty_value+: Specifies the object that is to be substituted for each empty field.
-#
-# :include: ../doc/csv/options/common/row_sep.rdoc
-#
-# :include: ../doc/csv/options/common/col_sep.rdoc
-#
-# :include: ../doc/csv/options/common/quote_char.rdoc
-#
-# :include: ../doc/csv/options/parsing/field_size_limit.rdoc
-#
-# :include: ../doc/csv/options/parsing/converters.rdoc
-#
-# :include: ../doc/csv/options/parsing/unconverted_fields.rdoc
-#
-# :include: ../doc/csv/options/parsing/headers.rdoc
-#
-# :include: ../doc/csv/options/parsing/return_headers.rdoc
-#
-# :include: ../doc/csv/options/parsing/header_converters.rdoc
-#
-# :include: ../doc/csv/options/parsing/skip_blanks.rdoc
-#
-# :include: ../doc/csv/options/parsing/skip_lines.rdoc
-#
-# :include: ../doc/csv/options/parsing/strip.rdoc
-#
-# :include: ../doc/csv/options/parsing/liberal_parsing.rdoc
-#
-# :include: ../doc/csv/options/parsing/nil_value.rdoc
-#
-# :include: ../doc/csv/options/parsing/empty_value.rdoc
-#
-# ==== Options for Generating
-#
-# Options for generating, described in detail below, include:
-# - +row_sep+: Specifies the row separator; used to delimit rows.
-# - +col_sep+: Specifies the column separator; used to delimit fields.
-# - +quote_char+: Specifies the quote character; used to quote fields.
-# - +write_headers+: Specifies whether headers are to be written.
-# - +force_quotes+: Specifies whether each output field is to be quoted.
-# - +quote_empty+: Specifies whether each empty output field is to be quoted.
-# - +write_converters+: Specifies the field converters to be used in writing.
-# - +write_nil_value+: Specifies the object that is to be substituted for each +nil+-valued field.
-# - +write_empty_value+: Specifies the object that is to be substituted for each empty field.
-#
-# :include: ../doc/csv/options/common/row_sep.rdoc
-#
-# :include: ../doc/csv/options/common/col_sep.rdoc
-#
-# :include: ../doc/csv/options/common/quote_char.rdoc
-#
-# :include: ../doc/csv/options/generating/write_headers.rdoc
-#
-# :include: ../doc/csv/options/generating/force_quotes.rdoc
-#
-# :include: ../doc/csv/options/generating/quote_empty.rdoc
-#
-# :include: ../doc/csv/options/generating/write_converters.rdoc
-#
-# :include: ../doc/csv/options/generating/write_nil_value.rdoc
-#
-# :include: ../doc/csv/options/generating/write_empty_value.rdoc
-#
-# === \CSV with Headers
-#
-# CSV allows to specify column names of CSV file, whether they are in data, or
-# provided separately. If headers are specified, reading methods return an instance
-# of CSV::Table, consisting of CSV::Row.
-#
-# # Headers are part of data
-# data = CSV.parse(<<~ROWS, headers: true)
-# Name,Department,Salary
-# Bob,Engineering,1000
-# Jane,Sales,2000
-# John,Management,5000
-# ROWS
-#
-# data.class #=> CSV::Table
-# data.first #=> #<CSV::Row "Name":"Bob" "Department":"Engineering" "Salary":"1000">
-# data.first.to_h #=> {"Name"=>"Bob", "Department"=>"Engineering", "Salary"=>"1000"}
-#
-# # Headers provided by developer
-# data = CSV.parse('Bob,Engineering,1000', headers: %i[name department salary])
-# data.first #=> #<CSV::Row name:"Bob" department:"Engineering" salary:"1000">
-#
-# === \Converters
-#
-# By default, each value (field or header) parsed by \CSV is formed into a \String.
-# You can use a _field_ _converter_ or _header_ _converter_
-# to intercept and modify the parsed values:
-# - See {Field Converters}[#class-CSV-label-Field+Converters].
-# - See {Header Converters}[#class-CSV-label-Header+Converters].
-#
-# Also by default, each value to be written during generation is written 'as-is'.
-# You can use a _write_ _converter_ to modify values before writing.
-# - See {Write Converters}[#class-CSV-label-Write+Converters].
-#
-# ==== Specifying \Converters
-#
-# You can specify converters for parsing or generating in the +options+
-# argument to various \CSV methods:
-# - Option +converters+ for converting parsed field values.
-# - Option +header_converters+ for converting parsed header values.
-# - Option +write_converters+ for converting values to be written (generated).
-#
-# There are three forms for specifying converters:
-# - A converter proc: executable code to be used for conversion.
-# - A converter name: the name of a stored converter.
-# - A converter list: an array of converter procs, converter names, and converter lists.
-#
-# ===== Converter Procs
-#
-# This converter proc, +strip_converter+, accepts a value +field+
-# and returns <tt>field.strip</tt>:
-# strip_converter = proc {|field| field.strip }
-# In this call to <tt>CSV.parse</tt>,
-# the keyword argument <tt>converters: string_converter</tt>
-# specifies that:
-# - \Proc +string_converter+ is to be called for each parsed field.
-# - The converter's return value is to replace the +field+ value.
-# Example:
-# string = " foo , 0 \n bar , 1 \n baz , 2 \n"
-# array = CSV.parse(string, converters: strip_converter)
-# array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
-#
-# A converter proc can receive a second argument, +field_info+,
-# that contains details about the field.
-# This modified +strip_converter+ displays its arguments:
-# strip_converter = proc do |field, field_info|
-# p [field, field_info]
-# field.strip
-# end
-# string = " foo , 0 \n bar , 1 \n baz , 2 \n"
-# array = CSV.parse(string, converters: strip_converter)
-# array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
-# Output:
-# [" foo ", #<struct CSV::FieldInfo index=0, line=1, header=nil>]
-# [" 0 ", #<struct CSV::FieldInfo index=1, line=1, header=nil>]
-# [" bar ", #<struct CSV::FieldInfo index=0, line=2, header=nil>]
-# [" 1 ", #<struct CSV::FieldInfo index=1, line=2, header=nil>]
-# [" baz ", #<struct CSV::FieldInfo index=0, line=3, header=nil>]
-# [" 2 ", #<struct CSV::FieldInfo index=1, line=3, header=nil>]
-# Each CSV::FieldInfo object shows:
-# - The 0-based field index.
-# - The 1-based line index.
-# - The field header, if any.
-#
-# ===== Stored \Converters
-#
-# A converter may be given a name and stored in a structure where
-# the parsing methods can find it by name.
-#
-# The storage structure for field converters is the \Hash CSV::Converters.
-# It has several built-in converter procs:
-# - <tt>:integer</tt>: converts each \String-embedded integer into a true \Integer.
-# - <tt>:float</tt>: converts each \String-embedded float into a true \Float.
-# - <tt>:date</tt>: converts each \String-embedded date into a true \Date.
-# - <tt>:date_time</tt>: converts each \String-embedded date-time into a true \DateTime
-# .
-# This example creates a converter proc, then stores it:
-# strip_converter = proc {|field| field.strip }
-# CSV::Converters[:strip] = strip_converter
-# Then the parsing method call can refer to the converter
-# by its name, <tt>:strip</tt>:
-# string = " foo , 0 \n bar , 1 \n baz , 2 \n"
-# array = CSV.parse(string, converters: :strip)
-# array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
-#
-# The storage structure for header converters is the \Hash CSV::HeaderConverters,
-# which works in the same way.
-# It also has built-in converter procs:
-# - <tt>:downcase</tt>: Downcases each header.
-# - <tt>:symbol</tt>: Converts each header to a \Symbol.
-#
-# There is no such storage structure for write headers.
-#
-# In order for the parsing methods to access stored converters in non-main-Ractors, the
-# storage structure must be made shareable first.
-# Therefore, <tt>Ractor.make_shareable(CSV::Converters)</tt> and
-# <tt>Ractor.make_shareable(CSV::HeaderConverters)</tt> must be called before the creation
-# of Ractors that use the converters stored in these structures. (Since making the storage
-# structures shareable involves freezing them, any custom converters that are to be used
-# must be added first.)
-#
-# ===== Converter Lists
-#
-# A _converter_ _list_ is an \Array that may include any assortment of:
-# - Converter procs.
-# - Names of stored converters.
-# - Nested converter lists.
-#
-# Examples:
-# numeric_converters = [:integer, :float]
-# date_converters = [:date, :date_time]
-# [numeric_converters, strip_converter]
-# [strip_converter, date_converters, :float]
-#
-# Like a converter proc, a converter list may be named and stored in either
-# \CSV::Converters or CSV::HeaderConverters:
-# CSV::Converters[:custom] = [strip_converter, date_converters, :float]
-# CSV::HeaderConverters[:custom] = [:downcase, :symbol]
-#
-# There are two built-in converter lists:
-# CSV::Converters[:numeric] # => [:integer, :float]
-# CSV::Converters[:all] # => [:date_time, :numeric]
-#
-# ==== Field \Converters
-#
-# With no conversion, all parsed fields in all rows become Strings:
-# string = "foo,0\nbar,1\nbaz,2\n"
-# ary = CSV.parse(string)
-# ary # => # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
-#
-# When you specify a field converter, each parsed field is passed to the converter;
-# its return value becomes the stored value for the field.
-# A converter might, for example, convert an integer embedded in a \String
-# into a true \Integer.
-# (In fact, that's what built-in field converter +:integer+ does.)
-#
-# There are three ways to use field \converters.
-#
-# - Using option {converters}[#class-CSV-label-Option+converters] with a parsing method:
-# ary = CSV.parse(string, converters: :integer)
-# ary # => [0, 1, 2] # => [["foo", 0], ["bar", 1], ["baz", 2]]
-# - Using option {converters}[#class-CSV-label-Option+converters] with a new \CSV instance:
-# csv = CSV.new(string, converters: :integer)
-# # Field converters in effect:
-# csv.converters # => [:integer]
-# csv.read # => [["foo", 0], ["bar", 1], ["baz", 2]]
-# - Using method #convert to add a field converter to a \CSV instance:
-# csv = CSV.new(string)
-# # Add a converter.
-# csv.convert(:integer)
-# csv.converters # => [:integer]
-# csv.read # => [["foo", 0], ["bar", 1], ["baz", 2]]
-#
-# Installing a field converter does not affect already-read rows:
-# csv = CSV.new(string)
-# csv.shift # => ["foo", "0"]
-# # Add a converter.
-# csv.convert(:integer)
-# csv.converters # => [:integer]
-# csv.read # => [["bar", 1], ["baz", 2]]
-#
-# There are additional built-in \converters, and custom \converters are also supported.
-#
-# ===== Built-In Field \Converters
-#
-# The built-in field converters are in \Hash CSV::Converters:
-# - Each key is a field converter name.
-# - Each value is one of:
-# - A \Proc field converter.
-# - An \Array of field converter names.
-#
-# Display:
-# CSV::Converters.each_pair do |name, value|
-# if value.kind_of?(Proc)
-# p [name, value.class]
-# else
-# p [name, value]
-# end
-# end
-# Output:
-# [:integer, Proc]
-# [:float, Proc]
-# [:numeric, [:integer, :float]]
-# [:date, Proc]
-# [:date_time, Proc]
-# [:all, [:date_time, :numeric]]
-#
-# Each of these converters transcodes values to UTF-8 before attempting conversion.
-# If a value cannot be transcoded to UTF-8 the conversion will
-# fail and the value will remain unconverted.
-#
-# Converter +:integer+ converts each field that Integer() accepts:
-# data = '0,1,2,x'
-# # Without the converter
-# csv = CSV.parse_line(data)
-# csv # => ["0", "1", "2", "x"]
-# # With the converter
-# csv = CSV.parse_line(data, converters: :integer)
-# csv # => [0, 1, 2, "x"]
-#
-# Converter +:float+ converts each field that Float() accepts:
-# data = '1.0,3.14159,x'
-# # Without the converter
-# csv = CSV.parse_line(data)
-# csv # => ["1.0", "3.14159", "x"]
-# # With the converter
-# csv = CSV.parse_line(data, converters: :float)
-# csv # => [1.0, 3.14159, "x"]
-#
-# Converter +:numeric+ converts with both +:integer+ and +:float+..
-#
-# Converter +:date+ converts each field that Date::parse accepts:
-# data = '2001-02-03,x'
-# # Without the converter
-# csv = CSV.parse_line(data)
-# csv # => ["2001-02-03", "x"]
-# # With the converter
-# csv = CSV.parse_line(data, converters: :date)
-# csv # => [#<Date: 2001-02-03 ((2451944j,0s,0n),+0s,2299161j)>, "x"]
-#
-# Converter +:date_time+ converts each field that DateTime::parse accepts:
-# data = '2020-05-07T14:59:00-05:00,x'
-# # Without the converter
-# csv = CSV.parse_line(data)
-# csv # => ["2020-05-07T14:59:00-05:00", "x"]
-# # With the converter
-# csv = CSV.parse_line(data, converters: :date_time)
-# csv # => [#<DateTime: 2020-05-07T14:59:00-05:00 ((2458977j,71940s,0n),-18000s,2299161j)>, "x"]
-#
-# Converter +:numeric+ converts with both +:date_time+ and +:numeric+..
-#
-# As seen above, method #convert adds \converters to a \CSV instance,
-# and method #converters returns an \Array of the \converters in effect:
-# csv = CSV.new('0,1,2')
-# csv.converters # => []
-# csv.convert(:integer)
-# csv.converters # => [:integer]
-# csv.convert(:date)
-# csv.converters # => [:integer, :date]
-#
-# ===== Custom Field \Converters
-#
-# You can define a custom field converter:
-# strip_converter = proc {|field| field.strip }
-# string = " foo , 0 \n bar , 1 \n baz , 2 \n"
-# array = CSV.parse(string, converters: strip_converter)
-# array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
-# You can register the converter in \Converters \Hash,
-# which allows you to refer to it by name:
-# CSV::Converters[:strip] = strip_converter
-# string = " foo , 0 \n bar , 1 \n baz , 2 \n"
-# array = CSV.parse(string, converters: :strip)
-# array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
-#
-# ==== Header \Converters
-#
-# Header converters operate only on headers (and not on other rows).
-#
-# There are three ways to use header \converters;
-# these examples use built-in header converter +:downcase+,
-# which downcases each parsed header.
-#
-# - Option +header_converters+ with a singleton parsing method:
-# string = "Name,Count\nFoo,0\n,Bar,1\nBaz,2"
-# tbl = CSV.parse(string, headers: true, header_converters: :downcase)
-# tbl.class # => CSV::Table
-# tbl.headers # => ["name", "count"]
-#
-# - Option +header_converters+ with a new \CSV instance:
-# csv = CSV.new(string, header_converters: :downcase)
-# # Header converters in effect:
-# csv.header_converters # => [:downcase]
-# tbl = CSV.parse(string, headers: true)
-# tbl.headers # => ["Name", "Count"]
-#
-# - Method #header_convert adds a header converter to a \CSV instance:
-# csv = CSV.new(string)
-# # Add a header converter.
-# csv.header_convert(:downcase)
-# csv.header_converters # => [:downcase]
-# tbl = CSV.parse(string, headers: true)
-# tbl.headers # => ["Name", "Count"]
-#
-# ===== Built-In Header \Converters
-#
-# The built-in header \converters are in \Hash CSV::HeaderConverters.
-# The keys there are the names of the \converters:
-# CSV::HeaderConverters.keys # => [:downcase, :symbol]
-#
-# Converter +:downcase+ converts each header by downcasing it:
-# string = "Name,Count\nFoo,0\n,Bar,1\nBaz,2"
-# tbl = CSV.parse(string, headers: true, header_converters: :downcase)
-# tbl.class # => CSV::Table
-# tbl.headers # => ["name", "count"]
-#
-# Converter +:symbol+ converts each header by making it into a \Symbol:
-# string = "Name,Count\nFoo,0\n,Bar,1\nBaz,2"
-# tbl = CSV.parse(string, headers: true, header_converters: :symbol)
-# tbl.headers # => [:name, :count]
-# Details:
-# - Strips leading and trailing whitespace.
-# - Downcases the header.
-# - Replaces embedded spaces with underscores.
-# - Removes non-word characters.
-# - Makes the string into a \Symbol.
-#
-# ===== Custom Header \Converters
-#
-# You can define a custom header converter:
-# upcase_converter = proc {|header| header.upcase }
-# string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
-# table = CSV.parse(string, headers: true, header_converters: upcase_converter)
-# table # => #<CSV::Table mode:col_or_row row_count:4>
-# table.headers # => ["NAME", "VALUE"]
-# You can register the converter in \HeaderConverters \Hash,
-# which allows you to refer to it by name:
-# CSV::HeaderConverters[:upcase] = upcase_converter
-# table = CSV.parse(string, headers: true, header_converters: :upcase)
-# table # => #<CSV::Table mode:col_or_row row_count:4>
-# table.headers # => ["NAME", "VALUE"]
-#
-# ===== Write \Converters
-#
-# When you specify a write converter for generating \CSV,
-# each field to be written is passed to the converter;
-# its return value becomes the new value for the field.
-# A converter might, for example, strip whitespace from a field.
-#
-# Using no write converter (all fields unmodified):
-# output_string = CSV.generate do |csv|
-# csv << [' foo ', 0]
-# csv << [' bar ', 1]
-# csv << [' baz ', 2]
-# end
-# output_string # => " foo ,0\n bar ,1\n baz ,2\n"
-# Using option +write_converters+ with two custom write converters:
-# strip_converter = proc {|field| field.respond_to?(:strip) ? field.strip : field }
-# upcase_converter = proc {|field| field.respond_to?(:upcase) ? field.upcase : field }
-# write_converters = [strip_converter, upcase_converter]
-# output_string = CSV.generate(write_converters: write_converters) do |csv|
-# csv << [' foo ', 0]
-# csv << [' bar ', 1]
-# csv << [' baz ', 2]
-# end
-# output_string # => "FOO,0\nBAR,1\nBAZ,2\n"
-#
-# === Character Encodings (M17n or Multilingualization)
-#
-# This new CSV parser is m17n savvy. The parser works in the Encoding of the IO
-# or String object being read from or written to. Your data is never transcoded
-# (unless you ask Ruby to transcode it for you) and will literally be parsed in
-# the Encoding it is in. Thus CSV will return Arrays or Rows of Strings in the
-# Encoding of your data. This is accomplished by transcoding the parser itself
-# into your Encoding.
-#
-# Some transcoding must take place, of course, to accomplish this multiencoding
-# support. For example, <tt>:col_sep</tt>, <tt>:row_sep</tt>, and
-# <tt>:quote_char</tt> must be transcoded to match your data. Hopefully this
-# makes the entire process feel transparent, since CSV's defaults should just
-# magically work for your data. However, you can set these values manually in
-# the target Encoding to avoid the translation.
-#
-# It's also important to note that while all of CSV's core parser is now
-# Encoding agnostic, some features are not. For example, the built-in
-# converters will try to transcode data to UTF-8 before making conversions.
-# Again, you can provide custom converters that are aware of your Encodings to
-# avoid this translation. It's just too hard for me to support native
-# conversions in all of Ruby's Encodings.
-#
-# Anyway, the practical side of this is simple: make sure IO and String objects
-# passed into CSV have the proper Encoding set and everything should just work.
-# CSV methods that allow you to open IO objects (CSV::foreach(), CSV::open(),
-# CSV::read(), and CSV::readlines()) do allow you to specify the Encoding.
-#
-# One minor exception comes when generating CSV into a String with an Encoding
-# that is not ASCII compatible. There's no existing data for CSV to use to
-# prepare itself and thus you will probably need to manually specify the desired
-# Encoding for most of those cases. It will try to guess using the fields in a
-# row of output though, when using CSV::generate_line() or Array#to_csv().
-#
-# I try to point out any other Encoding issues in the documentation of methods
-# as they come up.
-#
-# This has been tested to the best of my ability with all non-"dummy" Encodings
-# Ruby ships with. However, it is brave new code and may have some bugs.
-# Please feel free to {report}[mailto:james@grayproductions.net] any issues you
-# find with it.
-#
-class CSV
-
- # The error thrown when the parser encounters illegal CSV formatting.
- class MalformedCSVError < RuntimeError
- attr_reader :line_number
- alias_method :lineno, :line_number
- def initialize(message, line_number)
- @line_number = line_number
- super("#{message} in line #{line_number}.")
- end
- end
-
- # The error thrown when the parser encounters invalid encoding in CSV.
- class InvalidEncodingError < MalformedCSVError
- attr_reader :encoding
- def initialize(encoding, line_number)
- @encoding = encoding
- super("Invalid byte sequence in #{encoding}", line_number)
- end
- end
-
- #
- # A FieldInfo Struct contains details about a field's position in the data
- # source it was read from. CSV will pass this Struct to some blocks that make
- # decisions based on field structure. See CSV.convert_fields() for an
- # example.
- #
- # <b><tt>index</tt></b>:: The zero-based index of the field in its row.
- # <b><tt>line</tt></b>:: The line of the data source this row is from.
- # <b><tt>header</tt></b>:: The header for the column, when available.
- # <b><tt>quoted?</tt></b>:: True or false, whether the original value is quoted or not.
- #
- FieldInfo = Struct.new(:index, :line, :header, :quoted?)
-
- # A Regexp used to find and convert some common Date formats.
- DateMatcher = / \A(?: (\w+,?\s+)?\w+\s+\d{1,2},?\s+\d{2,4} |
- \d{4}-\d{2}-\d{2} )\z /x
- # A Regexp used to find and convert some common DateTime formats.
- DateTimeMatcher =
- / \A(?: (\w+,?\s+)?\w+\s+\d{1,2}\s+\d{1,2}:\d{1,2}:\d{1,2},?\s+\d{2,4} |
- # ISO-8601 and RFC-3339 (space instead of T) recognized by DateTime.parse
- \d{4}-\d{2}-\d{2}
- (?:[T\s]\d{2}:\d{2}(?::\d{2}(?:\.\d+)?(?:[+-]\d{2}(?::\d{2})|Z)?)?)?
- )\z /x
-
- # The encoding used by all converters.
- ConverterEncoding = Encoding.find("UTF-8")
-
- # A \Hash containing the names and \Procs for the built-in field converters.
- # See {Built-In Field Converters}[#class-CSV-label-Built-In+Field+Converters].
- #
- # This \Hash is intentionally left unfrozen, and may be extended with
- # custom field converters.
- # See {Custom Field Converters}[#class-CSV-label-Custom+Field+Converters].
- Converters = {
- integer: lambda { |f|
- Integer(f.encode(ConverterEncoding)) rescue f
- },
- float: lambda { |f|
- Float(f.encode(ConverterEncoding)) rescue f
- },
- numeric: [:integer, :float],
- date: lambda { |f|
- begin
- e = f.encode(ConverterEncoding)
- e.match?(DateMatcher) ? Date.parse(e) : f
- rescue # encoding conversion or date parse errors
- f
- end
- },
- date_time: lambda { |f|
- begin
- e = f.encode(ConverterEncoding)
- e.match?(DateTimeMatcher) ? DateTime.parse(e) : f
- rescue # encoding conversion or date parse errors
- f
- end
- },
- all: [:date_time, :numeric],
- }
-
- # A \Hash containing the names and \Procs for the built-in header converters.
- # See {Built-In Header Converters}[#class-CSV-label-Built-In+Header+Converters].
- #
- # This \Hash is intentionally left unfrozen, and may be extended with
- # custom field converters.
- # See {Custom Header Converters}[#class-CSV-label-Custom+Header+Converters].
- HeaderConverters = {
- downcase: lambda { |h| h.encode(ConverterEncoding).downcase },
- symbol: lambda { |h|
- h.encode(ConverterEncoding).downcase.gsub(/[^\s\w]+/, "").strip.
- gsub(/\s+/, "_").to_sym
- },
- symbol_raw: lambda { |h| h.encode(ConverterEncoding).to_sym }
- }
-
- # Default values for method options.
- DEFAULT_OPTIONS = {
- # For both parsing and generating.
- col_sep: ",",
- row_sep: :auto,
- quote_char: '"',
- # For parsing.
- field_size_limit: nil,
- max_field_size: nil,
- converters: nil,
- unconverted_fields: nil,
- headers: false,
- return_headers: false,
- header_converters: nil,
- skip_blanks: false,
- skip_lines: nil,
- liberal_parsing: false,
- nil_value: nil,
- empty_value: "",
- strip: false,
- # For generating.
- write_headers: nil,
- quote_empty: true,
- force_quotes: false,
- write_converters: nil,
- write_nil_value: nil,
- write_empty_value: "",
- }.freeze
-
- class << self
- # :call-seq:
- # instance(string, **options)
- # instance(io = $stdout, **options)
- # instance(string, **options) {|csv| ... }
- # instance(io = $stdout, **options) {|csv| ... }
- #
- # Creates or retrieves cached \CSV objects.
- # For arguments and options, see CSV.new.
- #
- # This API is not Ractor-safe.
- #
- # ---
- #
- # With no block given, returns a \CSV object.
- #
- # The first call to +instance+ creates and caches a \CSV object:
- # s0 = 's0'
- # csv0 = CSV.instance(s0)
- # csv0.class # => CSV
- #
- # Subsequent calls to +instance+ with that _same_ +string+ or +io+
- # retrieve that same cached object:
- # csv1 = CSV.instance(s0)
- # csv1.class # => CSV
- # csv1.equal?(csv0) # => true # Same CSV object
- #
- # A subsequent call to +instance+ with a _different_ +string+ or +io+
- # creates and caches a _different_ \CSV object.
- # s1 = 's1'
- # csv2 = CSV.instance(s1)
- # csv2.equal?(csv0) # => false # Different CSV object
- #
- # All the cached objects remains available:
- # csv3 = CSV.instance(s0)
- # csv3.equal?(csv0) # true # Same CSV object
- # csv4 = CSV.instance(s1)
- # csv4.equal?(csv2) # true # Same CSV object
- #
- # ---
- #
- # When a block is given, calls the block with the created or retrieved
- # \CSV object; returns the block's return value:
- # CSV.instance(s0) {|csv| :foo } # => :foo
- def instance(data = $stdout, **options)
- # create a _signature_ for this method call, data object and options
- sig = [data.object_id] +
- options.values_at(*DEFAULT_OPTIONS.keys)
-
- # fetch or create the instance for this signature
- @@instances ||= Hash.new
- instance = (@@instances[sig] ||= new(data, **options))
-
- if block_given?
- yield instance # run block, if given, returning result
- else
- instance # or return the instance
- end
- end
-
- # :call-seq:
- # filter(in_string_or_io, **options) {|row| ... } -> array_of_arrays or csv_table
- # filter(in_string_or_io, out_string_or_io, **options) {|row| ... } -> array_of_arrays or csv_table
- # filter(**options) {|row| ... } -> array_of_arrays or csv_table
- #
- # - Parses \CSV from a source (\String, \IO stream, or ARGF).
- # - Calls the given block with each parsed row:
- # - Without headers, each row is an \Array.
- # - With headers, each row is a CSV::Row.
- # - Generates \CSV to an output (\String, \IO stream, or STDOUT).
- # - Returns the parsed source:
- # - Without headers, an \Array of \Arrays.
- # - With headers, a CSV::Table.
- #
- # When +in_string_or_io+ is given, but not +out_string_or_io+,
- # parses from the given +in_string_or_io+
- # and generates to STDOUT.
- #
- # \String input without headers:
- #
- # in_string = "foo,0\nbar,1\nbaz,2"
- # CSV.filter(in_string) do |row|
- # row[0].upcase!
- # row[1] = - row[1].to_i
- # end # => [["FOO", 0], ["BAR", -1], ["BAZ", -2]]
- #
- # Output (to STDOUT):
- #
- # FOO,0
- # BAR,-1
- # BAZ,-2
- #
- # \String input with headers:
- #
- # in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2"
- # CSV.filter(in_string, headers: true) do |row|
- # row[0].upcase!
- # row[1] = - row[1].to_i
- # end # => #<CSV::Table mode:col_or_row row_count:4>
- #
- # Output (to STDOUT):
- #
- # Name,Value
- # FOO,0
- # BAR,-1
- # BAZ,-2
- #
- # \IO stream input without headers:
- #
- # File.write('t.csv', "foo,0\nbar,1\nbaz,2")
- # File.open('t.csv') do |in_io|
- # CSV.filter(in_io) do |row|
- # row[0].upcase!
- # row[1] = - row[1].to_i
- # end
- # end # => [["FOO", 0], ["BAR", -1], ["BAZ", -2]]
- #
- # Output (to STDOUT):
- #
- # FOO,0
- # BAR,-1
- # BAZ,-2
- #
- # \IO stream input with headers:
- #
- # File.write('t.csv', "Name,Value\nfoo,0\nbar,1\nbaz,2")
- # File.open('t.csv') do |in_io|
- # CSV.filter(in_io, headers: true) do |row|
- # row[0].upcase!
- # row[1] = - row[1].to_i
- # end
- # end # => #<CSV::Table mode:col_or_row row_count:4>
- #
- # Output (to STDOUT):
- #
- # Name,Value
- # FOO,0
- # BAR,-1
- # BAZ,-2
- #
- # When both +in_string_or_io+ and +out_string_or_io+ are given,
- # parses from +in_string_or_io+ and generates to +out_string_or_io+.
- #
- # \String output without headers:
- #
- # in_string = "foo,0\nbar,1\nbaz,2"
- # out_string = ''
- # CSV.filter(in_string, out_string) do |row|
- # row[0].upcase!
- # row[1] = - row[1].to_i
- # end # => [["FOO", 0], ["BAR", -1], ["BAZ", -2]]
- # out_string # => "FOO,0\nBAR,-1\nBAZ,-2\n"
- #
- # \String output with headers:
- #
- # in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2"
- # out_string = ''
- # CSV.filter(in_string, out_string, headers: true) do |row|
- # row[0].upcase!
- # row[1] = - row[1].to_i
- # end # => #<CSV::Table mode:col_or_row row_count:4>
- # out_string # => "Name,Value\nFOO,0\nBAR,-1\nBAZ,-2\n"
- #
- # \IO stream output without headers:
- #
- # in_string = "foo,0\nbar,1\nbaz,2"
- # File.open('t.csv', 'w') do |out_io|
- # CSV.filter(in_string, out_io) do |row|
- # row[0].upcase!
- # row[1] = - row[1].to_i
- # end
- # end # => [["FOO", 0], ["BAR", -1], ["BAZ", -2]]
- # File.read('t.csv') # => "FOO,0\nBAR,-1\nBAZ,-2\n"
- #
- # \IO stream output with headers:
- #
- # in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2"
- # File.open('t.csv', 'w') do |out_io|
- # CSV.filter(in_string, out_io, headers: true) do |row|
- # row[0].upcase!
- # row[1] = - row[1].to_i
- # end
- # end # => #<CSV::Table mode:col_or_row row_count:4>
- # File.read('t.csv') # => "Name,Value\nFOO,0\nBAR,-1\nBAZ,-2\n"
- #
- # When neither +in_string_or_io+ nor +out_string_or_io+ given,
- # parses from {ARGF}[rdoc-ref:ARGF]
- # and generates to STDOUT.
- #
- # Without headers:
- #
- # # Put Ruby code into a file.
- # ruby = <<-EOT
- # require 'csv'
- # CSV.filter do |row|
- # row[0].upcase!
- # row[1] = - row[1].to_i
- # end
- # EOT
- # File.write('t.rb', ruby)
- # # Put some CSV into a file.
- # File.write('t.csv', "foo,0\nbar,1\nbaz,2")
- # # Run the Ruby code with CSV filename as argument.
- # system(Gem.ruby, "t.rb", "t.csv")
- #
- # Output (to STDOUT):
- #
- # FOO,0
- # BAR,-1
- # BAZ,-2
- #
- # With headers:
- #
- # # Put Ruby code into a file.
- # ruby = <<-EOT
- # require 'csv'
- # CSV.filter(headers: true) do |row|
- # row[0].upcase!
- # row[1] = - row[1].to_i
- # end
- # EOT
- # File.write('t.rb', ruby)
- # # Put some CSV into a file.
- # File.write('t.csv', "Name,Value\nfoo,0\nbar,1\nbaz,2")
- # # Run the Ruby code with CSV filename as argument.
- # system(Gem.ruby, "t.rb", "t.csv")
- #
- # Output (to STDOUT):
- #
- # Name,Value
- # FOO,0
- # BAR,-1
- # BAZ,-2
- #
- # Arguments:
- #
- # * Argument +in_string_or_io+ must be a \String or an \IO stream.
- # * Argument +out_string_or_io+ must be a \String or an \IO stream.
- # * Arguments <tt>**options</tt> must be keyword options.
- # See {Options for Parsing}[#class-CSV-label-Options+for+Parsing].
- def filter(input=nil, output=nil, **options)
- # parse options for input, output, or both
- in_options, out_options = Hash.new, {row_sep: InputRecordSeparator.value}
- options.each do |key, value|
- case key
- when /\Ain(?:put)?_(.+)\Z/
- in_options[$1.to_sym] = value
- when /\Aout(?:put)?_(.+)\Z/
- out_options[$1.to_sym] = value
- else
- in_options[key] = value
- out_options[key] = value
- end
- end
-
- # build input and output wrappers
- input = new(input || ARGF, **in_options)
- output = new(output || $stdout, **out_options)
-
- # process headers
- need_manual_header_output =
- (in_options[:headers] and
- out_options[:headers] == true and
- out_options[:write_headers])
- if need_manual_header_output
- first_row = input.shift
- if first_row
- if first_row.is_a?(Row)
- headers = first_row.headers
- yield headers
- output << headers
- end
- yield first_row
- output << first_row
- end
- end
-
- # read, yield, write
- input.each do |row|
- yield row
- output << row
- end
- end
-
- #
- # :call-seq:
- # foreach(path_or_io, mode='r', **options) {|row| ... )
- # foreach(path_or_io, mode='r', **options) -> new_enumerator
- #
- # Calls the block with each row read from source +path_or_io+.
- #
- # \Path input without headers:
- #
- # string = "foo,0\nbar,1\nbaz,2\n"
- # in_path = 't.csv'
- # File.write(in_path, string)
- # CSV.foreach(in_path) {|row| p row }
- #
- # Output:
- #
- # ["foo", "0"]
- # ["bar", "1"]
- # ["baz", "2"]
- #
- # \Path input with headers:
- #
- # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # in_path = 't.csv'
- # File.write(in_path, string)
- # CSV.foreach(in_path, headers: true) {|row| p row }
- #
- # Output:
- #
- # <CSV::Row "Name":"foo" "Value":"0">
- # <CSV::Row "Name":"bar" "Value":"1">
- # <CSV::Row "Name":"baz" "Value":"2">
- #
- # \IO stream input without headers:
- #
- # string = "foo,0\nbar,1\nbaz,2\n"
- # path = 't.csv'
- # File.write(path, string)
- # File.open('t.csv') do |in_io|
- # CSV.foreach(in_io) {|row| p row }
- # end
- #
- # Output:
- #
- # ["foo", "0"]
- # ["bar", "1"]
- # ["baz", "2"]
- #
- # \IO stream input with headers:
- #
- # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # path = 't.csv'
- # File.write(path, string)
- # File.open('t.csv') do |in_io|
- # CSV.foreach(in_io, headers: true) {|row| p row }
- # end
- #
- # Output:
- #
- # <CSV::Row "Name":"foo" "Value":"0">
- # <CSV::Row "Name":"bar" "Value":"1">
- # <CSV::Row "Name":"baz" "Value":"2">
- #
- # With no block given, returns an \Enumerator:
- #
- # string = "foo,0\nbar,1\nbaz,2\n"
- # path = 't.csv'
- # File.write(path, string)
- # CSV.foreach(path) # => #<Enumerator: CSV:foreach("t.csv", "r")>
- #
- # Arguments:
- # * Argument +path_or_io+ must be a file path or an \IO stream.
- # * Argument +mode+, if given, must be a \File mode.
- # See {Access Modes}[rdoc-ref:File@Access+Modes].
- # * Arguments <tt>**options</tt> must be keyword options.
- # See {Options for Parsing}[#class-CSV-label-Options+for+Parsing].
- # * This method optionally accepts an additional <tt>:encoding</tt> option
- # that you can use to specify the Encoding of the data read from +path+ or +io+.
- # You must provide this unless your data is in the encoding
- # given by <tt>Encoding::default_external</tt>.
- # Parsing will use this to determine how to parse the data.
- # You may provide a second Encoding to
- # have the data transcoded as it is read. For example,
- # encoding: 'UTF-32BE:UTF-8'
- # would read +UTF-32BE+ data from the file
- # but transcode it to +UTF-8+ before parsing.
- def foreach(path, mode="r", **options, &block)
- return to_enum(__method__, path, mode, **options) unless block_given?
- open(path, mode, **options) do |csv|
- csv.each(&block)
- end
- end
-
- #
- # :call-seq:
- # generate(csv_string, **options) {|csv| ... }
- # generate(**options) {|csv| ... }
- #
- # * Argument +csv_string+, if given, must be a \String object;
- # defaults to a new empty \String.
- # * Arguments +options+, if given, should be generating options.
- # See {Options for Generating}[#class-CSV-label-Options+for+Generating].
- #
- # ---
- #
- # Creates a new \CSV object via <tt>CSV.new(csv_string, **options)</tt>;
- # calls the block with the \CSV object, which the block may modify;
- # returns the \String generated from the \CSV object.
- #
- # Note that a passed \String *is* modified by this method.
- # Pass <tt>csv_string</tt>.dup if the \String must be preserved.
- #
- # This method has one additional option: <tt>:encoding</tt>,
- # which sets the base Encoding for the output if no no +str+ is specified.
- # CSV needs this hint if you plan to output non-ASCII compatible data.
- #
- # ---
- #
- # Add lines:
- # input_string = "foo,0\nbar,1\nbaz,2\n"
- # output_string = CSV.generate(input_string) do |csv|
- # csv << ['bat', 3]
- # csv << ['bam', 4]
- # end
- # output_string # => "foo,0\nbar,1\nbaz,2\nbat,3\nbam,4\n"
- # input_string # => "foo,0\nbar,1\nbaz,2\nbat,3\nbam,4\n"
- # output_string.equal?(input_string) # => true # Same string, modified
- #
- # Add lines into new string, preserving old string:
- # input_string = "foo,0\nbar,1\nbaz,2\n"
- # output_string = CSV.generate(input_string.dup) do |csv|
- # csv << ['bat', 3]
- # csv << ['bam', 4]
- # end
- # output_string # => "foo,0\nbar,1\nbaz,2\nbat,3\nbam,4\n"
- # input_string # => "foo,0\nbar,1\nbaz,2\n"
- # output_string.equal?(input_string) # => false # Different strings
- #
- # Create lines from nothing:
- # output_string = CSV.generate do |csv|
- # csv << ['foo', 0]
- # csv << ['bar', 1]
- # csv << ['baz', 2]
- # end
- # output_string # => "foo,0\nbar,1\nbaz,2\n"
- #
- # ---
- #
- # Raises an exception if +csv_string+ is not a \String object:
- # # Raises TypeError (no implicit conversion of Integer into String)
- # CSV.generate(0)
- #
- def generate(str=nil, **options)
- encoding = options[:encoding]
- # add a default empty String, if none was given
- if str
- str = StringIO.new(str)
- str.seek(0, IO::SEEK_END)
- str.set_encoding(encoding) if encoding
- else
- str = +""
- str.force_encoding(encoding) if encoding
- end
- csv = new(str, **options) # wrap
- yield csv # yield for appending
- csv.string # return final String
- end
-
- # :call-seq:
- # CSV.generate_line(ary)
- # CSV.generate_line(ary, **options)
- #
- # Returns the \String created by generating \CSV from +ary+
- # using the specified +options+.
- #
- # Argument +ary+ must be an \Array.
- #
- # Special options:
- # * Option <tt>:row_sep</tt> defaults to <tt>"\n"> on Ruby 3.0 or later
- # and <tt>$INPUT_RECORD_SEPARATOR</tt> (<tt>$/</tt>) otherwise.:
- # $INPUT_RECORD_SEPARATOR # => "\n"
- # * This method accepts an additional option, <tt>:encoding</tt>, which sets the base
- # Encoding for the output. This method will try to guess your Encoding from
- # the first non-+nil+ field in +row+, if possible, but you may need to use
- # this parameter as a backup plan.
- #
- # For other +options+,
- # see {Options for Generating}[#class-CSV-label-Options+for+Generating].
- #
- # ---
- #
- # Returns the \String generated from an \Array:
- # CSV.generate_line(['foo', '0']) # => "foo,0\n"
- #
- # ---
- #
- # Raises an exception if +ary+ is not an \Array:
- # # Raises NoMethodError (undefined method `find' for :foo:Symbol)
- # CSV.generate_line(:foo)
- #
- def generate_line(row, **options)
- options = {row_sep: InputRecordSeparator.value}.merge(options)
- str = +""
- if options[:encoding]
- str.force_encoding(options[:encoding])
- else
- fallback_encoding = nil
- output_encoding = nil
- row.each do |field|
- next unless field.is_a?(String)
- fallback_encoding ||= field.encoding
- next if field.ascii_only?
- output_encoding = field.encoding
- break
- end
- output_encoding ||= fallback_encoding
- if output_encoding
- str.force_encoding(output_encoding)
- end
- end
- (new(str, **options) << row).string
- end
-
- # :call-seq:
- # CSV.generate_lines(rows)
- # CSV.generate_lines(rows, **options)
- #
- # Returns the \String created by generating \CSV from
- # using the specified +options+.
- #
- # Argument +rows+ must be an \Array of row. Row is \Array of \String or \CSV::Row.
- #
- # Special options:
- # * Option <tt>:row_sep</tt> defaults to <tt>"\n"</tt> on Ruby 3.0 or later
- # and <tt>$INPUT_RECORD_SEPARATOR</tt> (<tt>$/</tt>) otherwise.:
- # $INPUT_RECORD_SEPARATOR # => "\n"
- # * This method accepts an additional option, <tt>:encoding</tt>, which sets the base
- # Encoding for the output. This method will try to guess your Encoding from
- # the first non-+nil+ field in +row+, if possible, but you may need to use
- # this parameter as a backup plan.
- #
- # For other +options+,
- # see {Options for Generating}[#class-CSV-label-Options+for+Generating].
- #
- # ---
- #
- # Returns the \String generated from an
- # CSV.generate_lines([['foo', '0'], ['bar', '1'], ['baz', '2']]) # => "foo,0\nbar,1\nbaz,2\n"
- #
- # ---
- #
- # Raises an exception
- # # Raises NoMethodError (undefined method `each' for :foo:Symbol)
- # CSV.generate_lines(:foo)
- #
- def generate_lines(rows, **options)
- self.generate(**options) do |csv|
- rows.each do |row|
- csv << row
- end
- end
- end
-
- #
- # :call-seq:
- # open(file_path, mode = "rb", **options ) -> new_csv
- # open(io, mode = "rb", **options ) -> new_csv
- # open(file_path, mode = "rb", **options ) { |csv| ... } -> object
- # open(io, mode = "rb", **options ) { |csv| ... } -> object
- #
- # possible options elements:
- # keyword form:
- # :invalid => nil # raise error on invalid byte sequence (default)
- # :invalid => :replace # replace invalid byte sequence
- # :undef => :replace # replace undefined conversion
- # :replace => string # replacement string ("?" or "\uFFFD" if not specified)
- #
- # * Argument +path+, if given, must be the path to a file.
- # :include: ../doc/csv/arguments/io.rdoc
- # * Argument +mode+, if given, must be a \File mode.
- # See {Access Modes}[rdoc-ref:File@Access+Modes].
- # * Arguments <tt>**options</tt> must be keyword options.
- # See {Options for Generating}[#class-CSV-label-Options+for+Generating].
- # * This method optionally accepts an additional <tt>:encoding</tt> option
- # that you can use to specify the Encoding of the data read from +path+ or +io+.
- # You must provide this unless your data is in the encoding
- # given by <tt>Encoding::default_external</tt>.
- # Parsing will use this to determine how to parse the data.
- # You may provide a second Encoding to
- # have the data transcoded as it is read. For example,
- # encoding: 'UTF-32BE:UTF-8'
- # would read +UTF-32BE+ data from the file
- # but transcode it to +UTF-8+ before parsing.
- #
- # ---
- #
- # These examples assume prior execution of:
- # string = "foo,0\nbar,1\nbaz,2\n"
- # path = 't.csv'
- # File.write(path, string)
- #
- # ---
- #
- # With no block given, returns a new \CSV object.
- #
- # Create a \CSV object using a file path:
- # csv = CSV.open(path)
- # csv # => #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
- #
- # Create a \CSV object using an open \File:
- # csv = CSV.open(File.open(path))
- # csv # => #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
- #
- # ---
- #
- # With a block given, calls the block with the created \CSV object;
- # returns the block's return value:
- #
- # Using a file path:
- # csv = CSV.open(path) {|csv| p csv}
- # csv # => #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
- # Output:
- # #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
- #
- # Using an open \File:
- # csv = CSV.open(File.open(path)) {|csv| p csv}
- # csv # => #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
- # Output:
- # #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
- #
- # ---
- #
- # Raises an exception if the argument is not a \String object or \IO object:
- # # Raises TypeError (no implicit conversion of Symbol into String)
- # CSV.open(:foo)
- def open(filename, mode="r", **options)
- # wrap a File opened with the remaining +args+ with no newline
- # decorator
- file_opts = options.dup
- unless file_opts.key?(:newline)
- file_opts[:universal_newline] ||= false
- end
- options.delete(:invalid)
- options.delete(:undef)
- options.delete(:replace)
- options.delete_if {|k, _| /newline\z/.match?(k)}
-
- begin
- f = File.open(filename, mode, **file_opts)
- rescue ArgumentError => e
- raise unless /needs binmode/.match?(e.message) and mode == "r"
- mode = "rb"
- file_opts = {encoding: Encoding.default_external}.merge(file_opts)
- retry
- end
- begin
- csv = new(f, **options)
- rescue Exception
- f.close
- raise
- end
-
- # handle blocks like Ruby's open(), not like the CSV library
- if block_given?
- begin
- yield csv
- ensure
- csv.close
- end
- else
- csv
- end
- end
-
- #
- # :call-seq:
- # parse(string) -> array_of_arrays
- # parse(io) -> array_of_arrays
- # parse(string, headers: ..., **options) -> csv_table
- # parse(io, headers: ..., **options) -> csv_table
- # parse(string, **options) {|row| ... }
- # parse(io, **options) {|row| ... }
- #
- # Parses +string+ or +io+ using the specified +options+.
- #
- # - Argument +string+ should be a \String object;
- # it will be put into a new StringIO object positioned at the beginning.
- # :include: ../doc/csv/arguments/io.rdoc
- # - Argument +options+: see {Options for Parsing}[#class-CSV-label-Options+for+Parsing]
- #
- # ====== Without Option +headers+
- #
- # Without {option +headers+}[#class-CSV-label-Option+headers] case.
- #
- # These examples assume prior execution of:
- # string = "foo,0\nbar,1\nbaz,2\n"
- # path = 't.csv'
- # File.write(path, string)
- #
- # ---
- #
- # With no block given, returns an \Array of Arrays formed from the source.
- #
- # Parse a \String:
- # a_of_a = CSV.parse(string)
- # a_of_a # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
- #
- # Parse an open \File:
- # a_of_a = File.open(path) do |file|
- # CSV.parse(file)
- # end
- # a_of_a # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
- #
- # ---
- #
- # With a block given, calls the block with each parsed row:
- #
- # Parse a \String:
- # CSV.parse(string) {|row| p row }
- #
- # Output:
- # ["foo", "0"]
- # ["bar", "1"]
- # ["baz", "2"]
- #
- # Parse an open \File:
- # File.open(path) do |file|
- # CSV.parse(file) {|row| p row }
- # end
- #
- # Output:
- # ["foo", "0"]
- # ["bar", "1"]
- # ["baz", "2"]
- #
- # ====== With Option +headers+
- #
- # With {option +headers+}[#class-CSV-label-Option+headers] case.
- #
- # These examples assume prior execution of:
- # string = "Name,Count\nfoo,0\nbar,1\nbaz,2\n"
- # path = 't.csv'
- # File.write(path, string)
- #
- # ---
- #
- # With no block given, returns a CSV::Table object formed from the source.
- #
- # Parse a \String:
- # csv_table = CSV.parse(string, headers: ['Name', 'Count'])
- # csv_table # => #<CSV::Table mode:col_or_row row_count:5>
- #
- # Parse an open \File:
- # csv_table = File.open(path) do |file|
- # CSV.parse(file, headers: ['Name', 'Count'])
- # end
- # csv_table # => #<CSV::Table mode:col_or_row row_count:4>
- #
- # ---
- #
- # With a block given, calls the block with each parsed row,
- # which has been formed into a CSV::Row object:
- #
- # Parse a \String:
- # CSV.parse(string, headers: ['Name', 'Count']) {|row| p row }
- #
- # Output:
- # # <CSV::Row "Name":"foo" "Count":"0">
- # # <CSV::Row "Name":"bar" "Count":"1">
- # # <CSV::Row "Name":"baz" "Count":"2">
- #
- # Parse an open \File:
- # File.open(path) do |file|
- # CSV.parse(file, headers: ['Name', 'Count']) {|row| p row }
- # end
- #
- # Output:
- # # <CSV::Row "Name":"foo" "Count":"0">
- # # <CSV::Row "Name":"bar" "Count":"1">
- # # <CSV::Row "Name":"baz" "Count":"2">
- #
- # ---
- #
- # Raises an exception if the argument is not a \String object or \IO object:
- # # Raises NoMethodError (undefined method `close' for :foo:Symbol)
- # CSV.parse(:foo)
- def parse(str, **options, &block)
- csv = new(str, **options)
-
- return csv.each(&block) if block_given?
-
- # slurp contents, if no block is given
- begin
- csv.read
- ensure
- csv.close
- end
- end
-
- # :call-seq:
- # CSV.parse_line(string) -> new_array or nil
- # CSV.parse_line(io) -> new_array or nil
- # CSV.parse_line(string, **options) -> new_array or nil
- # CSV.parse_line(io, **options) -> new_array or nil
- # CSV.parse_line(string, headers: true, **options) -> csv_row or nil
- # CSV.parse_line(io, headers: true, **options) -> csv_row or nil
- #
- # Returns the data created by parsing the first line of +string+ or +io+
- # using the specified +options+.
- #
- # - Argument +string+ should be a \String object;
- # it will be put into a new StringIO object positioned at the beginning.
- # :include: ../doc/csv/arguments/io.rdoc
- # - Argument +options+: see {Options for Parsing}[#class-CSV-label-Options+for+Parsing]
- #
- # ====== Without Option +headers+
- #
- # Without option +headers+, returns the first row as a new \Array.
- #
- # These examples assume prior execution of:
- # string = "foo,0\nbar,1\nbaz,2\n"
- # path = 't.csv'
- # File.write(path, string)
- #
- # Parse the first line from a \String object:
- # CSV.parse_line(string) # => ["foo", "0"]
- #
- # Parse the first line from a File object:
- # File.open(path) do |file|
- # CSV.parse_line(file) # => ["foo", "0"]
- # end # => ["foo", "0"]
- #
- # Returns +nil+ if the argument is an empty \String:
- # CSV.parse_line('') # => nil
- #
- # ====== With Option +headers+
- #
- # With {option +headers+}[#class-CSV-label-Option+headers],
- # returns the first row as a CSV::Row object.
- #
- # These examples assume prior execution of:
- # string = "Name,Count\nfoo,0\nbar,1\nbaz,2\n"
- # path = 't.csv'
- # File.write(path, string)
- #
- # Parse the first line from a \String object:
- # CSV.parse_line(string, headers: true) # => #<CSV::Row "Name":"foo" "Count":"0">
- #
- # Parse the first line from a File object:
- # File.open(path) do |file|
- # CSV.parse_line(file, headers: true)
- # end # => #<CSV::Row "Name":"foo" "Count":"0">
- #
- # ---
- #
- # Raises an exception if the argument is +nil+:
- # # Raises ArgumentError (Cannot parse nil as CSV):
- # CSV.parse_line(nil)
- #
- def parse_line(line, **options)
- new(line, **options).each.first
- end
-
- #
- # :call-seq:
- # read(source, **options) -> array_of_arrays
- # read(source, headers: true, **options) -> csv_table
- #
- # Opens the given +source+ with the given +options+ (see CSV.open),
- # reads the source (see CSV#read), and returns the result,
- # which will be either an \Array of Arrays or a CSV::Table.
- #
- # Without headers:
- # string = "foo,0\nbar,1\nbaz,2\n"
- # path = 't.csv'
- # File.write(path, string)
- # CSV.read(path) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
- #
- # With headers:
- # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # path = 't.csv'
- # File.write(path, string)
- # CSV.read(path, headers: true) # => #<CSV::Table mode:col_or_row row_count:4>
- def read(path, **options)
- open(path, **options) { |csv| csv.read }
- end
-
- # :call-seq:
- # CSV.readlines(source, **options)
- #
- # Alias for CSV.read.
- def readlines(path, **options)
- read(path, **options)
- end
-
- # :call-seq:
- # CSV.table(source, **options)
- #
- # Calls CSV.read with +source+, +options+, and certain default options:
- # - +headers+: +true+
- # - +converters+: +:numeric+
- # - +header_converters+: +:symbol+
- #
- # Returns a CSV::Table object.
- #
- # Example:
- # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # path = 't.csv'
- # File.write(path, string)
- # CSV.table(path) # => #<CSV::Table mode:col_or_row row_count:4>
- def table(path, **options)
- default_options = {
- headers: true,
- converters: :numeric,
- header_converters: :symbol,
- }
- options = default_options.merge(options)
- read(path, **options)
- end
- end
-
- # :call-seq:
- # CSV.new(string)
- # CSV.new(io)
- # CSV.new(string, **options)
- # CSV.new(io, **options)
- #
- # Returns the new \CSV object created using +string+ or +io+
- # and the specified +options+.
- #
- # - Argument +string+ should be a \String object;
- # it will be put into a new StringIO object positioned at the beginning.
- # :include: ../doc/csv/arguments/io.rdoc
- # - Argument +options+: See:
- # * {Options for Parsing}[#class-CSV-label-Options+for+Parsing]
- # * {Options for Generating}[#class-CSV-label-Options+for+Generating]
- # For performance reasons, the options cannot be overridden
- # in a \CSV object, so those specified here will endure.
- #
- # In addition to the \CSV instance methods, several \IO methods are delegated.
- # See {Delegated Methods}[#class-CSV-label-Delegated+Methods].
- #
- # ---
- #
- # Create a \CSV object from a \String object:
- # csv = CSV.new('foo,0')
- # csv # => #<CSV io_type:StringIO encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
- #
- # Create a \CSV object from a \File object:
- # File.write('t.csv', 'foo,0')
- # csv = CSV.new(File.open('t.csv'))
- # csv # => #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
- #
- # ---
- #
- # Raises an exception if the argument is +nil+:
- # # Raises ArgumentError (Cannot parse nil as CSV):
- # CSV.new(nil)
- #
- def initialize(data,
- col_sep: ",",
- row_sep: :auto,
- quote_char: '"',
- field_size_limit: nil,
- max_field_size: nil,
- converters: nil,
- unconverted_fields: nil,
- headers: false,
- return_headers: false,
- write_headers: nil,
- header_converters: nil,
- skip_blanks: false,
- force_quotes: false,
- skip_lines: nil,
- liberal_parsing: false,
- internal_encoding: nil,
- external_encoding: nil,
- encoding: nil,
- nil_value: nil,
- empty_value: "",
- strip: false,
- quote_empty: true,
- write_converters: nil,
- write_nil_value: nil,
- write_empty_value: "")
- raise ArgumentError.new("Cannot parse nil as CSV") if data.nil?
-
- if data.is_a?(String)
- if encoding
- if encoding.is_a?(String)
- data_external_encoding, data_internal_encoding = encoding.split(":", 2)
- if data_internal_encoding
- data = data.encode(data_internal_encoding, data_external_encoding)
- else
- data = data.dup.force_encoding(data_external_encoding)
- end
- else
- data = data.dup.force_encoding(encoding)
- end
- end
- @io = StringIO.new(data)
- else
- @io = data
- end
- @encoding = determine_encoding(encoding, internal_encoding)
-
- @base_fields_converter_options = {
- nil_value: nil_value,
- empty_value: empty_value,
- }
- @write_fields_converter_options = {
- nil_value: write_nil_value,
- empty_value: write_empty_value,
- }
- @initial_converters = converters
- @initial_header_converters = header_converters
- @initial_write_converters = write_converters
-
- if max_field_size.nil? and field_size_limit
- max_field_size = field_size_limit - 1
- end
- @parser_options = {
- column_separator: col_sep,
- row_separator: row_sep,
- quote_character: quote_char,
- max_field_size: max_field_size,
- unconverted_fields: unconverted_fields,
- headers: headers,
- return_headers: return_headers,
- skip_blanks: skip_blanks,
- skip_lines: skip_lines,
- liberal_parsing: liberal_parsing,
- encoding: @encoding,
- nil_value: nil_value,
- empty_value: empty_value,
- strip: strip,
- }
- @parser = nil
- @parser_enumerator = nil
- @eof_error = nil
-
- @writer_options = {
- encoding: @encoding,
- force_encoding: (not encoding.nil?),
- force_quotes: force_quotes,
- headers: headers,
- write_headers: write_headers,
- column_separator: col_sep,
- row_separator: row_sep,
- quote_character: quote_char,
- quote_empty: quote_empty,
- }
-
- @writer = nil
- writer if @writer_options[:write_headers]
- end
-
- # :call-seq:
- # csv.col_sep -> string
- #
- # Returns the encoded column separator; used for parsing and writing;
- # see {Option +col_sep+}[#class-CSV-label-Option+col_sep]:
- # CSV.new('').col_sep # => ","
- def col_sep
- parser.column_separator
- end
-
- # :call-seq:
- # csv.row_sep -> string
- #
- # Returns the encoded row separator; used for parsing and writing;
- # see {Option +row_sep+}[#class-CSV-label-Option+row_sep]:
- # CSV.new('').row_sep # => "\n"
- def row_sep
- parser.row_separator
- end
-
- # :call-seq:
- # csv.quote_char -> character
- #
- # Returns the encoded quote character; used for parsing and writing;
- # see {Option +quote_char+}[#class-CSV-label-Option+quote_char]:
- # CSV.new('').quote_char # => "\""
- def quote_char
- parser.quote_character
- end
-
- # :call-seq:
- # csv.field_size_limit -> integer or nil
- #
- # Returns the limit for field size; used for parsing;
- # see {Option +field_size_limit+}[#class-CSV-label-Option+field_size_limit]:
- # CSV.new('').field_size_limit # => nil
- #
- # Deprecated since 3.2.3. Use +max_field_size+ instead.
- def field_size_limit
- parser.field_size_limit
- end
-
- # :call-seq:
- # csv.max_field_size -> integer or nil
- #
- # Returns the limit for field size; used for parsing;
- # see {Option +max_field_size+}[#class-CSV-label-Option+max_field_size]:
- # CSV.new('').max_field_size # => nil
- #
- # Since 3.2.3.
- def max_field_size
- parser.max_field_size
- end
-
- # :call-seq:
- # csv.skip_lines -> regexp or nil
- #
- # Returns the \Regexp used to identify comment lines; used for parsing;
- # see {Option +skip_lines+}[#class-CSV-label-Option+skip_lines]:
- # CSV.new('').skip_lines # => nil
- def skip_lines
- parser.skip_lines
- end
-
- # :call-seq:
- # csv.converters -> array
- #
- # Returns an \Array containing field converters;
- # see {Field Converters}[#class-CSV-label-Field+Converters]:
- # csv = CSV.new('')
- # csv.converters # => []
- # csv.convert(:integer)
- # csv.converters # => [:integer]
- # csv.convert(proc {|x| x.to_s })
- # csv.converters
- #
- # Notes that you need to call
- # +Ractor.make_shareable(CSV::Converters)+ on the main Ractor to use
- # this method.
- def converters
- parser_fields_converter.map do |converter|
- name = Converters.rassoc(converter)
- name ? name.first : converter
- end
- end
-
- # :call-seq:
- # csv.unconverted_fields? -> object
- #
- # Returns the value that determines whether unconverted fields are to be
- # available; used for parsing;
- # see {Option +unconverted_fields+}[#class-CSV-label-Option+unconverted_fields]:
- # CSV.new('').unconverted_fields? # => nil
- def unconverted_fields?
- parser.unconverted_fields?
- end
-
- # :call-seq:
- # csv.headers -> object
- #
- # Returns the value that determines whether headers are used; used for parsing;
- # see {Option +headers+}[#class-CSV-label-Option+headers]:
- # CSV.new('').headers # => nil
- def headers
- if @writer
- @writer.headers
- else
- parsed_headers = parser.headers
- return parsed_headers if parsed_headers
- raw_headers = @parser_options[:headers]
- raw_headers = nil if raw_headers == false
- raw_headers
- end
- end
-
- # :call-seq:
- # csv.return_headers? -> true or false
- #
- # Returns the value that determines whether headers are to be returned; used for parsing;
- # see {Option +return_headers+}[#class-CSV-label-Option+return_headers]:
- # CSV.new('').return_headers? # => false
- def return_headers?
- parser.return_headers?
- end
-
- # :call-seq:
- # csv.write_headers? -> true or false
- #
- # Returns the value that determines whether headers are to be written; used for generating;
- # see {Option +write_headers+}[#class-CSV-label-Option+write_headers]:
- # CSV.new('').write_headers? # => nil
- def write_headers?
- @writer_options[:write_headers]
- end
-
- # :call-seq:
- # csv.header_converters -> array
- #
- # Returns an \Array containing header converters; used for parsing;
- # see {Header Converters}[#class-CSV-label-Header+Converters]:
- # CSV.new('').header_converters # => []
- #
- # Notes that you need to call
- # +Ractor.make_shareable(CSV::HeaderConverters)+ on the main Ractor
- # to use this method.
- def header_converters
- header_fields_converter.map do |converter|
- name = HeaderConverters.rassoc(converter)
- name ? name.first : converter
- end
- end
-
- # :call-seq:
- # csv.skip_blanks? -> true or false
- #
- # Returns the value that determines whether blank lines are to be ignored; used for parsing;
- # see {Option +skip_blanks+}[#class-CSV-label-Option+skip_blanks]:
- # CSV.new('').skip_blanks? # => false
- def skip_blanks?
- parser.skip_blanks?
- end
-
- # :call-seq:
- # csv.force_quotes? -> true or false
- #
- # Returns the value that determines whether all output fields are to be quoted;
- # used for generating;
- # see {Option +force_quotes+}[#class-CSV-label-Option+force_quotes]:
- # CSV.new('').force_quotes? # => false
- def force_quotes?
- @writer_options[:force_quotes]
- end
-
- # :call-seq:
- # csv.liberal_parsing? -> true or false
- #
- # Returns the value that determines whether illegal input is to be handled; used for parsing;
- # see {Option +liberal_parsing+}[#class-CSV-label-Option+liberal_parsing]:
- # CSV.new('').liberal_parsing? # => false
- def liberal_parsing?
- parser.liberal_parsing?
- end
-
- # :call-seq:
- # csv.encoding -> encoding
- #
- # Returns the encoding used for parsing and generating;
- # see {Character Encodings (M17n or Multilingualization)}[#class-CSV-label-Character+Encodings+-28M17n+or+Multilingualization-29]:
- # CSV.new('').encoding # => #<Encoding:UTF-8>
- attr_reader :encoding
-
- # :call-seq:
- # csv.line_no -> integer
- #
- # Returns the count of the rows parsed or generated.
- #
- # Parsing:
- # string = "foo,0\nbar,1\nbaz,2\n"
- # path = 't.csv'
- # File.write(path, string)
- # CSV.open(path) do |csv|
- # csv.each do |row|
- # p [csv.lineno, row]
- # end
- # end
- # Output:
- # [1, ["foo", "0"]]
- # [2, ["bar", "1"]]
- # [3, ["baz", "2"]]
- #
- # Generating:
- # CSV.generate do |csv|
- # p csv.lineno; csv << ['foo', 0]
- # p csv.lineno; csv << ['bar', 1]
- # p csv.lineno; csv << ['baz', 2]
- # end
- # Output:
- # 0
- # 1
- # 2
- def lineno
- if @writer
- @writer.lineno
- else
- parser.lineno
- end
- end
-
- # :call-seq:
- # csv.line -> array
- #
- # Returns the line most recently read:
- # string = "foo,0\nbar,1\nbaz,2\n"
- # path = 't.csv'
- # File.write(path, string)
- # CSV.open(path) do |csv|
- # csv.each do |row|
- # p [csv.lineno, csv.line]
- # end
- # end
- # Output:
- # [1, "foo,0\n"]
- # [2, "bar,1\n"]
- # [3, "baz,2\n"]
- def line
- parser.line
- end
-
- ### IO and StringIO Delegation ###
-
- extend Forwardable
- def_delegators :@io, :binmode, :close, :close_read, :close_write,
- :closed?, :external_encoding, :fcntl,
- :fileno, :flush, :fsync, :internal_encoding,
- :isatty, :pid, :pos, :pos=, :reopen,
- :seek, :string, :sync, :sync=, :tell,
- :truncate, :tty?
-
- def binmode?
- if @io.respond_to?(:binmode?)
- @io.binmode?
- else
- false
- end
- end
-
- def flock(*args)
- raise NotImplementedError unless @io.respond_to?(:flock)
- @io.flock(*args)
- end
-
- def ioctl(*args)
- raise NotImplementedError unless @io.respond_to?(:ioctl)
- @io.ioctl(*args)
- end
-
- def path
- @io.path if @io.respond_to?(:path)
- end
-
- def stat(*args)
- raise NotImplementedError unless @io.respond_to?(:stat)
- @io.stat(*args)
- end
-
- def to_i
- raise NotImplementedError unless @io.respond_to?(:to_i)
- @io.to_i
- end
-
- def to_io
- @io.respond_to?(:to_io) ? @io.to_io : @io
- end
-
- def eof?
- return false if @eof_error
- begin
- parser_enumerator.peek
- false
- rescue MalformedCSVError => error
- @eof_error = error
- false
- rescue StopIteration
- true
- end
- end
- alias_method :eof, :eof?
-
- # Rewinds the underlying IO object and resets CSV's lineno() counter.
- def rewind
- @parser = nil
- @parser_enumerator = nil
- @eof_error = nil
- @writer.rewind if @writer
- @io.rewind
- end
-
- ### End Delegation ###
-
- # :call-seq:
- # csv << row -> self
- #
- # Appends a row to +self+.
- #
- # - Argument +row+ must be an \Array object or a CSV::Row object.
- # - The output stream must be open for writing.
- #
- # ---
- #
- # Append Arrays:
- # CSV.generate do |csv|
- # csv << ['foo', 0]
- # csv << ['bar', 1]
- # csv << ['baz', 2]
- # end # => "foo,0\nbar,1\nbaz,2\n"
- #
- # Append CSV::Rows:
- # headers = []
- # CSV.generate do |csv|
- # csv << CSV::Row.new(headers, ['foo', 0])
- # csv << CSV::Row.new(headers, ['bar', 1])
- # csv << CSV::Row.new(headers, ['baz', 2])
- # end # => "foo,0\nbar,1\nbaz,2\n"
- #
- # Headers in CSV::Row objects are not appended:
- # headers = ['Name', 'Count']
- # CSV.generate do |csv|
- # csv << CSV::Row.new(headers, ['foo', 0])
- # csv << CSV::Row.new(headers, ['bar', 1])
- # csv << CSV::Row.new(headers, ['baz', 2])
- # end # => "foo,0\nbar,1\nbaz,2\n"
- #
- # ---
- #
- # Raises an exception if +row+ is not an \Array or \CSV::Row:
- # CSV.generate do |csv|
- # # Raises NoMethodError (undefined method `collect' for :foo:Symbol)
- # csv << :foo
- # end
- #
- # Raises an exception if the output stream is not opened for writing:
- # path = 't.csv'
- # File.write(path, '')
- # File.open(path) do |file|
- # CSV.open(file) do |csv|
- # # Raises IOError (not opened for writing)
- # csv << ['foo', 0]
- # end
- # end
- def <<(row)
- writer << row
- self
- end
- alias_method :add_row, :<<
- alias_method :puts, :<<
-
- # :call-seq:
- # convert(converter_name) -> array_of_procs
- # convert {|field, field_info| ... } -> array_of_procs
- #
- # - With no block, installs a field converter (a \Proc).
- # - With a block, defines and installs a custom field converter.
- # - Returns the \Array of installed field converters.
- #
- # - Argument +converter_name+, if given, should be the name
- # of an existing field converter.
- #
- # See {Field Converters}[#class-CSV-label-Field+Converters].
- # ---
- #
- # With no block, installs a field converter:
- # csv = CSV.new('')
- # csv.convert(:integer)
- # csv.convert(:float)
- # csv.convert(:date)
- # csv.converters # => [:integer, :float, :date]
- #
- # ---
- #
- # The block, if given, is called for each field:
- # - Argument +field+ is the field value.
- # - Argument +field_info+ is a CSV::FieldInfo object
- # containing details about the field.
- #
- # The examples here assume the prior execution of:
- # string = "foo,0\nbar,1\nbaz,2\n"
- # path = 't.csv'
- # File.write(path, string)
- #
- # Example giving a block:
- # csv = CSV.open(path)
- # csv.convert {|field, field_info| p [field, field_info]; field.upcase }
- # csv.read # => [["FOO", "0"], ["BAR", "1"], ["BAZ", "2"]]
- #
- # Output:
- # ["foo", #<struct CSV::FieldInfo index=0, line=1, header=nil>]
- # ["0", #<struct CSV::FieldInfo index=1, line=1, header=nil>]
- # ["bar", #<struct CSV::FieldInfo index=0, line=2, header=nil>]
- # ["1", #<struct CSV::FieldInfo index=1, line=2, header=nil>]
- # ["baz", #<struct CSV::FieldInfo index=0, line=3, header=nil>]
- # ["2", #<struct CSV::FieldInfo index=1, line=3, header=nil>]
- #
- # The block need not return a \String object:
- # csv = CSV.open(path)
- # csv.convert {|field, field_info| field.to_sym }
- # csv.read # => [[:foo, :"0"], [:bar, :"1"], [:baz, :"2"]]
- #
- # If +converter_name+ is given, the block is not called:
- # csv = CSV.open(path)
- # csv.convert(:integer) {|field, field_info| fail 'Cannot happen' }
- # csv.read # => [["foo", 0], ["bar", 1], ["baz", 2]]
- #
- # ---
- #
- # Raises a parse-time exception if +converter_name+ is not the name of a built-in
- # field converter:
- # csv = CSV.open(path)
- # csv.convert(:nosuch) => [nil]
- # # Raises NoMethodError (undefined method `arity' for nil:NilClass)
- # csv.read
- def convert(name = nil, &converter)
- parser_fields_converter.add_converter(name, &converter)
- end
-
- # :call-seq:
- # header_convert(converter_name) -> array_of_procs
- # header_convert {|header, field_info| ... } -> array_of_procs
- #
- # - With no block, installs a header converter (a \Proc).
- # - With a block, defines and installs a custom header converter.
- # - Returns the \Array of installed header converters.
- #
- # - Argument +converter_name+, if given, should be the name
- # of an existing header converter.
- #
- # See {Header Converters}[#class-CSV-label-Header+Converters].
- # ---
- #
- # With no block, installs a header converter:
- # csv = CSV.new('')
- # csv.header_convert(:symbol)
- # csv.header_convert(:downcase)
- # csv.header_converters # => [:symbol, :downcase]
- #
- # ---
- #
- # The block, if given, is called for each header:
- # - Argument +header+ is the header value.
- # - Argument +field_info+ is a CSV::FieldInfo object
- # containing details about the header.
- #
- # The examples here assume the prior execution of:
- # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # path = 't.csv'
- # File.write(path, string)
- #
- # Example giving a block:
- # csv = CSV.open(path, headers: true)
- # csv.header_convert {|header, field_info| p [header, field_info]; header.upcase }
- # table = csv.read
- # table # => #<CSV::Table mode:col_or_row row_count:4>
- # table.headers # => ["NAME", "VALUE"]
- #
- # Output:
- # ["Name", #<struct CSV::FieldInfo index=0, line=1, header=nil>]
- # ["Value", #<struct CSV::FieldInfo index=1, line=1, header=nil>]
-
- # The block need not return a \String object:
- # csv = CSV.open(path, headers: true)
- # csv.header_convert {|header, field_info| header.to_sym }
- # table = csv.read
- # table.headers # => [:Name, :Value]
- #
- # If +converter_name+ is given, the block is not called:
- # csv = CSV.open(path, headers: true)
- # csv.header_convert(:downcase) {|header, field_info| fail 'Cannot happen' }
- # table = csv.read
- # table.headers # => ["name", "value"]
- # ---
- #
- # Raises a parse-time exception if +converter_name+ is not the name of a built-in
- # field converter:
- # csv = CSV.open(path, headers: true)
- # csv.header_convert(:nosuch)
- # # Raises NoMethodError (undefined method `arity' for nil:NilClass)
- # csv.read
- def header_convert(name = nil, &converter)
- header_fields_converter.add_converter(name, &converter)
- end
-
- include Enumerable
-
- # :call-seq:
- # csv.each -> enumerator
- # csv.each {|row| ...}
- #
- # Calls the block with each successive row.
- # The data source must be opened for reading.
- #
- # Without headers:
- # string = "foo,0\nbar,1\nbaz,2\n"
- # csv = CSV.new(string)
- # csv.each do |row|
- # p row
- # end
- # Output:
- # ["foo", "0"]
- # ["bar", "1"]
- # ["baz", "2"]
- #
- # With headers:
- # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # csv = CSV.new(string, headers: true)
- # csv.each do |row|
- # p row
- # end
- # Output:
- # <CSV::Row "Name":"foo" "Value":"0">
- # <CSV::Row "Name":"bar" "Value":"1">
- # <CSV::Row "Name":"baz" "Value":"2">
- #
- # ---
- #
- # Raises an exception if the source is not opened for reading:
- # string = "foo,0\nbar,1\nbaz,2\n"
- # csv = CSV.new(string)
- # csv.close
- # # Raises IOError (not opened for reading)
- # csv.each do |row|
- # p row
- # end
- def each(&block)
- return to_enum(__method__) unless block_given?
- begin
- while true
- yield(parser_enumerator.next)
- end
- rescue StopIteration
- end
- end
-
- # :call-seq:
- # csv.read -> array or csv_table
- #
- # Forms the remaining rows from +self+ into:
- # - A CSV::Table object, if headers are in use.
- # - An \Array of Arrays, otherwise.
- #
- # The data source must be opened for reading.
- #
- # Without headers:
- # string = "foo,0\nbar,1\nbaz,2\n"
- # path = 't.csv'
- # File.write(path, string)
- # csv = CSV.open(path)
- # csv.read # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
- #
- # With headers:
- # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # path = 't.csv'
- # File.write(path, string)
- # csv = CSV.open(path, headers: true)
- # csv.read # => #<CSV::Table mode:col_or_row row_count:4>
- #
- # ---
- #
- # Raises an exception if the source is not opened for reading:
- # string = "foo,0\nbar,1\nbaz,2\n"
- # csv = CSV.new(string)
- # csv.close
- # # Raises IOError (not opened for reading)
- # csv.read
- def read
- rows = to_a
- if parser.use_headers?
- Table.new(rows, headers: parser.headers)
- else
- rows
- end
- end
- alias_method :readlines, :read
-
- # :call-seq:
- # csv.header_row? -> true or false
- #
- # Returns +true+ if the next row to be read is a header row\;
- # +false+ otherwise.
- #
- # Without headers:
- # string = "foo,0\nbar,1\nbaz,2\n"
- # csv = CSV.new(string)
- # csv.header_row? # => false
- #
- # With headers:
- # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # csv = CSV.new(string, headers: true)
- # csv.header_row? # => true
- # csv.shift # => #<CSV::Row "Name":"foo" "Value":"0">
- # csv.header_row? # => false
- #
- # ---
- #
- # Raises an exception if the source is not opened for reading:
- # string = "foo,0\nbar,1\nbaz,2\n"
- # csv = CSV.new(string)
- # csv.close
- # # Raises IOError (not opened for reading)
- # csv.header_row?
- def header_row?
- parser.header_row?
- end
-
- # :call-seq:
- # csv.shift -> array, csv_row, or nil
- #
- # Returns the next row of data as:
- # - An \Array if no headers are used.
- # - A CSV::Row object if headers are used.
- #
- # The data source must be opened for reading.
- #
- # Without headers:
- # string = "foo,0\nbar,1\nbaz,2\n"
- # csv = CSV.new(string)
- # csv.shift # => ["foo", "0"]
- # csv.shift # => ["bar", "1"]
- # csv.shift # => ["baz", "2"]
- # csv.shift # => nil
- #
- # With headers:
- # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # csv = CSV.new(string, headers: true)
- # csv.shift # => #<CSV::Row "Name":"foo" "Value":"0">
- # csv.shift # => #<CSV::Row "Name":"bar" "Value":"1">
- # csv.shift # => #<CSV::Row "Name":"baz" "Value":"2">
- # csv.shift # => nil
- #
- # ---
- #
- # Raises an exception if the source is not opened for reading:
- # string = "foo,0\nbar,1\nbaz,2\n"
- # csv = CSV.new(string)
- # csv.close
- # # Raises IOError (not opened for reading)
- # csv.shift
- def shift
- if @eof_error
- eof_error, @eof_error = @eof_error, nil
- raise eof_error
- end
- begin
- parser_enumerator.next
- rescue StopIteration
- nil
- end
- end
- alias_method :gets, :shift
- alias_method :readline, :shift
-
- # :call-seq:
- # csv.inspect -> string
- #
- # Returns a \String showing certain properties of +self+:
- # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # csv = CSV.new(string, headers: true)
- # s = csv.inspect
- # s # => "#<CSV io_type:StringIO encoding:UTF-8 lineno:0 col_sep:\",\" row_sep:\"\\n\" quote_char:\"\\\"\" headers:true>"
- def inspect
- str = ["#<", self.class.to_s, " io_type:"]
- # show type of wrapped IO
- if @io == $stdout then str << "$stdout"
- elsif @io == $stdin then str << "$stdin"
- elsif @io == $stderr then str << "$stderr"
- else str << @io.class.to_s
- end
- # show IO.path(), if available
- if @io.respond_to?(:path) and (p = @io.path)
- str << " io_path:" << p.inspect
- end
- # show encoding
- str << " encoding:" << @encoding.name
- # show other attributes
- ["lineno", "col_sep", "row_sep", "quote_char"].each do |attr_name|
- if a = __send__(attr_name)
- str << " " << attr_name << ":" << a.inspect
- end
- end
- ["skip_blanks", "liberal_parsing"].each do |attr_name|
- if a = __send__("#{attr_name}?")
- str << " " << attr_name << ":" << a.inspect
- end
- end
- _headers = headers
- str << " headers:" << _headers.inspect if _headers
- str << ">"
- begin
- str.join('')
- rescue # any encoding error
- str.map do |s|
- e = Encoding::Converter.asciicompat_encoding(s.encoding)
- e ? s.encode(e) : s.force_encoding("ASCII-8BIT")
- end.join('')
- end
- end
-
- private
-
- def determine_encoding(encoding, internal_encoding)
- # honor the IO encoding if we can, otherwise default to ASCII-8BIT
- io_encoding = raw_encoding
- return io_encoding if io_encoding
-
- return Encoding.find(internal_encoding) if internal_encoding
-
- if encoding
- encoding, = encoding.split(":", 2) if encoding.is_a?(String)
- return Encoding.find(encoding)
- end
-
- Encoding.default_internal || Encoding.default_external
- end
-
- def normalize_converters(converters)
- converters ||= []
- unless converters.is_a?(Array)
- converters = [converters]
- end
- converters.collect do |converter|
- case converter
- when Proc # custom code block
- [nil, converter]
- else # by name
- [converter, nil]
- end
- end
- end
-
- #
- # Processes +fields+ with <tt>@converters</tt>, or <tt>@header_converters</tt>
- # if +headers+ is passed as +true+, returning the converted field set. Any
- # converter that changes the field into something other than a String halts
- # the pipeline of conversion for that field. This is primarily an efficiency
- # shortcut.
- #
- def convert_fields(fields, headers = false)
- if headers
- header_fields_converter.convert(fields, nil, 0)
- else
- parser_fields_converter.convert(fields, @headers, lineno)
- end
- end
-
- #
- # Returns the encoding of the internal IO object.
- #
- def raw_encoding
- if @io.respond_to? :internal_encoding
- @io.internal_encoding || @io.external_encoding
- elsif @io.respond_to? :encoding
- @io.encoding
- else
- nil
- end
- end
-
- def parser_fields_converter
- @parser_fields_converter ||= build_parser_fields_converter
- end
-
- def build_parser_fields_converter
- specific_options = {
- builtin_converters_name: :Converters,
- }
- options = @base_fields_converter_options.merge(specific_options)
- build_fields_converter(@initial_converters, options)
- end
-
- def header_fields_converter
- @header_fields_converter ||= build_header_fields_converter
- end
-
- def build_header_fields_converter
- specific_options = {
- builtin_converters_name: :HeaderConverters,
- accept_nil: true,
- }
- options = @base_fields_converter_options.merge(specific_options)
- build_fields_converter(@initial_header_converters, options)
- end
-
- def writer_fields_converter
- @writer_fields_converter ||= build_writer_fields_converter
- end
-
- def build_writer_fields_converter
- build_fields_converter(@initial_write_converters,
- @write_fields_converter_options)
- end
-
- def build_fields_converter(initial_converters, options)
- fields_converter = FieldsConverter.new(options)
- normalize_converters(initial_converters).each do |name, converter|
- fields_converter.add_converter(name, &converter)
- end
- fields_converter
- end
-
- def parser
- @parser ||= Parser.new(@io, parser_options)
- end
-
- def parser_options
- @parser_options.merge(header_fields_converter: header_fields_converter,
- fields_converter: parser_fields_converter)
- end
-
- def parser_enumerator
- @parser_enumerator ||= parser.parse
- end
-
- def writer
- @writer ||= Writer.new(@io, writer_options)
- end
-
- def writer_options
- @writer_options.merge(header_fields_converter: header_fields_converter,
- fields_converter: writer_fields_converter)
- end
-end
-
-# Passes +args+ to CSV::instance.
-#
-# CSV("CSV,data").read
-# #=> [["CSV", "data"]]
-#
-# If a block is given, the instance is passed the block and the return value
-# becomes the return value of the block.
-#
-# CSV("CSV,data") { |c|
-# c.read.any? { |a| a.include?("data") }
-# } #=> true
-#
-# CSV("CSV,data") { |c|
-# c.read.any? { |a| a.include?("zombies") }
-# } #=> false
-#
-# CSV options may also be given.
-#
-# io = StringIO.new
-# CSV(io, col_sep: ";") { |csv| csv << ["a", "b", "c"] }
-#
-# This API is not Ractor-safe.
-#
-def CSV(*args, **options, &block)
- CSV.instance(*args, **options, &block)
-end
-
-require_relative "csv/version"
-require_relative "csv/core_ext/array"
-require_relative "csv/core_ext/string"
diff --git a/lib/csv/core_ext/array.rb b/lib/csv/core_ext/array.rb
deleted file mode 100644
index 8beb06b082..0000000000
--- a/lib/csv/core_ext/array.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-class Array # :nodoc:
- # Equivalent to CSV::generate_line(self, options)
- #
- # ["CSV", "data"].to_csv
- # #=> "CSV,data\n"
- def to_csv(**options)
- CSV.generate_line(self, **options)
- end
-end
diff --git a/lib/csv/core_ext/string.rb b/lib/csv/core_ext/string.rb
deleted file mode 100644
index 9b1d31c2a4..0000000000
--- a/lib/csv/core_ext/string.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-class String # :nodoc:
- # Equivalent to CSV::parse_line(self, options)
- #
- # "CSV,data".parse_csv
- # #=> ["CSV", "data"]
- def parse_csv(**options)
- CSV.parse_line(self, **options)
- end
-end
diff --git a/lib/csv/csv.gemspec b/lib/csv/csv.gemspec
deleted file mode 100644
index 11c5b0f2a6..0000000000
--- a/lib/csv/csv.gemspec
+++ /dev/null
@@ -1,64 +0,0 @@
-# frozen_string_literal: true
-
-begin
- require_relative "lib/csv/version"
-rescue LoadError
- # for Ruby core repository
- require_relative "version"
-end
-
-Gem::Specification.new do |spec|
- spec.name = "csv"
- spec.version = CSV::VERSION
- spec.authors = ["James Edward Gray II", "Kouhei Sutou"]
- spec.email = [nil, "kou@cozmixng.org"]
-
- spec.summary = "CSV Reading and Writing"
- spec.description = "The CSV library provides a complete interface to CSV files and data. It offers tools to enable you to read and write to and from Strings or IO objects, as needed."
- spec.homepage = "https://github.com/ruby/csv"
- spec.licenses = ["Ruby", "BSD-2-Clause"]
-
- lib_path = "lib"
- spec.require_paths = [lib_path]
- files = []
- lib_dir = File.join(__dir__, lib_path)
- if File.exist?(lib_dir)
- Dir.chdir(lib_dir) do
- Dir.glob("**/*.rb").each do |file|
- files << "lib/#{file}"
- end
- end
- end
- doc_dir = File.join(__dir__, "doc")
- if File.exist?(doc_dir)
- Dir.chdir(doc_dir) do
- Dir.glob("**/*.rdoc").each do |rdoc_file|
- files << "doc/#{rdoc_file}"
- end
- end
- end
- spec.files = files
- spec.rdoc_options.concat(["--main", "README.md"])
- rdoc_files = [
- "LICENSE.txt",
- "NEWS.md",
- "README.md",
- ]
- recipes_dir = File.join(doc_dir, "csv", "recipes")
- if File.exist?(recipes_dir)
- Dir.chdir(recipes_dir) do
- Dir.glob("**/*.rdoc").each do |recipe_file|
- rdoc_files << "doc/csv/recipes/#{recipe_file}"
- end
- end
- end
- spec.extra_rdoc_files = rdoc_files
-
- spec.required_ruby_version = ">= 2.5.0"
-
- # spec.add_dependency "stringio", ">= 0.1.3"
- spec.add_development_dependency "bundler"
- spec.add_development_dependency "rake"
- spec.add_development_dependency "benchmark_driver"
- spec.add_development_dependency "test-unit", ">= 3.4.8"
-end
diff --git a/lib/csv/fields_converter.rb b/lib/csv/fields_converter.rb
deleted file mode 100644
index d15977d379..0000000000
--- a/lib/csv/fields_converter.rb
+++ /dev/null
@@ -1,89 +0,0 @@
-# frozen_string_literal: true
-
-class CSV
- # Note: Don't use this class directly. This is an internal class.
- class FieldsConverter
- include Enumerable
- #
- # A CSV::FieldsConverter is a data structure for storing the
- # fields converter properties to be passed as a parameter
- # when parsing a new file (e.g. CSV::Parser.new(@io, parser_options))
- #
-
- def initialize(options={})
- @converters = []
- @nil_value = options[:nil_value]
- @empty_value = options[:empty_value]
- @empty_value_is_empty_string = (@empty_value == "")
- @accept_nil = options[:accept_nil]
- @builtin_converters_name = options[:builtin_converters_name]
- @need_static_convert = need_static_convert?
- end
-
- def add_converter(name=nil, &converter)
- if name.nil? # custom converter
- @converters << converter
- else # named converter
- combo = builtin_converters[name]
- case combo
- when Array # combo converter
- combo.each do |sub_name|
- add_converter(sub_name)
- end
- else # individual named converter
- @converters << combo
- end
- end
- end
-
- def each(&block)
- @converters.each(&block)
- end
-
- def empty?
- @converters.empty?
- end
-
- def convert(fields, headers, lineno, quoted_fields)
- return fields unless need_convert?
-
- fields.collect.with_index do |field, index|
- if field.nil?
- field = @nil_value
- elsif field.is_a?(String) and field.empty?
- field = @empty_value unless @empty_value_is_empty_string
- end
- @converters.each do |converter|
- break if field.nil? and @accept_nil
- if converter.arity == 1 # straight field converter
- field = converter[field]
- else # FieldInfo converter
- if headers
- header = headers[index]
- else
- header = nil
- end
- quoted = quoted_fields[index]
- field = converter[field, FieldInfo.new(index, lineno, header, quoted)]
- end
- break unless field.is_a?(String) # short-circuit pipeline for speed
- end
- field # final state of each field, converted or original
- end
- end
-
- private
- def need_static_convert?
- not (@nil_value.nil? and @empty_value_is_empty_string)
- end
-
- def need_convert?
- @need_static_convert or
- (not @converters.empty?)
- end
-
- def builtin_converters
- @builtin_converters ||= ::CSV.const_get(@builtin_converters_name)
- end
- end
-end
diff --git a/lib/csv/input_record_separator.rb b/lib/csv/input_record_separator.rb
deleted file mode 100644
index 7a99343c0c..0000000000
--- a/lib/csv/input_record_separator.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require "English"
-require "stringio"
-
-class CSV
- module InputRecordSeparator
- class << self
- if RUBY_VERSION >= "3.0.0"
- def value
- "\n"
- end
- else
- def value
- $INPUT_RECORD_SEPARATOR
- end
- end
- end
- end
-end
diff --git a/lib/csv/parser.rb b/lib/csv/parser.rb
deleted file mode 100644
index 4da87fbac8..0000000000
--- a/lib/csv/parser.rb
+++ /dev/null
@@ -1,1288 +0,0 @@
-# frozen_string_literal: true
-
-require "strscan"
-
-require_relative "input_record_separator"
-require_relative "row"
-require_relative "table"
-
-class CSV
- # Note: Don't use this class directly. This is an internal class.
- class Parser
- #
- # A CSV::Parser is m17n aware. The parser works in the Encoding of the IO
- # or String object being read from or written to. Your data is never transcoded
- # (unless you ask Ruby to transcode it for you) and will literally be parsed in
- # the Encoding it is in. Thus CSV will return Arrays or Rows of Strings in the
- # Encoding of your data. This is accomplished by transcoding the parser itself
- # into your Encoding.
- #
-
- # Raised when encoding is invalid.
- class InvalidEncoding < StandardError
- end
-
- # Raised when unexpected case is happen.
- class UnexpectedError < StandardError
- end
-
- #
- # CSV::Scanner receives a CSV output, scans it and return the content.
- # It also controls the life cycle of the object with its methods +keep_start+,
- # +keep_end+, +keep_back+, +keep_drop+.
- #
- # Uses StringScanner (the official strscan gem). Strscan provides lexical
- # scanning operations on a String. We inherit its object and take advantage
- # on the methods. For more information, please visit:
- # https://ruby-doc.org/stdlib-2.6.1/libdoc/strscan/rdoc/StringScanner.html
- #
- class Scanner < StringScanner
- alias_method :scan_all, :scan
-
- def initialize(*args)
- super
- @keeps = []
- end
-
- def each_line(row_separator)
- position = pos
- rest.each_line(row_separator) do |line|
- position += line.bytesize
- self.pos = position
- yield(line)
- end
- end
-
- def keep_start
- @keeps.push(pos)
- end
-
- def keep_end
- start = @keeps.pop
- string.byteslice(start, pos - start)
- end
-
- def keep_back
- self.pos = @keeps.pop
- end
-
- def keep_drop
- @keeps.pop
- end
- end
-
- #
- # CSV::InputsScanner receives IO inputs, encoding and the chunk_size.
- # It also controls the life cycle of the object with its methods +keep_start+,
- # +keep_end+, +keep_back+, +keep_drop+.
- #
- # CSV::InputsScanner.scan() tries to match with pattern at the current position.
- # If there's a match, the scanner advances the "scan pointer" and returns the matched string.
- # Otherwise, the scanner returns nil.
- #
- # CSV::InputsScanner.rest() returns the "rest" of the string (i.e. everything after the scan pointer).
- # If there is no more data (eos? = true), it returns "".
- #
- class InputsScanner
- def initialize(inputs, encoding, row_separator, chunk_size: 8192)
- @inputs = inputs.dup
- @encoding = encoding
- @row_separator = row_separator
- @chunk_size = chunk_size
- @last_scanner = @inputs.empty?
- @keeps = []
- read_chunk
- end
-
- def each_line(row_separator)
- return enum_for(__method__, row_separator) unless block_given?
- buffer = nil
- input = @scanner.rest
- position = @scanner.pos
- offset = 0
- n_row_separator_chars = row_separator.size
- # trace(__method__, :start, input)
- while true
- input.each_line(row_separator) do |line|
- @scanner.pos += line.bytesize
- if buffer
- if n_row_separator_chars == 2 and
- buffer.end_with?(row_separator[0]) and
- line.start_with?(row_separator[1])
- buffer << line[0]
- line = line[1..-1]
- position += buffer.bytesize + offset
- @scanner.pos = position
- offset = 0
- yield(buffer)
- buffer = nil
- next if line.empty?
- else
- buffer << line
- line = buffer
- buffer = nil
- end
- end
- if line.end_with?(row_separator)
- position += line.bytesize + offset
- @scanner.pos = position
- offset = 0
- yield(line)
- else
- buffer = line
- end
- end
- break unless read_chunk
- input = @scanner.rest
- position = @scanner.pos
- offset = -buffer.bytesize if buffer
- end
- yield(buffer) if buffer
- end
-
- def scan(pattern)
- # trace(__method__, pattern, :start)
- value = @scanner.scan(pattern)
- # trace(__method__, pattern, :done, :last, value) if @last_scanner
- return value if @last_scanner
-
- read_chunk if value and @scanner.eos?
- # trace(__method__, pattern, :done, value)
- value
- end
-
- def scan_all(pattern)
- # trace(__method__, pattern, :start)
- value = @scanner.scan(pattern)
- # trace(__method__, pattern, :done, :last, value) if @last_scanner
- return value if @last_scanner
-
- # trace(__method__, pattern, :done, :nil) if value.nil?
- return nil if value.nil?
- while @scanner.eos? and read_chunk and (sub_value = @scanner.scan(pattern))
- # trace(__method__, pattern, :sub, sub_value)
- value << sub_value
- end
- # trace(__method__, pattern, :done, value)
- value
- end
-
- def eos?
- @scanner.eos?
- end
-
- def keep_start
- # trace(__method__, :start)
- adjust_last_keep
- @keeps.push([@scanner, @scanner.pos, nil])
- # trace(__method__, :done)
- end
-
- def keep_end
- # trace(__method__, :start)
- scanner, start, buffer = @keeps.pop
- if scanner == @scanner
- keep = @scanner.string.byteslice(start, @scanner.pos - start)
- else
- keep = @scanner.string.byteslice(0, @scanner.pos)
- end
- if buffer
- buffer << keep
- keep = buffer
- end
- # trace(__method__, :done, keep)
- keep
- end
-
- def keep_back
- # trace(__method__, :start)
- scanner, start, buffer = @keeps.pop
- if buffer
- # trace(__method__, :rescan, start, buffer)
- string = @scanner.string
- if scanner == @scanner
- keep = string.byteslice(start,
- string.bytesize - @scanner.pos - start)
- else
- keep = string
- end
- if keep and not keep.empty?
- @inputs.unshift(StringIO.new(keep))
- @last_scanner = false
- end
- @scanner = StringScanner.new(buffer)
- else
- if @scanner != scanner
- message = "scanners are different but no buffer: "
- message += "#{@scanner.inspect}(#{@scanner.object_id}): "
- message += "#{scanner.inspect}(#{scanner.object_id})"
- raise UnexpectedError, message
- end
- # trace(__method__, :repos, start, buffer)
- @scanner.pos = start
- end
- read_chunk if @scanner.eos?
- end
-
- def keep_drop
- _, _, buffer = @keeps.pop
- # trace(__method__, :done, :empty) unless buffer
- return unless buffer
-
- last_keep = @keeps.last
- # trace(__method__, :done, :no_last_keep) unless last_keep
- return unless last_keep
-
- if last_keep[2]
- last_keep[2] << buffer
- else
- last_keep[2] = buffer
- end
- # trace(__method__, :done)
- end
-
- def rest
- @scanner.rest
- end
-
- def check(pattern)
- @scanner.check(pattern)
- end
-
- private
- def trace(*args)
- pp([*args, @scanner, @scanner&.string, @scanner&.pos, @keeps])
- end
-
- def adjust_last_keep
- # trace(__method__, :start)
-
- keep = @keeps.last
- # trace(__method__, :done, :empty) if keep.nil?
- return if keep.nil?
-
- scanner, start, buffer = keep
- string = @scanner.string
- if @scanner != scanner
- start = 0
- end
- if start == 0 and @scanner.eos?
- keep_data = string
- else
- keep_data = string.byteslice(start, @scanner.pos - start)
- end
- if keep_data
- if buffer
- buffer << keep_data
- else
- keep[2] = keep_data.dup
- end
- end
-
- # trace(__method__, :done)
- end
-
- def read_chunk
- return false if @last_scanner
-
- adjust_last_keep
-
- input = @inputs.first
- case input
- when StringIO
- string = input.read
- raise InvalidEncoding unless string.valid_encoding?
- # trace(__method__, :stringio, string)
- @scanner = StringScanner.new(string)
- @inputs.shift
- @last_scanner = @inputs.empty?
- true
- else
- chunk = input.gets(@row_separator, @chunk_size)
- if chunk
- raise InvalidEncoding unless chunk.valid_encoding?
- # trace(__method__, :chunk, chunk)
- @scanner = StringScanner.new(chunk)
- if input.respond_to?(:eof?) and input.eof?
- @inputs.shift
- @last_scanner = @inputs.empty?
- end
- true
- else
- # trace(__method__, :no_chunk)
- @scanner = StringScanner.new("".encode(@encoding))
- @inputs.shift
- @last_scanner = @inputs.empty?
- if @last_scanner
- false
- else
- read_chunk
- end
- end
- end
- end
- end
-
- def initialize(input, options)
- @input = input
- @options = options
- @samples = []
-
- prepare
- end
-
- def column_separator
- @column_separator
- end
-
- def row_separator
- @row_separator
- end
-
- def quote_character
- @quote_character
- end
-
- def field_size_limit
- @max_field_size&.succ
- end
-
- def max_field_size
- @max_field_size
- end
-
- def skip_lines
- @skip_lines
- end
-
- def unconverted_fields?
- @unconverted_fields
- end
-
- def headers
- @headers
- end
-
- def header_row?
- @use_headers and @headers.nil?
- end
-
- def return_headers?
- @return_headers
- end
-
- def skip_blanks?
- @skip_blanks
- end
-
- def liberal_parsing?
- @liberal_parsing
- end
-
- def lineno
- @lineno
- end
-
- def line
- last_line
- end
-
- def parse(&block)
- return to_enum(__method__) unless block_given?
-
- if @return_headers and @headers and @raw_headers
- headers = Row.new(@headers, @raw_headers, true)
- if @unconverted_fields
- headers = add_unconverted_fields(headers, [])
- end
- yield headers
- end
-
- begin
- @scanner ||= build_scanner
- if quote_character.nil?
- parse_no_quote(&block)
- elsif @need_robust_parsing
- parse_quotable_robust(&block)
- else
- parse_quotable_loose(&block)
- end
- rescue InvalidEncoding
- if @scanner
- ignore_broken_line
- lineno = @lineno
- else
- lineno = @lineno + 1
- end
- raise InvalidEncodingError.new(@encoding, lineno)
- rescue UnexpectedError => error
- if @scanner
- ignore_broken_line
- lineno = @lineno
- else
- lineno = @lineno + 1
- end
- message = "This should not be happen: #{error.message}: "
- message += "Please report this to https://github.com/ruby/csv/issues"
- raise MalformedCSVError.new(message, lineno)
- end
- end
-
- def use_headers?
- @use_headers
- end
-
- private
- # A set of tasks to prepare the file in order to parse it
- def prepare
- prepare_variable
- prepare_quote_character
- prepare_backslash
- prepare_skip_lines
- prepare_strip
- prepare_separators
- validate_strip_and_col_sep_options
- prepare_quoted
- prepare_unquoted
- prepare_line
- prepare_header
- prepare_parser
- end
-
- def prepare_variable
- @need_robust_parsing = false
- @encoding = @options[:encoding]
- liberal_parsing = @options[:liberal_parsing]
- if liberal_parsing
- @liberal_parsing = true
- if liberal_parsing.is_a?(Hash)
- @double_quote_outside_quote =
- liberal_parsing[:double_quote_outside_quote]
- @backslash_quote = liberal_parsing[:backslash_quote]
- else
- @double_quote_outside_quote = false
- @backslash_quote = false
- end
- @need_robust_parsing = true
- else
- @liberal_parsing = false
- @backslash_quote = false
- end
- @unconverted_fields = @options[:unconverted_fields]
- @max_field_size = @options[:max_field_size]
- @skip_blanks = @options[:skip_blanks]
- @fields_converter = @options[:fields_converter]
- @header_fields_converter = @options[:header_fields_converter]
- end
-
- def prepare_quote_character
- @quote_character = @options[:quote_character]
- if @quote_character.nil?
- @escaped_quote_character = nil
- @escaped_quote = nil
- else
- @quote_character = @quote_character.to_s.encode(@encoding)
- if @quote_character.length != 1
- message = ":quote_char has to be nil or a single character String"
- raise ArgumentError, message
- end
- @escaped_quote_character = Regexp.escape(@quote_character)
- @escaped_quote = Regexp.new(@escaped_quote_character)
- end
- end
-
- def prepare_backslash
- return unless @backslash_quote
-
- @backslash_character = "\\".encode(@encoding)
-
- @escaped_backslash_character = Regexp.escape(@backslash_character)
- @escaped_backslash = Regexp.new(@escaped_backslash_character)
- if @quote_character.nil?
- @backslash_quote_character = nil
- else
- @backslash_quote_character =
- @backslash_character + @escaped_quote_character
- end
- end
-
- def prepare_skip_lines
- skip_lines = @options[:skip_lines]
- case skip_lines
- when String
- @skip_lines = skip_lines.encode(@encoding)
- when Regexp, nil
- @skip_lines = skip_lines
- else
- unless skip_lines.respond_to?(:match)
- message =
- ":skip_lines has to respond to \#match: #{skip_lines.inspect}"
- raise ArgumentError, message
- end
- @skip_lines = skip_lines
- end
- end
-
- def prepare_strip
- @strip = @options[:strip]
- @escaped_strip = nil
- @strip_value = nil
- @rstrip_value = nil
- if @strip.is_a?(String)
- case @strip.length
- when 0
- raise ArgumentError, ":strip must not be an empty String"
- when 1
- # ok
- else
- raise ArgumentError, ":strip doesn't support 2 or more characters yet"
- end
- @strip = @strip.encode(@encoding)
- @escaped_strip = Regexp.escape(@strip)
- if @quote_character
- @strip_value = Regexp.new(@escaped_strip +
- "+".encode(@encoding))
- @rstrip_value = Regexp.new(@escaped_strip +
- "+\\z".encode(@encoding))
- end
- @need_robust_parsing = true
- elsif @strip
- strip_values = " \t\f\v"
- @escaped_strip = strip_values.encode(@encoding)
- if @quote_character
- @strip_value = Regexp.new("[#{strip_values}]+".encode(@encoding))
- @rstrip_value = Regexp.new("[#{strip_values}]+\\z".encode(@encoding))
- end
- @need_robust_parsing = true
- end
- end
-
- begin
- StringScanner.new("x").scan("x")
- rescue TypeError
- STRING_SCANNER_SCAN_ACCEPT_STRING = false
- else
- STRING_SCANNER_SCAN_ACCEPT_STRING = true
- end
-
- def prepare_separators
- column_separator = @options[:column_separator]
- @column_separator = column_separator.to_s.encode(@encoding)
- if @column_separator.size < 1
- message = ":col_sep must be 1 or more characters: "
- message += column_separator.inspect
- raise ArgumentError, message
- end
- @row_separator =
- resolve_row_separator(@options[:row_separator]).encode(@encoding)
-
- @escaped_column_separator = Regexp.escape(@column_separator)
- @escaped_first_column_separator = Regexp.escape(@column_separator[0])
- if @column_separator.size > 1
- @column_end = Regexp.new(@escaped_column_separator)
- @column_ends = @column_separator.each_char.collect do |char|
- Regexp.new(Regexp.escape(char))
- end
- @first_column_separators = Regexp.new(@escaped_first_column_separator +
- "+".encode(@encoding))
- else
- if STRING_SCANNER_SCAN_ACCEPT_STRING
- @column_end = @column_separator
- else
- @column_end = Regexp.new(@escaped_column_separator)
- end
- @column_ends = nil
- @first_column_separators = nil
- end
-
- escaped_row_separator = Regexp.escape(@row_separator)
- @row_end = Regexp.new(escaped_row_separator)
- if @row_separator.size > 1
- @row_ends = @row_separator.each_char.collect do |char|
- Regexp.new(Regexp.escape(char))
- end
- else
- @row_ends = nil
- end
-
- @cr = "\r".encode(@encoding)
- @lf = "\n".encode(@encoding)
- @line_end = Regexp.new("\r\n|\n|\r".encode(@encoding))
- @not_line_end = Regexp.new("[^\r\n]+".encode(@encoding))
- end
-
- # This method verifies that there are no (obvious) ambiguities with the
- # provided +col_sep+ and +strip+ parsing options. For example, if +col_sep+
- # and +strip+ were both equal to +\t+, then there would be no clear way to
- # parse the input.
- def validate_strip_and_col_sep_options
- return unless @strip
-
- if @strip.is_a?(String)
- if @column_separator.start_with?(@strip) || @column_separator.end_with?(@strip)
- raise ArgumentError,
- "The provided strip (#{@escaped_strip}) and " \
- "col_sep (#{@escaped_column_separator}) options are incompatible."
- end
- else
- if Regexp.new("\\A[#{@escaped_strip}]|[#{@escaped_strip}]\\z").match?(@column_separator)
- raise ArgumentError,
- "The provided strip (true) and " \
- "col_sep (#{@escaped_column_separator}) options are incompatible."
- end
- end
- end
-
- def prepare_quoted
- if @quote_character
- @quotes = Regexp.new(@escaped_quote_character +
- "+".encode(@encoding))
- no_quoted_values = @escaped_quote_character.dup
- if @backslash_quote
- no_quoted_values << @escaped_backslash_character
- end
- @quoted_value = Regexp.new("[^".encode(@encoding) +
- no_quoted_values +
- "]+".encode(@encoding))
- end
- if @escaped_strip
- @split_column_separator = Regexp.new(@escaped_strip +
- "*".encode(@encoding) +
- @escaped_column_separator +
- @escaped_strip +
- "*".encode(@encoding))
- else
- if @column_separator == " ".encode(@encoding)
- @split_column_separator = Regexp.new(@escaped_column_separator)
- else
- @split_column_separator = @column_separator
- end
- end
- end
-
- def prepare_unquoted
- return if @quote_character.nil?
-
- no_unquoted_values = "\r\n".encode(@encoding)
- no_unquoted_values << @escaped_first_column_separator
- unless @liberal_parsing
- no_unquoted_values << @escaped_quote_character
- end
- @unquoted_value = Regexp.new("[^".encode(@encoding) +
- no_unquoted_values +
- "]+".encode(@encoding))
- end
-
- def resolve_row_separator(separator)
- if separator == :auto
- cr = "\r".encode(@encoding)
- lf = "\n".encode(@encoding)
- if @input.is_a?(StringIO)
- pos = @input.pos
- separator = detect_row_separator(@input.read, cr, lf)
- @input.seek(pos)
- elsif @input.respond_to?(:gets)
- if @input.is_a?(File)
- chunk_size = 32 * 1024
- else
- chunk_size = 1024
- end
- begin
- while separator == :auto
- #
- # if we run out of data, it's probably a single line
- # (ensure will set default value)
- #
- break unless sample = @input.gets(nil, chunk_size)
-
- # extend sample if we're unsure of the line ending
- if sample.end_with?(cr)
- sample << (@input.gets(nil, 1) || "")
- end
-
- @samples << sample
-
- separator = detect_row_separator(sample, cr, lf)
- end
- rescue IOError
- # do nothing: ensure will set default
- end
- end
- separator = InputRecordSeparator.value if separator == :auto
- end
- separator.to_s.encode(@encoding)
- end
-
- def detect_row_separator(sample, cr, lf)
- lf_index = sample.index(lf)
- if lf_index
- cr_index = sample[0, lf_index].index(cr)
- else
- cr_index = sample.index(cr)
- end
- if cr_index and lf_index
- if cr_index + 1 == lf_index
- cr + lf
- elsif cr_index < lf_index
- cr
- else
- lf
- end
- elsif cr_index
- cr
- elsif lf_index
- lf
- else
- :auto
- end
- end
-
- def prepare_line
- @lineno = 0
- @last_line = nil
- @scanner = nil
- end
-
- def last_line
- if @scanner
- @last_line ||= @scanner.keep_end
- else
- @last_line
- end
- end
-
- def prepare_header
- @return_headers = @options[:return_headers]
-
- headers = @options[:headers]
- case headers
- when Array
- @raw_headers = headers
- quoted_fields = [false] * @raw_headers.size
- @use_headers = true
- when String
- @raw_headers, quoted_fields = parse_headers(headers)
- @use_headers = true
- when nil, false
- @raw_headers = nil
- @use_headers = false
- else
- @raw_headers = nil
- @use_headers = true
- end
- if @raw_headers
- @headers = adjust_headers(@raw_headers, quoted_fields)
- else
- @headers = nil
- end
- end
-
- def parse_headers(row)
- quoted_fields = []
- converter = lambda do |field, info|
- quoted_fields << info.quoted?
- field
- end
- headers = CSV.parse_line(row,
- col_sep: @column_separator,
- row_sep: @row_separator,
- quote_char: @quote_character,
- converters: [converter])
- [headers, quoted_fields]
- end
-
- def adjust_headers(headers, quoted_fields)
- adjusted_headers = @header_fields_converter.convert(headers, nil, @lineno, quoted_fields)
- adjusted_headers.each {|h| h.freeze if h.is_a? String}
- adjusted_headers
- end
-
- def prepare_parser
- @may_quoted = may_quoted?
- end
-
- def may_quoted?
- return false if @quote_character.nil?
-
- if @input.is_a?(StringIO)
- pos = @input.pos
- sample = @input.read
- @input.seek(pos)
- else
- return false if @samples.empty?
- sample = @samples.first
- end
- sample[0, 128].index(@quote_character)
- end
-
- class UnoptimizedStringIO # :nodoc:
- def initialize(string)
- @io = StringIO.new(string, "rb:#{string.encoding}")
- end
-
- def gets(*args)
- @io.gets(*args)
- end
-
- def each_line(*args, &block)
- @io.each_line(*args, &block)
- end
-
- def eof?
- @io.eof?
- end
- end
-
- SCANNER_TEST = (ENV["CSV_PARSER_SCANNER_TEST"] == "yes")
- if SCANNER_TEST
- SCANNER_TEST_CHUNK_SIZE_NAME = "CSV_PARSER_SCANNER_TEST_CHUNK_SIZE"
- SCANNER_TEST_CHUNK_SIZE_VALUE = ENV[SCANNER_TEST_CHUNK_SIZE_NAME]
- def build_scanner
- inputs = @samples.collect do |sample|
- UnoptimizedStringIO.new(sample)
- end
- if @input.is_a?(StringIO)
- inputs << UnoptimizedStringIO.new(@input.read)
- else
- inputs << @input
- end
- begin
- chunk_size_value = ENV[SCANNER_TEST_CHUNK_SIZE_NAME]
- rescue # Ractor::IsolationError
- # Ractor on Ruby 3.0 can't read ENV value.
- chunk_size_value = SCANNER_TEST_CHUNK_SIZE_VALUE
- end
- chunk_size = Integer((chunk_size_value || "1"), 10)
- InputsScanner.new(inputs,
- @encoding,
- @row_separator,
- chunk_size: chunk_size)
- end
- else
- def build_scanner
- string = nil
- if @samples.empty? and @input.is_a?(StringIO)
- string = @input.read
- elsif @samples.size == 1 and
- @input != ARGF and
- @input.respond_to?(:eof?) and
- @input.eof?
- string = @samples[0]
- end
- if string
- unless string.valid_encoding?
- index = string.lines(@row_separator).index do |line|
- !line.valid_encoding?
- end
- if index
- raise InvalidEncodingError.new(@encoding, @lineno + index + 1)
- end
- end
- Scanner.new(string)
- else
- inputs = @samples.collect do |sample|
- StringIO.new(sample)
- end
- inputs << @input
- InputsScanner.new(inputs, @encoding, @row_separator)
- end
- end
- end
-
- def skip_needless_lines
- return unless @skip_lines
-
- until @scanner.eos?
- @scanner.keep_start
- line = @scanner.scan_all(@not_line_end) || "".encode(@encoding)
- line << @row_separator if parse_row_end
- if skip_line?(line)
- @lineno += 1
- @scanner.keep_drop
- else
- @scanner.keep_back
- return
- end
- end
- end
-
- def skip_line?(line)
- line = line.delete_suffix(@row_separator)
- case @skip_lines
- when String
- line.include?(@skip_lines)
- when Regexp
- @skip_lines.match?(line)
- else
- @skip_lines.match(line)
- end
- end
-
- def validate_field_size(field)
- return unless @max_field_size
- return if field.size <= @max_field_size
- ignore_broken_line
- message = "Field size exceeded: #{field.size} > #{@max_field_size}"
- raise MalformedCSVError.new(message, @lineno)
- end
-
- def parse_no_quote(&block)
- @scanner.each_line(@row_separator) do |line|
- next if @skip_lines and skip_line?(line)
- original_line = line
- line = line.delete_suffix(@row_separator)
-
- if line.empty?
- next if @skip_blanks
- row = []
- quoted_fields = []
- else
- line = strip_value(line)
- row = line.split(@split_column_separator, -1)
- quoted_fields = [false] * row.size
- if @max_field_size
- row.each do |column|
- validate_field_size(column)
- end
- end
- n_columns = row.size
- i = 0
- while i < n_columns
- row[i] = nil if row[i].empty?
- i += 1
- end
- end
- @last_line = original_line
- emit_row(row, quoted_fields, &block)
- end
- end
-
- def parse_quotable_loose(&block)
- @scanner.keep_start
- @scanner.each_line(@row_separator) do |line|
- if @skip_lines and skip_line?(line)
- @scanner.keep_drop
- @scanner.keep_start
- next
- end
- original_line = line
- line = line.delete_suffix(@row_separator)
-
- if line.empty?
- if @skip_blanks
- @scanner.keep_drop
- @scanner.keep_start
- next
- end
- row = []
- quoted_fields = []
- elsif line.include?(@cr) or line.include?(@lf)
- @scanner.keep_back
- @need_robust_parsing = true
- return parse_quotable_robust(&block)
- else
- row = line.split(@split_column_separator, -1)
- quoted_fields = []
- n_columns = row.size
- i = 0
- while i < n_columns
- column = row[i]
- if column.empty?
- quoted_fields << false
- row[i] = nil
- else
- n_quotes = column.count(@quote_character)
- if n_quotes.zero?
- quoted_fields << false
- # no quote
- elsif n_quotes == 2 and
- column.start_with?(@quote_character) and
- column.end_with?(@quote_character)
- quoted_fields << true
- row[i] = column[1..-2]
- else
- @scanner.keep_back
- @need_robust_parsing = true
- return parse_quotable_robust(&block)
- end
- validate_field_size(row[i])
- end
- i += 1
- end
- end
- @scanner.keep_drop
- @scanner.keep_start
- @last_line = original_line
- emit_row(row, quoted_fields, &block)
- end
- @scanner.keep_drop
- end
-
- def parse_quotable_robust(&block)
- row = []
- quoted_fields = []
- skip_needless_lines
- start_row
- while true
- @quoted_column_value = false
- @unquoted_column_value = false
- @scanner.scan_all(@strip_value) if @strip_value
- value = parse_column_value
- if value
- @scanner.scan_all(@strip_value) if @strip_value
- validate_field_size(value)
- end
- if parse_column_end
- row << value
- quoted_fields << @quoted_column_value
- elsif parse_row_end
- if row.empty? and value.nil?
- emit_row([], [], &block) unless @skip_blanks
- else
- row << value
- quoted_fields << @quoted_column_value
- emit_row(row, quoted_fields, &block)
- row = []
- quoted_fields = []
- end
- skip_needless_lines
- start_row
- elsif @scanner.eos?
- break if row.empty? and value.nil?
- row << value
- quoted_fields << @quoted_column_value
- emit_row(row, quoted_fields, &block)
- break
- else
- if @quoted_column_value
- if liberal_parsing? and (new_line = @scanner.check(@line_end))
- message =
- "Illegal end-of-line sequence outside of a quoted field " +
- "<#{new_line.inspect}>"
- else
- message = "Any value after quoted field isn't allowed"
- end
- ignore_broken_line
- raise MalformedCSVError.new(message, @lineno)
- elsif @unquoted_column_value and
- (new_line = @scanner.scan(@line_end))
- ignore_broken_line
- message = "Unquoted fields do not allow new line " +
- "<#{new_line.inspect}>"
- raise MalformedCSVError.new(message, @lineno)
- elsif @scanner.rest.start_with?(@quote_character)
- ignore_broken_line
- message = "Illegal quoting"
- raise MalformedCSVError.new(message, @lineno)
- elsif (new_line = @scanner.scan(@line_end))
- ignore_broken_line
- message = "New line must be <#{@row_separator.inspect}> " +
- "not <#{new_line.inspect}>"
- raise MalformedCSVError.new(message, @lineno)
- else
- ignore_broken_line
- raise MalformedCSVError.new("TODO: Meaningful message",
- @lineno)
- end
- end
- end
- end
-
- def parse_column_value
- if @liberal_parsing
- quoted_value = parse_quoted_column_value
- if quoted_value
- @scanner.scan_all(@strip_value) if @strip_value
- unquoted_value = parse_unquoted_column_value
- if unquoted_value
- if @double_quote_outside_quote
- unquoted_value = unquoted_value.gsub(@quote_character * 2,
- @quote_character)
- if quoted_value.empty? # %Q{""...} case
- return @quote_character + unquoted_value
- end
- end
- @quote_character + quoted_value + @quote_character + unquoted_value
- else
- quoted_value
- end
- else
- parse_unquoted_column_value
- end
- elsif @may_quoted
- parse_quoted_column_value ||
- parse_unquoted_column_value
- else
- parse_unquoted_column_value ||
- parse_quoted_column_value
- end
- end
-
- def parse_unquoted_column_value
- value = @scanner.scan_all(@unquoted_value)
- return nil unless value
-
- @unquoted_column_value = true
- if @first_column_separators
- while true
- @scanner.keep_start
- is_column_end = @column_ends.all? do |column_end|
- @scanner.scan(column_end)
- end
- @scanner.keep_back
- break if is_column_end
- sub_separator = @scanner.scan_all(@first_column_separators)
- break if sub_separator.nil?
- value << sub_separator
- sub_value = @scanner.scan_all(@unquoted_value)
- break if sub_value.nil?
- value << sub_value
- end
- end
- value.gsub!(@backslash_quote_character, @quote_character) if @backslash_quote
- if @rstrip_value
- value.gsub!(@rstrip_value, "")
- end
- value
- end
-
- def parse_quoted_column_value
- quotes = @scanner.scan_all(@quotes)
- return nil unless quotes
-
- @quoted_column_value = true
- n_quotes = quotes.size
- if (n_quotes % 2).zero?
- quotes[0, (n_quotes - 2) / 2]
- else
- value = quotes[0, n_quotes / 2]
- while true
- quoted_value = @scanner.scan_all(@quoted_value)
- value << quoted_value if quoted_value
- if @backslash_quote
- if @scanner.scan(@escaped_backslash)
- if @scanner.scan(@escaped_quote)
- value << @quote_character
- else
- value << @backslash_character
- end
- next
- end
- end
-
- quotes = @scanner.scan_all(@quotes)
- unless quotes
- ignore_broken_line
- message = "Unclosed quoted field"
- raise MalformedCSVError.new(message, @lineno)
- end
- n_quotes = quotes.size
- if n_quotes == 1
- break
- else
- value << quotes[0, n_quotes / 2]
- break if (n_quotes % 2) == 1
- end
- end
- value
- end
- end
-
- def parse_column_end
- return true if @scanner.scan(@column_end)
- return false unless @column_ends
-
- @scanner.keep_start
- if @column_ends.all? {|column_end| @scanner.scan(column_end)}
- @scanner.keep_drop
- true
- else
- @scanner.keep_back
- false
- end
- end
-
- def parse_row_end
- return true if @scanner.scan(@row_end)
- return false unless @row_ends
- @scanner.keep_start
- if @row_ends.all? {|row_end| @scanner.scan(row_end)}
- @scanner.keep_drop
- true
- else
- @scanner.keep_back
- false
- end
- end
-
- def strip_value(value)
- return value unless @strip
- return value if value.nil?
-
- case @strip
- when String
- while value.delete_prefix!(@strip)
- # do nothing
- end
- while value.delete_suffix!(@strip)
- # do nothing
- end
- else
- value.strip!
- end
- value
- end
-
- def ignore_broken_line
- @scanner.scan_all(@not_line_end)
- @scanner.scan_all(@line_end)
- @lineno += 1
- end
-
- def start_row
- if @last_line
- @last_line = nil
- else
- @scanner.keep_drop
- end
- @scanner.keep_start
- end
-
- def emit_row(row, quoted_fields, &block)
- @lineno += 1
-
- raw_row = row
- if @use_headers
- if @headers.nil?
- @headers = adjust_headers(row, quoted_fields)
- return unless @return_headers
- row = Row.new(@headers, row, true)
- else
- row = Row.new(@headers,
- @fields_converter.convert(raw_row, @headers, @lineno, quoted_fields))
- end
- else
- # convert fields, if needed...
- row = @fields_converter.convert(raw_row, nil, @lineno, quoted_fields)
- end
-
- # inject unconverted fields and accessor, if requested...
- if @unconverted_fields and not row.respond_to?(:unconverted_fields)
- add_unconverted_fields(row, raw_row)
- end
-
- yield(row)
- end
-
- # This method injects an instance variable <tt>unconverted_fields</tt> into
- # +row+ and an accessor method for +row+ called unconverted_fields(). The
- # variable is set to the contents of +fields+.
- def add_unconverted_fields(row, fields)
- class << row
- attr_reader :unconverted_fields
- end
- row.instance_variable_set(:@unconverted_fields, fields)
- row
- end
- end
-end
diff --git a/lib/csv/row.rb b/lib/csv/row.rb
deleted file mode 100644
index 86323f7d0a..0000000000
--- a/lib/csv/row.rb
+++ /dev/null
@@ -1,757 +0,0 @@
-# frozen_string_literal: true
-
-require "forwardable"
-
-class CSV
- # = \CSV::Row
- # A \CSV::Row instance represents a \CSV table row.
- # (see {class CSV}[../CSV.html]).
- #
- # The instance may have:
- # - Fields: each is an object, not necessarily a \String.
- # - Headers: each serves a key, and also need not be a \String.
- #
- # === Instance Methods
- #
- # \CSV::Row has three groups of instance methods:
- # - Its own internally defined instance methods.
- # - Methods included by module Enumerable.
- # - Methods delegated to class Array.:
- # * Array#empty?
- # * Array#length
- # * Array#size
- #
- # == Creating a \CSV::Row Instance
- #
- # Commonly, a new \CSV::Row instance is created by parsing \CSV source
- # that has headers:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # table.each {|row| p row }
- # Output:
- # #<CSV::Row "Name":"foo" "Value":"0">
- # #<CSV::Row "Name":"bar" "Value":"1">
- # #<CSV::Row "Name":"baz" "Value":"2">
- #
- # You can also create a row directly. See ::new.
- #
- # == Headers
- #
- # Like a \CSV::Table, a \CSV::Row has headers.
- #
- # A \CSV::Row that was created by parsing \CSV source
- # inherits its headers from the table:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # row = table.first
- # row.headers # => ["Name", "Value"]
- #
- # You can also create a new row with headers;
- # like the keys in a \Hash, the headers need not be Strings:
- # row = CSV::Row.new([:name, :value], ['foo', 0])
- # row.headers # => [:name, :value]
- #
- # The new row retains its headers even if added to a table
- # that has headers:
- # table << row # => #<CSV::Table mode:col_or_row row_count:5>
- # row.headers # => [:name, :value]
- # row[:name] # => "foo"
- # row['Name'] # => nil
- #
- #
- #
- # == Accessing Fields
- #
- # You may access a field in a \CSV::Row with either its \Integer index
- # (\Array-style) or its header (\Hash-style).
- #
- # Fetch a field using method #[]:
- # row = CSV::Row.new(['Name', 'Value'], ['foo', 0])
- # row[1] # => 0
- # row['Value'] # => 0
- #
- # Set a field using method #[]=:
- # row = CSV::Row.new(['Name', 'Value'], ['foo', 0])
- # row # => #<CSV::Row "Name":"foo" "Value":0>
- # row[0] = 'bar'
- # row['Value'] = 1
- # row # => #<CSV::Row "Name":"bar" "Value":1>
- #
- class Row
- # :call-seq:
- # CSV::Row.new(headers, fields, header_row = false) -> csv_row
- #
- # Returns the new \CSV::Row instance constructed from
- # arguments +headers+ and +fields+; both should be Arrays;
- # note that the fields need not be Strings:
- # row = CSV::Row.new(['Name', 'Value'], ['foo', 0])
- # row # => #<CSV::Row "Name":"foo" "Value":0>
- #
- # If the \Array lengths are different, the shorter is +nil+-filled:
- # row = CSV::Row.new(['Name', 'Value', 'Date', 'Size'], ['foo', 0])
- # row # => #<CSV::Row "Name":"foo" "Value":0 "Date":nil "Size":nil>
- #
- # Each \CSV::Row object is either a <i>field row</i> or a <i>header row</i>;
- # by default, a new row is a field row; for the row created above:
- # row.field_row? # => true
- # row.header_row? # => false
- #
- # If the optional argument +header_row+ is given as +true+,
- # the created row is a header row:
- # row = CSV::Row.new(['Name', 'Value'], ['foo', 0], header_row = true)
- # row # => #<CSV::Row "Name":"foo" "Value":0>
- # row.field_row? # => false
- # row.header_row? # => true
- def initialize(headers, fields, header_row = false)
- @header_row = header_row
- headers.each { |h| h.freeze if h.is_a? String }
-
- # handle extra headers or fields
- @row = if headers.size >= fields.size
- headers.zip(fields)
- else
- fields.zip(headers).each(&:reverse!)
- end
- end
-
- # Internal data format used to compare equality.
- attr_reader :row
- protected :row
-
- ### Array Delegation ###
-
- extend Forwardable
- def_delegators :@row, :empty?, :length, :size
-
- # :call-seq:
- # row.initialize_copy(other_row) -> self
- #
- # Calls superclass method.
- def initialize_copy(other)
- super_return_value = super
- @row = @row.collect(&:dup)
- super_return_value
- end
-
- # :call-seq:
- # row.header_row? -> true or false
- #
- # Returns +true+ if this is a header row, +false+ otherwise.
- def header_row?
- @header_row
- end
-
- # :call-seq:
- # row.field_row? -> true or false
- #
- # Returns +true+ if this is a field row, +false+ otherwise.
- def field_row?
- not header_row?
- end
-
- # :call-seq:
- # row.headers -> array_of_headers
- #
- # Returns the headers for this row:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # row = table.first
- # row.headers # => ["Name", "Value"]
- def headers
- @row.map(&:first)
- end
-
- # :call-seq:
- # field(index) -> value
- # field(header) -> value
- # field(header, offset) -> value
- #
- # Returns the field value for the given +index+ or +header+.
- #
- # ---
- #
- # Fetch field value by \Integer index:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row.field(0) # => "foo"
- # row.field(1) # => "bar"
- #
- # Counts backward from the last column if +index+ is negative:
- # row.field(-1) # => "0"
- # row.field(-2) # => "foo"
- #
- # Returns +nil+ if +index+ is out of range:
- # row.field(2) # => nil
- # row.field(-3) # => nil
- #
- # ---
- #
- # Fetch field value by header (first found):
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row.field('Name') # => "Foo"
- #
- # Fetch field value by header, ignoring +offset+ leading fields:
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row.field('Name', 2) # => "Baz"
- #
- # Returns +nil+ if the header does not exist.
- def field(header_or_index, minimum_index = 0)
- # locate the pair
- finder = (header_or_index.is_a?(Integer) || header_or_index.is_a?(Range)) ? :[] : :assoc
- pair = @row[minimum_index..-1].public_send(finder, header_or_index)
-
- # return the field if we have a pair
- if pair.nil?
- nil
- else
- header_or_index.is_a?(Range) ? pair.map(&:last) : pair.last
- end
- end
- alias_method :[], :field
-
- #
- # :call-seq:
- # fetch(header) -> value
- # fetch(header, default) -> value
- # fetch(header) {|row| ... } -> value
- #
- # Returns the field value as specified by +header+.
- #
- # ---
- #
- # With the single argument +header+, returns the field value
- # for that header (first found):
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row.fetch('Name') # => "Foo"
- #
- # Raises exception +KeyError+ if the header does not exist.
- #
- # ---
- #
- # With arguments +header+ and +default+ given,
- # returns the field value for the header (first found)
- # if the header exists, otherwise returns +default+:
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row.fetch('Name', '') # => "Foo"
- # row.fetch(:nosuch, '') # => ""
- #
- # ---
- #
- # With argument +header+ and a block given,
- # returns the field value for the header (first found)
- # if the header exists; otherwise calls the block
- # and returns its return value:
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row.fetch('Name') {|header| fail 'Cannot happen' } # => "Foo"
- # row.fetch(:nosuch) {|header| "Header '#{header} not found'" } # => "Header 'nosuch not found'"
- def fetch(header, *varargs)
- raise ArgumentError, "Too many arguments" if varargs.length > 1
- pair = @row.assoc(header)
- if pair
- pair.last
- else
- if block_given?
- yield header
- elsif varargs.empty?
- raise KeyError, "key not found: #{header}"
- else
- varargs.first
- end
- end
- end
-
- # :call-seq:
- # row.has_key?(header) -> true or false
- #
- # Returns +true+ if there is a field with the given +header+,
- # +false+ otherwise.
- def has_key?(header)
- !!@row.assoc(header)
- end
- alias_method :include?, :has_key?
- alias_method :key?, :has_key?
- alias_method :member?, :has_key?
- alias_method :header?, :has_key?
-
- #
- # :call-seq:
- # row[index] = value -> value
- # row[header, offset] = value -> value
- # row[header] = value -> value
- #
- # Assigns the field value for the given +index+ or +header+;
- # returns +value+.
- #
- # ---
- #
- # Assign field value by \Integer index:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row[0] = 'Bat'
- # row[1] = 3
- # row # => #<CSV::Row "Name":"Bat" "Value":3>
- #
- # Counts backward from the last column if +index+ is negative:
- # row[-1] = 4
- # row[-2] = 'Bam'
- # row # => #<CSV::Row "Name":"Bam" "Value":4>
- #
- # Extends the row with <tt>nil:nil</tt> if positive +index+ is not in the row:
- # row[4] = 5
- # row # => #<CSV::Row "Name":"bad" "Value":4 nil:nil nil:nil nil:5>
- #
- # Raises IndexError if negative +index+ is too small (too far from zero).
- #
- # ---
- #
- # Assign field value by header (first found):
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row['Name'] = 'Bat'
- # row # => #<CSV::Row "Name":"Bat" "Name":"Bar" "Name":"Baz">
- #
- # Assign field value by header, ignoring +offset+ leading fields:
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row['Name', 2] = 4
- # row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":4>
- #
- # Append new field by (new) header:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row['New'] = 6
- # row# => #<CSV::Row "Name":"foo" "Value":"0" "New":6>
- def []=(*args)
- value = args.pop
-
- if args.first.is_a? Integer
- if @row[args.first].nil? # extending past the end with index
- @row[args.first] = [nil, value]
- @row.map! { |pair| pair.nil? ? [nil, nil] : pair }
- else # normal index assignment
- @row[args.first][1] = value
- end
- else
- index = index(*args)
- if index.nil? # appending a field
- self << [args.first, value]
- else # normal header assignment
- @row[index][1] = value
- end
- end
- end
-
- #
- # :call-seq:
- # row << [header, value] -> self
- # row << hash -> self
- # row << value -> self
- #
- # Adds a field to +self+; returns +self+:
- #
- # If the argument is a 2-element \Array <tt>[header, value]</tt>,
- # a field is added with the given +header+ and +value+:
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row << ['NAME', 'Bat']
- # row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" "NAME":"Bat">
- #
- # If the argument is a \Hash, each <tt>key-value</tt> pair is added
- # as a field with header +key+ and value +value+.
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row << {NAME: 'Bat', name: 'Bam'}
- # row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" NAME:"Bat" name:"Bam">
- #
- # Otherwise, the given +value+ is added as a field with no header.
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row << 'Bag'
- # row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" nil:"Bag">
- def <<(arg)
- if arg.is_a?(Array) and arg.size == 2 # appending a header and name
- @row << arg
- elsif arg.is_a?(Hash) # append header and name pairs
- arg.each { |pair| @row << pair }
- else # append field value
- @row << [nil, arg]
- end
-
- self # for chaining
- end
-
- # :call-seq:
- # row.push(*values) -> self
- #
- # Appends each of the given +values+ to +self+ as a field; returns +self+:
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row.push('Bat', 'Bam')
- # row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" nil:"Bat" nil:"Bam">
- def push(*args)
- args.each { |arg| self << arg }
-
- self # for chaining
- end
-
- #
- # :call-seq:
- # delete(index) -> [header, value] or nil
- # delete(header) -> [header, value] or empty_array
- # delete(header, offset) -> [header, value] or empty_array
- #
- # Removes a specified field from +self+; returns the 2-element \Array
- # <tt>[header, value]</tt> if the field exists.
- #
- # If an \Integer argument +index+ is given,
- # removes and returns the field at offset +index+,
- # or returns +nil+ if the field does not exist:
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row.delete(1) # => ["Name", "Bar"]
- # row.delete(50) # => nil
- #
- # Otherwise, if the single argument +header+ is given,
- # removes and returns the first-found field with the given header,
- # of returns a new empty \Array if the field does not exist:
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row.delete('Name') # => ["Name", "Foo"]
- # row.delete('NAME') # => []
- #
- # If argument +header+ and \Integer argument +offset+ are given,
- # removes and returns the first-found field with the given header
- # whose +index+ is at least as large as +offset+:
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row.delete('Name', 1) # => ["Name", "Bar"]
- # row.delete('NAME', 1) # => []
- def delete(header_or_index, minimum_index = 0)
- if header_or_index.is_a? Integer # by index
- @row.delete_at(header_or_index)
- elsif i = index(header_or_index, minimum_index) # by header
- @row.delete_at(i)
- else
- [ ]
- end
- end
-
- # :call-seq:
- # row.delete_if {|header, value| ... } -> self
- #
- # Removes fields from +self+ as selected by the block; returns +self+.
- #
- # Removes each field for which the block returns a truthy value:
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row.delete_if {|header, value| value.start_with?('B') } # => true
- # row # => #<CSV::Row "Name":"Foo">
- # row.delete_if {|header, value| header.start_with?('B') } # => false
- #
- # If no block is given, returns a new Enumerator:
- # row.delete_if # => #<Enumerator: #<CSV::Row "Name":"Foo">:delete_if>
- def delete_if(&block)
- return enum_for(__method__) { size } unless block_given?
-
- @row.delete_if(&block)
-
- self # for chaining
- end
-
- # :call-seq:
- # self.fields(*specifiers) -> array_of_fields
- #
- # Returns field values per the given +specifiers+, which may be any mixture of:
- # - \Integer index.
- # - \Range of \Integer indexes.
- # - 2-element \Array containing a header and offset.
- # - Header.
- # - \Range of headers.
- #
- # For +specifier+ in one of the first four cases above,
- # returns the result of <tt>self.field(specifier)</tt>; see #field.
- #
- # Although there may be any number of +specifiers+,
- # the examples here will illustrate one at a time.
- #
- # When the specifier is an \Integer +index+,
- # returns <tt>self.field(index)</tt>L
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row.fields(1) # => ["Bar"]
- #
- # When the specifier is a \Range of \Integers +range+,
- # returns <tt>self.field(range)</tt>:
- # row.fields(1..2) # => ["Bar", "Baz"]
- #
- # When the specifier is a 2-element \Array +array+,
- # returns <tt>self.field(array)</tt>L
- # row.fields('Name', 1) # => ["Foo", "Bar"]
- #
- # When the specifier is a header +header+,
- # returns <tt>self.field(header)</tt>L
- # row.fields('Name') # => ["Foo"]
- #
- # When the specifier is a \Range of headers +range+,
- # forms a new \Range +new_range+ from the indexes of
- # <tt>range.start</tt> and <tt>range.end</tt>,
- # and returns <tt>self.field(new_range)</tt>:
- # source = "Name,NAME,name\nFoo,Bar,Baz\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row.fields('Name'..'NAME') # => ["Foo", "Bar"]
- #
- # Returns all fields if no argument given:
- # row.fields # => ["Foo", "Bar", "Baz"]
- def fields(*headers_and_or_indices)
- if headers_and_or_indices.empty? # return all fields--no arguments
- @row.map(&:last)
- else # or work like values_at()
- all = []
- headers_and_or_indices.each do |h_or_i|
- if h_or_i.is_a? Range
- index_begin = h_or_i.begin.is_a?(Integer) ? h_or_i.begin :
- index(h_or_i.begin)
- index_end = h_or_i.end.is_a?(Integer) ? h_or_i.end :
- index(h_or_i.end)
- new_range = h_or_i.exclude_end? ? (index_begin...index_end) :
- (index_begin..index_end)
- all.concat(fields.values_at(new_range))
- else
- all << field(*Array(h_or_i))
- end
- end
- return all
- end
- end
- alias_method :values_at, :fields
-
- # :call-seq:
- # index(header) -> index
- # index(header, offset) -> index
- #
- # Returns the index for the given header, if it exists;
- # otherwise returns +nil+.
- #
- # With the single argument +header+, returns the index
- # of the first-found field with the given +header+:
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row.index('Name') # => 0
- # row.index('NAME') # => nil
- #
- # With arguments +header+ and +offset+,
- # returns the index of the first-found field with given +header+,
- # but ignoring the first +offset+ fields:
- # row.index('Name', 1) # => 1
- # row.index('Name', 3) # => nil
- def index(header, minimum_index = 0)
- # find the pair
- index = headers[minimum_index..-1].index(header)
- # return the index at the right offset, if we found one
- index.nil? ? nil : index + minimum_index
- end
-
- # :call-seq:
- # row.field?(value) -> true or false
- #
- # Returns +true+ if +value+ is a field in this row, +false+ otherwise:
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row.field?('Bar') # => true
- # row.field?('BAR') # => false
- def field?(data)
- fields.include? data
- end
-
- include Enumerable
-
- # :call-seq:
- # row.each {|header, value| ... } -> self
- #
- # Calls the block with each header-value pair; returns +self+:
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row.each {|header, value| p [header, value] }
- # Output:
- # ["Name", "Foo"]
- # ["Name", "Bar"]
- # ["Name", "Baz"]
- #
- # If no block is given, returns a new Enumerator:
- # row.each # => #<Enumerator: #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz">:each>
- def each(&block)
- return enum_for(__method__) { size } unless block_given?
-
- @row.each(&block)
-
- self # for chaining
- end
-
- alias_method :each_pair, :each
-
- # :call-seq:
- # row == other -> true or false
- #
- # Returns +true+ if +other+ is a /CSV::Row that has the same
- # fields (headers and values) in the same order as +self+;
- # otherwise returns +false+:
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # other_row = table[0]
- # row == other_row # => true
- # other_row = table[1]
- # row == other_row # => false
- def ==(other)
- return @row == other.row if other.is_a? CSV::Row
- @row == other
- end
-
- # :call-seq:
- # row.to_h -> hash
- #
- # Returns the new \Hash formed by adding each header-value pair in +self+
- # as a key-value pair in the \Hash.
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row.to_h # => {"Name"=>"foo", "Value"=>"0"}
- #
- # Header order is preserved, but repeated headers are ignored:
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row.to_h # => {"Name"=>"Foo"}
- def to_h
- hash = {}
- each do |key, _value|
- hash[key] = self[key] unless hash.key?(key)
- end
- hash
- end
- alias_method :to_hash, :to_h
-
- # :call-seq:
- # row.deconstruct_keys(keys) -> hash
- #
- # Returns the new \Hash suitable for pattern matching containing only the
- # keys specified as an argument.
- def deconstruct_keys(keys)
- if keys.nil?
- to_h
- else
- keys.to_h { |key| [key, self[key]] }
- end
- end
-
- alias_method :to_ary, :to_a
-
- # :call-seq:
- # row.deconstruct -> array
- #
- # Returns the new \Array suitable for pattern matching containing the values
- # of the row.
- def deconstruct
- fields
- end
-
- # :call-seq:
- # row.to_csv -> csv_string
- #
- # Returns the row as a \CSV String. Headers are not included:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row.to_csv # => "foo,0\n"
- def to_csv(**options)
- fields.to_csv(**options)
- end
- alias_method :to_s, :to_csv
-
- # :call-seq:
- # row.dig(index_or_header, *identifiers) -> object
- #
- # Finds and returns the object in nested object that is specified
- # by +index_or_header+ and +specifiers+.
- #
- # The nested objects may be instances of various classes.
- # See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
- #
- # Examples:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row.dig(1) # => "0"
- # row.dig('Value') # => "0"
- # row.dig(5) # => nil
- def dig(index_or_header, *indexes)
- value = field(index_or_header)
- if value.nil?
- nil
- elsif indexes.empty?
- value
- else
- unless value.respond_to?(:dig)
- raise TypeError, "#{value.class} does not have \#dig method"
- end
- value.dig(*indexes)
- end
- end
-
- # :call-seq:
- # row.inspect -> string
- #
- # Returns an ASCII-compatible \String showing:
- # - Class \CSV::Row.
- # - Header-value pairs.
- # Example:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # row = table[0]
- # row.inspect # => "#<CSV::Row \"Name\":\"foo\" \"Value\":\"0\">"
- def inspect
- str = ["#<", self.class.to_s]
- each do |header, field|
- str << " " << (header.is_a?(Symbol) ? header.to_s : header.inspect) <<
- ":" << field.inspect
- end
- str << ">"
- begin
- str.join('')
- rescue # any encoding error
- str.map do |s|
- e = Encoding::Converter.asciicompat_encoding(s.encoding)
- e ? s.encode(e) : s.force_encoding("ASCII-8BIT")
- end.join('')
- end
- end
- end
-end
diff --git a/lib/csv/table.rb b/lib/csv/table.rb
deleted file mode 100644
index fb19f5453f..0000000000
--- a/lib/csv/table.rb
+++ /dev/null
@@ -1,1055 +0,0 @@
-# frozen_string_literal: true
-
-require "forwardable"
-
-class CSV
- # = \CSV::Table
- # A \CSV::Table instance represents \CSV data.
- # (see {class CSV}[../CSV.html]).
- #
- # The instance may have:
- # - Rows: each is a Table::Row object.
- # - Headers: names for the columns.
- #
- # === Instance Methods
- #
- # \CSV::Table has three groups of instance methods:
- # - Its own internally defined instance methods.
- # - Methods included by module Enumerable.
- # - Methods delegated to class Array.:
- # * Array#empty?
- # * Array#length
- # * Array#size
- #
- # == Creating a \CSV::Table Instance
- #
- # Commonly, a new \CSV::Table instance is created by parsing \CSV source
- # using headers:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # table.class # => CSV::Table
- #
- # You can also create an instance directly. See ::new.
- #
- # == Headers
- #
- # If a table has headers, the headers serve as labels for the columns of data.
- # Each header serves as the label for its column.
- #
- # The headers for a \CSV::Table object are stored as an \Array of Strings.
- #
- # Commonly, headers are defined in the first row of \CSV source:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # table.headers # => ["Name", "Value"]
- #
- # If no headers are defined, the \Array is empty:
- # table = CSV::Table.new([])
- # table.headers # => []
- #
- # == Access Modes
- #
- # \CSV::Table provides three modes for accessing table data:
- # - \Row mode.
- # - Column mode.
- # - Mixed mode (the default for a new table).
- #
- # The access mode for a\CSV::Table instance affects the behavior
- # of some of its instance methods:
- # - #[]
- # - #[]=
- # - #delete
- # - #delete_if
- # - #each
- # - #values_at
- #
- # === \Row Mode
- #
- # Set a table to row mode with method #by_row!:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # table.by_row! # => #<CSV::Table mode:row row_count:4>
- #
- # Specify a single row by an \Integer index:
- # # Get a row.
- # table[1] # => #<CSV::Row "Name":"bar" "Value":"1">
- # # Set a row, then get it.
- # table[1] = CSV::Row.new(['Name', 'Value'], ['bam', 3])
- # table[1] # => #<CSV::Row "Name":"bam" "Value":3>
- #
- # Specify a sequence of rows by a \Range:
- # # Get rows.
- # table[1..2] # => [#<CSV::Row "Name":"bam" "Value":3>, #<CSV::Row "Name":"baz" "Value":"2">]
- # # Set rows, then get them.
- # table[1..2] = [
- # CSV::Row.new(['Name', 'Value'], ['bat', 4]),
- # CSV::Row.new(['Name', 'Value'], ['bad', 5]),
- # ]
- # table[1..2] # => [["Name", #<CSV::Row "Name":"bat" "Value":4>], ["Value", #<CSV::Row "Name":"bad" "Value":5>]]
- #
- # === Column Mode
- #
- # Set a table to column mode with method #by_col!:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # table.by_col! # => #<CSV::Table mode:col row_count:4>
- #
- # Specify a column by an \Integer index:
- # # Get a column.
- # table[0]
- # # Set a column, then get it.
- # table[0] = ['FOO', 'BAR', 'BAZ']
- # table[0] # => ["FOO", "BAR", "BAZ"]
- #
- # Specify a column by its \String header:
- # # Get a column.
- # table['Name'] # => ["FOO", "BAR", "BAZ"]
- # # Set a column, then get it.
- # table['Name'] = ['Foo', 'Bar', 'Baz']
- # table['Name'] # => ["Foo", "Bar", "Baz"]
- #
- # === Mixed Mode
- #
- # In mixed mode, you can refer to either rows or columns:
- # - An \Integer index refers to a row.
- # - A \Range index refers to multiple rows.
- # - A \String index refers to a column.
- #
- # Set a table to mixed mode with method #by_col_or_row!:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # table.by_col_or_row! # => #<CSV::Table mode:col_or_row row_count:4>
- #
- # Specify a single row by an \Integer index:
- # # Get a row.
- # table[1] # => #<CSV::Row "Name":"bar" "Value":"1">
- # # Set a row, then get it.
- # table[1] = CSV::Row.new(['Name', 'Value'], ['bam', 3])
- # table[1] # => #<CSV::Row "Name":"bam" "Value":3>
- #
- # Specify a sequence of rows by a \Range:
- # # Get rows.
- # table[1..2] # => [#<CSV::Row "Name":"bam" "Value":3>, #<CSV::Row "Name":"baz" "Value":"2">]
- # # Set rows, then get them.
- # table[1] = CSV::Row.new(['Name', 'Value'], ['bat', 4])
- # table[2] = CSV::Row.new(['Name', 'Value'], ['bad', 5])
- # table[1..2] # => [["Name", #<CSV::Row "Name":"bat" "Value":4>], ["Value", #<CSV::Row "Name":"bad" "Value":5>]]
- #
- # Specify a column by its \String header:
- # # Get a column.
- # table['Name'] # => ["foo", "bat", "bad"]
- # # Set a column, then get it.
- # table['Name'] = ['Foo', 'Bar', 'Baz']
- # table['Name'] # => ["Foo", "Bar", "Baz"]
- class Table
- # :call-seq:
- # CSV::Table.new(array_of_rows, headers = nil) -> csv_table
- #
- # Returns a new \CSV::Table object.
- #
- # - Argument +array_of_rows+ must be an \Array of CSV::Row objects.
- # - Argument +headers+, if given, may be an \Array of Strings.
- #
- # ---
- #
- # Create an empty \CSV::Table object:
- # table = CSV::Table.new([])
- # table # => #<CSV::Table mode:col_or_row row_count:1>
- #
- # Create a non-empty \CSV::Table object:
- # rows = [
- # CSV::Row.new([], []),
- # CSV::Row.new([], []),
- # CSV::Row.new([], []),
- # ]
- # table = CSV::Table.new(rows)
- # table # => #<CSV::Table mode:col_or_row row_count:4>
- #
- # ---
- #
- # If argument +headers+ is an \Array of Strings,
- # those Strings become the table's headers:
- # table = CSV::Table.new([], headers: ['Name', 'Age'])
- # table.headers # => ["Name", "Age"]
- #
- # If argument +headers+ is not given and the table has rows,
- # the headers are taken from the first row:
- # rows = [
- # CSV::Row.new(['Foo', 'Bar'], []),
- # CSV::Row.new(['foo', 'bar'], []),
- # CSV::Row.new(['FOO', 'BAR'], []),
- # ]
- # table = CSV::Table.new(rows)
- # table.headers # => ["Foo", "Bar"]
- #
- # If argument +headers+ is not given and the table is empty (has no rows),
- # the headers are also empty:
- # table = CSV::Table.new([])
- # table.headers # => []
- #
- # ---
- #
- # Raises an exception if argument +array_of_rows+ is not an \Array object:
- # # Raises NoMethodError (undefined method `first' for :foo:Symbol):
- # CSV::Table.new(:foo)
- #
- # Raises an exception if an element of +array_of_rows+ is not a \CSV::Table object:
- # # Raises NoMethodError (undefined method `headers' for :foo:Symbol):
- # CSV::Table.new([:foo])
- def initialize(array_of_rows, headers: nil)
- @table = array_of_rows
- @headers = headers
- unless @headers
- if @table.empty?
- @headers = []
- else
- @headers = @table.first.headers
- end
- end
-
- @mode = :col_or_row
- end
-
- # The current access mode for indexing and iteration.
- attr_reader :mode
-
- # Internal data format used to compare equality.
- attr_reader :table
- protected :table
-
- ### Array Delegation ###
-
- extend Forwardable
- def_delegators :@table, :empty?, :length, :size
-
- # :call-seq:
- # table.by_col -> table_dup
- #
- # Returns a duplicate of +self+, in column mode
- # (see {Column Mode}[#class-CSV::Table-label-Column+Mode]):
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # table.mode # => :col_or_row
- # dup_table = table.by_col
- # dup_table.mode # => :col
- # dup_table.equal?(table) # => false # It's a dup
- #
- # This may be used to chain method calls without changing the mode
- # (but also will affect performance and memory usage):
- # dup_table.by_col['Name']
- #
- # Also note that changes to the duplicate table will not affect the original.
- def by_col
- self.class.new(@table.dup).by_col!
- end
-
- # :call-seq:
- # table.by_col! -> self
- #
- # Sets the mode for +self+ to column mode
- # (see {Column Mode}[#class-CSV::Table-label-Column+Mode]); returns +self+:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # table.mode # => :col_or_row
- # table1 = table.by_col!
- # table.mode # => :col
- # table1.equal?(table) # => true # Returned self
- def by_col!
- @mode = :col
-
- self
- end
-
- # :call-seq:
- # table.by_col_or_row -> table_dup
- #
- # Returns a duplicate of +self+, in mixed mode
- # (see {Mixed Mode}[#class-CSV::Table-label-Mixed+Mode]):
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true).by_col!
- # table.mode # => :col
- # dup_table = table.by_col_or_row
- # dup_table.mode # => :col_or_row
- # dup_table.equal?(table) # => false # It's a dup
- #
- # This may be used to chain method calls without changing the mode
- # (but also will affect performance and memory usage):
- # dup_table.by_col_or_row['Name']
- #
- # Also note that changes to the duplicate table will not affect the original.
- def by_col_or_row
- self.class.new(@table.dup).by_col_or_row!
- end
-
- # :call-seq:
- # table.by_col_or_row! -> self
- #
- # Sets the mode for +self+ to mixed mode
- # (see {Mixed Mode}[#class-CSV::Table-label-Mixed+Mode]); returns +self+:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true).by_col!
- # table.mode # => :col
- # table1 = table.by_col_or_row!
- # table.mode # => :col_or_row
- # table1.equal?(table) # => true # Returned self
- def by_col_or_row!
- @mode = :col_or_row
-
- self
- end
-
- # :call-seq:
- # table.by_row -> table_dup
- #
- # Returns a duplicate of +self+, in row mode
- # (see {Row Mode}[#class-CSV::Table-label-Row+Mode]):
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # table.mode # => :col_or_row
- # dup_table = table.by_row
- # dup_table.mode # => :row
- # dup_table.equal?(table) # => false # It's a dup
- #
- # This may be used to chain method calls without changing the mode
- # (but also will affect performance and memory usage):
- # dup_table.by_row[1]
- #
- # Also note that changes to the duplicate table will not affect the original.
- def by_row
- self.class.new(@table.dup).by_row!
- end
-
- # :call-seq:
- # table.by_row! -> self
- #
- # Sets the mode for +self+ to row mode
- # (see {Row Mode}[#class-CSV::Table-label-Row+Mode]); returns +self+:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # table.mode # => :col_or_row
- # table1 = table.by_row!
- # table.mode # => :row
- # table1.equal?(table) # => true # Returned self
- def by_row!
- @mode = :row
-
- self
- end
-
- # :call-seq:
- # table.headers -> array_of_headers
- #
- # Returns a new \Array containing the \String headers for the table.
- #
- # If the table is not empty, returns the headers from the first row:
- # rows = [
- # CSV::Row.new(['Foo', 'Bar'], []),
- # CSV::Row.new(['FOO', 'BAR'], []),
- # CSV::Row.new(['foo', 'bar'], []),
- # ]
- # table = CSV::Table.new(rows)
- # table.headers # => ["Foo", "Bar"]
- # table.delete(0)
- # table.headers # => ["FOO", "BAR"]
- # table.delete(0)
- # table.headers # => ["foo", "bar"]
- #
- # If the table is empty, returns a copy of the headers in the table itself:
- # table.delete(0)
- # table.headers # => ["Foo", "Bar"]
- def headers
- if @table.empty?
- @headers.dup
- else
- @table.first.headers
- end
- end
-
- # :call-seq:
- # table[n] -> row or column_data
- # table[range] -> array_of_rows or array_of_column_data
- # table[header] -> array_of_column_data
- #
- # Returns data from the table; does not modify the table.
- #
- # ---
- #
- # Fetch a \Row by Its \Integer Index::
- # - Form: <tt>table[n]</tt>, +n+ an integer.
- # - Access mode: <tt>:row</tt> or <tt>:col_or_row</tt>.
- # - Return value: _nth_ row of the table, if that row exists;
- # otherwise +nil+.
- #
- # Returns the _nth_ row of the table if that row exists:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # table.by_row! # => #<CSV::Table mode:row row_count:4>
- # table[1] # => #<CSV::Row "Name":"bar" "Value":"1">
- # table.by_col_or_row! # => #<CSV::Table mode:col_or_row row_count:4>
- # table[1] # => #<CSV::Row "Name":"bar" "Value":"1">
- #
- # Counts backward from the last row if +n+ is negative:
- # table[-1] # => #<CSV::Row "Name":"baz" "Value":"2">
- #
- # Returns +nil+ if +n+ is too large or too small:
- # table[4] # => nil
- # table[-4] # => nil
- #
- # Raises an exception if the access mode is <tt>:row</tt>
- # and +n+ is not an \Integer:
- # table.by_row! # => #<CSV::Table mode:row row_count:4>
- # # Raises TypeError (no implicit conversion of String into Integer):
- # table['Name']
- #
- # ---
- #
- # Fetch a Column by Its \Integer Index::
- # - Form: <tt>table[n]</tt>, +n+ an \Integer.
- # - Access mode: <tt>:col</tt>.
- # - Return value: _nth_ column of the table, if that column exists;
- # otherwise an \Array of +nil+ fields of length <tt>self.size</tt>.
- #
- # Returns the _nth_ column of the table if that column exists:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # table.by_col! # => #<CSV::Table mode:col row_count:4>
- # table[1] # => ["0", "1", "2"]
- #
- # Counts backward from the last column if +n+ is negative:
- # table[-2] # => ["foo", "bar", "baz"]
- #
- # Returns an \Array of +nil+ fields if +n+ is too large or too small:
- # table[4] # => [nil, nil, nil]
- # table[-4] # => [nil, nil, nil]
- #
- # ---
- #
- # Fetch Rows by \Range::
- # - Form: <tt>table[range]</tt>, +range+ a \Range object.
- # - Access mode: <tt>:row</tt> or <tt>:col_or_row</tt>.
- # - Return value: rows from the table, beginning at row <tt>range.start</tt>,
- # if those rows exists.
- #
- # Returns rows from the table, beginning at row <tt>range.first</tt>,
- # if those rows exist:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # table.by_row! # => #<CSV::Table mode:row row_count:4>
- # rows = table[1..2] # => #<CSV::Row "Name":"bar" "Value":"1">
- # rows # => [#<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"baz" "Value":"2">]
- # table.by_col_or_row! # => #<CSV::Table mode:col_or_row row_count:4>
- # rows = table[1..2] # => #<CSV::Row "Name":"bar" "Value":"1">
- # rows # => [#<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"baz" "Value":"2">]
- #
- # If there are too few rows, returns all from <tt>range.start</tt> to the end:
- # rows = table[1..50] # => #<CSV::Row "Name":"bar" "Value":"1">
- # rows # => [#<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"baz" "Value":"2">]
- #
- # Special case: if <tt>range.start == table.size</tt>, returns an empty \Array:
- # table[table.size..50] # => []
- #
- # If <tt>range.end</tt> is negative, calculates the ending index from the end:
- # rows = table[0..-1]
- # rows # => [#<CSV::Row "Name":"foo" "Value":"0">, #<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"baz" "Value":"2">]
- #
- # If <tt>range.start</tt> is negative, calculates the starting index from the end:
- # rows = table[-1..2]
- # rows # => [#<CSV::Row "Name":"baz" "Value":"2">]
- #
- # If <tt>range.start</tt> is larger than <tt>table.size</tt>, returns +nil+:
- # table[4..4] # => nil
- #
- # ---
- #
- # Fetch Columns by \Range::
- # - Form: <tt>table[range]</tt>, +range+ a \Range object.
- # - Access mode: <tt>:col</tt>.
- # - Return value: column data from the table, beginning at column <tt>range.start</tt>,
- # if those columns exist.
- #
- # Returns column values from the table, if the column exists;
- # the values are arranged by row:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # table.by_col!
- # table[0..1] # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
- #
- # Special case: if <tt>range.start == headers.size</tt>,
- # returns an \Array (size: <tt>table.size</tt>) of empty \Arrays:
- # table[table.headers.size..50] # => [[], [], []]
- #
- # If <tt>range.end</tt> is negative, calculates the ending index from the end:
- # table[0..-1] # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
- #
- # If <tt>range.start</tt> is negative, calculates the starting index from the end:
- # table[-2..2] # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
- #
- # If <tt>range.start</tt> is larger than <tt>table.size</tt>,
- # returns an \Array of +nil+ values:
- # table[4..4] # => [nil, nil, nil]
- #
- # ---
- #
- # Fetch a Column by Its \String Header::
- # - Form: <tt>table[header]</tt>, +header+ a \String header.
- # - Access mode: <tt>:col</tt> or <tt>:col_or_row</tt>
- # - Return value: column data from the table, if that +header+ exists.
- #
- # Returns column values from the table, if the column exists:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # table.by_col! # => #<CSV::Table mode:col row_count:4>
- # table['Name'] # => ["foo", "bar", "baz"]
- # table.by_col_or_row! # => #<CSV::Table mode:col_or_row row_count:4>
- # col = table['Name']
- # col # => ["foo", "bar", "baz"]
- #
- # Modifying the returned column values does not modify the table:
- # col[0] = 'bat'
- # col # => ["bat", "bar", "baz"]
- # table['Name'] # => ["foo", "bar", "baz"]
- #
- # Returns an \Array of +nil+ values if there is no such column:
- # table['Nosuch'] # => [nil, nil, nil]
- def [](index_or_header)
- if @mode == :row or # by index
- (@mode == :col_or_row and (index_or_header.is_a?(Integer) or index_or_header.is_a?(Range)))
- @table[index_or_header]
- else # by header
- @table.map { |row| row[index_or_header] }
- end
- end
-
- # :call-seq:
- # table[n] = row -> row
- # table[n] = field_or_array_of_fields -> field_or_array_of_fields
- # table[header] = field_or_array_of_fields -> field_or_array_of_fields
- #
- # Puts data onto the table.
- #
- # ---
- #
- # Set a \Row by Its \Integer Index::
- # - Form: <tt>table[n] = row</tt>, +n+ an \Integer,
- # +row+ a \CSV::Row instance or an \Array of fields.
- # - Access mode: <tt>:row</tt> or <tt>:col_or_row</tt>.
- # - Return value: +row+.
- #
- # If the row exists, it is replaced:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # new_row = CSV::Row.new(['Name', 'Value'], ['bat', 3])
- # table.by_row! # => #<CSV::Table mode:row row_count:4>
- # return_value = table[0] = new_row
- # return_value.equal?(new_row) # => true # Returned the row
- # table[0].to_h # => {"Name"=>"bat", "Value"=>3}
- #
- # With access mode <tt>:col_or_row</tt>:
- # table.by_col_or_row! # => #<CSV::Table mode:col_or_row row_count:4>
- # table[0] = CSV::Row.new(['Name', 'Value'], ['bam', 4])
- # table[0].to_h # => {"Name"=>"bam", "Value"=>4}
- #
- # With an \Array instead of a \CSV::Row, inherits headers from the table:
- # array = ['bad', 5]
- # return_value = table[0] = array
- # return_value.equal?(array) # => true # Returned the array
- # table[0].to_h # => {"Name"=>"bad", "Value"=>5}
- #
- # If the row does not exist, extends the table by adding rows:
- # assigns rows with +nil+ as needed:
- # table.size # => 3
- # table[5] = ['bag', 6]
- # table.size # => 6
- # table[3] # => nil
- # table[4]# => nil
- # table[5].to_h # => {"Name"=>"bag", "Value"=>6}
- #
- # Note that the +nil+ rows are actually +nil+, not a row of +nil+ fields.
- #
- # ---
- #
- # Set a Column by Its \Integer Index::
- # - Form: <tt>table[n] = array_of_fields</tt>, +n+ an \Integer,
- # +array_of_fields+ an \Array of \String fields.
- # - Access mode: <tt>:col</tt>.
- # - Return value: +array_of_fields+.
- #
- # If the column exists, it is replaced:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # new_col = [3, 4, 5]
- # table.by_col! # => #<CSV::Table mode:col row_count:4>
- # return_value = table[1] = new_col
- # return_value.equal?(new_col) # => true # Returned the column
- # table[1] # => [3, 4, 5]
- # # The rows, as revised:
- # table.by_row! # => #<CSV::Table mode:row row_count:4>
- # table[0].to_h # => {"Name"=>"foo", "Value"=>3}
- # table[1].to_h # => {"Name"=>"bar", "Value"=>4}
- # table[2].to_h # => {"Name"=>"baz", "Value"=>5}
- # table.by_col! # => #<CSV::Table mode:col row_count:4>
- #
- # If there are too few values, fills with +nil+ values:
- # table[1] = [0]
- # table[1] # => [0, nil, nil]
- #
- # If there are too many values, ignores the extra values:
- # table[1] = [0, 1, 2, 3, 4]
- # table[1] # => [0, 1, 2]
- #
- # If a single value is given, replaces all fields in the column with that value:
- # table[1] = 'bat'
- # table[1] # => ["bat", "bat", "bat"]
- #
- # ---
- #
- # Set a Column by Its \String Header::
- # - Form: <tt>table[header] = field_or_array_of_fields</tt>,
- # +header+ a \String header, +field_or_array_of_fields+ a field value
- # or an \Array of \String fields.
- # - Access mode: <tt>:col</tt> or <tt>:col_or_row</tt>.
- # - Return value: +field_or_array_of_fields+.
- #
- # If the column exists, it is replaced:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # new_col = [3, 4, 5]
- # table.by_col! # => #<CSV::Table mode:col row_count:4>
- # return_value = table['Value'] = new_col
- # return_value.equal?(new_col) # => true # Returned the column
- # table['Value'] # => [3, 4, 5]
- # # The rows, as revised:
- # table.by_row! # => #<CSV::Table mode:row row_count:4>
- # table[0].to_h # => {"Name"=>"foo", "Value"=>3}
- # table[1].to_h # => {"Name"=>"bar", "Value"=>4}
- # table[2].to_h # => {"Name"=>"baz", "Value"=>5}
- # table.by_col! # => #<CSV::Table mode:col row_count:4>
- #
- # If there are too few values, fills with +nil+ values:
- # table['Value'] = [0]
- # table['Value'] # => [0, nil, nil]
- #
- # If there are too many values, ignores the extra values:
- # table['Value'] = [0, 1, 2, 3, 4]
- # table['Value'] # => [0, 1, 2]
- #
- # If the column does not exist, extends the table by adding columns:
- # table['Note'] = ['x', 'y', 'z']
- # table['Note'] # => ["x", "y", "z"]
- # # The rows, as revised:
- # table.by_row!
- # table[0].to_h # => {"Name"=>"foo", "Value"=>0, "Note"=>"x"}
- # table[1].to_h # => {"Name"=>"bar", "Value"=>1, "Note"=>"y"}
- # table[2].to_h # => {"Name"=>"baz", "Value"=>2, "Note"=>"z"}
- # table.by_col!
- #
- # If a single value is given, replaces all fields in the column with that value:
- # table['Value'] = 'bat'
- # table['Value'] # => ["bat", "bat", "bat"]
- def []=(index_or_header, value)
- if @mode == :row or # by index
- (@mode == :col_or_row and index_or_header.is_a? Integer)
- if value.is_a? Array
- @table[index_or_header] = Row.new(headers, value)
- else
- @table[index_or_header] = value
- end
- else # set column
- unless index_or_header.is_a? Integer
- index = @headers.index(index_or_header) || @headers.size
- @headers[index] = index_or_header
- end
- if value.is_a? Array # multiple values
- @table.each_with_index do |row, i|
- if row.header_row?
- row[index_or_header] = index_or_header
- else
- row[index_or_header] = value[i]
- end
- end
- else # repeated value
- @table.each do |row|
- if row.header_row?
- row[index_or_header] = index_or_header
- else
- row[index_or_header] = value
- end
- end
- end
- end
- end
-
- # :call-seq:
- # table.values_at(*indexes) -> array_of_rows
- # table.values_at(*headers) -> array_of_columns_data
- #
- # If the access mode is <tt>:row</tt> or <tt>:col_or_row</tt>,
- # and each argument is either an \Integer or a \Range,
- # returns rows.
- # Otherwise, returns columns data.
- #
- # In either case, the returned values are in the order
- # specified by the arguments. Arguments may be repeated.
- #
- # ---
- #
- # Returns rows as an \Array of \CSV::Row objects.
- #
- # No argument:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # table.values_at # => []
- #
- # One index:
- # values = table.values_at(0)
- # values # => [#<CSV::Row "Name":"foo" "Value":"0">]
- #
- # Two indexes:
- # values = table.values_at(2, 0)
- # values # => [#<CSV::Row "Name":"baz" "Value":"2">, #<CSV::Row "Name":"foo" "Value":"0">]
- #
- # One \Range:
- # values = table.values_at(1..2)
- # values # => [#<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"baz" "Value":"2">]
- #
- # \Ranges and indexes:
- # values = table.values_at(0..1, 1..2, 0, 2)
- # pp values
- # Output:
- # [#<CSV::Row "Name":"foo" "Value":"0">,
- # #<CSV::Row "Name":"bar" "Value":"1">,
- # #<CSV::Row "Name":"bar" "Value":"1">,
- # #<CSV::Row "Name":"baz" "Value":"2">,
- # #<CSV::Row "Name":"foo" "Value":"0">,
- # #<CSV::Row "Name":"baz" "Value":"2">]
- #
- # ---
- #
- # Returns columns data as row Arrays,
- # each consisting of the specified columns data for that row:
- # values = table.values_at('Name')
- # values # => [["foo"], ["bar"], ["baz"]]
- # values = table.values_at('Value', 'Name')
- # values # => [["0", "foo"], ["1", "bar"], ["2", "baz"]]
- def values_at(*indices_or_headers)
- if @mode == :row or # by indices
- ( @mode == :col_or_row and indices_or_headers.all? do |index|
- index.is_a?(Integer) or
- ( index.is_a?(Range) and
- index.first.is_a?(Integer) and
- index.last.is_a?(Integer) )
- end )
- @table.values_at(*indices_or_headers)
- else # by headers
- @table.map { |row| row.values_at(*indices_or_headers) }
- end
- end
-
- # :call-seq:
- # table << row_or_array -> self
- #
- # If +row_or_array+ is a \CSV::Row object,
- # it is appended to the table:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # table << CSV::Row.new(table.headers, ['bat', 3])
- # table[3] # => #<CSV::Row "Name":"bat" "Value":3>
- #
- # If +row_or_array+ is an \Array, it is used to create a new
- # \CSV::Row object which is then appended to the table:
- # table << ['bam', 4]
- # table[4] # => #<CSV::Row "Name":"bam" "Value":4>
- def <<(row_or_array)
- if row_or_array.is_a? Array # append Array
- @table << Row.new(headers, row_or_array)
- else # append Row
- @table << row_or_array
- end
-
- self # for chaining
- end
-
- #
- # :call-seq:
- # table.push(*rows_or_arrays) -> self
- #
- # A shortcut for appending multiple rows. Equivalent to:
- # rows.each {|row| self << row }
- #
- # Each argument may be either a \CSV::Row object or an \Array:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # rows = [
- # CSV::Row.new(table.headers, ['bat', 3]),
- # ['bam', 4]
- # ]
- # table.push(*rows)
- # table[3..4] # => [#<CSV::Row "Name":"bat" "Value":3>, #<CSV::Row "Name":"bam" "Value":4>]
- def push(*rows)
- rows.each { |row| self << row }
-
- self # for chaining
- end
-
- # :call-seq:
- # table.delete(*indexes) -> deleted_values
- # table.delete(*headers) -> deleted_values
- #
- # If the access mode is <tt>:row</tt> or <tt>:col_or_row</tt>,
- # and each argument is either an \Integer or a \Range,
- # returns deleted rows.
- # Otherwise, returns deleted columns data.
- #
- # In either case, the returned values are in the order
- # specified by the arguments. Arguments may be repeated.
- #
- # ---
- #
- # Returns rows as an \Array of \CSV::Row objects.
- #
- # One index:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # deleted_values = table.delete(0)
- # deleted_values # => [#<CSV::Row "Name":"foo" "Value":"0">]
- #
- # Two indexes:
- # table = CSV.parse(source, headers: true)
- # deleted_values = table.delete(2, 0)
- # deleted_values # => [#<CSV::Row "Name":"baz" "Value":"2">, #<CSV::Row "Name":"foo" "Value":"0">]
- #
- # ---
- #
- # Returns columns data as column Arrays.
- #
- # One header:
- # table = CSV.parse(source, headers: true)
- # deleted_values = table.delete('Name')
- # deleted_values # => ["foo", "bar", "baz"]
- #
- # Two headers:
- # table = CSV.parse(source, headers: true)
- # deleted_values = table.delete('Value', 'Name')
- # deleted_values # => [["0", "1", "2"], ["foo", "bar", "baz"]]
- def delete(*indexes_or_headers)
- if indexes_or_headers.empty?
- raise ArgumentError, "wrong number of arguments (given 0, expected 1+)"
- end
- deleted_values = indexes_or_headers.map do |index_or_header|
- if @mode == :row or # by index
- (@mode == :col_or_row and index_or_header.is_a? Integer)
- @table.delete_at(index_or_header)
- else # by header
- if index_or_header.is_a? Integer
- @headers.delete_at(index_or_header)
- else
- @headers.delete(index_or_header)
- end
- @table.map { |row| row.delete(index_or_header).last }
- end
- end
- if indexes_or_headers.size == 1
- deleted_values[0]
- else
- deleted_values
- end
- end
-
- # :call-seq:
- # table.delete_if {|row_or_column| ... } -> self
- #
- # Removes rows or columns for which the block returns a truthy value;
- # returns +self+.
- #
- # Removes rows when the access mode is <tt>:row</tt> or <tt>:col_or_row</tt>;
- # calls the block with each \CSV::Row object:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # table.by_row! # => #<CSV::Table mode:row row_count:4>
- # table.size # => 3
- # table.delete_if {|row| row['Name'].start_with?('b') }
- # table.size # => 1
- #
- # Removes columns when the access mode is <tt>:col</tt>;
- # calls the block with each column as a 2-element array
- # containing the header and an \Array of column fields:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # table.by_col! # => #<CSV::Table mode:col row_count:4>
- # table.headers.size # => 2
- # table.delete_if {|column_data| column_data[1].include?('2') }
- # table.headers.size # => 1
- #
- # Returns a new \Enumerator if no block is given:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # table.delete_if # => #<Enumerator: #<CSV::Table mode:col_or_row row_count:4>:delete_if>
- def delete_if(&block)
- return enum_for(__method__) { @mode == :row or @mode == :col_or_row ? size : headers.size } unless block_given?
-
- if @mode == :row or @mode == :col_or_row # by index
- @table.delete_if(&block)
- else # by header
- headers.each do |header|
- delete(header) if yield([header, self[header]])
- end
- end
-
- self # for chaining
- end
-
- include Enumerable
-
- # :call-seq:
- # table.each {|row_or_column| ... ) -> self
- #
- # Calls the block with each row or column; returns +self+.
- #
- # When the access mode is <tt>:row</tt> or <tt>:col_or_row</tt>,
- # calls the block with each \CSV::Row object:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # table.by_row! # => #<CSV::Table mode:row row_count:4>
- # table.each {|row| p row }
- # Output:
- # #<CSV::Row "Name":"foo" "Value":"0">
- # #<CSV::Row "Name":"bar" "Value":"1">
- # #<CSV::Row "Name":"baz" "Value":"2">
- #
- # When the access mode is <tt>:col</tt>,
- # calls the block with each column as a 2-element array
- # containing the header and an \Array of column fields:
- # table.by_col! # => #<CSV::Table mode:col row_count:4>
- # table.each {|column_data| p column_data }
- # Output:
- # ["Name", ["foo", "bar", "baz"]]
- # ["Value", ["0", "1", "2"]]
- #
- # Returns a new \Enumerator if no block is given:
- # table.each # => #<Enumerator: #<CSV::Table mode:col row_count:4>:each>
- def each(&block)
- return enum_for(__method__) { @mode == :col ? headers.size : size } unless block_given?
-
- if @mode == :col
- headers.each.with_index do |header, i|
- yield([header, @table.map {|row| row[header, i]}])
- end
- else
- @table.each(&block)
- end
-
- self # for chaining
- end
-
- # :call-seq:
- # table == other_table -> true or false
- #
- # Returns +true+ if all each row of +self+ <tt>==</tt>
- # the corresponding row of +other_table+, otherwise, +false+.
- #
- # The access mode does no affect the result.
- #
- # Equal tables:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # other_table = CSV.parse(source, headers: true)
- # table == other_table # => true
- #
- # Different row count:
- # other_table.delete(2)
- # table == other_table # => false
- #
- # Different last row:
- # other_table << ['bat', 3]
- # table == other_table # => false
- def ==(other)
- return @table == other.table if other.is_a? CSV::Table
- @table == other
- end
-
- # :call-seq:
- # table.to_a -> array_of_arrays
- #
- # Returns the table as an \Array of \Arrays;
- # the headers are in the first row:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # table.to_a # => [["Name", "Value"], ["foo", "0"], ["bar", "1"], ["baz", "2"]]
- def to_a
- array = [headers]
- @table.each do |row|
- array.push(row.fields) unless row.header_row?
- end
-
- array
- end
-
- # :call-seq:
- # table.to_csv(**options) -> csv_string
- #
- # Returns the table as \CSV string.
- # See {Options for Generating}[../CSV.html#class-CSV-label-Options+for+Generating].
- #
- # Defaults option +write_headers+ to +true+:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # table.to_csv # => "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- #
- # Omits the headers if option +write_headers+ is given as +false+
- # (see {Option +write_headers+}[../CSV.html#class-CSV-label-Option+write_headers]):
- # table.to_csv(write_headers: false) # => "foo,0\nbar,1\nbaz,2\n"
- #
- # Limit rows if option +limit+ is given like +2+:
- # table.to_csv(limit: 2) # => "Name,Value\nfoo,0\nbar,1\n"
- def to_csv(write_headers: true, limit: nil, **options)
- array = write_headers ? [headers.to_csv(**options)] : []
- limit ||= @table.size
- limit = @table.size + 1 + limit if limit < 0
- limit = 0 if limit < 0
- @table.first(limit).each do |row|
- array.push(row.fields.to_csv(**options)) unless row.header_row?
- end
-
- array.join("")
- end
- alias_method :to_s, :to_csv
-
- #
- # Extracts the nested value specified by the sequence of +index+ or +header+ objects by calling dig at each step,
- # returning nil if any intermediate step is nil.
- #
- def dig(index_or_header, *index_or_headers)
- value = self[index_or_header]
- if value.nil?
- nil
- elsif index_or_headers.empty?
- value
- else
- unless value.respond_to?(:dig)
- raise TypeError, "#{value.class} does not have \#dig method"
- end
- value.dig(*index_or_headers)
- end
- end
-
- # :call-seq:
- # table.inspect => string
- #
- # Returns a <tt>US-ASCII</tt>-encoded \String showing table:
- # - Class: <tt>CSV::Table</tt>.
- # - Access mode: <tt>:row</tt>, <tt>:col</tt>, or <tt>:col_or_row</tt>.
- # - Size: Row count, including the header row.
- #
- # Example:
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
- # table = CSV.parse(source, headers: true)
- # table.inspect # => "#<CSV::Table mode:col_or_row row_count:4>\nName,Value\nfoo,0\nbar,1\nbaz,2\n"
- #
- def inspect
- inspected = +"#<#{self.class} mode:#{@mode} row_count:#{to_a.size}>"
- summary = to_csv(limit: 5)
- inspected << "\n" << summary if summary.encoding.ascii_compatible?
- inspected
- end
- end
-end
diff --git a/lib/csv/version.rb b/lib/csv/version.rb
deleted file mode 100644
index 9c65803a34..0000000000
--- a/lib/csv/version.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# frozen_string_literal: true
-
-class CSV
- # The version of the installed library.
- VERSION = "3.2.8"
-end
diff --git a/lib/csv/writer.rb b/lib/csv/writer.rb
deleted file mode 100644
index 030a295bc9..0000000000
--- a/lib/csv/writer.rb
+++ /dev/null
@@ -1,210 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "input_record_separator"
-require_relative "row"
-
-class CSV
- # Note: Don't use this class directly. This is an internal class.
- class Writer
- #
- # A CSV::Writer receives an output, prepares the header, format and output.
- # It allows us to write new rows in the object and rewind it.
- #
- attr_reader :lineno
- attr_reader :headers
-
- def initialize(output, options)
- @output = output
- @options = options
- @lineno = 0
- @fields_converter = nil
- prepare
- if @options[:write_headers] and @headers
- self << @headers
- end
- @fields_converter = @options[:fields_converter]
- end
-
- #
- # Adds a new row
- #
- def <<(row)
- case row
- when Row
- row = row.fields
- when Hash
- row = @headers.collect {|header| row[header]}
- end
-
- @headers ||= row if @use_headers
- @lineno += 1
-
- if @fields_converter
- quoted_fields = [false] * row.size
- row = @fields_converter.convert(row, nil, lineno, quoted_fields)
- end
-
- i = -1
- converted_row = row.collect do |field|
- i += 1
- quote(field, i)
- end
- line = converted_row.join(@column_separator) + @row_separator
- if @output_encoding
- line = line.encode(@output_encoding)
- end
- @output << line
-
- self
- end
-
- #
- # Winds back to the beginning
- #
- def rewind
- @lineno = 0
- @headers = nil if @options[:headers].nil?
- end
-
- private
- def prepare
- @encoding = @options[:encoding]
-
- prepare_header
- prepare_format
- prepare_output
- end
-
- def prepare_header
- headers = @options[:headers]
- case headers
- when Array
- @headers = headers
- @use_headers = true
- when String
- @headers = CSV.parse_line(headers,
- col_sep: @options[:column_separator],
- row_sep: @options[:row_separator],
- quote_char: @options[:quote_character])
- @use_headers = true
- when true
- @headers = nil
- @use_headers = true
- else
- @headers = nil
- @use_headers = false
- end
- return unless @headers
-
- converter = @options[:header_fields_converter]
- @headers = converter.convert(@headers, nil, 0, [])
- @headers.each do |header|
- header.freeze if header.is_a?(String)
- end
- end
-
- def prepare_force_quotes_fields(force_quotes)
- @force_quotes_fields = {}
- force_quotes.each do |name_or_index|
- case name_or_index
- when Integer
- index = name_or_index
- @force_quotes_fields[index] = true
- when String, Symbol
- name = name_or_index.to_s
- if @headers.nil?
- message = ":headers is required when you use field name " +
- "in :force_quotes: " +
- "#{name_or_index.inspect}: #{force_quotes.inspect}"
- raise ArgumentError, message
- end
- index = @headers.index(name)
- next if index.nil?
- @force_quotes_fields[index] = true
- else
- message = ":force_quotes element must be " +
- "field index or field name: " +
- "#{name_or_index.inspect}: #{force_quotes.inspect}"
- raise ArgumentError, message
- end
- end
- end
-
- def prepare_format
- @column_separator = @options[:column_separator].to_s.encode(@encoding)
- row_separator = @options[:row_separator]
- if row_separator == :auto
- @row_separator = InputRecordSeparator.value.encode(@encoding)
- else
- @row_separator = row_separator.to_s.encode(@encoding)
- end
- @quote_character = @options[:quote_character]
- force_quotes = @options[:force_quotes]
- if force_quotes.is_a?(Array)
- prepare_force_quotes_fields(force_quotes)
- @force_quotes = false
- elsif force_quotes
- @force_quotes_fields = nil
- @force_quotes = true
- else
- @force_quotes_fields = nil
- @force_quotes = false
- end
- unless @force_quotes
- @quotable_pattern =
- Regexp.new("[\r\n".encode(@encoding) +
- Regexp.escape(@column_separator) +
- Regexp.escape(@quote_character.encode(@encoding)) +
- "]".encode(@encoding))
- end
- @quote_empty = @options.fetch(:quote_empty, true)
- end
-
- def prepare_output
- @output_encoding = nil
- return unless @output.is_a?(StringIO)
-
- output_encoding = @output.internal_encoding || @output.external_encoding
- if @encoding != output_encoding
- if @options[:force_encoding]
- @output_encoding = output_encoding
- else
- compatible_encoding = Encoding.compatible?(@encoding, output_encoding)
- if compatible_encoding
- @output.set_encoding(compatible_encoding)
- @output.seek(0, IO::SEEK_END)
- end
- end
- end
- end
-
- def quote_field(field)
- field = String(field)
- encoded_quote_character = @quote_character.encode(field.encoding)
- encoded_quote_character +
- field.gsub(encoded_quote_character,
- encoded_quote_character * 2) +
- encoded_quote_character
- end
-
- def quote(field, i)
- if @force_quotes
- quote_field(field)
- elsif @force_quotes_fields and @force_quotes_fields[i]
- quote_field(field)
- else
- if field.nil? # represent +nil+ fields as empty unquoted fields
- ""
- else
- field = String(field) # Stringify fields
- # represent empty fields as empty quoted fields
- if (@quote_empty and field.empty?) or (field.valid_encoding? and @quotable_pattern.match?(field))
- quote_field(field)
- else
- field # unquoted field
- end
- end
- end
- end
- end
-end
diff --git a/lib/delegate.rb b/lib/delegate.rb
index 4d8994d8a0..1ea4fb985b 100644
--- a/lib/delegate.rb
+++ b/lib/delegate.rb
@@ -186,7 +186,7 @@ class Delegator < BasicObject
# method calls are being delegated to.
#
def __getobj__
- __raise__ ::NotImplementedError, "need to define `__getobj__'"
+ __raise__ ::NotImplementedError, "need to define '__getobj__'"
end
#
@@ -194,7 +194,7 @@ class Delegator < BasicObject
# to _obj_.
#
def __setobj__(obj)
- __raise__ ::NotImplementedError, "need to define `__setobj__'"
+ __raise__ ::NotImplementedError, "need to define '__setobj__'"
end
#
diff --git a/lib/did_you_mean/did_you_mean.gemspec b/lib/did_you_mean/did_you_mean.gemspec
index 8fe5723129..be4ac76b4b 100644
--- a/lib/did_you_mean/did_you_mean.gemspec
+++ b/lib/did_you_mean/did_you_mean.gemspec
@@ -22,6 +22,4 @@ Gem::Specification.new do |spec|
spec.require_paths = ["lib"]
spec.required_ruby_version = '>= 2.5.0'
-
- spec.add_development_dependency "rake"
end
diff --git a/lib/did_you_mean/jaro_winkler.rb b/lib/did_you_mean/jaro_winkler.rb
index 56db130af4..9a3e57f6d7 100644
--- a/lib/did_you_mean/jaro_winkler.rb
+++ b/lib/did_you_mean/jaro_winkler.rb
@@ -8,8 +8,7 @@ module DidYouMean
m = 0.0
t = 0.0
- range = (length2 / 2).floor - 1
- range = 0 if range < 0
+ range = length2 > 3 ? length2 / 2 - 1 : 0
flags1 = 0
flags2 = 0
@@ -72,10 +71,8 @@ module DidYouMean
codepoints2 = str2.codepoints
prefix_bonus = 0
- i = 0
str1.each_codepoint do |char1|
- char1 == codepoints2[i] && i < 4 ? prefix_bonus += 1 : break
- i += 1
+ char1 == codepoints2[prefix_bonus] && prefix_bonus < 4 ? prefix_bonus += 1 : break
end
jaro_distance + (prefix_bonus * WEIGHT * (1 - jaro_distance))
diff --git a/lib/did_you_mean/spell_checkers/key_error_checker.rb b/lib/did_you_mean/spell_checkers/key_error_checker.rb
index be4bea7789..955bff1be6 100644
--- a/lib/did_you_mean/spell_checkers/key_error_checker.rb
+++ b/lib/did_you_mean/spell_checkers/key_error_checker.rb
@@ -14,7 +14,15 @@ module DidYouMean
private
def exact_matches
- @exact_matches ||= @keys.select { |word| @key == word.to_s }.map(&:inspect)
+ @exact_matches ||= @keys.select { |word| @key == word.to_s }.map { |obj| format_object(obj) }
+ end
+
+ def format_object(symbol_or_object)
+ if symbol_or_object.is_a?(Symbol)
+ ":#{symbol_or_object}"
+ else
+ symbol_or_object.to_s
+ end
end
end
end
diff --git a/lib/did_you_mean/spell_checkers/pattern_key_name_checker.rb b/lib/did_you_mean/spell_checkers/pattern_key_name_checker.rb
index ed263c8f93..622d4dee25 100644
--- a/lib/did_you_mean/spell_checkers/pattern_key_name_checker.rb
+++ b/lib/did_you_mean/spell_checkers/pattern_key_name_checker.rb
@@ -14,7 +14,15 @@ module DidYouMean
private
def exact_matches
- @exact_matches ||= @keys.select { |word| @key == word.to_s }.map(&:inspect)
+ @exact_matches ||= @keys.select { |word| @key == word.to_s }.map { |obj| format_object(obj) }
+ end
+
+ def format_object(symbol_or_object)
+ if symbol_or_object.is_a?(Symbol)
+ ":#{symbol_or_object}"
+ else
+ symbol_or_object.to_s
+ end
end
end
end
diff --git a/lib/drb.rb b/lib/drb.rb
deleted file mode 100644
index 2bb4716fa2..0000000000
--- a/lib/drb.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-# frozen_string_literal: false
-require 'drb/drb'
-
diff --git a/lib/drb/acl.rb b/lib/drb/acl.rb
deleted file mode 100644
index b004656f09..0000000000
--- a/lib/drb/acl.rb
+++ /dev/null
@@ -1,239 +0,0 @@
-# frozen_string_literal: false
-# Copyright (c) 2000,2002,2003 Masatoshi SEKI
-#
-# acl.rb is copyrighted free software by Masatoshi SEKI.
-# You can redistribute it and/or modify it under the same terms as Ruby.
-
-require 'ipaddr'
-
-##
-# Simple Access Control Lists.
-#
-# Access control lists are composed of "allow" and "deny" halves to control
-# access. Use "all" or "*" to match any address. To match a specific address
-# use any address or address mask that IPAddr can understand.
-#
-# Example:
-#
-# list = %w[
-# deny all
-# allow 192.168.1.1
-# allow ::ffff:192.168.1.2
-# allow 192.168.1.3
-# ]
-#
-# # From Socket#peeraddr, see also ACL#allow_socket?
-# addr = ["AF_INET", 10, "lc630", "192.168.1.3"]
-#
-# acl = ACL.new
-# p acl.allow_addr?(addr) # => true
-#
-# acl = ACL.new(list, ACL::DENY_ALLOW)
-# p acl.allow_addr?(addr) # => true
-
-class ACL
-
- ##
- # The current version of ACL
-
- VERSION=["2.0.0"]
-
- ##
- # An entry in an ACL
-
- class ACLEntry
-
- ##
- # Creates a new entry using +str+.
- #
- # +str+ may be "*" or "all" to match any address, an IP address string
- # to match a specific address, an IP address mask per IPAddr, or one
- # containing "*" to match part of an IPv4 address.
- #
- # IPAddr::InvalidPrefixError may be raised when an IP network
- # address with an invalid netmask/prefix is given.
-
- def initialize(str)
- if str == '*' or str == 'all'
- @pat = [:all]
- elsif str.include?('*')
- @pat = [:name, dot_pat(str)]
- else
- begin
- @pat = [:ip, IPAddr.new(str)]
- rescue IPAddr::InvalidPrefixError
- # In this case, `str` shouldn't be a host name pattern
- # because it contains a slash.
- raise
- rescue ArgumentError
- @pat = [:name, dot_pat(str)]
- end
- end
- end
-
- private
-
- ##
- # Creates a regular expression to match IPv4 addresses
-
- def dot_pat_str(str)
- list = str.split('.').collect { |s|
- (s == '*') ? '.+' : s
- }
- list.join("\\.")
- end
-
- private
-
- ##
- # Creates a Regexp to match an address.
-
- def dot_pat(str)
- /\A#{dot_pat_str(str)}\z/
- end
-
- public
-
- ##
- # Matches +addr+ against this entry.
-
- def match(addr)
- case @pat[0]
- when :all
- true
- when :ip
- begin
- ipaddr = IPAddr.new(addr[3])
- ipaddr = ipaddr.ipv4_mapped if @pat[1].ipv6? && ipaddr.ipv4?
- rescue ArgumentError
- return false
- end
- (@pat[1].include?(ipaddr)) ? true : false
- when :name
- (@pat[1] =~ addr[2]) ? true : false
- else
- false
- end
- end
- end
-
- ##
- # A list of ACLEntry objects. Used to implement the allow and deny halves
- # of an ACL
-
- class ACLList
-
- ##
- # Creates an empty ACLList
-
- def initialize
- @list = []
- end
-
- public
-
- ##
- # Matches +addr+ against each ACLEntry in this list.
-
- def match(addr)
- @list.each do |e|
- return true if e.match(addr)
- end
- false
- end
-
- public
-
- ##
- # Adds +str+ as an ACLEntry in this list
-
- def add(str)
- @list.push(ACLEntry.new(str))
- end
-
- end
-
- ##
- # Default to deny
-
- DENY_ALLOW = 0
-
- ##
- # Default to allow
-
- ALLOW_DENY = 1
-
- ##
- # Creates a new ACL from +list+ with an evaluation +order+ of DENY_ALLOW or
- # ALLOW_DENY.
- #
- # An ACL +list+ is an Array of "allow" or "deny" and an address or address
- # mask or "all" or "*" to match any address:
- #
- # %w[
- # deny all
- # allow 192.0.2.2
- # allow 192.0.2.128/26
- # ]
-
- def initialize(list=nil, order = DENY_ALLOW)
- @order = order
- @deny = ACLList.new
- @allow = ACLList.new
- install_list(list) if list
- end
-
- public
-
- ##
- # Allow connections from Socket +soc+?
-
- def allow_socket?(soc)
- allow_addr?(soc.peeraddr)
- end
-
- public
-
- ##
- # Allow connections from addrinfo +addr+? It must be formatted like
- # Socket#peeraddr:
- #
- # ["AF_INET", 10, "lc630", "192.0.2.1"]
-
- def allow_addr?(addr)
- case @order
- when DENY_ALLOW
- return true if @allow.match(addr)
- return false if @deny.match(addr)
- return true
- when ALLOW_DENY
- return false if @deny.match(addr)
- return true if @allow.match(addr)
- return false
- else
- false
- end
- end
-
- public
-
- ##
- # Adds +list+ of ACL entries to this ACL.
-
- def install_list(list)
- i = 0
- while i < list.size
- permission, domain = list.slice(i,2)
- case permission.downcase
- when 'allow'
- @allow.add(domain)
- when 'deny'
- @deny.add(domain)
- else
- raise "Invalid ACL entry #{list}"
- end
- i += 2
- end
- end
-
-end
diff --git a/lib/drb/drb.gemspec b/lib/drb/drb.gemspec
deleted file mode 100644
index c9d7e40a51..0000000000
--- a/lib/drb/drb.gemspec
+++ /dev/null
@@ -1,43 +0,0 @@
-begin
- require_relative "lib/drb/version"
-rescue LoadError # Fallback to load version file in ruby core repository
- require_relative "version"
-end
-
-Gem::Specification.new do |spec|
- spec.name = "drb"
- spec.version = DRb::VERSION
- spec.authors = ["Masatoshi SEKI"]
- spec.email = ["seki@ruby-lang.org"]
-
- spec.summary = %q{Distributed object system for Ruby}
- spec.description = %q{Distributed object system for Ruby}
- spec.homepage = "https://github.com/ruby/drb"
- spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
- spec.licenses = ["Ruby", "BSD-2-Clause"]
-
- spec.metadata["homepage_uri"] = spec.homepage
- spec.metadata["source_code_uri"] = spec.homepage
-
- spec.files = %w[
- LICENSE.txt
- drb.gemspec
- lib/drb.rb
- lib/drb/acl.rb
- lib/drb/drb.rb
- lib/drb/eq.rb
- lib/drb/extserv.rb
- lib/drb/extservm.rb
- lib/drb/gw.rb
- lib/drb/invokemethod.rb
- lib/drb/observer.rb
- lib/drb/ssl.rb
- lib/drb/timeridconv.rb
- lib/drb/unix.rb
- lib/drb/version.rb
- lib/drb/weakidconv.rb
- ]
- spec.require_paths = ["lib"]
-
- spec.add_dependency "ruby2_keywords"
-end
diff --git a/lib/drb/drb.rb b/lib/drb/drb.rb
deleted file mode 100644
index 5a85e42975..0000000000
--- a/lib/drb/drb.rb
+++ /dev/null
@@ -1,1943 +0,0 @@
-# frozen_string_literal: false
-#
-# = drb/drb.rb
-#
-# Distributed Ruby: _dRuby_
-#
-# Copyright (c) 1999-2003 Masatoshi SEKI. You can redistribute it and/or
-# modify it under the same terms as Ruby.
-#
-# Author:: Masatoshi SEKI
-#
-# Documentation:: William Webber (william@williamwebber.com)
-#
-# == Overview
-#
-# dRuby is a distributed object system for Ruby. It allows an object in one
-# Ruby process to invoke methods on an object in another Ruby process on the
-# same or a different machine.
-#
-# The Ruby standard library contains the core classes of the dRuby package.
-# However, the full package also includes access control lists and the
-# Rinda tuple-space distributed task management system, as well as a
-# large number of samples. The full dRuby package can be downloaded from
-# the dRuby home page (see *References*).
-#
-# For an introduction and examples of usage see the documentation to the
-# DRb module.
-#
-# == References
-#
-# [http://www2a.biglobe.ne.jp/~seki/ruby/druby.html]
-# The dRuby home page, in Japanese. Contains the full dRuby package
-# and links to other Japanese-language sources.
-#
-# [http://www2a.biglobe.ne.jp/~seki/ruby/druby.en.html]
-# The English version of the dRuby home page.
-#
-# [http://pragprog.com/book/sidruby/the-druby-book]
-# The dRuby Book: Distributed and Parallel Computing with Ruby
-# by Masatoshi Seki and Makoto Inoue
-#
-# [http://www.ruby-doc.org/docs/ProgrammingRuby/html/ospace.html]
-# The chapter from *Programming* *Ruby* by Dave Thomas and Andy Hunt
-# which discusses dRuby.
-#
-# [http://www.clio.ne.jp/home/web-i31s/Flotuard/Ruby/PRC2K_seki/dRuby.en.html]
-# Translation of presentation on Ruby by Masatoshi Seki.
-
-require 'socket'
-require 'io/wait'
-require 'monitor'
-require_relative 'eq'
-require_relative 'version'
-
-#
-# == Overview
-#
-# dRuby is a distributed object system for Ruby. It is written in
-# pure Ruby and uses its own protocol. No add-in services are needed
-# beyond those provided by the Ruby runtime, such as TCP sockets. It
-# does not rely on or interoperate with other distributed object
-# systems such as CORBA, RMI, or .NET.
-#
-# dRuby allows methods to be called in one Ruby process upon a Ruby
-# object located in another Ruby process, even on another machine.
-# References to objects can be passed between processes. Method
-# arguments and return values are dumped and loaded in marshalled
-# format. All of this is done transparently to both the caller of the
-# remote method and the object that it is called upon.
-#
-# An object in a remote process is locally represented by a
-# DRb::DRbObject instance. This acts as a sort of proxy for the
-# remote object. Methods called upon this DRbObject instance are
-# forwarded to its remote object. This is arranged dynamically at run
-# time. There are no statically declared interfaces for remote
-# objects, such as CORBA's IDL.
-#
-# dRuby calls made into a process are handled by a DRb::DRbServer
-# instance within that process. This reconstitutes the method call,
-# invokes it upon the specified local object, and returns the value to
-# the remote caller. Any object can receive calls over dRuby. There
-# is no need to implement a special interface, or mixin special
-# functionality. Nor, in the general case, does an object need to
-# explicitly register itself with a DRbServer in order to receive
-# dRuby calls.
-#
-# One process wishing to make dRuby calls upon another process must
-# somehow obtain an initial reference to an object in the remote
-# process by some means other than as the return value of a remote
-# method call, as there is initially no remote object reference it can
-# invoke a method upon. This is done by attaching to the server by
-# URI. Each DRbServer binds itself to a URI such as
-# 'druby://example.com:8787'. A DRbServer can have an object attached
-# to it that acts as the server's *front* *object*. A DRbObject can
-# be explicitly created from the server's URI. This DRbObject's
-# remote object will be the server's front object. This front object
-# can then return references to other Ruby objects in the DRbServer's
-# process.
-#
-# Method calls made over dRuby behave largely the same as normal Ruby
-# method calls made within a process. Method calls with blocks are
-# supported, as are raising exceptions. In addition to a method's
-# standard errors, a dRuby call may also raise one of the
-# dRuby-specific errors, all of which are subclasses of DRb::DRbError.
-#
-# Any type of object can be passed as an argument to a dRuby call or
-# returned as its return value. By default, such objects are dumped
-# or marshalled at the local end, then loaded or unmarshalled at the
-# remote end. The remote end therefore receives a copy of the local
-# object, not a distributed reference to it; methods invoked upon this
-# copy are executed entirely in the remote process, not passed on to
-# the local original. This has semantics similar to pass-by-value.
-#
-# However, if an object cannot be marshalled, a dRuby reference to it
-# is passed or returned instead. This will turn up at the remote end
-# as a DRbObject instance. All methods invoked upon this remote proxy
-# are forwarded to the local object, as described in the discussion of
-# DRbObjects. This has semantics similar to the normal Ruby
-# pass-by-reference.
-#
-# The easiest way to signal that we want an otherwise marshallable
-# object to be passed or returned as a DRbObject reference, rather
-# than marshalled and sent as a copy, is to include the
-# DRb::DRbUndumped mixin module.
-#
-# dRuby supports calling remote methods with blocks. As blocks (or
-# rather the Proc objects that represent them) are not marshallable,
-# the block executes in the local, not the remote, context. Each
-# value yielded to the block is passed from the remote object to the
-# local block, then the value returned by each block invocation is
-# passed back to the remote execution context to be collected, before
-# the collected values are finally returned to the local context as
-# the return value of the method invocation.
-#
-# == Examples of usage
-#
-# For more dRuby samples, see the +samples+ directory in the full
-# dRuby distribution.
-#
-# === dRuby in client/server mode
-#
-# This illustrates setting up a simple client-server drb
-# system. Run the server and client code in different terminals,
-# starting the server code first.
-#
-# ==== Server code
-#
-# require 'drb/drb'
-#
-# # The URI for the server to connect to
-# URI="druby://localhost:8787"
-#
-# class TimeServer
-#
-# def get_current_time
-# return Time.now
-# end
-#
-# end
-#
-# # The object that handles requests on the server
-# FRONT_OBJECT=TimeServer.new
-#
-# DRb.start_service(URI, FRONT_OBJECT)
-# # Wait for the drb server thread to finish before exiting.
-# DRb.thread.join
-#
-# ==== Client code
-#
-# require 'drb/drb'
-#
-# # The URI to connect to
-# SERVER_URI="druby://localhost:8787"
-#
-# # Start a local DRbServer to handle callbacks.
-# #
-# # Not necessary for this small example, but will be required
-# # as soon as we pass a non-marshallable object as an argument
-# # to a dRuby call.
-# #
-# # Note: this must be called at least once per process to take any effect.
-# # This is particularly important if your application forks.
-# DRb.start_service
-#
-# timeserver = DRbObject.new_with_uri(SERVER_URI)
-# puts timeserver.get_current_time
-#
-# === Remote objects under dRuby
-#
-# This example illustrates returning a reference to an object
-# from a dRuby call. The Logger instances live in the server
-# process. References to them are returned to the client process,
-# where methods can be invoked upon them. These methods are
-# executed in the server process.
-#
-# ==== Server code
-#
-# require 'drb/drb'
-#
-# URI="druby://localhost:8787"
-#
-# class Logger
-#
-# # Make dRuby send Logger instances as dRuby references,
-# # not copies.
-# include DRb::DRbUndumped
-#
-# def initialize(n, fname)
-# @name = n
-# @filename = fname
-# end
-#
-# def log(message)
-# File.open(@filename, "a") do |f|
-# f.puts("#{Time.now}: #{@name}: #{message}")
-# end
-# end
-#
-# end
-#
-# # We have a central object for creating and retrieving loggers.
-# # This retains a local reference to all loggers created. This
-# # is so an existing logger can be looked up by name, but also
-# # to prevent loggers from being garbage collected. A dRuby
-# # reference to an object is not sufficient to prevent it being
-# # garbage collected!
-# class LoggerFactory
-#
-# def initialize(bdir)
-# @basedir = bdir
-# @loggers = {}
-# end
-#
-# def get_logger(name)
-# if !@loggers.has_key? name
-# # make the filename safe, then declare it to be so
-# fname = name.gsub(/[.\/\\\:]/, "_")
-# @loggers[name] = Logger.new(name, @basedir + "/" + fname)
-# end
-# return @loggers[name]
-# end
-#
-# end
-#
-# FRONT_OBJECT=LoggerFactory.new("/tmp/dlog")
-#
-# DRb.start_service(URI, FRONT_OBJECT)
-# DRb.thread.join
-#
-# ==== Client code
-#
-# require 'drb/drb'
-#
-# SERVER_URI="druby://localhost:8787"
-#
-# DRb.start_service
-#
-# log_service=DRbObject.new_with_uri(SERVER_URI)
-#
-# ["loga", "logb", "logc"].each do |logname|
-#
-# logger=log_service.get_logger(logname)
-#
-# logger.log("Hello, world!")
-# logger.log("Goodbye, world!")
-# logger.log("=== EOT ===")
-#
-# end
-#
-# == Security
-#
-# As with all network services, security needs to be considered when
-# using dRuby. By allowing external access to a Ruby object, you are
-# not only allowing outside clients to call the methods you have
-# defined for that object, but by default to execute arbitrary Ruby
-# code on your server. Consider the following:
-#
-# # !!! UNSAFE CODE !!!
-# ro = DRbObject::new_with_uri("druby://your.server.com:8989")
-# class << ro
-# undef :instance_eval # force call to be passed to remote object
-# end
-# ro.instance_eval("`rm -rf *`")
-#
-# The dangers posed by instance_eval and friends are such that a
-# DRbServer should only be used when clients are trusted.
-#
-# A DRbServer can be configured with an access control list to
-# selectively allow or deny access from specified IP addresses. The
-# main druby distribution provides the ACL class for this purpose. In
-# general, this mechanism should only be used alongside, rather than
-# as a replacement for, a good firewall.
-#
-# == dRuby internals
-#
-# dRuby is implemented using three main components: a remote method
-# call marshaller/unmarshaller; a transport protocol; and an
-# ID-to-object mapper. The latter two can be directly, and the first
-# indirectly, replaced, in order to provide different behaviour and
-# capabilities.
-#
-# Marshalling and unmarshalling of remote method calls is performed by
-# a DRb::DRbMessage instance. This uses the Marshal module to dump
-# the method call before sending it over the transport layer, then
-# reconstitute it at the other end. There is normally no need to
-# replace this component, and no direct way is provided to do so.
-# However, it is possible to implement an alternative marshalling
-# scheme as part of an implementation of the transport layer.
-#
-# The transport layer is responsible for opening client and server
-# network connections and forwarding dRuby request across them.
-# Normally, it uses DRb::DRbMessage internally to manage marshalling
-# and unmarshalling. The transport layer is managed by
-# DRb::DRbProtocol. Multiple protocols can be installed in
-# DRbProtocol at the one time; selection between them is determined by
-# the scheme of a dRuby URI. The default transport protocol is
-# selected by the scheme 'druby:', and implemented by
-# DRb::DRbTCPSocket. This uses plain TCP/IP sockets for
-# communication. An alternative protocol, using UNIX domain sockets,
-# is implemented by DRb::DRbUNIXSocket in the file drb/unix.rb, and
-# selected by the scheme 'drbunix:'. A sample implementation over
-# HTTP can be found in the samples accompanying the main dRuby
-# distribution.
-#
-# The ID-to-object mapping component maps dRuby object ids to the
-# objects they refer to, and vice versa. The implementation to use
-# can be specified as part of a DRb::DRbServer's configuration. The
-# default implementation is provided by DRb::DRbIdConv. It uses an
-# object's ObjectSpace id as its dRuby id. This means that the dRuby
-# reference to that object only remains meaningful for the lifetime of
-# the object's process and the lifetime of the object within that
-# process. A modified implementation is provided by DRb::TimerIdConv
-# in the file drb/timeridconv.rb. This implementation retains a local
-# reference to all objects exported over dRuby for a configurable
-# period of time (defaulting to ten minutes), to prevent them being
-# garbage-collected within this time. Another sample implementation
-# is provided in sample/name.rb in the main dRuby distribution. This
-# allows objects to specify their own id or "name". A dRuby reference
-# can be made persistent across processes by having each process
-# register an object using the same dRuby name.
-#
-module DRb
-
- # Superclass of all errors raised in the DRb module.
- class DRbError < RuntimeError; end
-
- # Error raised when an error occurs on the underlying communication
- # protocol.
- class DRbConnError < DRbError; end
-
- # Class responsible for converting between an object and its id.
- #
- # This, the default implementation, uses an object's local ObjectSpace
- # __id__ as its id. This means that an object's identification over
- # drb remains valid only while that object instance remains alive
- # within the server runtime.
- #
- # For alternative mechanisms, see DRb::TimerIdConv in drb/timeridconv.rb
- # and DRbNameIdConv in sample/name.rb in the full drb distribution.
- class DRbIdConv
-
- # Convert an object reference id to an object.
- #
- # This implementation looks up the reference id in the local object
- # space and returns the object it refers to.
- def to_obj(ref)
- ObjectSpace._id2ref(ref)
- end
-
- # Convert an object into a reference id.
- #
- # This implementation returns the object's __id__ in the local
- # object space.
- def to_id(obj)
- case obj
- when Object
- obj.nil? ? nil : obj.__id__
- when BasicObject
- obj.__id__
- end
- end
- end
-
- # Mixin module making an object undumpable or unmarshallable.
- #
- # If an object which includes this module is returned by method
- # called over drb, then the object remains in the server space
- # and a reference to the object is returned, rather than the
- # object being marshalled and moved into the client space.
- module DRbUndumped
- def _dump(dummy) # :nodoc:
- raise TypeError, 'can\'t dump'
- end
- end
-
- # Error raised by the DRb module when an attempt is made to refer to
- # the context's current drb server but the context does not have one.
- # See #current_server.
- class DRbServerNotFound < DRbError; end
-
- # Error raised by the DRbProtocol module when it cannot find any
- # protocol implementation support the scheme specified in a URI.
- class DRbBadURI < DRbError; end
-
- # Error raised by a dRuby protocol when it doesn't support the
- # scheme specified in a URI. See DRb::DRbProtocol.
- class DRbBadScheme < DRbError; end
-
- # An exception wrapping a DRb::DRbUnknown object
- class DRbUnknownError < DRbError
-
- # Create a new DRbUnknownError for the DRb::DRbUnknown object +unknown+
- def initialize(unknown)
- @unknown = unknown
- super(unknown.name)
- end
-
- # Get the wrapped DRb::DRbUnknown object.
- attr_reader :unknown
-
- def self._load(s) # :nodoc:
- Marshal::load(s)
- end
-
- def _dump(lv) # :nodoc:
- Marshal::dump(@unknown)
- end
- end
-
- # An exception wrapping an error object
- class DRbRemoteError < DRbError
-
- # Creates a new remote error that wraps the Exception +error+
- def initialize(error)
- @reason = error.class.to_s
- super("#{error.message} (#{error.class})")
- set_backtrace(error.backtrace)
- end
-
- # the class of the error, as a string.
- attr_reader :reason
- end
-
- # Class wrapping a marshalled object whose type is unknown locally.
- #
- # If an object is returned by a method invoked over drb, but the
- # class of the object is unknown in the client namespace, or
- # the object is a constant unknown in the client namespace, then
- # the still-marshalled object is returned wrapped in a DRbUnknown instance.
- #
- # If this object is passed as an argument to a method invoked over
- # drb, then the wrapped object is passed instead.
- #
- # The class or constant name of the object can be read from the
- # +name+ attribute. The marshalled object is held in the +buf+
- # attribute.
- class DRbUnknown
-
- # Create a new DRbUnknown object.
- #
- # +buf+ is a string containing a marshalled object that could not
- # be unmarshalled. +err+ is the error message that was raised
- # when the unmarshalling failed. It is used to determine the
- # name of the unmarshalled object.
- def initialize(err, buf)
- case err.to_s
- when /uninitialized constant (\S+)/
- @name = $1
- when /undefined class\/module (\S+)/
- @name = $1
- else
- @name = nil
- end
- @buf = buf
- end
-
- # The name of the unknown thing.
- #
- # Class name for unknown objects; variable name for unknown
- # constants.
- attr_reader :name
-
- # Buffer contained the marshalled, unknown object.
- attr_reader :buf
-
- def self._load(s) # :nodoc:
- begin
- Marshal::load(s)
- rescue NameError, ArgumentError
- DRbUnknown.new($!, s)
- end
- end
-
- def _dump(lv) # :nodoc:
- @buf
- end
-
- # Attempt to load the wrapped marshalled object again.
- #
- # If the class of the object is now known locally, the object
- # will be unmarshalled and returned. Otherwise, a new
- # but identical DRbUnknown object will be returned.
- def reload
- self.class._load(@buf)
- end
-
- # Create a DRbUnknownError exception containing this object.
- def exception
- DRbUnknownError.new(self)
- end
- end
-
- # An Array wrapper that can be sent to another server via DRb.
- #
- # All entries in the array will be dumped or be references that point to
- # the local server.
-
- class DRbArray
-
- # Creates a new DRbArray that either dumps or wraps all the items in the
- # Array +ary+ so they can be loaded by a remote DRb server.
-
- def initialize(ary)
- @ary = ary.collect { |obj|
- if obj.kind_of? DRbUndumped
- DRbObject.new(obj)
- else
- begin
- Marshal.dump(obj)
- obj
- rescue
- DRbObject.new(obj)
- end
- end
- }
- end
-
- def self._load(s) # :nodoc:
- Marshal::load(s)
- end
-
- def _dump(lv) # :nodoc:
- Marshal.dump(@ary)
- end
- end
-
- # Handler for sending and receiving drb messages.
- #
- # This takes care of the low-level marshalling and unmarshalling
- # of drb requests and responses sent over the wire between server
- # and client. This relieves the implementor of a new drb
- # protocol layer with having to deal with these details.
- #
- # The user does not have to directly deal with this object in
- # normal use.
- class DRbMessage
- def initialize(config) # :nodoc:
- @load_limit = config[:load_limit]
- @argc_limit = config[:argc_limit]
- end
-
- def dump(obj, error=false) # :nodoc:
- case obj
- when DRbUndumped
- obj = make_proxy(obj, error)
- when Object
- # nothing
- else
- obj = make_proxy(obj, error)
- end
- begin
- str = Marshal::dump(obj)
- rescue
- str = Marshal::dump(make_proxy(obj, error))
- end
- [str.size].pack('N') + str
- end
-
- def load(soc) # :nodoc:
- begin
- sz = soc.read(4) # sizeof (N)
- rescue
- raise(DRbConnError, $!.message, $!.backtrace)
- end
- raise(DRbConnError, 'connection closed') if sz.nil?
- raise(DRbConnError, 'premature header') if sz.size < 4
- sz = sz.unpack('N')[0]
- raise(DRbConnError, "too large packet #{sz}") if @load_limit < sz
- begin
- str = soc.read(sz)
- rescue
- raise(DRbConnError, $!.message, $!.backtrace)
- end
- raise(DRbConnError, 'connection closed') if str.nil?
- raise(DRbConnError, 'premature marshal format(can\'t read)') if str.size < sz
- DRb.mutex.synchronize do
- begin
- Marshal::load(str)
- rescue NameError, ArgumentError
- DRbUnknown.new($!, str)
- end
- end
- end
-
- def send_request(stream, ref, msg_id, arg, b) # :nodoc:
- ary = []
- ary.push(dump(ref.__drbref))
- ary.push(dump(msg_id.id2name))
- ary.push(dump(arg.length))
- arg.each do |e|
- ary.push(dump(e))
- end
- ary.push(dump(b))
- stream.write(ary.join(''))
- rescue
- raise(DRbConnError, $!.message, $!.backtrace)
- end
-
- def recv_request(stream) # :nodoc:
- ref = load(stream)
- ro = DRb.to_obj(ref)
- msg = load(stream)
- argc = load(stream)
- raise(DRbConnError, "too many arguments") if @argc_limit < argc
- argv = Array.new(argc, nil)
- argc.times do |n|
- argv[n] = load(stream)
- end
- block = load(stream)
- return ro, msg, argv, block
- end
-
- def send_reply(stream, succ, result) # :nodoc:
- stream.write(dump(succ) + dump(result, !succ))
- rescue
- raise(DRbConnError, $!.message, $!.backtrace)
- end
-
- def recv_reply(stream) # :nodoc:
- succ = load(stream)
- result = load(stream)
- [succ, result]
- end
-
- private
- def make_proxy(obj, error=false) # :nodoc:
- if error
- DRbRemoteError.new(obj)
- else
- DRbObject.new(obj)
- end
- end
- end
-
- # Module managing the underlying network protocol(s) used by drb.
- #
- # By default, drb uses the DRbTCPSocket protocol. Other protocols
- # can be defined. A protocol must define the following class methods:
- #
- # [open(uri, config)] Open a client connection to the server at +uri+,
- # using configuration +config+. Return a protocol
- # instance for this connection.
- # [open_server(uri, config)] Open a server listening at +uri+,
- # using configuration +config+. Return a
- # protocol instance for this listener.
- # [uri_option(uri, config)] Take a URI, possibly containing an option
- # component (e.g. a trailing '?param=val'),
- # and return a [uri, option] tuple.
- #
- # All of these methods should raise a DRbBadScheme error if the URI
- # does not identify the protocol they support (e.g. "druby:" for
- # the standard Ruby protocol). This is how the DRbProtocol module,
- # given a URI, determines which protocol implementation serves that
- # protocol.
- #
- # The protocol instance returned by #open_server must have the
- # following methods:
- #
- # [accept] Accept a new connection to the server. Returns a protocol
- # instance capable of communicating with the client.
- # [close] Close the server connection.
- # [uri] Get the URI for this server.
- #
- # The protocol instance returned by #open must have the following methods:
- #
- # [send_request (ref, msg_id, arg, b)]
- # Send a request to +ref+ with the given message id and arguments.
- # This is most easily implemented by calling DRbMessage.send_request,
- # providing a stream that sits on top of the current protocol.
- # [recv_reply]
- # Receive a reply from the server and return it as a [success-boolean,
- # reply-value] pair. This is most easily implemented by calling
- # DRb.recv_reply, providing a stream that sits on top of the
- # current protocol.
- # [alive?]
- # Is this connection still alive?
- # [close]
- # Close this connection.
- #
- # The protocol instance returned by #open_server().accept() must have
- # the following methods:
- #
- # [recv_request]
- # Receive a request from the client and return a [object, message,
- # args, block] tuple. This is most easily implemented by calling
- # DRbMessage.recv_request, providing a stream that sits on top of
- # the current protocol.
- # [send_reply(succ, result)]
- # Send a reply to the client. This is most easily implemented
- # by calling DRbMessage.send_reply, providing a stream that sits
- # on top of the current protocol.
- # [close]
- # Close this connection.
- #
- # A new protocol is registered with the DRbProtocol module using
- # the add_protocol method.
- #
- # For examples of other protocols, see DRbUNIXSocket in drb/unix.rb,
- # and HTTP0 in sample/http0.rb and sample/http0serv.rb in the full
- # drb distribution.
- module DRbProtocol
-
- # Add a new protocol to the DRbProtocol module.
- def add_protocol(prot)
- @protocol.push(prot)
- end
- module_function :add_protocol
-
- # Open a client connection to +uri+ with the configuration +config+.
- #
- # The DRbProtocol module asks each registered protocol in turn to
- # try to open the URI. Each protocol signals that it does not handle that
- # URI by raising a DRbBadScheme error. If no protocol recognises the
- # URI, then a DRbBadURI error is raised. If a protocol accepts the
- # URI, but an error occurs in opening it, a DRbConnError is raised.
- def open(uri, config, first=true)
- @protocol.each do |prot|
- begin
- return prot.open(uri, config)
- rescue DRbBadScheme
- rescue DRbConnError
- raise($!)
- rescue
- raise(DRbConnError, "#{uri} - #{$!.inspect}")
- end
- end
- if first && (config[:auto_load] != false)
- auto_load(uri)
- return open(uri, config, false)
- end
- raise DRbBadURI, 'can\'t parse uri:' + uri
- end
- module_function :open
-
- # Open a server listening for connections at +uri+ with
- # configuration +config+.
- #
- # The DRbProtocol module asks each registered protocol in turn to
- # try to open a server at the URI. Each protocol signals that it does
- # not handle that URI by raising a DRbBadScheme error. If no protocol
- # recognises the URI, then a DRbBadURI error is raised. If a protocol
- # accepts the URI, but an error occurs in opening it, the underlying
- # error is passed on to the caller.
- def open_server(uri, config, first=true)
- @protocol.each do |prot|
- begin
- return prot.open_server(uri, config)
- rescue DRbBadScheme
- end
- end
- if first && (config[:auto_load] != false)
- auto_load(uri)
- return open_server(uri, config, false)
- end
- raise DRbBadURI, 'can\'t parse uri:' + uri
- end
- module_function :open_server
-
- # Parse +uri+ into a [uri, option] pair.
- #
- # The DRbProtocol module asks each registered protocol in turn to
- # try to parse the URI. Each protocol signals that it does not handle that
- # URI by raising a DRbBadScheme error. If no protocol recognises the
- # URI, then a DRbBadURI error is raised.
- def uri_option(uri, config, first=true)
- @protocol.each do |prot|
- begin
- uri, opt = prot.uri_option(uri, config)
- # opt = nil if opt == ''
- return uri, opt
- rescue DRbBadScheme
- end
- end
- if first && (config[:auto_load] != false)
- auto_load(uri)
- return uri_option(uri, config, false)
- end
- raise DRbBadURI, 'can\'t parse uri:' + uri
- end
- module_function :uri_option
-
- def auto_load(uri) # :nodoc:
- if /\Adrb([a-z0-9]+):/ =~ uri
- require("drb/#{$1}") rescue nil
- end
- end
- module_function :auto_load
- end
-
- # The default drb protocol which communicates over a TCP socket.
- #
- # The DRb TCP protocol URI looks like:
- # <code>druby://<host>:<port>?<option></code>. The option is optional.
-
- class DRbTCPSocket
- # :stopdoc:
- private
- def self.parse_uri(uri)
- if /\Adruby:\/\/(.*?):(\d+)(\?(.*))?\z/ =~ uri
- host = $1
- port = $2.to_i
- option = $4
- [host, port, option]
- else
- raise(DRbBadScheme, uri) unless uri.start_with?('druby:')
- raise(DRbBadURI, 'can\'t parse uri:' + uri)
- end
- end
-
- public
-
- # Open a client connection to +uri+ (DRb URI string) using configuration
- # +config+.
- #
- # This can raise DRb::DRbBadScheme or DRb::DRbBadURI if +uri+ is not for a
- # recognized protocol. See DRb::DRbServer.new for information on built-in
- # URI protocols.
- def self.open(uri, config)
- host, port, = parse_uri(uri)
- soc = TCPSocket.open(host, port)
- self.new(uri, soc, config)
- end
-
- # Returns the hostname of this server
- def self.getservername
- host = Socket::gethostname
- begin
- Socket::getaddrinfo(host, nil,
- Socket::AF_UNSPEC,
- Socket::SOCK_STREAM,
- 0,
- Socket::AI_PASSIVE)[0][3]
- rescue
- 'localhost'
- end
- end
-
- # For the families available for +host+, returns a TCPServer on +port+.
- # If +port+ is 0 the first available port is used. IPv4 servers are
- # preferred over IPv6 servers.
- def self.open_server_inaddr_any(host, port)
- infos = Socket::getaddrinfo(host, nil,
- Socket::AF_UNSPEC,
- Socket::SOCK_STREAM,
- 0,
- Socket::AI_PASSIVE)
- families = Hash[*infos.collect { |af, *_| af }.uniq.zip([]).flatten]
- return TCPServer.open('0.0.0.0', port) if families.has_key?('AF_INET')
- return TCPServer.open('::', port) if families.has_key?('AF_INET6')
- return TCPServer.open(port)
- # :stopdoc:
- end
-
- # Open a server listening for connections at +uri+ using
- # configuration +config+.
- def self.open_server(uri, config)
- uri = 'druby://:0' unless uri
- host, port, _ = parse_uri(uri)
- config = {:tcp_original_host => host}.update(config)
- if host.size == 0
- host = getservername
- soc = open_server_inaddr_any(host, port)
- else
- soc = TCPServer.open(host, port)
- end
- port = soc.addr[1] if port == 0
- config[:tcp_port] = port
- uri = "druby://#{host}:#{port}"
- self.new(uri, soc, config)
- end
-
- # Parse +uri+ into a [uri, option] pair.
- def self.uri_option(uri, config)
- host, port, option = parse_uri(uri)
- return "druby://#{host}:#{port}", option
- end
-
- # Create a new DRbTCPSocket instance.
- #
- # +uri+ is the URI we are connected to.
- # +soc+ is the tcp socket we are bound to. +config+ is our
- # configuration.
- def initialize(uri, soc, config={})
- @uri = uri
- @socket = soc
- @config = config
- @acl = config[:tcp_acl]
- @msg = DRbMessage.new(config)
- set_sockopt(@socket)
- @shutdown_pipe_r, @shutdown_pipe_w = IO.pipe
- end
-
- # Get the URI that we are connected to.
- attr_reader :uri
-
- # Get the address of our TCP peer (the other end of the socket
- # we are bound to.
- def peeraddr
- @socket.peeraddr
- end
-
- # Get the socket.
- def stream; @socket; end
-
- # On the client side, send a request to the server.
- def send_request(ref, msg_id, arg, b)
- @msg.send_request(stream, ref, msg_id, arg, b)
- end
-
- # On the server side, receive a request from the client.
- def recv_request
- @msg.recv_request(stream)
- end
-
- # On the server side, send a reply to the client.
- def send_reply(succ, result)
- @msg.send_reply(stream, succ, result)
- end
-
- # On the client side, receive a reply from the server.
- def recv_reply
- @msg.recv_reply(stream)
- end
-
- public
-
- # Close the connection.
- #
- # If this is an instance returned by #open_server, then this stops
- # listening for new connections altogether. If this is an instance
- # returned by #open or by #accept, then it closes this particular
- # client-server session.
- def close
- shutdown
- if @socket
- @socket.close
- @socket = nil
- end
- close_shutdown_pipe
- end
-
- def close_shutdown_pipe
- @shutdown_pipe_w.close
- @shutdown_pipe_r.close
- end
- private :close_shutdown_pipe
-
- # On the server side, for an instance returned by #open_server,
- # accept a client connection and return a new instance to handle
- # the server's side of this client-server session.
- def accept
- while true
- s = accept_or_shutdown
- return nil unless s
- break if (@acl ? @acl.allow_socket?(s) : true)
- s.close
- end
- if @config[:tcp_original_host].to_s.size == 0
- uri = "druby://#{s.addr[3]}:#{@config[:tcp_port]}"
- else
- uri = @uri
- end
- self.class.new(uri, s, @config)
- end
-
- def accept_or_shutdown
- readables, = IO.select([@socket, @shutdown_pipe_r])
- if readables.include? @shutdown_pipe_r
- return nil
- end
- @socket.accept
- end
- private :accept_or_shutdown
-
- # Graceful shutdown
- def shutdown
- @shutdown_pipe_w.close
- end
-
- # Check to see if this connection is alive.
- def alive?
- return false unless @socket
- if @socket.to_io.wait_readable(0)
- close
- return false
- end
- true
- end
-
- def set_sockopt(soc) # :nodoc:
- soc.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
- rescue IOError, Errno::ECONNRESET, Errno::EINVAL
- # closed/shutdown socket, ignore error
- end
- end
-
- module DRbProtocol
- @protocol = [DRbTCPSocket] # default
- end
-
- class DRbURIOption # :nodoc: I don't understand the purpose of this class...
- def initialize(option)
- @option = option.to_s
- end
- attr_reader :option
- def to_s; @option; end
-
- def ==(other)
- return false unless DRbURIOption === other
- @option == other.option
- end
-
- def hash
- @option.hash
- end
-
- alias eql? ==
- end
-
- # Object wrapping a reference to a remote drb object.
- #
- # Method calls on this object are relayed to the remote
- # object that this object is a stub for.
- class DRbObject
-
- # Unmarshall a marshalled DRbObject.
- #
- # If the referenced object is located within the local server, then
- # the object itself is returned. Otherwise, a new DRbObject is
- # created to act as a stub for the remote referenced object.
- def self._load(s)
- uri, ref = Marshal.load(s)
-
- if DRb.here?(uri)
- obj = DRb.to_obj(ref)
- return obj
- end
-
- self.new_with(uri, ref)
- end
-
- # Creates a DRb::DRbObject given the reference information to the remote
- # host +uri+ and object +ref+.
-
- def self.new_with(uri, ref)
- it = self.allocate
- it.instance_variable_set(:@uri, uri)
- it.instance_variable_set(:@ref, ref)
- it
- end
-
- # Create a new DRbObject from a URI alone.
- def self.new_with_uri(uri)
- self.new(nil, uri)
- end
-
- # Marshall this object.
- #
- # The URI and ref of the object are marshalled.
- def _dump(lv)
- Marshal.dump([@uri, @ref])
- end
-
- # Create a new remote object stub.
- #
- # +obj+ is the (local) object we want to create a stub for. Normally
- # this is +nil+. +uri+ is the URI of the remote object that this
- # will be a stub for.
- def initialize(obj, uri=nil)
- @uri = nil
- @ref = nil
- case obj
- when Object
- is_nil = obj.nil?
- when BasicObject
- is_nil = false
- end
-
- if is_nil
- return if uri.nil?
- @uri, option = DRbProtocol.uri_option(uri, DRb.config)
- @ref = DRbURIOption.new(option) unless option.nil?
- else
- @uri = uri ? uri : (DRb.uri rescue nil)
- @ref = obj ? DRb.to_id(obj) : nil
- end
- end
-
- # Get the URI of the remote object.
- def __drburi
- @uri
- end
-
- # Get the reference of the object, if local.
- def __drbref
- @ref
- end
-
- undef :to_s
- undef :to_a if respond_to?(:to_a)
-
- # Routes respond_to? to the referenced remote object.
- def respond_to?(msg_id, priv=false)
- case msg_id
- when :_dump
- true
- when :marshal_dump
- false
- else
- method_missing(:respond_to?, msg_id, priv)
- end
- end
-
- # Routes method calls to the referenced remote object.
- ruby2_keywords def method_missing(msg_id, *a, &b)
- if DRb.here?(@uri)
- obj = DRb.to_obj(@ref)
- DRb.current_server.check_insecure_method(obj, msg_id)
- return obj.__send__(msg_id, *a, &b)
- end
-
- succ, result = self.class.with_friend(@uri) do
- DRbConn.open(@uri) do |conn|
- conn.send_message(self, msg_id, a, b)
- end
- end
-
- if succ
- return result
- elsif DRbUnknown === result
- raise result
- else
- bt = self.class.prepare_backtrace(@uri, result)
- result.set_backtrace(bt + caller)
- raise result
- end
- end
-
- # Given the +uri+ of another host executes the block provided.
- def self.with_friend(uri) # :nodoc:
- friend = DRb.fetch_server(uri)
- return yield() unless friend
-
- save = Thread.current['DRb']
- Thread.current['DRb'] = { 'server' => friend }
- return yield
- ensure
- Thread.current['DRb'] = save if friend
- end
-
- # Returns a modified backtrace from +result+ with the +uri+ where each call
- # in the backtrace came from.
- def self.prepare_backtrace(uri, result) # :nodoc:
- prefix = "(#{uri}) "
- bt = []
- result.backtrace.each do |x|
- break if /`__send__'$/ =~ x
- if /\A\(druby:\/\// =~ x
- bt.push(x)
- else
- bt.push(prefix + x)
- end
- end
- bt
- end
-
- def pretty_print(q) # :nodoc:
- q.pp_object(self)
- end
-
- def pretty_print_cycle(q) # :nodoc:
- q.object_address_group(self) {
- q.breakable
- q.text '...'
- }
- end
- end
-
- class ThreadObject
- include MonitorMixin
-
- def initialize(&blk)
- super()
- @wait_ev = new_cond
- @req_ev = new_cond
- @res_ev = new_cond
- @status = :wait
- @req = nil
- @res = nil
- @thread = Thread.new(self, &blk)
- end
-
- def alive?
- @thread.alive?
- end
-
- def kill
- @thread.kill
- @thread.join
- end
-
- def method_missing(msg, *arg, &blk)
- synchronize do
- @wait_ev.wait_until { @status == :wait }
- @req = [msg] + arg
- @status = :req
- @req_ev.broadcast
- @res_ev.wait_until { @status == :res }
- value = @res
- @req = @res = nil
- @status = :wait
- @wait_ev.broadcast
- return value
- end
- end
-
- def _execute()
- synchronize do
- @req_ev.wait_until { @status == :req }
- @res = yield(@req)
- @status = :res
- @res_ev.signal
- end
- end
- end
-
- # Class handling the connection between a DRbObject and the
- # server the real object lives on.
- #
- # This class maintains a pool of connections, to reduce the
- # overhead of starting and closing down connections for each
- # method call.
- #
- # This class is used internally by DRbObject. The user does
- # not normally need to deal with it directly.
- class DRbConn
- POOL_SIZE = 16 # :nodoc:
-
- def self.make_pool
- ThreadObject.new do |queue|
- pool = []
- while true
- queue._execute do |message|
- case(message[0])
- when :take then
- remote_uri = message[1]
- conn = nil
- new_pool = []
- pool.each do |c|
- if conn.nil? and c.uri == remote_uri
- conn = c if c.alive?
- else
- new_pool.push c
- end
- end
- pool = new_pool
- conn
- when :store then
- conn = message[1]
- pool.unshift(conn)
- pool.pop.close while pool.size > POOL_SIZE
- conn
- else
- nil
- end
- end
- end
- end
- end
- @pool_proxy = nil
-
- def self.stop_pool
- @pool_proxy&.kill
- @pool_proxy = nil
- end
-
- def self.open(remote_uri) # :nodoc:
- begin
- @pool_proxy = make_pool unless @pool_proxy&.alive?
-
- conn = @pool_proxy.take(remote_uri)
- conn = self.new(remote_uri) unless conn
- succ, result = yield(conn)
- return succ, result
-
- ensure
- if conn
- if succ
- @pool_proxy.store(conn)
- else
- conn.close
- end
- end
- end
- end
-
- def initialize(remote_uri) # :nodoc:
- @uri = remote_uri
- @protocol = DRbProtocol.open(remote_uri, DRb.config)
- end
- attr_reader :uri # :nodoc:
-
- def send_message(ref, msg_id, arg, block) # :nodoc:
- @protocol.send_request(ref, msg_id, arg, block)
- @protocol.recv_reply
- end
-
- def close # :nodoc:
- @protocol.close
- @protocol = nil
- end
-
- def alive? # :nodoc:
- return false unless @protocol
- @protocol.alive?
- end
- end
-
- # Class representing a drb server instance.
- #
- # A DRbServer must be running in the local process before any incoming
- # dRuby calls can be accepted, or any local objects can be passed as
- # dRuby references to remote processes, even if those local objects are
- # never actually called remotely. You do not need to start a DRbServer
- # in the local process if you are only making outgoing dRuby calls
- # passing marshalled parameters.
- #
- # Unless multiple servers are being used, the local DRbServer is normally
- # started by calling DRb.start_service.
- class DRbServer
- @@acl = nil
- @@idconv = DRbIdConv.new
- @@secondary_server = nil
- @@argc_limit = 256
- @@load_limit = 0xffffffff
- @@verbose = false
-
- # Set the default value for the :argc_limit option.
- #
- # See #new(). The initial default value is 256.
- def self.default_argc_limit(argc)
- @@argc_limit = argc
- end
-
- # Set the default value for the :load_limit option.
- #
- # See #new(). The initial default value is 25 MB.
- def self.default_load_limit(sz)
- @@load_limit = sz
- end
-
- # Set the default access control list to +acl+. The default ACL is +nil+.
- #
- # See also DRb::ACL and #new()
- def self.default_acl(acl)
- @@acl = acl
- end
-
- # Set the default value for the :id_conv option.
- #
- # See #new(). The initial default value is a DRbIdConv instance.
- def self.default_id_conv(idconv)
- @@idconv = idconv
- end
-
- # Set the default value of the :verbose option.
- #
- # See #new(). The initial default value is false.
- def self.verbose=(on)
- @@verbose = on
- end
-
- # Get the default value of the :verbose option.
- def self.verbose
- @@verbose
- end
-
- def self.make_config(hash={}) # :nodoc:
- default_config = {
- :idconv => @@idconv,
- :verbose => @@verbose,
- :tcp_acl => @@acl,
- :load_limit => @@load_limit,
- :argc_limit => @@argc_limit,
- }
- default_config.update(hash)
- end
-
- # Create a new DRbServer instance.
- #
- # +uri+ is the URI to bind to. This is normally of the form
- # 'druby://<hostname>:<port>' where <hostname> is a hostname of
- # the local machine. If nil, then the system's default hostname
- # will be bound to, on a port selected by the system; these value
- # can be retrieved from the +uri+ attribute. 'druby:' specifies
- # the default dRuby transport protocol: another protocol, such
- # as 'drbunix:', can be specified instead.
- #
- # +front+ is the front object for the server, that is, the object
- # to which remote method calls on the server will be passed. If
- # nil, then the server will not accept remote method calls.
- #
- # If +config_or_acl+ is a hash, it is the configuration to
- # use for this server. The following options are recognised:
- #
- # :idconv :: an id-to-object conversion object. This defaults
- # to an instance of the class DRb::DRbIdConv.
- # :verbose :: if true, all unsuccessful remote calls on objects
- # in the server will be logged to $stdout. false
- # by default.
- # :tcp_acl :: the access control list for this server. See
- # the ACL class from the main dRuby distribution.
- # :load_limit :: the maximum message size in bytes accepted by
- # the server. Defaults to 25 MB (26214400).
- # :argc_limit :: the maximum number of arguments to a remote
- # method accepted by the server. Defaults to
- # 256.
- # The default values of these options can be modified on
- # a class-wide basis by the class methods #default_argc_limit,
- # #default_load_limit, #default_acl, #default_id_conv,
- # and #verbose=
- #
- # If +config_or_acl+ is not a hash, but is not nil, it is
- # assumed to be the access control list for this server.
- # See the :tcp_acl option for more details.
- #
- # If no other server is currently set as the primary server,
- # this will become the primary server.
- #
- # The server will immediately start running in its own thread.
- def initialize(uri=nil, front=nil, config_or_acl=nil)
- if Hash === config_or_acl
- config = config_or_acl.dup
- else
- acl = config_or_acl || @@acl
- config = {
- :tcp_acl => acl
- }
- end
-
- @config = self.class.make_config(config)
-
- @protocol = DRbProtocol.open_server(uri, @config)
- @uri = @protocol.uri
- @exported_uri = [@uri]
-
- @front = front
- @idconv = @config[:idconv]
-
- @grp = ThreadGroup.new
- @thread = run
-
- DRb.regist_server(self)
- end
-
- # The URI of this DRbServer.
- attr_reader :uri
-
- # The main thread of this DRbServer.
- #
- # This is the thread that listens for and accepts connections
- # from clients, not that handles each client's request-response
- # session.
- attr_reader :thread
-
- # The front object of the DRbServer.
- #
- # This object receives remote method calls made on the server's
- # URI alone, with an object id.
- attr_reader :front
-
- # The configuration of this DRbServer
- attr_reader :config
-
- # Set whether to operate in verbose mode.
- #
- # In verbose mode, failed calls are logged to stdout.
- def verbose=(v); @config[:verbose]=v; end
-
- # Get whether the server is in verbose mode.
- #
- # In verbose mode, failed calls are logged to stdout.
- def verbose; @config[:verbose]; end
-
- # Is this server alive?
- def alive?
- @thread.alive?
- end
-
- # Is +uri+ the URI for this server?
- def here?(uri)
- @exported_uri.include?(uri)
- end
-
- # Stop this server.
- def stop_service
- DRb.remove_server(self)
- if Thread.current['DRb'] && Thread.current['DRb']['server'] == self
- Thread.current['DRb']['stop_service'] = true
- else
- shutdown
- end
- end
-
- # Convert a dRuby reference to the local object it refers to.
- def to_obj(ref)
- return front if ref.nil?
- return front[ref.to_s] if DRbURIOption === ref
- @idconv.to_obj(ref)
- end
-
- # Convert a local object to a dRuby reference.
- def to_id(obj)
- return nil if obj.__id__ == front.__id__
- @idconv.to_id(obj)
- end
-
- private
-
- def shutdown
- current = Thread.current
- if @protocol.respond_to? :shutdown
- @protocol.shutdown
- else
- [@thread, *@grp.list].each { |thread|
- thread.kill unless thread == current # xxx: Thread#kill
- }
- end
- @thread.join unless @thread == current
- end
-
- ##
- # Starts the DRb main loop in a new thread.
-
- def run
- Thread.start do
- begin
- while main_loop
- end
- ensure
- @protocol.close if @protocol
- end
- end
- end
-
- # List of insecure methods.
- #
- # These methods are not callable via dRuby.
- INSECURE_METHOD = [
- :__send__
- ]
-
- # Has a method been included in the list of insecure methods?
- def insecure_method?(msg_id)
- INSECURE_METHOD.include?(msg_id)
- end
-
- # Coerce an object to a string, providing our own representation if
- # to_s is not defined for the object.
- def any_to_s(obj)
- "#{obj}:#{obj.class}"
- rescue
- Kernel.instance_method(:to_s).bind_call(obj)
- end
-
- # Check that a method is callable via dRuby.
- #
- # +obj+ is the object we want to invoke the method on. +msg_id+ is the
- # method name, as a Symbol.
- #
- # If the method is an insecure method (see #insecure_method?) a
- # SecurityError is thrown. If the method is private or undefined,
- # a NameError is thrown.
- def check_insecure_method(obj, msg_id)
- return true if Proc === obj && msg_id == :__drb_yield
- raise(ArgumentError, "#{any_to_s(msg_id)} is not a symbol") unless Symbol == msg_id.class
- raise(SecurityError, "insecure method `#{msg_id}'") if insecure_method?(msg_id)
-
- case obj
- when Object
- if obj.private_methods.include?(msg_id)
- desc = any_to_s(obj)
- raise NoMethodError, "private method `#{msg_id}' called for #{desc}"
- elsif obj.protected_methods.include?(msg_id)
- desc = any_to_s(obj)
- raise NoMethodError, "protected method `#{msg_id}' called for #{desc}"
- else
- true
- end
- else
- if Kernel.instance_method(:private_methods).bind(obj).call.include?(msg_id)
- desc = any_to_s(obj)
- raise NoMethodError, "private method `#{msg_id}' called for #{desc}"
- elsif Kernel.instance_method(:protected_methods).bind(obj).call.include?(msg_id)
- desc = any_to_s(obj)
- raise NoMethodError, "protected method `#{msg_id}' called for #{desc}"
- else
- true
- end
- end
- end
- public :check_insecure_method
-
- class InvokeMethod # :nodoc:
- def initialize(drb_server, client)
- @drb_server = drb_server
- @client = client
- end
-
- def perform
- begin
- setup_message
- ensure
- @result = nil
- @succ = false
- end
-
- if @block
- @result = perform_with_block
- else
- @result = perform_without_block
- end
- @succ = true
- case @result
- when Array
- if @msg_id == :to_ary
- @result = DRbArray.new(@result)
- end
- end
- return @succ, @result
- rescue NoMemoryError, SystemExit, SystemStackError, SecurityError
- raise
- rescue Exception
- @result = $!
- return @succ, @result
- end
-
- private
- def init_with_client
- obj, msg, argv, block = @client.recv_request
- @obj = obj
- @msg_id = msg.intern
- @argv = argv
- @block = block
- end
-
- def check_insecure_method
- @drb_server.check_insecure_method(@obj, @msg_id)
- end
-
- def setup_message
- init_with_client
- check_insecure_method
- end
-
- def perform_without_block
- if Proc === @obj && @msg_id == :__drb_yield
- if @argv.size == 1
- ary = @argv
- else
- ary = [@argv]
- end
- ary.collect(&@obj)[0]
- else
- @obj.__send__(@msg_id, *@argv)
- end
- end
-
- end
-
- require_relative 'invokemethod'
- class InvokeMethod
- include InvokeMethod18Mixin
- end
-
- def error_print(exception)
- exception.backtrace.inject(true) do |first, x|
- if first
- $stderr.puts "#{x}: #{exception} (#{exception.class})"
- else
- $stderr.puts "\tfrom #{x}"
- end
- false
- end
- end
-
- # The main loop performed by a DRbServer's internal thread.
- #
- # Accepts a connection from a client, and starts up its own
- # thread to handle it. This thread loops, receiving requests
- # from the client, invoking them on a local object, and
- # returning responses, until the client closes the connection
- # or a local method call fails.
- def main_loop
- client0 = @protocol.accept
- return nil if !client0
- Thread.start(client0) do |client|
- @grp.add Thread.current
- Thread.current['DRb'] = { 'client' => client ,
- 'server' => self }
- DRb.mutex.synchronize do
- client_uri = client.uri
- @exported_uri << client_uri unless @exported_uri.include?(client_uri)
- end
- _last_invoke_method = nil
- loop do
- begin
- succ = false
- invoke_method = InvokeMethod.new(self, client)
- succ, result = invoke_method.perform
- error_print(result) if !succ && verbose
- unless DRbConnError === result && result.message == 'connection closed'
- client.send_reply(succ, result)
- end
- rescue Exception => e
- error_print(e) if verbose
- ensure
- _last_invoke_method = invoke_method
- client.close unless succ
- if Thread.current['DRb']['stop_service']
- shutdown
- break
- end
- break unless succ
- end
- end
- end
- end
- end
-
- @primary_server = nil
-
- # Start a dRuby server locally.
- #
- # The new dRuby server will become the primary server, even
- # if another server is currently the primary server.
- #
- # +uri+ is the URI for the server to bind to. If nil,
- # the server will bind to random port on the default local host
- # name and use the default dRuby protocol.
- #
- # +front+ is the server's front object. This may be nil.
- #
- # +config+ is the configuration for the new server. This may
- # be nil.
- #
- # See DRbServer::new.
- def start_service(uri=nil, front=nil, config=nil)
- @primary_server = DRbServer.new(uri, front, config)
- end
- module_function :start_service
-
- # The primary local dRuby server.
- #
- # This is the server created by the #start_service call.
- attr_accessor :primary_server
- module_function :primary_server=, :primary_server
-
- # Get the 'current' server.
- #
- # In the context of execution taking place within the main
- # thread of a dRuby server (typically, as a result of a remote
- # call on the server or one of its objects), the current
- # server is that server. Otherwise, the current server is
- # the primary server.
- #
- # If the above rule fails to find a server, a DRbServerNotFound
- # error is raised.
- def current_server
- drb = Thread.current['DRb']
- server = (drb && drb['server']) ? drb['server'] : @primary_server
- raise DRbServerNotFound unless server
- return server
- end
- module_function :current_server
-
- # Stop the local dRuby server.
- #
- # This operates on the primary server. If there is no primary
- # server currently running, it is a noop.
- def stop_service
- @primary_server.stop_service if @primary_server
- @primary_server = nil
- end
- module_function :stop_service
-
- # Get the URI defining the local dRuby space.
- #
- # This is the URI of the current server. See #current_server.
- def uri
- drb = Thread.current['DRb']
- client = (drb && drb['client'])
- if client
- uri = client.uri
- return uri if uri
- end
- current_server.uri
- end
- module_function :uri
-
- # Is +uri+ the URI for the current local server?
- def here?(uri)
- current_server.here?(uri) rescue false
- # (current_server.uri rescue nil) == uri
- end
- module_function :here?
-
- # Get the configuration of the current server.
- #
- # If there is no current server, this returns the default configuration.
- # See #current_server and DRbServer::make_config.
- def config
- current_server.config
- rescue
- DRbServer.make_config
- end
- module_function :config
-
- # Get the front object of the current server.
- #
- # This raises a DRbServerNotFound error if there is no current server.
- # See #current_server.
- def front
- current_server.front
- end
- module_function :front
-
- # Convert a reference into an object using the current server.
- #
- # This raises a DRbServerNotFound error if there is no current server.
- # See #current_server.
- def to_obj(ref)
- current_server.to_obj(ref)
- end
-
- # Get a reference id for an object using the current server.
- #
- # This raises a DRbServerNotFound error if there is no current server.
- # See #current_server.
- def to_id(obj)
- current_server.to_id(obj)
- end
- module_function :to_id
- module_function :to_obj
-
- # Get the thread of the primary server.
- #
- # This returns nil if there is no primary server. See #primary_server.
- def thread
- @primary_server ? @primary_server.thread : nil
- end
- module_function :thread
-
- # Set the default id conversion object.
- #
- # This is expected to be an instance such as DRb::DRbIdConv that responds to
- # #to_id and #to_obj that can convert objects to and from DRb references.
- #
- # See DRbServer#default_id_conv.
- def install_id_conv(idconv)
- DRbServer.default_id_conv(idconv)
- end
- module_function :install_id_conv
-
- # Set the default ACL to +acl+.
- #
- # See DRb::DRbServer.default_acl.
- def install_acl(acl)
- DRbServer.default_acl(acl)
- end
- module_function :install_acl
-
- @mutex = Thread::Mutex.new
- def mutex # :nodoc:
- @mutex
- end
- module_function :mutex
-
- @server = {}
- # Registers +server+ with DRb.
- #
- # This is called when a new DRb::DRbServer is created.
- #
- # If there is no primary server then +server+ becomes the primary server.
- #
- # Example:
- #
- # require 'drb'
- #
- # s = DRb::DRbServer.new # automatically calls regist_server
- # DRb.fetch_server s.uri #=> #<DRb::DRbServer:0x...>
- def regist_server(server)
- @server[server.uri] = server
- mutex.synchronize do
- @primary_server = server unless @primary_server
- end
- end
- module_function :regist_server
-
- # Removes +server+ from the list of registered servers.
- def remove_server(server)
- @server.delete(server.uri)
- mutex.synchronize do
- if @primary_server == server
- @primary_server = nil
- end
- end
- end
- module_function :remove_server
-
- # Retrieves the server with the given +uri+.
- #
- # See also regist_server and remove_server.
- def fetch_server(uri)
- @server[uri]
- end
- module_function :fetch_server
-end
-
-# :stopdoc:
-DRbObject = DRb::DRbObject
-DRbUndumped = DRb::DRbUndumped
-DRbIdConv = DRb::DRbIdConv
diff --git a/lib/drb/eq.rb b/lib/drb/eq.rb
deleted file mode 100644
index 15ca5cae42..0000000000
--- a/lib/drb/eq.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: false
-module DRb
- class DRbObject # :nodoc:
- def ==(other)
- return false unless DRbObject === other
- (@ref == other.__drbref) && (@uri == other.__drburi)
- end
-
- def hash
- [@uri, @ref].hash
- end
-
- alias eql? ==
- end
-end
diff --git a/lib/drb/extserv.rb b/lib/drb/extserv.rb
deleted file mode 100644
index 9523fe84e3..0000000000
--- a/lib/drb/extserv.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: false
-=begin
- external service
- Copyright (c) 2000,2002 Masatoshi SEKI
-=end
-
-require_relative 'drb'
-require 'monitor'
-
-module DRb
- class ExtServ
- include MonitorMixin
- include DRbUndumped
-
- def initialize(there, name, server=nil)
- super()
- @server = server || DRb::primary_server
- @name = name
- ro = DRbObject.new(nil, there)
- synchronize do
- @invoker = ro.register(name, DRbObject.new(self, @server.uri))
- end
- end
- attr_reader :server
-
- def front
- DRbObject.new(nil, @server.uri)
- end
-
- def stop_service
- synchronize do
- @invoker.unregister(@name)
- server = @server
- @server = nil
- server.stop_service
- true
- end
- end
-
- def alive?
- @server ? @server.alive? : false
- end
- end
-end
diff --git a/lib/drb/extservm.rb b/lib/drb/extservm.rb
deleted file mode 100644
index 9333a108e5..0000000000
--- a/lib/drb/extservm.rb
+++ /dev/null
@@ -1,94 +0,0 @@
-# frozen_string_literal: false
-=begin
- external service manager
- Copyright (c) 2000 Masatoshi SEKI
-=end
-
-require_relative 'drb'
-require 'monitor'
-
-module DRb
- class ExtServManager
- include DRbUndumped
- include MonitorMixin
-
- @@command = {}
-
- def self.command
- @@command
- end
-
- def self.command=(cmd)
- @@command = cmd
- end
-
- def initialize
- super()
- @cond = new_cond
- @servers = {}
- @waiting = []
- @queue = Thread::Queue.new
- @thread = invoke_thread
- @uri = nil
- end
- attr_accessor :uri
-
- def service(name)
- synchronize do
- while true
- server = @servers[name]
- return server if server && server.alive? # server may be `false'
- invoke_service(name)
- @cond.wait
- end
- end
- end
-
- def register(name, ro)
- synchronize do
- @servers[name] = ro
- @cond.signal
- end
- self
- end
- alias regist register
-
- def unregister(name)
- synchronize do
- @servers.delete(name)
- end
- end
- alias unregist unregister
-
- private
- def invoke_thread
- Thread.new do
- while name = @queue.pop
- invoke_service_command(name, @@command[name])
- end
- end
- end
-
- def invoke_service(name)
- @queue.push(name)
- end
-
- def invoke_service_command(name, command)
- raise "invalid command. name: #{name}" unless command
- synchronize do
- return if @servers.include?(name)
- @servers[name] = false
- end
- uri = @uri || DRb.uri
- if command.respond_to? :to_ary
- command = command.to_ary + [uri, name]
- pid = spawn(*command)
- else
- pid = spawn("#{command} #{uri} #{name}")
- end
- th = Process.detach(pid)
- th[:drb_service] = name
- th
- end
- end
-end
diff --git a/lib/drb/gw.rb b/lib/drb/gw.rb
deleted file mode 100644
index 65a525476e..0000000000
--- a/lib/drb/gw.rb
+++ /dev/null
@@ -1,161 +0,0 @@
-# frozen_string_literal: false
-require_relative 'drb'
-require 'monitor'
-
-module DRb
-
- # Gateway id conversion forms a gateway between different DRb protocols or
- # networks.
- #
- # The gateway needs to install this id conversion and create servers for
- # each of the protocols or networks it will be a gateway between. It then
- # needs to create a server that attaches to each of these networks. For
- # example:
- #
- # require 'drb/drb'
- # require 'drb/unix'
- # require 'drb/gw'
- #
- # DRb.install_id_conv DRb::GWIdConv.new
- # gw = DRb::GW.new
- # s1 = DRb::DRbServer.new 'drbunix:/path/to/gateway', gw
- # s2 = DRb::DRbServer.new 'druby://example:10000', gw
- #
- # s1.thread.join
- # s2.thread.join
- #
- # Each client must register services with the gateway, for example:
- #
- # DRb.start_service 'drbunix:', nil # an anonymous server
- # gw = DRbObject.new nil, 'drbunix:/path/to/gateway'
- # gw[:unix] = some_service
- # DRb.thread.join
-
- class GWIdConv < DRbIdConv
- def to_obj(ref) # :nodoc:
- if Array === ref && ref[0] == :DRbObject
- return DRbObject.new_with(ref[1], ref[2])
- end
- super(ref)
- end
- end
-
- # The GW provides a synchronized store for participants in the gateway to
- # communicate.
-
- class GW
- include MonitorMixin
-
- # Creates a new GW
-
- def initialize
- super()
- @hash = {}
- end
-
- # Retrieves +key+ from the GW
-
- def [](key)
- synchronize do
- @hash[key]
- end
- end
-
- # Stores value +v+ at +key+ in the GW
-
- def []=(key, v)
- synchronize do
- @hash[key] = v
- end
- end
- end
-
- class DRbObject # :nodoc:
- def self._load(s)
- uri, ref = Marshal.load(s)
- if DRb.uri == uri
- return ref ? DRb.to_obj(ref) : DRb.front
- end
-
- self.new_with(DRb.uri, [:DRbObject, uri, ref])
- end
-
- def _dump(lv)
- if DRb.uri == @uri
- if Array === @ref && @ref[0] == :DRbObject
- Marshal.dump([@ref[1], @ref[2]])
- else
- Marshal.dump([@uri, @ref]) # ??
- end
- else
- Marshal.dump([DRb.uri, [:DRbObject, @uri, @ref]])
- end
- end
- end
-end
-
-=begin
-DRb.install_id_conv(DRb::GWIdConv.new)
-
-front = DRb::GW.new
-
-s1 = DRb::DRbServer.new('drbunix:/tmp/gw_b_a', front)
-s2 = DRb::DRbServer.new('drbunix:/tmp/gw_b_c', front)
-
-s1.thread.join
-s2.thread.join
-=end
-
-=begin
-# foo.rb
-
-require 'drb/drb'
-
-class Foo
- include DRbUndumped
- def initialize(name, peer=nil)
- @name = name
- @peer = peer
- end
-
- def ping(obj)
- puts "#{@name}: ping: #{obj.inspect}"
- @peer.ping(self) if @peer
- end
-end
-=end
-
-=begin
-# gw_a.rb
-require 'drb/unix'
-require 'foo'
-
-obj = Foo.new('a')
-DRb.start_service("drbunix:/tmp/gw_a", obj)
-
-robj = DRbObject.new_with_uri('drbunix:/tmp/gw_b_a')
-robj[:a] = obj
-
-DRb.thread.join
-=end
-
-=begin
-# gw_c.rb
-require 'drb/unix'
-require 'foo'
-
-foo = Foo.new('c', nil)
-
-DRb.start_service("drbunix:/tmp/gw_c", nil)
-
-robj = DRbObject.new_with_uri("drbunix:/tmp/gw_b_c")
-
-puts "c->b"
-a = robj[:a]
-sleep 2
-
-a.ping(foo)
-
-DRb.thread.join
-=end
-
diff --git a/lib/drb/invokemethod.rb b/lib/drb/invokemethod.rb
deleted file mode 100644
index 0fae6d52b6..0000000000
--- a/lib/drb/invokemethod.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: false
-# for ruby-1.8.0
-
-module DRb # :nodoc: all
- class DRbServer
- module InvokeMethod18Mixin
- def block_yield(x)
- if x.size == 1 && x[0].class == Array
- x[0] = DRbArray.new(x[0])
- end
- @block.call(*x)
- end
-
- def perform_with_block
- @obj.__send__(@msg_id, *@argv) do |*x|
- jump_error = nil
- begin
- block_value = block_yield(x)
- rescue LocalJumpError
- jump_error = $!
- end
- if jump_error
- case jump_error.reason
- when :break
- break(jump_error.exit_value)
- else
- raise jump_error
- end
- end
- block_value
- end
- end
- end
- end
-end
diff --git a/lib/drb/observer.rb b/lib/drb/observer.rb
deleted file mode 100644
index 0fb7301edf..0000000000
--- a/lib/drb/observer.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: false
-require 'observer'
-
-module DRb
- # The Observable module extended to DRb. See Observable for details.
- module DRbObservable
- include Observable
-
- # Notifies observers of a change in state. See also
- # Observable#notify_observers
- def notify_observers(*arg)
- if defined? @observer_state and @observer_state
- if defined? @observer_peers
- @observer_peers.each do |observer, method|
- begin
- observer.__send__(method, *arg)
- rescue
- delete_observer(observer)
- end
- end
- end
- @observer_state = false
- end
- end
- end
-end
diff --git a/lib/drb/ssl.rb b/lib/drb/ssl.rb
deleted file mode 100644
index 392d6560e9..0000000000
--- a/lib/drb/ssl.rb
+++ /dev/null
@@ -1,354 +0,0 @@
-# frozen_string_literal: false
-require 'socket'
-require 'openssl'
-require_relative 'drb'
-require 'singleton'
-
-module DRb
-
- # The protocol for DRb over an SSL socket
- #
- # The URI for a DRb socket over SSL is:
- # <code>drbssl://<host>:<port>?<option></code>. The option is optional
- class DRbSSLSocket < DRbTCPSocket
-
- # SSLConfig handles the needed SSL information for establishing a
- # DRbSSLSocket connection, including generating the X509 / RSA pair.
- #
- # An instance of this config can be passed to DRbSSLSocket.new,
- # DRbSSLSocket.open and DRbSSLSocket.open_server
- #
- # See DRb::DRbSSLSocket::SSLConfig.new for more details
- class SSLConfig
-
- # Default values for a SSLConfig instance.
- #
- # See DRb::DRbSSLSocket::SSLConfig.new for more details
- DEFAULT = {
- :SSLCertificate => nil,
- :SSLPrivateKey => nil,
- :SSLClientCA => nil,
- :SSLCACertificatePath => nil,
- :SSLCACertificateFile => nil,
- :SSLTmpDhCallback => nil,
- :SSLVerifyMode => ::OpenSSL::SSL::VERIFY_NONE,
- :SSLVerifyDepth => nil,
- :SSLVerifyCallback => nil, # custom verification
- :SSLCertificateStore => nil,
- # Must specify if you use auto generated certificate.
- :SSLCertName => nil, # e.g. [["CN","fqdn.example.com"]]
- :SSLCertComment => "Generated by Ruby/OpenSSL"
- }
-
- # Create a new DRb::DRbSSLSocket::SSLConfig instance
- #
- # The DRb::DRbSSLSocket will take either a +config+ Hash or an instance
- # of SSLConfig, and will setup the certificate for its session for the
- # configuration. If want it to generate a generic certificate, the bare
- # minimum is to provide the :SSLCertName
- #
- # === Config options
- #
- # From +config+ Hash:
- #
- # :SSLCertificate ::
- # An instance of OpenSSL::X509::Certificate. If this is not provided,
- # then a generic X509 is generated, with a correspond :SSLPrivateKey
- #
- # :SSLPrivateKey ::
- # A private key instance, like OpenSSL::PKey::RSA. This key must be
- # the key that signed the :SSLCertificate
- #
- # :SSLClientCA ::
- # An OpenSSL::X509::Certificate, or Array of certificates that will
- # used as ClientCAs in the SSL Context
- #
- # :SSLCACertificatePath ::
- # A path to the directory of CA certificates. The certificates must
- # be in PEM format.
- #
- # :SSLCACertificateFile ::
- # A path to a CA certificate file, in PEM format.
- #
- # :SSLTmpDhCallback ::
- # A DH callback. See OpenSSL::SSL::SSLContext.tmp_dh_callback
- #
- # :SSLMinVersion ::
- # This is the minimum SSL version to allow. See
- # OpenSSL::SSL::SSLContext#min_version=.
- #
- # :SSLMaxVersion ::
- # This is the maximum SSL version to allow. See
- # OpenSSL::SSL::SSLContext#max_version=.
- #
- # :SSLVerifyMode ::
- # This is the SSL verification mode. See OpenSSL::SSL::VERIFY_* for
- # available modes. The default is OpenSSL::SSL::VERIFY_NONE
- #
- # :SSLVerifyDepth ::
- # Number of CA certificates to walk, when verifying a certificate
- # chain.
- #
- # :SSLVerifyCallback ::
- # A callback to be used for additional verification. See
- # OpenSSL::SSL::SSLContext.verify_callback
- #
- # :SSLCertificateStore ::
- # A OpenSSL::X509::Store used for verification of certificates
- #
- # :SSLCertName ::
- # Issuer name for the certificate. This is required when generating
- # the certificate (if :SSLCertificate and :SSLPrivateKey were not
- # given). The value of this is to be an Array of pairs:
- #
- # [["C", "Raleigh"], ["ST","North Carolina"],
- # ["CN","fqdn.example.com"]]
- #
- # See also OpenSSL::X509::Name
- #
- # :SSLCertComment ::
- # A comment to be used for generating the certificate. The default is
- # "Generated by Ruby/OpenSSL"
- #
- #
- # === Example
- #
- # These values can be added after the fact, like a Hash.
- #
- # require 'drb/ssl'
- # c = DRb::DRbSSLSocket::SSLConfig.new {}
- # c[:SSLCertificate] =
- # OpenSSL::X509::Certificate.new(File.read('mycert.crt'))
- # c[:SSLPrivateKey] = OpenSSL::PKey::RSA.new(File.read('mycert.key'))
- # c[:SSLVerifyMode] = OpenSSL::SSL::VERIFY_PEER
- # c[:SSLCACertificatePath] = "/etc/ssl/certs/"
- # c.setup_certificate
- #
- # or
- #
- # require 'drb/ssl'
- # c = DRb::DRbSSLSocket::SSLConfig.new({
- # :SSLCertName => [["CN" => DRb::DRbSSLSocket.getservername]]
- # })
- # c.setup_certificate
- #
- def initialize(config)
- @config = config
- @cert = config[:SSLCertificate]
- @pkey = config[:SSLPrivateKey]
- @ssl_ctx = nil
- end
-
- # A convenience method to access the values like a Hash
- def [](key);
- @config[key] || DEFAULT[key]
- end
-
- # Connect to IO +tcp+, with context of the current certificate
- # configuration
- def connect(tcp)
- ssl = ::OpenSSL::SSL::SSLSocket.new(tcp, @ssl_ctx)
- ssl.sync = true
- ssl.connect
- ssl
- end
-
- # Accept connection to IO +tcp+, with context of the current certificate
- # configuration
- def accept(tcp)
- ssl = OpenSSL::SSL::SSLSocket.new(tcp, @ssl_ctx)
- ssl.sync = true
- ssl.accept
- ssl
- end
-
- # Ensures that :SSLCertificate and :SSLPrivateKey have been provided
- # or that a new certificate is generated with the other parameters
- # provided.
- def setup_certificate
- if @cert && @pkey
- return
- end
-
- rsa = OpenSSL::PKey::RSA.new(2048){|p, n|
- next unless self[:verbose]
- case p
- when 0; $stderr.putc "." # BN_generate_prime
- when 1; $stderr.putc "+" # BN_generate_prime
- when 2; $stderr.putc "*" # searching good prime,
- # n = #of try,
- # but also data from BN_generate_prime
- when 3; $stderr.putc "\n" # found good prime, n==0 - p, n==1 - q,
- # but also data from BN_generate_prime
- else; $stderr.putc "*" # BN_generate_prime
- end
- }
-
- cert = OpenSSL::X509::Certificate.new
- cert.version = 3
- cert.serial = 0
- name = OpenSSL::X509::Name.new(self[:SSLCertName])
- cert.subject = name
- cert.issuer = name
- cert.not_before = Time.now
- cert.not_after = Time.now + (365*24*60*60)
- cert.public_key = rsa.public_key
-
- ef = OpenSSL::X509::ExtensionFactory.new(nil,cert)
- cert.extensions = [
- ef.create_extension("basicConstraints","CA:FALSE"),
- ef.create_extension("subjectKeyIdentifier", "hash") ]
- ef.issuer_certificate = cert
- cert.add_extension(ef.create_extension("authorityKeyIdentifier",
- "keyid:always,issuer:always"))
- if comment = self[:SSLCertComment]
- cert.add_extension(ef.create_extension("nsComment", comment))
- end
- cert.sign(rsa, "SHA256")
-
- @cert = cert
- @pkey = rsa
- end
-
- # Establish the OpenSSL::SSL::SSLContext with the configuration
- # parameters provided.
- def setup_ssl_context
- ctx = ::OpenSSL::SSL::SSLContext.new
- ctx.cert = @cert
- ctx.key = @pkey
- ctx.min_version = self[:SSLMinVersion]
- ctx.max_version = self[:SSLMaxVersion]
- ctx.client_ca = self[:SSLClientCA]
- ctx.ca_path = self[:SSLCACertificatePath]
- ctx.ca_file = self[:SSLCACertificateFile]
- ctx.tmp_dh_callback = self[:SSLTmpDhCallback]
- ctx.verify_mode = self[:SSLVerifyMode]
- ctx.verify_depth = self[:SSLVerifyDepth]
- ctx.verify_callback = self[:SSLVerifyCallback]
- ctx.cert_store = self[:SSLCertificateStore]
- @ssl_ctx = ctx
- end
- end
-
- # Parse the dRuby +uri+ for an SSL connection.
- #
- # Expects drbssl://...
- #
- # Raises DRbBadScheme or DRbBadURI if +uri+ is not matching or malformed
- def self.parse_uri(uri) # :nodoc:
- if /\Adrbssl:\/\/(.*?):(\d+)(\?(.*))?\z/ =~ uri
- host = $1
- port = $2.to_i
- option = $4
- [host, port, option]
- else
- raise(DRbBadScheme, uri) unless uri.start_with?('drbssl:')
- raise(DRbBadURI, 'can\'t parse uri:' + uri)
- end
- end
-
- # Return an DRb::DRbSSLSocket instance as a client-side connection,
- # with the SSL connected. This is called from DRb::start_service or while
- # connecting to a remote object:
- #
- # DRb.start_service 'drbssl://localhost:0', front, config
- #
- # +uri+ is the URI we are connected to,
- # <code>'drbssl://localhost:0'</code> above, +config+ is our
- # configuration. Either a Hash or DRb::DRbSSLSocket::SSLConfig
- def self.open(uri, config)
- host, port, = parse_uri(uri)
- soc = TCPSocket.open(host, port)
- ssl_conf = SSLConfig::new(config)
- ssl_conf.setup_ssl_context
- ssl = ssl_conf.connect(soc)
- self.new(uri, ssl, ssl_conf, true)
- end
-
- # Returns a DRb::DRbSSLSocket instance as a server-side connection, with
- # the SSL connected. This is called from DRb::start_service or while
- # connecting to a remote object:
- #
- # DRb.start_service 'drbssl://localhost:0', front, config
- #
- # +uri+ is the URI we are connected to,
- # <code>'drbssl://localhost:0'</code> above, +config+ is our
- # configuration. Either a Hash or DRb::DRbSSLSocket::SSLConfig
- def self.open_server(uri, config)
- uri = 'drbssl://:0' unless uri
- host, port, = parse_uri(uri)
- if host.size == 0
- host = getservername
- soc = open_server_inaddr_any(host, port)
- else
- soc = TCPServer.open(host, port)
- end
- port = soc.addr[1] if port == 0
- @uri = "drbssl://#{host}:#{port}"
-
- ssl_conf = SSLConfig.new(config)
- ssl_conf.setup_certificate
- ssl_conf.setup_ssl_context
- self.new(@uri, soc, ssl_conf, false)
- end
-
- # This is a convenience method to parse +uri+ and separate out any
- # additional options appended in the +uri+.
- #
- # Returns an option-less uri and the option => [uri,option]
- #
- # The +config+ is completely unused, so passing nil is sufficient.
- def self.uri_option(uri, config) # :nodoc:
- host, port, option = parse_uri(uri)
- return "drbssl://#{host}:#{port}", option
- end
-
- # Create a DRb::DRbSSLSocket instance.
- #
- # +uri+ is the URI we are connected to.
- # +soc+ is the tcp socket we are bound to.
- # +config+ is our configuration. Either a Hash or SSLConfig
- # +is_established+ is a boolean of whether +soc+ is currently established
- #
- # This is called automatically based on the DRb protocol.
- def initialize(uri, soc, config, is_established)
- @ssl = is_established ? soc : nil
- super(uri, soc.to_io, config)
- end
-
- # Returns the SSL stream
- def stream; @ssl; end # :nodoc:
-
- # Closes the SSL stream before closing the dRuby connection.
- def close # :nodoc:
- if @ssl
- @ssl.close
- @ssl = nil
- end
- super
- end
-
- def accept # :nodoc:
- begin
- while true
- soc = accept_or_shutdown
- return nil unless soc
- break if (@acl ? @acl.allow_socket?(soc) : true)
- soc.close
- end
- begin
- ssl = @config.accept(soc)
- rescue Exception
- soc.close
- raise
- end
- self.class.new(uri, ssl, @config, true)
- rescue OpenSSL::SSL::SSLError
- warn("#{$!.message} (#{$!.class})", uplevel: 0) if @config[:verbose]
- retry
- end
- end
- end
-
- DRbProtocol.add_protocol(DRbSSLSocket)
-end
diff --git a/lib/drb/timeridconv.rb b/lib/drb/timeridconv.rb
deleted file mode 100644
index 3ead98a7f2..0000000000
--- a/lib/drb/timeridconv.rb
+++ /dev/null
@@ -1,97 +0,0 @@
-# frozen_string_literal: false
-require_relative 'drb'
-require 'monitor'
-
-module DRb
-
- # Timer id conversion keeps objects alive for a certain amount of time after
- # their last access. The default time period is 600 seconds and can be
- # changed upon initialization.
- #
- # To use TimerIdConv:
- #
- # DRb.install_id_conv TimerIdConv.new 60 # one minute
-
- class TimerIdConv < DRbIdConv
- class TimerHolder2 # :nodoc:
- include MonitorMixin
-
- class InvalidIndexError < RuntimeError; end
-
- def initialize(keeping=600)
- super()
- @sentinel = Object.new
- @gc = {}
- @renew = {}
- @keeping = keeping
- @expires = nil
- end
-
- def add(obj)
- synchronize do
- rotate
- key = obj.__id__
- @renew[key] = obj
- invoke_keeper
- return key
- end
- end
-
- def fetch(key)
- synchronize do
- rotate
- obj = peek(key)
- raise InvalidIndexError if obj == @sentinel
- @renew[key] = obj # KeepIt
- return obj
- end
- end
-
- private
- def peek(key)
- return @renew.fetch(key) { @gc.fetch(key, @sentinel) }
- end
-
- def invoke_keeper
- return if @expires
- @expires = Time.now + @keeping
- on_gc
- end
-
- def on_gc
- return unless Thread.main.alive?
- return if @expires.nil?
- Thread.new { rotate } if @expires < Time.now
- ObjectSpace.define_finalizer(Object.new) {on_gc}
- end
-
- def rotate
- synchronize do
- if @expires &.< Time.now
- @gc = @renew # GCed
- @renew = {}
- @expires = @gc.empty? ? nil : Time.now + @keeping
- end
- end
- end
- end
-
- # Creates a new TimerIdConv which will hold objects for +keeping+ seconds.
- def initialize(keeping=600)
- @holder = TimerHolder2.new(keeping)
- end
-
- def to_obj(ref) # :nodoc:
- return super if ref.nil?
- @holder.fetch(ref)
- rescue TimerHolder2::InvalidIndexError
- raise "invalid reference"
- end
-
- def to_id(obj) # :nodoc:
- return @holder.add(obj)
- end
- end
-end
-
-# DRb.install_id_conv(TimerIdConv.new)
diff --git a/lib/drb/unix.rb b/lib/drb/unix.rb
deleted file mode 100644
index 1629ad3bcd..0000000000
--- a/lib/drb/unix.rb
+++ /dev/null
@@ -1,118 +0,0 @@
-# frozen_string_literal: false
-require 'socket'
-require_relative 'drb'
-require 'tmpdir'
-
-raise(LoadError, "UNIXServer is required") unless defined?(UNIXServer)
-
-module DRb
-
- # Implements DRb over a UNIX socket
- #
- # DRb UNIX socket URIs look like <code>drbunix:<path>?<option></code>. The
- # option is optional.
-
- class DRbUNIXSocket < DRbTCPSocket
- # :stopdoc:
- def self.parse_uri(uri)
- if /\Adrbunix:(.*?)(\?(.*))?\z/ =~ uri
- filename = $1
- option = $3
- [filename, option]
- else
- raise(DRbBadScheme, uri) unless uri.start_with?('drbunix:')
- raise(DRbBadURI, 'can\'t parse uri:' + uri)
- end
- end
-
- def self.open(uri, config)
- filename, = parse_uri(uri)
- soc = UNIXSocket.open(filename)
- self.new(uri, soc, config)
- end
-
- def self.open_server(uri, config)
- filename, = parse_uri(uri)
- if filename.size == 0
- soc = temp_server
- filename = soc.path
- uri = 'drbunix:' + soc.path
- else
- soc = UNIXServer.open(filename)
- end
- owner = config[:UNIXFileOwner]
- group = config[:UNIXFileGroup]
- if owner || group
- require 'etc'
- owner = Etc.getpwnam( owner ).uid if owner
- group = Etc.getgrnam( group ).gid if group
- File.chown owner, group, filename
- end
- mode = config[:UNIXFileMode]
- File.chmod(mode, filename) if mode
-
- self.new(uri, soc, config, true)
- end
-
- def self.uri_option(uri, config)
- filename, option = parse_uri(uri)
- return "drbunix:#{filename}", option
- end
-
- def initialize(uri, soc, config={}, server_mode = false)
- super(uri, soc, config)
- set_sockopt(@socket)
- @server_mode = server_mode
- @acl = nil
- end
-
- # import from tempfile.rb
- Max_try = 10
- private
- def self.temp_server
- tmpdir = Dir::tmpdir
- n = 0
- while true
- begin
- tmpname = sprintf('%s/druby%d.%d', tmpdir, $$, n)
- lock = tmpname + '.lock'
- unless File.exist?(tmpname) or File.exist?(lock)
- Dir.mkdir(lock)
- break
- end
- rescue
- raise "cannot generate tempfile `%s'" % tmpname if n >= Max_try
- #sleep(1)
- end
- n += 1
- end
- soc = UNIXServer.new(tmpname)
- Dir.rmdir(lock)
- soc
- end
-
- public
- def close
- return unless @socket
- shutdown # DRbProtocol#shutdown
- path = @socket.path if @server_mode
- @socket.close
- File.unlink(path) if @server_mode
- @socket = nil
- close_shutdown_pipe
- end
-
- def accept
- s = accept_or_shutdown
- return nil unless s
- self.class.new(nil, s, @config)
- end
-
- def set_sockopt(soc)
- # no-op for now
- end
- end
-
- DRbProtocol.add_protocol(DRbUNIXSocket)
- # :startdoc:
-end
diff --git a/lib/drb/version.rb b/lib/drb/version.rb
deleted file mode 100644
index 73fa4c18fd..0000000000
--- a/lib/drb/version.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-module DRb
- VERSION = "2.2.0"
-end
diff --git a/lib/drb/weakidconv.rb b/lib/drb/weakidconv.rb
deleted file mode 100644
index ecf0bf515f..0000000000
--- a/lib/drb/weakidconv.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-# frozen_string_literal: false
-require_relative 'drb'
-require 'monitor'
-
-module DRb
-
- # To use WeakIdConv:
- #
- # DRb.start_service(nil, nil, {:idconv => DRb::WeakIdConv.new})
-
- class WeakIdConv < DRbIdConv
- class WeakSet
- include MonitorMixin
- def initialize
- super()
- @immutable = {}
- @map = ObjectSpace::WeakMap.new
- end
-
- def add(obj)
- synchronize do
- begin
- @map[obj] = self
- rescue ArgumentError
- @immutable[obj.__id__] = obj
- end
- return obj.__id__
- end
- end
-
- def fetch(ref)
- synchronize do
- @immutable.fetch(ref) {
- @map.each { |key, _|
- return key if key.__id__ == ref
- }
- raise RangeError.new("invalid reference")
- }
- end
- end
- end
-
- def initialize()
- super()
- @weak_set = WeakSet.new
- end
-
- def to_obj(ref) # :nodoc:
- return super if ref.nil?
- @weak_set.fetch(ref)
- end
-
- def to_id(obj) # :nodoc:
- return @weak_set.add(obj)
- end
- end
-end
-
-# DRb.install_id_conv(WeakIdConv.new)
diff --git a/lib/erb/version.rb b/lib/erb/version.rb
index 295fc5fa6f..b5fe39b330 100644
--- a/lib/erb/version.rb
+++ b/lib/erb/version.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
class ERB
- VERSION = '4.0.3'
+ VERSION = '4.0.4'
private_constant :VERSION
end
diff --git a/lib/error_highlight/base.rb b/lib/error_highlight/base.rb
index 7d2ff0c889..81b1b574de 100644
--- a/lib/error_highlight/base.rb
+++ b/lib/error_highlight/base.rb
@@ -54,11 +54,20 @@ module ErrorHighlight
return nil unless Thread::Backtrace::Location === loc
- node = RubyVM::AbstractSyntaxTree.of(loc, keep_script_lines: true)
+ node =
+ begin
+ RubyVM::AbstractSyntaxTree.of(loc, keep_script_lines: true)
+ rescue RuntimeError => error
+ # RubyVM::AbstractSyntaxTree.of raises an error with a message that
+ # includes "prism" when the ISEQ was compiled with the prism compiler.
+ # In this case, we'll try to parse again with prism instead.
+ raise unless error.message.include?("prism")
+ prism_find(loc, **opts)
+ end
Spotter.new(node, **opts).spot
- when RubyVM::AbstractSyntaxTree::Node
+ when RubyVM::AbstractSyntaxTree::Node, Prism::Node
Spotter.new(obj, **opts).spot
else
@@ -72,6 +81,71 @@ module ErrorHighlight
return nil
end
+ # Accepts a Thread::Backtrace::Location object and returns a Prism::Node
+ # corresponding to the location in the source code.
+ def self.prism_find(loc, point_type: :name, name: nil)
+ require "prism"
+ return nil if Prism::VERSION < "0.29.0"
+
+ path = loc.absolute_path
+ return unless path
+
+ lineno = loc.lineno
+ column = RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(loc)
+ tunnel = Prism.parse_file(path).value.tunnel(lineno, column)
+
+ # Prism provides the Prism::Node#tunnel API to find all of the nodes that
+ # correspond to the given line and column in the source code, with the first
+ # node in the list being the top-most node and the last node in the list
+ # being the bottom-most node.
+ tunnel.each_with_index.reverse_each.find do |part, index|
+ case part
+ when Prism::CallNode, Prism::CallOperatorWriteNode, Prism::IndexOperatorWriteNode, Prism::LocalVariableOperatorWriteNode
+ # If we find any of these nodes, we can stop searching as these are the
+ # nodes that triggered the exceptions.
+ break part
+ when Prism::ConstantReadNode, Prism::ConstantPathNode
+ if index != 0 && tunnel[index - 1].is_a?(Prism::ConstantPathOperatorWriteNode)
+ # If we're inside of a constant path operator write node, then this
+ # constant path may be highlighting a couple of different kinds of
+ # parts.
+ if part.name == name
+ # Explicitly turn off Foo::Bar += 1 where Foo and Bar are on
+ # different lines because error highlight expects this to not work.
+ break nil if part.delimiter_loc.end_line != part.name_loc.start_line
+
+ # Otherwise, because we have matched the name we can return this
+ # part.
+ break part
+ end
+
+ # If we haven't matched the name, it's the operator that we're looking
+ # for, and we can return the parent node here.
+ break tunnel[index - 1]
+ elsif part.name == name
+ # If we have matched the name of the constant, then we can return this
+ # inner node as the node that triggered the exception.
+ break part
+ else
+ # If we are at the beginning of the tunnel or we are at the beginning
+ # of a constant lookup chain, then we will return this node.
+ break part if index == 0 || !tunnel[index - 1].is_a?(Prism::ConstantPathNode)
+ end
+ when Prism::LocalVariableReadNode, Prism::ParenthesesNode
+ # If we find any of these nodes, we want to continue searching up the
+ # tree because these nodes cannot trigger the exceptions.
+ false
+ else
+ # If we find a different kind of node that we haven't already handled,
+ # we don't know how to handle it so we'll stop searching and assume this
+ # is not an exception we can decorate.
+ break nil
+ end
+ end
+ end
+
+ private_class_method :prism_find
+
class Spotter
class NonAscii < Exception; end
private_constant :NonAscii
@@ -196,6 +270,48 @@ module ErrorHighlight
when :OP_CDECL
spot_op_cdecl
+
+ when :call_node
+ case @point_type
+ when :name
+ prism_spot_call_for_name
+ when :args
+ prism_spot_call_for_args
+ end
+
+ when :local_variable_operator_write_node
+ case @point_type
+ when :name
+ prism_spot_local_variable_operator_write_for_name
+ when :args
+ prism_spot_local_variable_operator_write_for_args
+ end
+
+ when :call_operator_write_node
+ case @point_type
+ when :name
+ prism_spot_call_operator_write_for_name
+ when :args
+ prism_spot_call_operator_write_for_args
+ end
+
+ when :index_operator_write_node
+ case @point_type
+ when :name
+ prism_spot_index_operator_write_for_name
+ when :args
+ prism_spot_index_operator_write_for_args
+ end
+
+ when :constant_read_node
+ prism_spot_constant_read
+
+ when :constant_path_node
+ prism_spot_constant_path
+
+ when :constant_path_operator_write_node
+ prism_spot_constant_path_operator_write
+
end
if @snippet && @beg_column && @end_column && @beg_column < @end_column
@@ -539,6 +655,200 @@ module ErrorHighlight
@beg_lineno = @end_lineno = lineno
@snippet = @fetch[lineno]
end
+
+ # Take a location from the prism parser and set the necessary instance
+ # variables.
+ def prism_location(location)
+ @beg_lineno = location.start_line
+ @beg_column = location.start_column
+ @end_lineno = location.end_line
+ @end_column = location.end_column
+ @snippet = @fetch[@beg_lineno, @end_lineno]
+ end
+
+ # Example:
+ # x.foo
+ # ^^^^
+ # x.foo(42)
+ # ^^^^
+ # x&.foo
+ # ^^^^^
+ # x[42]
+ # ^^^^
+ # x.foo = 1
+ # ^^^^^^
+ # x[42] = 1
+ # ^^^^^^
+ # x + 1
+ # ^
+ # +x
+ # ^
+ # foo(42)
+ # ^^^
+ # foo 42
+ # ^^^
+ # foo
+ # ^^^
+ def prism_spot_call_for_name
+ # Explicitly turn off foo.() syntax because error_highlight expects this
+ # to not work.
+ return nil if @node.name == :call && @node.message_loc.nil?
+
+ location = @node.message_loc || @node.call_operator_loc || @node.location
+ location = @node.call_operator_loc.join(location) if @node.call_operator_loc&.start_line == location.start_line
+
+ # If the method name ends with "=" but the message does not, then this is
+ # a method call using the "attribute assignment" syntax
+ # (e.g., foo.bar = 1). In this case we need to go retrieve the = sign and
+ # add it to the location.
+ if (name = @node.name).end_with?("=") && !@node.message.end_with?("=")
+ location = location.adjoin("=")
+ end
+
+ prism_location(location)
+
+ if !name.end_with?("=") && !name.match?(/[[:alpha:]_\[]/)
+ # If the method name is an operator, then error_highlight only
+ # highlights the first line.
+ fetch_line(location.start_line)
+ end
+ end
+
+ # Example:
+ # x.foo(42)
+ # ^^
+ # x[42]
+ # ^^
+ # x.foo = 1
+ # ^
+ # x[42] = 1
+ # ^^^^^^^
+ # x[] = 1
+ # ^^^^^
+ # x + 1
+ # ^
+ # foo(42)
+ # ^^
+ # foo 42
+ # ^^
+ def prism_spot_call_for_args
+ # Explicitly turn off foo.() syntax because error_highlight expects this
+ # to not work.
+ return nil if @node.name == :call && @node.message_loc.nil?
+
+ if @node.name == :[]= && @node.opening == "[" && (@node.arguments&.arguments || []).length == 1
+ prism_location(@node.opening_loc.copy(start_offset: @node.opening_loc.start_offset + 1).join(@node.arguments.location))
+ else
+ prism_location(@node.arguments.location)
+ end
+ end
+
+ # Example:
+ # x += 1
+ # ^
+ def prism_spot_local_variable_operator_write_for_name
+ prism_location(@node.binary_operator_loc.chop)
+ end
+
+ # Example:
+ # x += 1
+ # ^
+ def prism_spot_local_variable_operator_write_for_args
+ prism_location(@node.value.location)
+ end
+
+ # Example:
+ # x.foo += 42
+ # ^^^ (for foo)
+ # x.foo += 42
+ # ^ (for +)
+ # x.foo += 42
+ # ^^^^^^^ (for foo=)
+ def prism_spot_call_operator_write_for_name
+ if !@name.start_with?(/[[:alpha:]_]/)
+ prism_location(@node.binary_operator_loc.chop)
+ else
+ location = @node.message_loc
+ if @node.call_operator_loc.start_line == location.start_line
+ location = @node.call_operator_loc.join(location)
+ end
+
+ location = location.adjoin("=") if @name.end_with?("=")
+ prism_location(location)
+ end
+ end
+
+ # Example:
+ # x.foo += 42
+ # ^^
+ def prism_spot_call_operator_write_for_args
+ prism_location(@node.value.location)
+ end
+
+ # Example:
+ # x[1] += 42
+ # ^^^ (for [])
+ # x[1] += 42
+ # ^ (for +)
+ # x[1] += 42
+ # ^^^^^^ (for []=)
+ def prism_spot_index_operator_write_for_name
+ case @name
+ when :[]
+ prism_location(@node.opening_loc.join(@node.closing_loc))
+ when :[]=
+ prism_location(@node.opening_loc.join(@node.closing_loc).adjoin("="))
+ else
+ # Explicitly turn off foo[] += 1 syntax when the operator is not on
+ # the same line because error_highlight expects this to not work.
+ return nil if @node.binary_operator_loc.start_line != @node.opening_loc.start_line
+
+ prism_location(@node.binary_operator_loc.chop)
+ end
+ end
+
+ # Example:
+ # x[1] += 42
+ # ^^^^^^^^
+ def prism_spot_index_operator_write_for_args
+ opening_loc =
+ if @node.arguments.nil?
+ @node.opening_loc.copy(start_offset: @node.opening_loc.start_offset + 1)
+ else
+ @node.arguments.location
+ end
+
+ prism_location(opening_loc.join(@node.value.location))
+ end
+
+ # Example:
+ # Foo
+ # ^^^
+ def prism_spot_constant_read
+ prism_location(@node.location)
+ end
+
+ # Example:
+ # Foo::Bar
+ # ^^^^^
+ def prism_spot_constant_path
+ if @node.parent && @node.parent.location.end_line == @node.location.end_line
+ fetch_line(@node.parent.location.end_line)
+ prism_location(@node.delimiter_loc.join(@node.name_loc))
+ else
+ fetch_line(@node.location.end_line)
+ location = @node.name_loc
+ location = @node.delimiter_loc.join(location) if @node.delimiter_loc.end_line == location.start_line
+ prism_location(location)
+ end
+ end
+
+ # Example:
+ # Foo::Bar += 1
+ # ^^^^^^^^
+ def prism_spot_constant_path_operator_write
+ prism_location(@node.binary_operator_loc.chop)
+ end
end
private_constant :Spotter
diff --git a/lib/error_highlight/version.rb b/lib/error_highlight/version.rb
index 5afe5f06d6..506d37fbc1 100644
--- a/lib/error_highlight/version.rb
+++ b/lib/error_highlight/version.rb
@@ -1,3 +1,3 @@
module ErrorHighlight
- VERSION = "0.5.1"
+ VERSION = "0.6.0"
end
diff --git a/lib/fileutils.rb b/lib/fileutils.rb
index 8ec5a3ad12..e8cc355760 100644
--- a/lib/fileutils.rb
+++ b/lib/fileutils.rb
@@ -180,6 +180,7 @@ end
# - {CVE-2004-0452}[https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0452].
#
module FileUtils
+ # The version number.
VERSION = "1.7.2"
def self.private_module_function(name) #:nodoc:
@@ -1651,7 +1652,7 @@ module FileUtils
when "a"
mask | 07777
else
- raise ArgumentError, "invalid `who' symbol in file mode: #{chr}"
+ raise ArgumentError, "invalid 'who' symbol in file mode: #{chr}"
end
end
end
@@ -1705,7 +1706,7 @@ module FileUtils
copy_mask = user_mask(chr)
(current_mode & copy_mask) / (copy_mask & 0111) * (user_mask & 0111)
else
- raise ArgumentError, "invalid `perm' symbol in file mode: #{chr}"
+ raise ArgumentError, "invalid 'perm' symbol in file mode: #{chr}"
end
end
@@ -2028,21 +2029,22 @@ module FileUtils
private
- module StreamUtils_
+ module StreamUtils_ # :nodoc:
+
private
case (defined?(::RbConfig) ? ::RbConfig::CONFIG['host_os'] : ::RUBY_PLATFORM)
when /mswin|mingw/
- def fu_windows?; true end
+ def fu_windows?; true end #:nodoc:
else
- def fu_windows?; false end
+ def fu_windows?; false end #:nodoc:
end
def fu_copy_stream0(src, dest, blksize = nil) #:nodoc:
IO.copy_stream(src, dest)
end
- def fu_stream_blksize(*streams)
+ def fu_stream_blksize(*streams) #:nodoc:
streams.each do |s|
next unless s.respond_to?(:stat)
size = fu_blksize(s.stat)
@@ -2051,14 +2053,14 @@ module FileUtils
fu_default_blksize()
end
- def fu_blksize(st)
+ def fu_blksize(st) #:nodoc:
s = st.blksize
return nil unless s
return nil if s == 0
s
end
- def fu_default_blksize
+ def fu_default_blksize #:nodoc:
1024
end
end
@@ -2503,7 +2505,7 @@ module FileUtils
end
private_module_function :fu_output_message
- def fu_split_path(path)
+ def fu_split_path(path) #:nodoc:
path = File.path(path)
list = []
until (parent, base = File.split(path); parent == path or parent == ".")
@@ -2524,7 +2526,7 @@ module FileUtils
end
private_module_function :fu_relative_components_from
- def fu_clean_components(*comp)
+ def fu_clean_components(*comp) #:nodoc:
comp.shift while comp.first == "."
return comp if comp.empty?
clean = [comp.shift]
@@ -2543,11 +2545,11 @@ module FileUtils
private_module_function :fu_clean_components
if fu_windows?
- def fu_starting_path?(path)
+ def fu_starting_path?(path) #:nodoc:
path&.start_with?(%r(\w:|/))
end
else
- def fu_starting_path?(path)
+ def fu_starting_path?(path) #:nodoc:
path&.start_with?("/")
end
end
diff --git a/lib/find.gemspec b/lib/find.gemspec
index cb845e9409..aef24a5028 100644
--- a/lib/find.gemspec
+++ b/lib/find.gemspec
@@ -25,7 +25,5 @@ Gem::Specification.new do |spec|
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
end
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
end
diff --git a/lib/getoptlong.gemspec b/lib/getoptlong.gemspec
deleted file mode 100644
index c2f65dcaab..0000000000
--- a/lib/getoptlong.gemspec
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-name = File.basename(__FILE__, ".gemspec")
-version = ["lib", Array.new(name.count("-")+1, ".").join("/")].find do |dir|
- break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
- /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
- end rescue nil
-end
-
-Gem::Specification.new do |spec|
- spec.name = name
- spec.version = version
- spec.authors = ["Yukihiro Matsumoto"]
- spec.email = ["matz@ruby-lang.org"]
-
- spec.summary = %q{GetoptLong for Ruby}
- spec.description = spec.summary
- spec.homepage = "https://github.com/ruby/getoptlong"
- spec.licenses = ["Ruby", "BSD-2-Clause"]
-
- spec.metadata["homepage_uri"] = spec.homepage
- spec.metadata["source_code_uri"] = spec.homepage
-
- # Specify which files should be added to the gem when it is released.
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
- `git ls-files -z 2>#{IO::NULL}`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
- end
- spec.require_paths = ["lib"]
-end
diff --git a/lib/getoptlong.rb b/lib/getoptlong.rb
deleted file mode 100644
index c825962160..0000000000
--- a/lib/getoptlong.rb
+++ /dev/null
@@ -1,867 +0,0 @@
-# frozen_string_literal: true
-#
-# GetoptLong for Ruby
-#
-# Copyright (C) 1998, 1999, 2000 Motoyuki Kasahara.
-#
-# You may redistribute and/or modify this library under the same license
-# terms as Ruby.
-
-# \Class \GetoptLong provides parsing both for options
-# and for regular arguments.
-#
-# Using \GetoptLong, you can define options for your program.
-# The program can then capture and respond to whatever options
-# are included in the command that executes the program.
-#
-# A simple example: file <tt>simple.rb</tt>:
-#
-# :include: ../sample/getoptlong/simple.rb
-#
-# If you are somewhat familiar with options,
-# you may want to skip to this
-# {full example}[#class-GetoptLong-label-Full+Example].
-#
-# == Options
-#
-# A \GetoptLong option has:
-#
-# - A string <em>option name</em>.
-# - Zero or more string <em>aliases</em> for the name.
-# - An <em>option type</em>.
-#
-# Options may be defined by calling singleton method GetoptLong.new,
-# which returns a new \GetoptLong object.
-# Options may then be processed by calling other methods
-# such as GetoptLong#each.
-#
-# === Option Name and Aliases
-#
-# In the array that defines an option,
-# the first element is the string option name.
-# Often the name takes the 'long' form, beginning with two hyphens.
-#
-# The option name may have any number of aliases,
-# which are defined by additional string elements.
-#
-# The name and each alias must be of one of two forms:
-#
-# - Two hyphens, followed by one or more letters.
-# - One hyphen, followed by a single letter.
-#
-# File <tt>aliases.rb</tt>:
-#
-# :include: ../sample/getoptlong/aliases.rb
-#
-# An option may be cited by its name,
-# or by any of its aliases;
-# the parsed option always reports the name, not an alias:
-#
-# $ ruby aliases.rb -a -p --xxx --aaa -x
-#
-# Output:
-#
-# ["--xxx", ""]
-# ["--xxx", ""]
-# ["--xxx", ""]
-# ["--xxx", ""]
-# ["--xxx", ""]
-#
-#
-# An option may also be cited by an abbreviation of its name or any alias,
-# as long as that abbreviation is unique among the options.
-#
-# File <tt>abbrev.rb</tt>:
-#
-# :include: ../sample/getoptlong/abbrev.rb
-#
-# Command line:
-#
-# $ ruby abbrev.rb --xxx --xx --xyz --xy
-#
-# Output:
-#
-# ["--xxx", ""]
-# ["--xxx", ""]
-# ["--xyz", ""]
-# ["--xyz", ""]
-#
-# This command line raises GetoptLong::AmbiguousOption:
-#
-# $ ruby abbrev.rb --x
-#
-# === Repetition
-#
-# An option may be cited more than once:
-#
-# $ ruby abbrev.rb --xxx --xyz --xxx --xyz
-#
-# Output:
-#
-# ["--xxx", ""]
-# ["--xyz", ""]
-# ["--xxx", ""]
-# ["--xyz", ""]
-#
-# === Treating Remaining Options as Arguments
-#
-# A option-like token that appears
-# anywhere after the token <tt>--</tt> is treated as an ordinary argument,
-# and is not processed as an option:
-#
-# $ ruby abbrev.rb --xxx --xyz -- --xxx --xyz
-#
-# Output:
-#
-# ["--xxx", ""]
-# ["--xyz", ""]
-#
-# === Option Types
-#
-# Each option definition includes an option type,
-# which controls whether the option takes an argument.
-#
-# File <tt>types.rb</tt>:
-#
-# :include: ../sample/getoptlong/types.rb
-#
-# Note that an option type has to do with the <em>option argument</em>
-# (whether it is required, optional, or forbidden),
-# not with whether the option itself is required.
-#
-# ==== Option with Required Argument
-#
-# An option of type <tt>GetoptLong::REQUIRED_ARGUMENT</tt>
-# must be followed by an argument, which is associated with that option:
-#
-# $ ruby types.rb --xxx foo
-#
-# Output:
-#
-# ["--xxx", "foo"]
-#
-# If the option is not last, its argument is whatever follows it
-# (even if the argument looks like another option):
-#
-# $ ruby types.rb --xxx --yyy
-#
-# Output:
-#
-# ["--xxx", "--yyy"]
-#
-# If the option is last, an exception is raised:
-#
-# $ ruby types.rb
-# # Raises GetoptLong::MissingArgument
-#
-# ==== Option with Optional Argument
-#
-# An option of type <tt>GetoptLong::OPTIONAL_ARGUMENT</tt>
-# may be followed by an argument, which if given is associated with that option.
-#
-# If the option is last, it does not have an argument:
-#
-# $ ruby types.rb --yyy
-#
-# Output:
-#
-# ["--yyy", ""]
-#
-# If the option is followed by another option, it does not have an argument:
-#
-# $ ruby types.rb --yyy --zzz
-#
-# Output:
-#
-# ["--yyy", ""]
-# ["--zzz", ""]
-#
-# Otherwise the option is followed by its argument, which is associated
-# with that option:
-#
-# $ ruby types.rb --yyy foo
-#
-# Output:
-#
-# ["--yyy", "foo"]
-#
-# ==== Option with No Argument
-#
-# An option of type <tt>GetoptLong::NO_ARGUMENT</tt> takes no argument:
-#
-# ruby types.rb --zzz foo
-#
-# Output:
-#
-# ["--zzz", ""]
-#
-# === ARGV
-#
-# You can process options either with method #each and a block,
-# or with method #get.
-#
-# During processing, each found option is removed, along with its argument
-# if there is one.
-# After processing, each remaining element was neither an option
-# nor the argument for an option.
-#
-# File <tt>argv.rb</tt>:
-#
-# :include: ../sample/getoptlong/argv.rb
-#
-# Command line:
-#
-# $ ruby argv.rb --xxx Foo --yyy Bar Baz --zzz Bat Bam
-#
-# Output:
-#
-# Original ARGV: ["--xxx", "Foo", "--yyy", "Bar", "Baz", "--zzz", "Bat", "Bam"]
-# ["--xxx", "Foo"]
-# ["--yyy", "Bar"]
-# ["--zzz", ""]
-# Remaining ARGV: ["Baz", "Bat", "Bam"]
-#
-# === Ordering
-#
-# There are three settings that control the way the options
-# are interpreted:
-#
-# - +PERMUTE+.
-# - +REQUIRE_ORDER+.
-# - +RETURN_IN_ORDER+.
-#
-# The initial setting for a new \GetoptLong object is +REQUIRE_ORDER+
-# if environment variable +POSIXLY_CORRECT+ is defined, +PERMUTE+ otherwise.
-#
-# ==== PERMUTE Ordering
-#
-# In the +PERMUTE+ ordering, options and other, non-option,
-# arguments may appear in any order and any mixture.
-#
-# File <tt>permute.rb</tt>:
-#
-# :include: ../sample/getoptlong/permute.rb
-#
-# Command line:
-#
-# $ ruby permute.rb Foo --zzz Bar --xxx Baz --yyy Bat Bam --xxx Bag Bah
-#
-# Output:
-#
-# Original ARGV: ["Foo", "--zzz", "Bar", "--xxx", "Baz", "--yyy", "Bat", "Bam", "--xxx", "Bag", "Bah"]
-# ["--zzz", ""]
-# ["--xxx", "Baz"]
-# ["--yyy", "Bat"]
-# ["--xxx", "Bag"]
-# Remaining ARGV: ["Foo", "Bar", "Bam", "Bah"]
-#
-# ==== REQUIRE_ORDER Ordering
-#
-# In the +REQUIRE_ORDER+ ordering, all options precede all non-options;
-# that is, each word after the first non-option word
-# is treated as a non-option word (even if it begins with a hyphen).
-#
-# File <tt>require_order.rb</tt>:
-#
-# :include: ../sample/getoptlong/require_order.rb
-#
-# Command line:
-#
-# $ ruby require_order.rb --xxx Foo Bar --xxx Baz --yyy Bat -zzz
-#
-# Output:
-#
-# Original ARGV: ["--xxx", "Foo", "Bar", "--xxx", "Baz", "--yyy", "Bat", "-zzz"]
-# ["--xxx", "Foo"]
-# Remaining ARGV: ["Bar", "--xxx", "Baz", "--yyy", "Bat", "-zzz"]
-#
-# ==== RETURN_IN_ORDER Ordering
-#
-# In the +RETURN_IN_ORDER+ ordering, every word is treated as an option.
-# A word that begins with a hyphen (or two) is treated in the usual way;
-# a word +word+ that does not so begin is treated as an option
-# whose name is an empty string, and whose value is +word+.
-#
-# File <tt>return_in_order.rb</tt>:
-#
-# :include: ../sample/getoptlong/return_in_order.rb
-#
-# Command line:
-#
-# $ ruby return_in_order.rb Foo --xxx Bar Baz --zzz Bat Bam
-#
-# Output:
-#
-# Original ARGV: ["Foo", "--xxx", "Bar", "Baz", "--zzz", "Bat", "Bam"]
-# ["", "Foo"]
-# ["--xxx", "Bar"]
-# ["", "Baz"]
-# ["--zzz", ""]
-# ["", "Bat"]
-# ["", "Bam"]
-# Remaining ARGV: []
-#
-# === Full Example
-#
-# File <tt>fibonacci.rb</tt>:
-#
-# :include: ../sample/getoptlong/fibonacci.rb
-#
-# Command line:
-#
-# $ ruby fibonacci.rb
-#
-# Output:
-#
-# Option --number is required.
-# Usage:
-#
-# -n n, --number n:
-# Compute Fibonacci number for n.
-# -v [boolean], --verbose [boolean]:
-# Show intermediate results; default is 'false'.
-# -h, --help:
-# Show this help.
-#
-# Command line:
-#
-# $ ruby fibonacci.rb --number
-#
-# Raises GetoptLong::MissingArgument:
-#
-# fibonacci.rb: option `--number' requires an argument
-#
-# Command line:
-#
-# $ ruby fibonacci.rb --number 6
-#
-# Output:
-#
-# 8
-#
-# Command line:
-#
-# $ ruby fibonacci.rb --number 6 --verbose
-#
-# Output:
-# 1
-# 2
-# 3
-# 5
-# 8
-#
-# Command line:
-#
-# $ ruby fibonacci.rb --number 6 --verbose yes
-#
-# Output:
-#
-# --verbose argument must be true or false
-# Usage:
-#
-# -n n, --number n:
-# Compute Fibonacci number for n.
-# -v [boolean], --verbose [boolean]:
-# Show intermediate results; default is 'false'.
-# -h, --help:
-# Show this help.
-#
-class GetoptLong
- # Version.
- VERSION = "0.2.1"
-
- #
- # Orderings.
- #
- ORDERINGS = [REQUIRE_ORDER = 0, PERMUTE = 1, RETURN_IN_ORDER = 2]
-
- #
- # Argument flags.
- #
- ARGUMENT_FLAGS = [NO_ARGUMENT = 0, REQUIRED_ARGUMENT = 1,
- OPTIONAL_ARGUMENT = 2]
-
- #
- # Status codes.
- #
- STATUS_YET, STATUS_STARTED, STATUS_TERMINATED = 0, 1, 2
-
- #
- # Error types.
- #
- class Error < StandardError; end
- class AmbiguousOption < Error; end
- class NeedlessArgument < Error; end
- class MissingArgument < Error; end
- class InvalidOption < Error; end
-
- #
- # Returns a new \GetoptLong object based on the given +arguments+.
- # See {Options}[#class-GetoptLong-label-Options].
- #
- # Example:
- #
- # :include: ../sample/getoptlong/simple.rb
- #
- # Raises an exception if:
- #
- # - Any of +arguments+ is not an array.
- # - Any option name or alias is not a string.
- # - Any option type is invalid.
- #
- def initialize(*arguments)
- #
- # Current ordering.
- #
- if ENV.include?('POSIXLY_CORRECT')
- @ordering = REQUIRE_ORDER
- else
- @ordering = PERMUTE
- end
-
- #
- # Hash table of option names.
- # Keys of the table are option names, and their values are canonical
- # names of the options.
- #
- @canonical_names = Hash.new
-
- #
- # Hash table of argument flags.
- # Keys of the table are option names, and their values are argument
- # flags of the options.
- #
- @argument_flags = Hash.new
-
- #
- # Whether error messages are output to $stderr.
- #
- @quiet = false
-
- #
- # Status code.
- #
- @status = STATUS_YET
-
- #
- # Error code.
- #
- @error = nil
-
- #
- # Error message.
- #
- @error_message = nil
-
- #
- # Rest of catenated short options.
- #
- @rest_singles = ''
-
- #
- # List of non-option-arguments.
- # Append them to ARGV when option processing is terminated.
- #
- @non_option_arguments = Array.new
-
- if 0 < arguments.length
- set_options(*arguments)
- end
- end
-
- # Sets the ordering; see {Ordering}[#class-GetoptLong-label-Ordering];
- # returns the new ordering.
- #
- # If the given +ordering+ is +PERMUTE+ and environment variable
- # +POSIXLY_CORRECT+ is defined, sets the ordering to +REQUIRE_ORDER+;
- # otherwise sets the ordering to +ordering+:
- #
- # options = GetoptLong.new
- # options.ordering == GetoptLong::PERMUTE # => true
- # options.ordering = GetoptLong::RETURN_IN_ORDER
- # options.ordering == GetoptLong::RETURN_IN_ORDER # => true
- # ENV['POSIXLY_CORRECT'] = 'true'
- # options.ordering = GetoptLong::PERMUTE
- # options.ordering == GetoptLong::REQUIRE_ORDER # => true
- #
- # Raises an exception if +ordering+ is invalid.
- #
- def ordering=(ordering)
- #
- # The method is failed if option processing has already started.
- #
- if @status != STATUS_YET
- set_error(ArgumentError, "argument error")
- raise RuntimeError,
- "invoke ordering=, but option processing has already started"
- end
-
- #
- # Check ordering.
- #
- if !ORDERINGS.include?(ordering)
- raise ArgumentError, "invalid ordering `#{ordering}'"
- end
- if ordering == PERMUTE && ENV.include?('POSIXLY_CORRECT')
- @ordering = REQUIRE_ORDER
- else
- @ordering = ordering
- end
- end
-
- #
- # Returns the ordering setting.
- #
- attr_reader :ordering
-
- #
- # Replaces existing options with those given by +arguments+,
- # which have the same form as the arguments to ::new;
- # returns +self+.
- #
- # Raises an exception if option processing has begun.
- #
- def set_options(*arguments)
- #
- # The method is failed if option processing has already started.
- #
- if @status != STATUS_YET
- raise RuntimeError,
- "invoke set_options, but option processing has already started"
- end
-
- #
- # Clear tables of option names and argument flags.
- #
- @canonical_names.clear
- @argument_flags.clear
-
- arguments.each do |arg|
- if !arg.is_a?(Array)
- raise ArgumentError, "the option list contains non-Array argument"
- end
-
- #
- # Find an argument flag and it set to `argument_flag'.
- #
- argument_flag = nil
- arg.each do |i|
- if ARGUMENT_FLAGS.include?(i)
- if argument_flag != nil
- raise ArgumentError, "too many argument-flags"
- end
- argument_flag = i
- end
- end
-
- raise ArgumentError, "no argument-flag" if argument_flag == nil
-
- canonical_name = nil
- arg.each do |i|
- #
- # Check an option name.
- #
- next if i == argument_flag
- begin
- if !i.is_a?(String) || i !~ /\A-([^-]|-.+)\z/
- raise ArgumentError, "an invalid option `#{i}'"
- end
- if (@canonical_names.include?(i))
- raise ArgumentError, "option redefined `#{i}'"
- end
- rescue
- @canonical_names.clear
- @argument_flags.clear
- raise
- end
-
- #
- # Register the option (`i') to the `@canonical_names' and
- # `@canonical_names' Hashes.
- #
- if canonical_name == nil
- canonical_name = i
- end
- @canonical_names[i] = canonical_name
- @argument_flags[i] = argument_flag
- end
- raise ArgumentError, "no option name" if canonical_name == nil
- end
- return self
- end
-
- #
- # Sets quiet mode and returns the given argument:
- #
- # - When +false+ or +nil+, error messages are written to <tt>$stdout</tt>.
- # - Otherwise, error messages are not written.
- #
- attr_writer :quiet
-
- #
- # Returns the quiet mode setting.
- #
- attr_reader :quiet
- alias quiet? quiet
-
- #
- # Terminate option processing;
- # returns +nil+ if processing has already terminated;
- # otherwise returns +self+.
- #
- def terminate
- return nil if @status == STATUS_TERMINATED
- raise RuntimeError, "an error has occurred" if @error != nil
-
- @status = STATUS_TERMINATED
- @non_option_arguments.reverse_each do |argument|
- ARGV.unshift(argument)
- end
-
- @canonical_names = nil
- @argument_flags = nil
- @rest_singles = nil
- @non_option_arguments = nil
-
- return self
- end
-
- #
- # Returns +true+ if option processing has terminated, +false+ otherwise.
- #
- def terminated?
- return @status == STATUS_TERMINATED
- end
-
- #
- # \Set an error (a protected method).
- #
- def set_error(type, message)
- $stderr.print("#{$0}: #{message}\n") if !@quiet
-
- @error = type
- @error_message = message
- @canonical_names = nil
- @argument_flags = nil
- @rest_singles = nil
- @non_option_arguments = nil
-
- raise type, message
- end
- protected :set_error
-
- #
- # Returns whether option processing has failed.
- #
- attr_reader :error
- alias error? error
-
- # Return the appropriate error message in POSIX-defined format.
- # If no error has occurred, returns +nil+.
- #
- def error_message
- return @error_message
- end
-
- #
- # Returns the next option as a 2-element array containing:
- #
- # - The option name (the name itself, not an alias).
- # - The option value.
- #
- # Returns +nil+ if there are no more options.
- #
- def get
- option_name, option_argument = nil, ''
-
- #
- # Check status.
- #
- return nil if @error != nil
- case @status
- when STATUS_YET
- @status = STATUS_STARTED
- when STATUS_TERMINATED
- return nil
- end
-
- #
- # Get next option argument.
- #
- if 0 < @rest_singles.length
- argument = '-' + @rest_singles
- elsif (ARGV.length == 0)
- terminate
- return nil
- elsif @ordering == PERMUTE
- while 0 < ARGV.length && ARGV[0] !~ /\A-./
- @non_option_arguments.push(ARGV.shift)
- end
- if ARGV.length == 0
- terminate
- return nil
- end
- argument = ARGV.shift
- elsif @ordering == REQUIRE_ORDER
- if (ARGV[0] !~ /\A-./)
- terminate
- return nil
- end
- argument = ARGV.shift
- else
- argument = ARGV.shift
- end
-
- #
- # Check the special argument `--'.
- # `--' indicates the end of the option list.
- #
- if argument == '--' && @rest_singles.length == 0
- terminate
- return nil
- end
-
- #
- # Check for long and short options.
- #
- if argument =~ /\A(--[^=]+)/ && @rest_singles.length == 0
- #
- # This is a long style option, which start with `--'.
- #
- pattern = $1
- if @canonical_names.include?(pattern)
- option_name = pattern
- else
- #
- # The option `option_name' is not registered in `@canonical_names'.
- # It may be an abbreviated.
- #
- matches = []
- @canonical_names.each_key do |key|
- if key.index(pattern) == 0
- option_name = key
- matches << key
- end
- end
- if 2 <= matches.length
- set_error(AmbiguousOption, "option `#{argument}' is ambiguous between #{matches.join(', ')}")
- elsif matches.length == 0
- set_error(InvalidOption, "unrecognized option `#{argument}'")
- end
- end
-
- #
- # Check an argument to the option.
- #
- if @argument_flags[option_name] == REQUIRED_ARGUMENT
- if argument =~ /=(.*)/m
- option_argument = $1
- elsif 0 < ARGV.length
- option_argument = ARGV.shift
- else
- set_error(MissingArgument,
- "option `#{argument}' requires an argument")
- end
- elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT
- if argument =~ /=(.*)/m
- option_argument = $1
- elsif 0 < ARGV.length && ARGV[0] !~ /\A-./
- option_argument = ARGV.shift
- else
- option_argument = ''
- end
- elsif argument =~ /=(.*)/m
- set_error(NeedlessArgument,
- "option `#{option_name}' doesn't allow an argument")
- end
-
- elsif argument =~ /\A(-(.))(.*)/m
- #
- # This is a short style option, which start with `-' (not `--').
- # Short options may be catenated (e.g. `-l -g' is equivalent to
- # `-lg').
- #
- option_name, ch, @rest_singles = $1, $2, $3
-
- if @canonical_names.include?(option_name)
- #
- # The option `option_name' is found in `@canonical_names'.
- # Check its argument.
- #
- if @argument_flags[option_name] == REQUIRED_ARGUMENT
- if 0 < @rest_singles.length
- option_argument = @rest_singles
- @rest_singles = ''
- elsif 0 < ARGV.length
- option_argument = ARGV.shift
- else
- # 1003.2 specifies the format of this message.
- set_error(MissingArgument, "option requires an argument -- #{ch}")
- end
- elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT
- if 0 < @rest_singles.length
- option_argument = @rest_singles
- @rest_singles = ''
- elsif 0 < ARGV.length && ARGV[0] !~ /\A-./
- option_argument = ARGV.shift
- else
- option_argument = ''
- end
- end
- else
- #
- # This is an invalid option.
- # 1003.2 specifies the format of this message.
- #
- if ENV.include?('POSIXLY_CORRECT')
- set_error(InvalidOption, "invalid option -- #{ch}")
- else
- set_error(InvalidOption, "invalid option -- #{ch}")
- end
- end
- else
- #
- # This is a non-option argument.
- # Only RETURN_IN_ORDER fell into here.
- #
- return '', argument
- end
-
- return @canonical_names[option_name], option_argument
- end
- alias get_option get
-
- #
- # Calls the given block with each option;
- # each option is a 2-element array containing:
- #
- # - The option name (the name itself, not an alias).
- # - The option value.
- #
- # Example:
- #
- # :include: ../sample/getoptlong/each.rb
- #
- # Command line:
- #
- # ruby each.rb -xxx Foo -x Bar --yyy Baz -y Bat --zzz
- #
- # Output:
- #
- # Original ARGV: ["-xxx", "Foo", "-x", "Bar", "--yyy", "Baz", "-y", "Bat", "--zzz"]
- # ["--xxx", "xx"]
- # ["--xxx", "Bar"]
- # ["--yyy", "Baz"]
- # ["--yyy", "Bat"]
- # ["--zzz", ""]
- # Remaining ARGV: ["Foo"]
- #
- def each
- loop do
- option_name, option_argument = get_option
- break if option_name == nil
- yield option_name, option_argument
- end
- end
- alias each_option each
-end
diff --git a/lib/ipaddr.rb b/lib/ipaddr.rb
index 75922baa90..dbb213c90a 100644
--- a/lib/ipaddr.rb
+++ b/lib/ipaddr.rb
@@ -40,7 +40,7 @@ require 'socket'
# p ipaddr3 #=> #<IPAddr: IPv4:192.168.2.0/255.255.255.0>
class IPAddr
- VERSION = "1.2.5"
+ VERSION = "1.2.6"
# 32 bit mask for IPv4
IN4MASK = 0xffffffff
@@ -52,7 +52,7 @@ class IPAddr
# Regexp _internally_ used for parsing IPv4 address.
RE_IPV4ADDRLIKE = %r{
\A
- (\d+) \. (\d+) \. (\d+) \. (\d+)
+ \d+ \. \d+ \. \d+ \. \d+
\z
}x
@@ -110,8 +110,13 @@ class IPAddr
# Convert a network byte ordered string form of an IP address into
# human readable form.
+ # It expects the string to be encoded in Encoding::ASCII_8BIT (BINARY).
def self.ntop(addr)
- case addr.size
+ if addr.is_a?(String) && addr.encoding != Encoding::BINARY
+ raise InvalidAddressError, "invalid encoding (given #{addr.encoding}, expected BINARY)"
+ end
+
+ case addr.bytesize
when 4
addr.unpack('C4').join('.')
when 16
@@ -222,6 +227,12 @@ class IPAddr
return str
end
+ # Returns a string containing the IP address representation in
+ # cidr notation
+ def cidr
+ format("%s/%s", to_s, prefix)
+ end
+
# Returns a network byte ordered string form of the IP address.
def hton
case @family
@@ -247,12 +258,17 @@ class IPAddr
end
# Returns true if the ipaddr is a loopback address.
+ # Loopback IPv4 addresses in the IPv4-mapped IPv6
+ # address range are also considered as loopback addresses.
def loopback?
case @family
when Socket::AF_INET
- @addr & 0xff000000 == 0x7f000000
+ @addr & 0xff000000 == 0x7f000000 # 127.0.0.1/8
when Socket::AF_INET6
- @addr == 1
+ @addr == 1 || # ::1
+ (@addr & 0xffff_0000_0000 == 0xffff_0000_0000 && (
+ @addr & 0xff000000 == 0x7f000000 # ::ffff:127.0.0.1/8
+ ))
else
raise AddressFamilyError, "unsupported address family"
end
@@ -282,15 +298,19 @@ class IPAddr
end
# Returns true if the ipaddr is a link-local address. IPv4
- # addresses in 169.254.0.0/16 reserved by RFC 3927 and Link-Local
+ # addresses in 169.254.0.0/16 reserved by RFC 3927 and link-local
# IPv6 Unicast Addresses in fe80::/10 reserved by RFC 4291 are
- # considered link-local.
+ # considered link-local. Link-local IPv4 addresses in the
+ # IPv4-mapped IPv6 address range are also considered link-local.
def link_local?
case @family
when Socket::AF_INET
@addr & 0xffff0000 == 0xa9fe0000 # 169.254.0.0/16
when Socket::AF_INET6
- @addr & 0xffc0_0000_0000_0000_0000_0000_0000_0000 == 0xfe80_0000_0000_0000_0000_0000_0000_0000
+ @addr & 0xffc0_0000_0000_0000_0000_0000_0000_0000 == 0xfe80_0000_0000_0000_0000_0000_0000_0000 || # fe80::/10
+ (@addr & 0xffff_0000_0000 == 0xffff_0000_0000 && (
+ @addr & 0xffff0000 == 0xa9fe0000 # ::ffff:169.254.0.0/16
+ ))
else
raise AddressFamilyError, "unsupported address family"
end
@@ -432,7 +452,7 @@ class IPAddr
when Integer
mask!(prefix)
else
- raise InvalidPrefixError, "prefix must be an integer: #{@addr}"
+ raise InvalidPrefixError, "prefix must be an integer"
end
end
@@ -457,6 +477,20 @@ class IPAddr
_to_string(@mask_addr)
end
+ # Returns the wildcard mask in string format e.g. 0.0.255.255
+ def wildcard_mask
+ case @family
+ when Socket::AF_INET
+ mask = IN4MASK ^ @mask_addr
+ when Socket::AF_INET6
+ mask = IN6MASK ^ @mask_addr
+ else
+ raise AddressFamilyError, "unsupported address family"
+ end
+
+ _to_string(mask)
+ end
+
# Returns the IPv6 zone identifier, if present.
# Raises InvalidAddressError if not an IPv6 address.
def zone_id
@@ -506,11 +540,11 @@ class IPAddr
case family[0] ? family[0] : @family
when Socket::AF_INET
if addr < 0 || addr > IN4MASK
- raise InvalidAddressError, "invalid address: #{@addr}"
+ raise InvalidAddressError, "invalid address: #{addr}"
end
when Socket::AF_INET6
if addr < 0 || addr > IN6MASK
- raise InvalidAddressError, "invalid address: #{@addr}"
+ raise InvalidAddressError, "invalid address: #{addr}"
end
else
raise AddressFamilyError, "unsupported address family"
@@ -537,12 +571,12 @@ class IPAddr
else
m = IPAddr.new(mask)
if m.family != @family
- raise InvalidPrefixError, "address family is not same: #{@addr}"
+ raise InvalidPrefixError, "address family is not same"
end
@mask_addr = m.to_i
n = @mask_addr ^ m.instance_variable_get(:@mask_addr)
unless ((n + 1) & n).zero?
- raise InvalidPrefixError, "invalid mask #{mask}: #{@addr}"
+ raise InvalidPrefixError, "invalid mask #{mask}"
end
@addr &= @mask_addr
return self
@@ -553,13 +587,13 @@ class IPAddr
case @family
when Socket::AF_INET
if prefixlen < 0 || prefixlen > 32
- raise InvalidPrefixError, "invalid length: #{@addr}"
+ raise InvalidPrefixError, "invalid length"
end
masklen = 32 - prefixlen
@mask_addr = ((IN4MASK >> masklen) << masklen)
when Socket::AF_INET6
if prefixlen < 0 || prefixlen > 128
- raise InvalidPrefixError, "invalid length: #{@addr}"
+ raise InvalidPrefixError, "invalid length"
end
masklen = 128 - prefixlen
@mask_addr = ((IN6MASK >> masklen) << masklen)
@@ -655,12 +689,12 @@ class IPAddr
when Array
octets = addr
else
- m = RE_IPV4ADDRLIKE.match(addr) or return nil
- octets = m.captures
+ RE_IPV4ADDRLIKE.match?(addr) or return nil
+ octets = addr.split('.')
end
octets.inject(0) { |i, s|
(n = s.to_i) < 256 or raise InvalidAddressError, "invalid address: #{@addr}"
- s.match(/\A0./) and raise InvalidAddressError, "zero-filled number in IPv4 address is ambiguous: #{@addr}"
+ (s != '0') && s.start_with?('0') and raise InvalidAddressError, "zero-filled number in IPv4 address is ambiguous: #{@addr}"
i << 8 | n
}
end
diff --git a/lib/irb.rb b/lib/irb.rb
index 655abaf069..b3435c257e 100644
--- a/lib/irb.rb
+++ b/lib/irb.rb
@@ -1,5 +1,6 @@
-# frozen_string_literal: false
-#
+# frozen_string_literal: true
+
+# :markup: markdown
# irb.rb - irb main module
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
#
@@ -9,7 +10,7 @@ require "reline"
require_relative "irb/init"
require_relative "irb/context"
-require_relative "irb/extend-command"
+require_relative "irb/default_commands"
require_relative "irb/ruby-lex"
require_relative "irb/statement"
@@ -20,352 +21,860 @@ require_relative "irb/color"
require_relative "irb/version"
require_relative "irb/easter-egg"
require_relative "irb/debug"
+require_relative "irb/pager"
-# IRB stands for "interactive Ruby" and is a tool to interactively execute Ruby
-# expressions read from the standard input.
+# ## IRB
+#
+# Module IRB ("Interactive Ruby") provides a shell-like interface that supports
+# user interaction with the Ruby interpreter.
#
-# The +irb+ command from your shell will start the interpreter.
+# It operates as a *read-eval-print loop*
+# ([REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop))
+# that:
#
-# == Usage
+# * ***Reads*** each character as you type. You can modify the IRB context to
+# change the way input works. See [Input](rdoc-ref:IRB@Input).
+# * ***Evaluates*** the code each time it has read a syntactically complete
+# passage.
+# * ***Prints*** after evaluating. You can modify the IRB context to change
+# the way output works. See [Output](rdoc-ref:IRB@Output).
#
-# Use of irb is easy if you know Ruby.
#
-# When executing irb, prompts are displayed as follows. Then, enter the Ruby
-# expression. An input is executed when it is syntactically complete.
+# Example:
#
# $ irb
-# irb(main):001:0> 1+2
-# #=> 3
-# irb(main):002:0> class Foo
-# irb(main):003:1> def foo
-# irb(main):004:2> print 1
-# irb(main):005:2> end
-# irb(main):006:1> end
-# #=> nil
-#
-# The singleline editor module or multiline editor module can be used with irb.
-# Use of multiline editor is default if it's installed.
-#
-# == Command line options
-#
-# :include: ./irb/lc/help-message
-#
-# == Commands
-#
-# The following commands are available on IRB.
-#
-# * cwws
-# * Show the current workspace.
-# * cb, cws, chws
-# * Change the current workspace to an object.
-# * bindings, workspaces
-# * Show workspaces.
-# * pushb, pushws
-# * Push an object to the workspace stack.
-# * popb, popws
-# * Pop a workspace from the workspace stack.
-# * load
-# * Load a Ruby file.
-# * require
-# * Require a Ruby file.
-# * source
-# * Loads a given file in the current session.
-# * irb
-# * Start a child IRB.
-# * jobs
-# * List of current sessions.
-# * fg
-# * Switches to the session of the given number.
-# * kill
-# * Kills the session with the given number.
-# * help
-# * Enter the mode to look up RI documents.
-# * irb_info
-# * Show information about IRB.
-# * ls
-# * Show methods, constants, and variables.
-# -g [query] or -G [query] allows you to filter out the output.
-# * measure
-# * measure enables the mode to measure processing time. measure :off disables it.
-# * $, show_source
-# * Show the source code of a given method or constant.
-# * @, whereami
-# * Show the source code around binding.irb again.
-# * debug
-# * Start the debugger of debug.gem.
-# * break, delete, next, step, continue, finish, backtrace, info, catch
-# * Start the debugger of debug.gem and run the command on it.
-#
-# == Configuration
-#
-# IRB reads a personal initialization file when it's invoked.
-# IRB searches a file in the following order and loads the first one found.
-#
-# * <tt>$IRBRC</tt> (if <tt>$IRBRC</tt> is set)
-# * <tt>$XDG_CONFIG_HOME/irb/irbrc</tt> (if <tt>$XDG_CONFIG_HOME</tt> is set)
-# * <tt>~/.irbrc</tt>
-# * +.config/irb/irbrc+
-# * +.irbrc+
-# * +irb.rc+
-# * +_irbrc+
-# * <code>$irbrc</code>
-#
-# The following are alternatives to the command line options. To use them type
-# as follows in an +irb+ session:
-#
-# IRB.conf[:IRB_NAME]="irb"
-# IRB.conf[:INSPECT_MODE]=nil
-# IRB.conf[:IRB_RC] = nil
-# IRB.conf[:BACK_TRACE_LIMIT]=16
-# IRB.conf[:USE_LOADER] = false
-# IRB.conf[:USE_MULTILINE] = nil
-# IRB.conf[:USE_SINGLELINE] = nil
-# IRB.conf[:USE_COLORIZE] = true
-# IRB.conf[:USE_TRACER] = false
-# IRB.conf[:USE_AUTOCOMPLETE] = true
-# IRB.conf[:IGNORE_SIGINT] = true
-# IRB.conf[:IGNORE_EOF] = false
-# IRB.conf[:PROMPT_MODE] = :DEFAULT
-# IRB.conf[:PROMPT] = {...}
-#
-# === Auto indentation
-#
-# To disable auto-indent mode in irb, add the following to your +.irbrc+:
+# irb(main):001> File.basename(Dir.pwd)
+# => "irb"
+# irb(main):002> Dir.entries('.').size
+# => 25
+# irb(main):003* Dir.entries('.').select do |entry|
+# irb(main):004* entry.start_with?('R')
+# irb(main):005> end
+# => ["README.md", "Rakefile"]
+#
+# The typed input may also include [\IRB-specific
+# commands](rdoc-ref:IRB@IRB-Specific+Commands).
+#
+# As seen above, you can start IRB by using the shell command `irb`.
+#
+# You can stop an IRB session by typing command `exit`:
+#
+# irb(main):006> exit
+# $
+#
+# At that point, IRB calls any hooks found in array `IRB.conf[:AT_EXIT]`, then
+# exits.
+#
+# ## Startup
+#
+# At startup, IRB:
+#
+# 1. Interprets (as Ruby code) the content of the [configuration
+# file](rdoc-ref:IRB@Configuration+File) (if given).
+# 2. Constructs the initial session context from [hash
+# IRB.conf](rdoc-ref:IRB@Hash+IRB.conf) and from default values; the hash
+# content may have been affected by [command-line
+# options](rdoc-ref:IB@Command-Line+Options), and by direct assignments in
+# the configuration file.
+# 3. Assigns the context to variable `conf`.
+# 4. Assigns command-line arguments to variable `ARGV`.
+# 5. Prints the [prompt](rdoc-ref:IRB@Prompt+and+Return+Formats).
+# 6. Puts the content of the [initialization
+# script](rdoc-ref:IRB@Initialization+Script) onto the IRB shell, just as if
+# it were user-typed commands.
+#
+#
+# ### The Command Line
+#
+# On the command line, all options precede all arguments; the first item that is
+# not recognized as an option is treated as an argument, as are all items that
+# follow.
+#
+# #### Command-Line Options
+#
+# Many command-line options affect entries in hash `IRB.conf`, which in turn
+# affect the initial configuration of the IRB session.
+#
+# Details of the options are described in the relevant subsections below.
+#
+# A cursory list of the IRB command-line options may be seen in the [help
+# message](https://raw.githubusercontent.com/ruby/irb/master/lib/irb/lc/help-message),
+# which is also displayed if you use command-line option `--help`.
+#
+# If you are interested in a specific option, consult the
+# [index](rdoc-ref:doc/irb/indexes.md@Index+of+Command-Line+Options).
+#
+# #### Command-Line Arguments
+#
+# Command-line arguments are passed to IRB in array `ARGV`:
+#
+# $ irb --noscript Foo Bar Baz
+# irb(main):001> ARGV
+# => ["Foo", "Bar", "Baz"]
+# irb(main):002> exit
+# $
+#
+# Command-line option `--` causes everything that follows to be treated as
+# arguments, even those that look like options:
+#
+# $ irb --noscript -- --noscript -- Foo Bar Baz
+# irb(main):001> ARGV
+# => ["--noscript", "--", "Foo", "Bar", "Baz"]
+# irb(main):002> exit
+# $
+#
+# ### Configuration File
+#
+# You can initialize IRB via a *configuration file*.
+#
+# If command-line option `-f` is given, no configuration file is looked for.
+#
+# Otherwise, IRB reads and interprets a configuration file if one is available.
+#
+# The configuration file can contain any Ruby code, and can usefully include
+# user code that:
+#
+# * Can then be debugged in IRB.
+# * Configures IRB itself.
+# * Requires or loads files.
+#
+#
+# The path to the configuration file is the first found among:
+#
+# * The value of variable `$IRBRC`, if defined.
+# * The value of variable `$XDG_CONFIG_HOME/irb/irbrc`, if defined.
+# * File `$HOME/.irbrc`, if it exists.
+# * File `$HOME/.config/irb/irbrc`, if it exists.
+# * File `.irbrc` in the current directory, if it exists.
+# * File `irb.rc` in the current directory, if it exists.
+# * File `_irbrc` in the current directory, if it exists.
+# * File `$irbrc` in the current directory, if it exists.
+#
+#
+# If the search fails, there is no configuration file.
+#
+# If the search succeeds, the configuration file is read as Ruby code, and so
+# can contain any Ruby programming you like.
+#
+# Method `conf.rc?` returns `true` if a configuration file was read, `false`
+# otherwise. Hash entry `IRB.conf[:RC]` also contains that value.
+#
+# ### Hash `IRB.conf`
+#
+# The initial entries in hash `IRB.conf` are determined by:
+#
+# * Default values.
+# * Command-line options, which may override defaults.
+# * Direct assignments in the configuration file.
+#
+#
+# You can see the hash by typing `IRB.conf`.
+#
+# Details of the entries' meanings are described in the relevant subsections
+# below.
+#
+# If you are interested in a specific entry, consult the
+# [index](rdoc-ref:doc/irb/indexes.md@Index+of+IRB.conf+Entries).
+#
+# ### Notes on Initialization Precedence
+#
+# * Any conflict between an entry in hash `IRB.conf` and a command-line option
+# is resolved in favor of the hash entry.
+# * Hash `IRB.conf` affects the context only once, when the configuration file
+# is interpreted; any subsequent changes to it do not affect the context and
+# are therefore essentially meaningless.
+#
+#
+# ### Initialization Script
+#
+# By default, the first command-line argument (after any options) is the path to
+# a Ruby initialization script.
+#
+# IRB reads the initialization script and puts its content onto the IRB shell,
+# just as if it were user-typed commands.
+#
+# Command-line option `--noscript` causes the first command-line argument to be
+# treated as an ordinary argument (instead of an initialization script);
+# `--script` is the default.
+#
+# ## Input
+#
+# This section describes the features that allow you to change the way IRB input
+# works; see also [Input and Output](rdoc-ref:IRB@Input+and+Output).
+#
+# ### Input Command History
+#
+# By default, IRB stores a history of up to 1000 input commands in a file named
+# `.irb_history`. The history file will be in the same directory as the
+# [configuration file](rdoc-ref:IRB@Configuration+File) if one is found, or in
+# `~/` otherwise.
+#
+# A new IRB session creates the history file if it does not exist, and appends
+# to the file if it does exist.
+#
+# You can change the filepath by adding to your configuration file:
+# `IRB.conf[:HISTORY_FILE] = *filepath*`, where *filepath* is a string filepath.
+#
+# During the session, method `conf.history_file` returns the filepath, and
+# method `conf.history_file = *new_filepath*` copies the history to the file at
+# *new_filepath*, which becomes the history file for the session.
+#
+# You can change the number of commands saved by adding to your configuration
+# file: `IRB.conf[:SAVE_HISTORY] = *n*`, wheHISTORY_FILEre *n* is one of:
+#
+# * Positive integer: the number of commands to be saved,
+# * Zero: all commands are to be saved.
+# * `nil`: no commands are to be saved,.
+#
+#
+# During the session, you can use methods `conf.save_history` or
+# `conf.save_history=` to retrieve or change the count.
+#
+# ### Command Aliases
+#
+# By default, IRB defines several command aliases:
+#
+# irb(main):001> conf.command_aliases
+# => {:"$"=>:show_source, :"@"=>:whereami}
+#
+# You can change the initial aliases in the configuration file with:
+#
+# IRB.conf[:COMMAND_ALIASES] = {foo: :show_source, bar: :whereami}
+#
+# You can replace the current aliases at any time with configuration method
+# `conf.command_aliases=`; Because `conf.command_aliases` is a hash, you can
+# modify it.
+#
+# ### End-of-File
+#
+# By default, `IRB.conf[:IGNORE_EOF]` is `false`, which means that typing the
+# end-of-file character `Ctrl-D` causes the session to exit.
+#
+# You can reverse that behavior by adding `IRB.conf[:IGNORE_EOF] = true` to the
+# configuration file.
+#
+# During the session, method `conf.ignore_eof?` returns the setting, and method
+# `conf.ignore_eof = *boolean*` sets it.
+#
+# ### SIGINT
+#
+# By default, `IRB.conf[:IGNORE_SIGINT]` is `true`, which means that typing the
+# interrupt character `Ctrl-C` causes the session to exit.
+#
+# You can reverse that behavior by adding `IRB.conf[:IGNORE_SIGING] = false` to
+# the configuration file.
+#
+# During the session, method `conf.ignore_siging?` returns the setting, and
+# method `conf.ignore_sigint = *boolean*` sets it.
+#
+# ### Automatic Completion
+#
+# By default, IRB enables [automatic
+# completion](https://en.wikipedia.org/wiki/Autocomplete#In_command-line_interpr
+# eters):
+#
+# You can disable it by either of these:
+#
+# * Adding `IRB.conf[:USE_AUTOCOMPLETE] = false` to the configuration file.
+# * Giving command-line option `--noautocomplete` (`--autocomplete` is the
+# default).
+#
+#
+# Method `conf.use_autocomplete?` returns `true` if automatic completion is
+# enabled, `false` otherwise.
+#
+# The setting may not be changed during the session.
+#
+# ### Automatic Indentation
+#
+# By default, IRB automatically indents lines of code to show structure (e.g.,
+# it indent the contents of a block).
+#
+# The current setting is returned by the configuration method
+# `conf.auto_indent_mode`.
+#
+# The default initial setting is `true`:
+#
+# irb(main):001> conf.auto_indent_mode
+# => true
+# irb(main):002* Dir.entries('.').select do |entry|
+# irb(main):003* entry.start_with?('R')
+# irb(main):004> end
+# => ["README.md", "Rakefile"]
+#
+# You can change the initial setting in the configuration file with:
#
# IRB.conf[:AUTO_INDENT] = false
#
-# === Autocompletion
+# Note that the *current* setting *may not* be changed in the IRB session.
+#
+# ### Input Method
+#
+# The IRB input method determines how command input is to be read; by default,
+# the input method for a session is IRB::RelineInputMethod. Unless the
+# value of the TERM environment variable is 'dumb', in which case the
+# most simplistic input method is used.
+#
+# You can set the input method by:
+#
+# * Adding to the configuration file:
+#
+# * `IRB.conf[:USE_SINGLELINE] = true` or `IRB.conf[:USE_MULTILINE]=
+# false` sets the input method to IRB::ReadlineInputMethod.
+# * `IRB.conf[:USE_SINGLELINE] = false` or `IRB.conf[:USE_MULTILINE] =
+# true` sets the input method to IRB::RelineInputMethod.
+#
+#
+# * Giving command-line options:
+#
+# * `--singleline` or `--nomultiline` sets the input method to
+# IRB::ReadlineInputMethod.
+# * `--nosingleline` or `--multiline` sets the input method to
+# IRB::RelineInputMethod.
+# * `--nosingleline` together with `--nomultiline` sets the
+# input to IRB::StdioInputMethod.
+#
+#
+# Method `conf.use_multiline?` and its synonym `conf.use_reline` return:
+#
+# * `true` if option `--multiline` was given.
+# * `false` if option `--nomultiline` was given.
+# * `nil` if neither was given.
+#
+#
+# Method `conf.use_singleline?` and its synonym `conf.use_readline` return:
+#
+# * `true` if option `--singleline` was given.
+# * `false` if option `--nosingleline` was given.
+# * `nil` if neither was given.
+#
+#
+# ## Output
+#
+# This section describes the features that allow you to change the way IRB
+# output works; see also [Input and Output](rdoc-ref:IRB@Input+and+Output).
+#
+# ### Return-Value Printing (Echoing)
+#
+# By default, IRB prints (echoes) the values returned by all input commands.
+#
+# You can change the initial behavior and suppress all echoing by:
+#
+# * Adding to the configuration file: `IRB.conf[:ECHO] = false`. (The default
+# value for this entry is `nil`, which means the same as `true`.)
+# * Giving command-line option `--noecho`. (The default is `--echo`.)
+#
+#
+# During the session, you can change the current setting with configuration
+# method `conf.echo=` (set to `true` or `false`).
+#
+# As stated above, by default IRB prints the values returned by all input
+# commands; but IRB offers special treatment for values returned by assignment
+# statements, which may be:
+#
+# * Printed with truncation (to fit on a single line of output), which is the
+# default; an ellipsis (`...` is suffixed, to indicate the truncation):
+#
+# irb(main):001> x = 'abc' * 100
+#
+#
+# > "abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc...
+#
+# * Printed in full (regardless of the length).
+# * Suppressed (not printed at all)
+#
+#
+# You can change the initial behavior by:
+#
+# * Adding to the configuration file: `IRB.conf[:ECHO_ON_ASSIGNMENT] = false`.
+# (The default value for this entry is `niL`, which means the same as
+# `:truncate`.)
+# * Giving command-line option `--noecho-on-assignment` or
+# `--echo-on-assignment`. (The default is `--truncate-echo-on-assignment`.)
+#
+#
+# During the session, you can change the current setting with configuration
+# method `conf.echo_on_assignment=` (set to `true`, `false`, or `:truncate`).
+#
+# By default, IRB formats returned values by calling method `inspect`.
+#
+# You can change the initial behavior by:
+#
+# * Adding to the configuration file: `IRB.conf[:INSPECT_MODE] = false`. (The
+# default value for this entry is `true`.)
+# * Giving command-line option `--noinspect`. (The default is `--inspect`.)
+#
+#
+# During the session, you can change the setting using method
+# `conf.inspect_mode=`.
+#
+# ### Multiline Output
+#
+# By default, IRB prefixes a newline to a multiline response.
+#
+# You can change the initial default value by adding to the configuration file:
+#
+# IRB.conf[:NEWLINE_BEFORE_MULTILINE_OUTPUT] = false
+#
+# During a session, you can retrieve or set the value using methods
+# `conf.newline_before_multiline_output?` and
+# `conf.newline_before_multiline_output=`.
+#
+# Examples:
+#
+# irb(main):001> conf.inspect_mode = false
+# => false
+# irb(main):002> "foo\nbar"
+# =>
+# foo
+# bar
+# irb(main):003> conf.newline_before_multiline_output = false
+# => false
+# irb(main):004> "foo\nbar"
+# => foo
+# bar
+#
+# ### Evaluation History
+#
+# By default, IRB saves no history of evaluations (returned values), and the
+# related methods `conf.eval_history`, `_`, and `__` are undefined.
+#
+# You can turn on that history, and set the maximum number of evaluations to be
+# stored:
+#
+# * In the configuration file: add `IRB.conf[:EVAL_HISTORY] = *n*`. (Examples
+# below assume that we've added `IRB.conf[:EVAL_HISTORY] = 5`.)
+# * In the session (at any time): `conf.eval_history = *n*`.
+#
+#
+# If `n` is zero, all evaluation history is stored.
+#
+# Doing either of the above:
+#
+# * Sets the maximum size of the evaluation history; defines method
+# `conf.eval_history`, which returns the maximum size `n` of the evaluation
+# history:
+#
+# irb(main):001> conf.eval_history = 5
+# => 5
+# irb(main):002> conf.eval_history
+# => 5
+#
+# * Defines variable `_`, which contains the most recent evaluation, or `nil`
+# if none; same as method `conf.last_value`:
+#
+# irb(main):003> _
+# => 5
+# irb(main):004> :foo
+# => :foo
+# irb(main):005> :bar
+# => :bar
+# irb(main):006> _
+# => :bar
+# irb(main):007> _
+# => :bar
+#
+# * Defines variable `__`:
+#
+# * `__` unadorned: contains all evaluation history:
+#
+# irb(main):008> :foo
+# => :foo
+# irb(main):009> :bar
+# => :bar
+# irb(main):010> :baz
+# => :baz
+# irb(main):011> :bat
+# => :bat
+# irb(main):012> :bam
+# => :bam
+# irb(main):013> __
+# =>
+# 9 :bar
+# 10 :baz
+# 11 :bat
+# 12 :bam
+# irb(main):014> __
+# =>
+# 10 :baz
+# 11 :bat
+# 12 :bam
+# 13 ...self-history...
+#
+# Note that when the evaluation is multiline, it is displayed
+# differently.
+#
+# * `__[`*m*`]`:
+#
+# * Positive *m*: contains the evaluation for the given line number,
+# or `nil` if that line number is not in the evaluation history:
+#
+# irb(main):015> __[12]
+# => :bam
+# irb(main):016> __[1]
+# => nil
#
-# To disable autocompletion for irb, add the following to your +.irbrc+:
+# * Negative *m*: contains the `mth`-from-end evaluation, or `nil` if
+# that evaluation is not in the evaluation history:
#
-# IRB.conf[:USE_AUTOCOMPLETE] = false
+# irb(main):017> __[-3]
+# => :bam
+# irb(main):018> __[-13]
+# => nil
#
-# To enable enhanced completion using type information, add the following to your +.irbrc+:
+# * Zero *m*: contains `nil`:
#
-# IRB.conf[:COMPLETOR] = :type
+# irb(main):019> __[0]
+# => nil
#
-# === History
#
-# By default, irb will store the last 1000 commands you used in
-# <code>IRB.conf[:HISTORY_FILE]</code> (<code>~/.irb_history</code> by default).
#
-# If you want to disable history, add the following to your +.irbrc+:
#
-# IRB.conf[:SAVE_HISTORY] = nil
+# ### Prompt and Return Formats
#
-# See IRB::Context#save_history= for more information.
+# By default, IRB uses the prompt and return value formats defined in its
+# `:DEFAULT` prompt mode.
#
-# The history of _results_ of commands evaluated is not stored by default,
-# but can be turned on to be stored with this +.irbrc+ setting:
+# #### The Default Prompt and Return Format
#
-# IRB.conf[:EVAL_HISTORY] = <number>
+# The default prompt and return values look like this:
#
-# See IRB::Context#eval_history= and EvalHistory class. The history of command
-# results is not permanently saved in any file.
+# irb(main):001> 1 + 1
+# => 2
+# irb(main):002> 2 + 2
+# => 4
#
-# == Customizing the IRB Prompt
+# The prompt includes:
#
-# In order to customize the prompt, you can change the following Hash:
+# * The name of the running program (`irb`); see [IRB
+# Name](rdoc-ref:IRB@IRB+Name).
+# * The name of the current session (`main`); See [IRB
+# Sessions](rdoc-ref:IRB@IRB+Sessions).
+# * A 3-digit line number (1-based).
#
-# IRB.conf[:PROMPT]
#
-# This example can be used in your +.irbrc+
+# The default prompt actually defines three formats:
#
-# IRB.conf[:PROMPT][:MY_PROMPT] = { # name of prompt mode
-# :AUTO_INDENT => false, # disables auto-indent mode
-# :PROMPT_I => ">> ", # simple prompt
-# :PROMPT_S => nil, # prompt for continuated strings
-# :PROMPT_C => nil, # prompt for continuated statement
-# :RETURN => " ==>%s\n" # format to return value
-# }
+# * One for most situations (as above):
+#
+# irb(main):003> Dir
+# => Dir
+#
+# * One for when the typed command is a statement continuation (adds trailing
+# asterisk):
+#
+# irb(main):004* Dir.
+#
+# * One for when the typed command is a string continuation (adds trailing
+# single-quote):
+#
+# irb(main):005' Dir.entries('.
+#
+#
+# You can see the prompt change as you type the characters in the following:
+#
+# irb(main):001* Dir.entries('.').select do |entry|
+# irb(main):002* entry.start_with?('R')
+# irb(main):003> end
+# => ["README.md", "Rakefile"]
+#
+# #### Pre-Defined Prompts
+#
+# IRB has several pre-defined prompts, stored in hash `IRB.conf[:PROMPT]`:
+#
+# irb(main):001> IRB.conf[:PROMPT].keys
+# => [:NULL, :DEFAULT, :CLASSIC, :SIMPLE, :INF_RUBY, :XMP]
+#
+# To see the full data for these, type `IRB.conf[:PROMPT]`.
+#
+# Most of these prompt definitions include specifiers that represent values like
+# the IRB name, session name, and line number; see [Prompt
+# Specifiers](rdoc-ref:IRB@Prompt+Specifiers).
+#
+# You can change the initial prompt and return format by:
+#
+# * Adding to the configuration file: `IRB.conf[:PROMPT] = *mode*` where
+# *mode* is the symbol name of a prompt mode.
+# * Giving a command-line option:
+#
+# * `--prompt *mode*`: sets the prompt mode to *mode*. where *mode* is the
+# symbol name of a prompt mode.
+# * `--simple-prompt` or `--sample-book-mode`: sets the prompt mode to
+# `:SIMPLE`.
+# * `--inf-ruby-mode`: sets the prompt mode to `:INF_RUBY` and suppresses
+# both `--multiline` and `--singleline`.
+# * `--noprompt`: suppresses prompting; does not affect echoing.
+#
+#
+#
+# You can retrieve or set the current prompt mode with methods
+#
+# `conf.prompt_mode` and `conf.prompt_mode=`.
+#
+# If you're interested in prompts and return formats other than the defaults,
+# you might experiment by trying some of the others.
+#
+# #### Custom Prompts
+#
+# You can also define custom prompts and return formats, which may be done
+# either in an IRB session or in the configuration file.
+#
+# A prompt in IRB actually defines three prompts, as seen above. For simple
+# custom data, we'll make all three the same:
+#
+# irb(main):001* IRB.conf[:PROMPT][:MY_PROMPT] = {
+# irb(main):002* PROMPT_I: ': ',
+# irb(main):003* PROMPT_C: ': ',
+# irb(main):004* PROMPT_S: ': ',
+# irb(main):005* RETURN: '=> '
+# irb(main):006> }
+# => {:PROMPT_I=>": ", :PROMPT_C=>": ", :PROMPT_S=>": ", :RETURN=>"=> "}
+#
+# If you define the custom prompt in the configuration file, you can also make
+# it the current prompt by adding:
#
# IRB.conf[:PROMPT_MODE] = :MY_PROMPT
#
-# Or, invoke irb with the above prompt mode by:
-#
-# irb --prompt my-prompt
-#
-# Constants +PROMPT_I+, +PROMPT_S+ and +PROMPT_C+ specify the format. In the
-# prompt specification, some special strings are available:
-#
-# %N # command name which is running
-# %m # to_s of main object (self)
-# %M # inspect of main object (self)
-# %l # type of string(", ', /, ]), `]' is inner %w[...]
-# %NNi # indent level. NN is digits and means as same as printf("%NNd").
-# # It can be omitted
-# %NNn # line number.
-# %% # %
-#
-# For instance, the default prompt mode is defined as follows:
-#
-# IRB.conf[:PROMPT_MODE][:DEFAULT] = {
-# :PROMPT_I => "%N(%m):%03n> ",
-# :PROMPT_S => "%N(%m):%03n%l ",
-# :PROMPT_C => "%N(%m):%03n* ",
-# :RETURN => "%s\n" # used to printf
-# }
-#
-# irb comes with a number of available modes:
-#
-# # :NULL:
-# # :PROMPT_I:
-# # :PROMPT_S:
-# # :PROMPT_C:
-# # :RETURN: |
-# # %s
-# # :DEFAULT:
-# # :PROMPT_I: ! '%N(%m):%03n> '
-# # :PROMPT_S: ! '%N(%m):%03n%l '
-# # :PROMPT_C: ! '%N(%m):%03n* '
-# # :RETURN: |
-# # => %s
-# # :CLASSIC:
-# # :PROMPT_I: ! '%N(%m):%03n:%i> '
-# # :PROMPT_S: ! '%N(%m):%03n:%i%l '
-# # :PROMPT_C: ! '%N(%m):%03n:%i* '
-# # :RETURN: |
-# # %s
-# # :SIMPLE:
-# # :PROMPT_I: ! '>> '
-# # :PROMPT_S:
-# # :PROMPT_C: ! '?> '
-# # :RETURN: |
-# # => %s
-# # :INF_RUBY:
-# # :PROMPT_I: ! '%N(%m):%03n> '
-# # :PROMPT_S:
-# # :PROMPT_C:
-# # :RETURN: |
-# # %s
-# # :AUTO_INDENT: true
-# # :XMP:
-# # :PROMPT_I:
-# # :PROMPT_S:
-# # :PROMPT_C:
-# # :RETURN: |2
-# # ==>%s
-#
-# == Restrictions
-#
-# Because irb evaluates input immediately after it is syntactically complete,
-# the results may be slightly different than directly using Ruby.
-#
-# == IRB Sessions
+# Regardless of where it's defined, you can make it the current prompt in a
+# session:
#
-# IRB has a special feature, that allows you to manage many sessions at once.
+# conf.prompt_mode = :MY_PROMPT
#
-# You can create new sessions with Irb.irb, and get a list of current sessions
-# with the +jobs+ command in the prompt.
+# You can view or modify the current prompt data with various configuration
+# methods:
+#
+# * `conf.prompt_mode`, `conf.prompt_mode=`.
+# * `conf.prompt_c`, `conf.c=`.
+# * `conf.prompt_i`, `conf.i=`.
+# * `conf.prompt_s`, `conf.s=`.
+# * `conf.return_format`, `return_format=`.
+#
+#
+# #### Prompt Specifiers
+#
+# A prompt's definition can include specifiers for which certain values are
+# substituted:
+#
+# * `%N`: the name of the running program.
+# * `%m`: the value of `self.to_s`.
+# * `%M`: the value of `self.inspect`.
+# * `%l`: an indication of the type of string; one of `"`, `'`, `/`, `]`.
+# * `%NNi`: Indentation level. NN is a 2-digit number that specifies the number
+# of digits of the indentation level (03 will result in 001).
+# * `%NNn`: Line number. NN is a 2-digit number that specifies the number
+# of digits of the line number (03 will result in 001).
+# * `%%`: Literal `%`.
+#
+#
+# ### Verbosity
+#
+# By default, IRB verbosity is disabled, which means that output is smaller
+# rather than larger.
+#
+# You can enable verbosity by:
+#
+# * Adding to the configuration file: `IRB.conf[:VERBOSE] = true` (the default
+# is `nil`).
+# * Giving command-line options `--verbose` (the default is `--noverbose`).
+#
+#
+# During a session, you can retrieve or set verbosity with methods
+# `conf.verbose` and `conf.verbose=`.
+#
+# ### Help
+#
+# Command-line option `--version` causes IRB to print its help text and exit.
+#
+# ### Version
+#
+# Command-line option `--version` causes IRB to print its version text and exit.
+#
+# ## Input and Output
+#
+# ### Color Highlighting
+#
+# By default, IRB color highlighting is enabled, and is used for both:
+#
+# * Input: As you type, IRB reads the typed characters and highlights elements
+# that it recognizes; it also highlights errors such as mismatched
+# parentheses.
+# * Output: IRB highlights syntactical elements.
+#
+#
+# You can disable color highlighting by:
+#
+# * Adding to the configuration file: `IRB.conf[:USE_COLORIZE] = false` (the
+# default value is `true`).
+# * Giving command-line option `--nocolorize`
+#
+#
+# ## Debugging
+#
+# Command-line option `-d` sets variables `$VERBOSE` and `$DEBUG` to `true`;
+# these have no effect on IRB output.
+#
+# ### Warnings
+#
+# Command-line option `-w` suppresses warnings.
+#
+# Command-line option `-W[*level*]` sets warning level;
+#
+# * 0=silence
+# * 1=medium
+# * 2=verbose
+#
+# ## Other Features
+#
+# ### Load Modules
+#
+# You can specify the names of modules that are to be required at startup.
+#
+# Array `conf.load_modules` determines the modules (if any) that are to be
+# required during session startup. The array is used only during session
+# startup, so the initial value is the only one that counts.
+#
+# The default initial value is `[]` (load no modules):
+#
+# irb(main):001> conf.load_modules
+# => []
+#
+# You can set the default initial value via:
+#
+# * Command-line option `-r`
+#
+# $ irb -r csv -r json
+# irb(main):001> conf.load_modules
+# => ["csv", "json"]
+#
+# * Hash entry `IRB.conf[:LOAD_MODULES] = *array*`:
+#
+# IRB.conf[:LOAD_MODULES] = %w[csv, json]
+#
+#
+# Note that the configuration file entry overrides the command-line options.
+#
+# ### RI Documentation Directories
+#
+# You can specify the paths to RI documentation directories that are to be
+# loaded (in addition to the default directories) at startup; see details about
+# RI by typing `ri --help`.
+#
+# Array `conf.extra_doc_dirs` determines the directories (if any) that are to be
+# loaded during session startup. The array is used only during session startup,
+# so the initial value is the only one that counts.
+#
+# The default initial value is `[]` (load no extra documentation):
+#
+# irb(main):001> conf.extra_doc_dirs
+# => []
+#
+# You can set the default initial value via:
#
-# === Commands
+# * Command-line option `--extra_doc_dir`
#
-# JobManager provides commands to handle the current sessions:
+# $ irb --extra-doc-dir your_doc_dir --extra-doc-dir my_doc_dir
+# irb(main):001> conf.extra_doc_dirs
+# => ["your_doc_dir", "my_doc_dir"]
#
-# jobs # List of current sessions
-# fg # Switches to the session of the given number
-# kill # Kills the session with the given number
+# * Hash entry `IRB.conf[:EXTRA_DOC_DIRS] = *array*`:
#
-# The +exit+ command, or ::irb_exit, will quit the current session and call any
-# exit hooks with IRB.irb_at_exit.
+# IRB.conf[:EXTRA_DOC_DIRS] = %w[your_doc_dir my_doc_dir]
#
-# A few commands for loading files within the session are also available:
#
-# +source+::
-# Loads a given file in the current session and displays the source lines,
-# see IrbLoader#source_file
-# +irb_load+::
-# Loads the given file similarly to Kernel#load, see IrbLoader#irb_load
-# +irb_require+::
-# Loads the given file similarly to Kernel#require
+# Note that the configuration file entry overrides the command-line options.
#
-# === Configuration
+# ### IRB Name
+#
+# You can specify a name for IRB.
+#
+# The default initial value is `'irb'`:
+#
+# irb(main):001> conf.irb_name
+# => "irb"
+#
+# You can set the default initial value via hash entry `IRB.conf[:IRB_NAME] =
+# *string*`:
+#
+# IRB.conf[:IRB_NAME] = 'foo'
+#
+# ### Application Name
+#
+# You can specify an application name for the IRB session.
+#
+# The default initial value is `'irb'`:
+#
+# irb(main):001> conf.ap_name
+# => "irb"
+#
+# You can set the default initial value via hash entry `IRB.conf[:AP_NAME] =
+# *string*`:
+#
+# IRB.conf[:AP_NAME] = 'my_ap_name'
+#
+# ### Configuration Monitor
+#
+# You can monitor changes to the configuration by assigning a proc to
+# `IRB.conf[:IRB_RC]` in the configuration file:
+#
+# IRB.conf[:IRB_RC] = proc {|conf| puts conf.class }
+#
+# Each time the configuration is changed, that proc is called with argument
+# `conf`:
+#
+# ### Encodings
+#
+# Command-line option `-E *ex*[:*in*]` sets initial external (ex) and internal
+# (in) encodings.
+#
+# Command-line option `-U` sets both to UTF-8.
+#
+# ### Commands
+#
+# Please use the `help` command to see the list of available commands.
+#
+# ### IRB Sessions
+#
+# IRB has a special feature, that allows you to manage many sessions at once.
+#
+# You can create new sessions with Irb.irb, and get a list of current sessions
+# with the `jobs` command in the prompt.
+#
+# #### Configuration
#
# The command line options, or IRB.conf, specify the default behavior of
# Irb.irb.
#
-# On the other hand, each conf in IRB@Command+line+options is used to
+# On the other hand, each conf in IRB@Command-Line+Options is used to
# individually configure IRB.irb.
#
-# If a proc is set for <code>IRB.conf[:IRB_RC]</code>, its will be invoked after execution
+# If a proc is set for `IRB.conf[:IRB_RC]`, its will be invoked after execution
# of that proc with the context of the current session as its argument. Each
# session can be configured using this mechanism.
#
-# === Session variables
+# #### Session variables
#
# There are a few variables in every Irb session that can come in handy:
#
-# <code>_</code>::
-# The value command executed, as a local variable
-# <code>__</code>::
-# The history of evaluated commands. Available only if
-# <code>IRB.conf[:EVAL_HISTORY]</code> is not +nil+ (which is the default).
-# See also IRB::Context#eval_history= and IRB::History.
-# <code>__[line_no]</code>::
-# Returns the evaluation value at the given line number, +line_no+.
-# If +line_no+ is a negative, the return value +line_no+ many lines before
-# the most recent return value.
-#
-# === Example using IRB Sessions
-#
-# # invoke a new session
-# irb(main):001:0> irb
-# # list open sessions
-# irb.1(main):001:0> jobs
-# #0->irb on main (#<Thread:0x400fb7e4> : stop)
-# #1->irb#1 on main (#<Thread:0x40125d64> : running)
-#
-# # change the active session
-# irb.1(main):002:0> fg 0
-# # define class Foo in top-level session
-# irb(main):002:0> class Foo;end
-# # invoke a new session with the context of Foo
-# irb(main):003:0> irb Foo
-# # define Foo#foo
-# irb.2(Foo):001:0> def foo
-# irb.2(Foo):002:1> print 1
-# irb.2(Foo):003:1> end
-#
-# # change the active session
-# irb.2(Foo):004:0> fg 0
-# # list open sessions
-# irb(main):004:0> jobs
-# #0->irb on main (#<Thread:0x400fb7e4> : running)
-# #1->irb#1 on main (#<Thread:0x40125d64> : stop)
-# #2->irb#2 on Foo (#<Thread:0x4011d54c> : stop)
-# # check if Foo#foo is available
-# irb(main):005:0> Foo.instance_methods #=> [:foo, ...]
-#
-# # change the active session
-# irb(main):006:0> fg 2
-# # define Foo#bar in the context of Foo
-# irb.2(Foo):005:0> def bar
-# irb.2(Foo):006:1> print "bar"
-# irb.2(Foo):007:1> end
-# irb.2(Foo):010:0> Foo.instance_methods #=> [:bar, :foo, ...]
-#
-# # change the active session
-# irb.2(Foo):011:0> fg 0
-# irb(main):007:0> f = Foo.new #=> #<Foo:0x4010af3c>
-# # invoke a new session with the context of f (instance of Foo)
-# irb(main):008:0> irb f
-# # list open sessions
-# irb.3(<Foo:0x4010af3c>):001:0> jobs
-# #0->irb on main (#<Thread:0x400fb7e4> : stop)
-# #1->irb#1 on main (#<Thread:0x40125d64> : stop)
-# #2->irb#2 on Foo (#<Thread:0x4011d54c> : stop)
-# #3->irb#3 on #<Foo:0x4010af3c> (#<Thread:0x4010a1e0> : running)
-# # evaluate f.foo
-# irb.3(<Foo:0x4010af3c>):002:0> foo #=> 1 => nil
-# # evaluate f.bar
-# irb.3(<Foo:0x4010af3c>):003:0> bar #=> bar => nil
-# # kill jobs 1, 2, and 3
-# irb.3(<Foo:0x4010af3c>):004:0> kill 1, 2, 3
-# # list open sessions, should only include main session
-# irb(main):009:0> jobs
-# #0->irb on main (#<Thread:0x400fb7e4> : running)
-# # quit irb
-# irb(main):010:0> exit
+# `_`
+# : The value command executed, as a local variable
+# `__`
+# : The history of evaluated commands. Available only if
+# `IRB.conf[:EVAL_HISTORY]` is not `nil` (which is the default). See also
+# IRB::Context#eval_history= and IRB::History.
+# `__[line_no]`
+# : Returns the evaluation value at the given line number, `line_no`. If
+# `line_no` is a negative, the return value `line_no` many lines before the
+# most recent return value.
+#
+#
+# ## Restrictions
+#
+# Ruby code typed into IRB behaves the same as Ruby code in a file, except that:
+#
+# * Because IRB evaluates input immediately after it is syntactically
+# complete, some results may be slightly different.
+# * Forking may not be well behaved.
+#
module IRB
# An exception raised by IRB.irb_abort
@@ -373,14 +882,14 @@ module IRB
# The current IRB::Context of the session, see IRB.conf
#
- # irb
- # irb(main):001:0> IRB.CurrentContext.irb_name = "foo"
- # foo(main):002:0> IRB.conf[:MAIN_CONTEXT].irb_name #=> "foo"
- def IRB.CurrentContext
+ # irb
+ # irb(main):001:0> IRB.CurrentContext.irb_name = "foo"
+ # foo(main):002:0> IRB.conf[:MAIN_CONTEXT].irb_name #=> "foo"
+ def IRB.CurrentContext # :nodoc:
IRB.conf[:MAIN_CONTEXT]
end
- # Initializes IRB and creates a new Irb.irb object at the +TOPLEVEL_BINDING+
+ # Initializes IRB and creates a new Irb.irb object at the `TOPLEVEL_BINDING`
def IRB.start(ap_path = nil)
STDOUT.sync = true
$0 = File::basename(ap_path, ".rb") if ap_path
@@ -396,42 +905,46 @@ module IRB
end
# Quits irb
- def IRB.irb_exit(irb, ret)
- throw :IRB_EXIT, ret
+ def IRB.irb_exit(*) # :nodoc:
+ throw :IRB_EXIT, false
end
# Aborts then interrupts irb.
#
- # Will raise an Abort exception, or the given +exception+.
- def IRB.irb_abort(irb, exception = Abort)
+ # Will raise an Abort exception, or the given `exception`.
+ def IRB.irb_abort(irb, exception = Abort) # :nodoc:
irb.context.thread.raise exception, "abort then interrupt!"
end
class Irb
# Note: instance and index assignment expressions could also be written like:
- # "foo.bar=(1)" and "foo.[]=(1, bar)", when expressed that way, the former
- # be parsed as :assign and echo will be suppressed, but the latter is
- # parsed as a :method_add_arg and the output won't be suppressed
+ # "foo.bar=(1)" and "foo.[]=(1, bar)", when expressed that way, the former be
+ # parsed as :assign and echo will be suppressed, but the latter is parsed as a
+ # :method_add_arg and the output won't be suppressed
PROMPT_MAIN_TRUNCATE_LENGTH = 32
- PROMPT_MAIN_TRUNCATE_OMISSION = '...'.freeze
- CONTROL_CHARACTERS_PATTERN = "\x00-\x1F".freeze
+ PROMPT_MAIN_TRUNCATE_OMISSION = '...'
+ CONTROL_CHARACTERS_PATTERN = "\x00-\x1F"
# Returns the current context of this irb session
attr_reader :context
# The lexer used by this irb session
attr_accessor :scanner
+ attr_reader :from_binding
+
# Creates a new irb session
- def initialize(workspace = nil, input_method = nil)
+ def initialize(workspace = nil, input_method = nil, from_binding: false)
+ @from_binding = from_binding
@context = Context.new(self, workspace, input_method)
- @context.workspace.load_commands_to_main
+ @context.workspace.load_helper_methods_to_main
@signal_status = :IN_IRB
@scanner = RubyLex.new
@line_no = 1
end
- # A hook point for `debug` command's breakpoint after :IRB_EXIT as well as its clean-up
+ # A hook point for `debug` command's breakpoint after :IRB_EXIT as well as its
+ # clean-up
def debug_break
# it means the debug integration has been activated
if defined?(DEBUGGER__) && DEBUGGER__.respond_to?(:capture_frames_without_irb)
@@ -444,29 +957,37 @@ module IRB
def debug_readline(binding)
workspace = IRB::WorkSpace.new(binding)
- context.workspace = workspace
- context.workspace.load_commands_to_main
+ context.replace_workspace(workspace)
+ context.workspace.load_helper_methods_to_main
@line_no += 1
# When users run:
- # 1. Debugging commands, like `step 2`
- # 2. Any input that's not irb-command, like `foo = 123`
+ # 1. Debugging commands, like `step 2`
+ # 2. Any input that's not irb-command, like `foo = 123`
#
- # Irb#eval_input will simply return the input, and we need to pass it to the debugger.
- input = if IRB.conf[:SAVE_HISTORY] && context.io.support_history_saving?
- # Previous IRB session's history has been saved when `Irb#run` is exited
- # We need to make sure the saved history is not saved again by reseting the counter
- context.io.reset_history_counter
+ #
+ # Irb#eval_input will simply return the input, and we need to pass it to the
+ # debugger.
+ input = nil
+ forced_exit = catch(:IRB_EXIT) do
+ if IRB.conf[:SAVE_HISTORY] && context.io.support_history_saving?
+ # Previous IRB session's history has been saved when `Irb#run` is exited We need
+ # to make sure the saved history is not saved again by resetting the counter
+ context.io.reset_history_counter
- begin
- eval_input
- ensure
- context.io.save_history
+ begin
+ input = eval_input
+ ensure
+ context.io.save_history
+ end
+ else
+ input = eval_input
end
- else
- eval_input
+ false
end
+ Kernel.exit if forced_exit
+
if input&.include?("\n")
@line_no += input.count("\n") - 1
end
@@ -477,6 +998,7 @@ module IRB
def run(conf = IRB.conf)
in_nested_session = !!conf[:MAIN_CONTEXT]
conf[:IRB_RC].call(context) if conf[:IRB_RC]
+ prev_context = conf[:MAIN_CONTEXT]
conf[:MAIN_CONTEXT] = context
save_history = !in_nested_session && conf[:SAVE_HISTORY] && context.io.support_history_saving?
@@ -490,13 +1012,24 @@ module IRB
end
begin
- catch(:IRB_EXIT) do
+ if defined?(RubyVM.keep_script_lines)
+ keep_script_lines_backup = RubyVM.keep_script_lines
+ RubyVM.keep_script_lines = true
+ end
+
+ forced_exit = catch(:IRB_EXIT) do
eval_input
end
ensure
+ # Do not restore to nil. It will cause IRB crash when used with threads.
+ IRB.conf[:MAIN_CONTEXT] = prev_context if prev_context
+
+ RubyVM.keep_script_lines = keep_script_lines_backup if defined?(RubyVM.keep_script_lines)
trap("SIGINT", prev_trap)
conf[:AT_EXIT].each{|hook| hook.call}
+
context.io.save_history if save_history
+ Kernel.exit if forced_exit
end
end
@@ -507,12 +1040,13 @@ module IRB
each_top_level_statement do |statement, line_no|
signal_status(:IN_EVAL) do
begin
- # If the integration with debugger is activated, we return certain input if it should be dealt with by debugger
+ # If the integration with debugger is activated, we return certain input if it
+ # should be dealt with by debugger
if @context.with_debugger && statement.should_be_handled_by_debugger?
return statement.code
end
- @context.evaluate(statement.evaluable_code, line_no)
+ @context.evaluate(statement, line_no)
if @context.echo? && !statement.suppresses_echo?
if statement.is_assignment?
@@ -559,7 +1093,7 @@ module IRB
return read_input(prompt) if @context.io.respond_to?(:check_termination)
# nomultiline
- code = ''
+ code = +''
line_offset = 0
loop do
line = read_input(prompt)
@@ -568,9 +1102,7 @@ module IRB
end
code << line
-
- # Accept any single-line input for symbol aliases or commands that transform args
- return code if single_line_command?(code)
+ return code if command?(code)
tokens, opens, terminated = @scanner.check_code_state(code, local_variables: @context.local_variables)
return code if terminated
@@ -585,34 +1117,48 @@ module IRB
loop do
code = readmultiline
break unless code
-
- if code != "\n"
- yield build_statement(code), @line_no
- end
+ yield build_statement(code), @line_no
@line_no += code.count("\n")
rescue RubyLex::TerminateLineInput
end
end
def build_statement(code)
+ if code.match?(/\A\n*\z/)
+ return Statement::EmptyInput.new
+ end
+
code.force_encoding(@context.io.encoding)
- command_or_alias, arg = code.split(/\s/, 2)
- # Transform a non-identifier alias (@, $) or keywords (next, break)
- command_name = @context.command_aliases[command_or_alias.to_sym]
- command = command_name || command_or_alias
- command_class = ExtendCommandBundle.load_command(command)
-
- if command_class
- Statement::Command.new(code, command, arg, command_class)
+ if (command, arg = parse_command(code))
+ command_class = Command.load_command(command)
+ Statement::Command.new(code, command_class, arg)
else
is_assignment_expression = @scanner.assignment_expression?(code, local_variables: @context.local_variables)
Statement::Expression.new(code, is_assignment_expression)
end
end
- def single_line_command?(code)
- command = code.split(/\s/, 2).first
- @context.symbol_alias?(command) || @context.transform_args?(command)
+ def parse_command(code)
+ command_name, arg = code.strip.split(/\s+/, 2)
+ return unless code.lines.size == 1 && command_name
+
+ arg ||= ''
+ command = command_name.to_sym
+ # Command aliases are always command. example: $, @
+ if (alias_name = @context.command_aliases[command])
+ return [alias_name, arg]
+ end
+
+ # Check visibility
+ public_method = !!Kernel.instance_method(:public_method).bind_call(@context.main, command) rescue false
+ private_method = !public_method && !!Kernel.instance_method(:method).bind_call(@context.main, command) rescue false
+ if Command.execute_as_command?(command, public_method: public_method, private_method: private_method)
+ [command, arg]
+ end
+ end
+
+ def command?(code)
+ !!parse_command(code)
end
def configure_io
@@ -630,8 +1176,7 @@ module IRB
false
end
else
- # Accept any single-line input for symbol aliases or commands that transform args
- next true if single_line_command?(code)
+ next true if command?(code)
_tokens, _opens, terminated = @scanner.check_code_state(code, local_variables: @context.local_variables)
terminated
@@ -640,13 +1185,13 @@ module IRB
end
if @context.io.respond_to?(:dynamic_prompt)
@context.io.dynamic_prompt do |lines|
- lines << '' if lines.empty?
tokens = RubyLex.ripper_lex_without_warning(lines.map{ |l| l + "\n" }.join, local_variables: @context.local_variables)
line_results = IRB::NestingParser.parse_by_line(tokens)
tokens_until_line = []
line_results.map.with_index do |(line_tokens, _prev_opens, next_opens, _min_depth), line_num_offset|
line_tokens.each do |token, _s|
- # Avoid appending duplicated token. Tokens that include "\n" like multiline tstring_content can exist in multiple lines.
+ # Avoid appending duplicated token. Tokens that include "n" like multiline
+ # tstring_content can exist in multiple lines.
tokens_until_line << token if token != tokens_until_line.last
end
continue = @scanner.should_continue?(tokens_until_line)
@@ -697,60 +1242,75 @@ module IRB
end
def handle_exception(exc)
- if exc.backtrace && exc.backtrace[0] =~ /\/irb(2)?(\/.*|-.*|\.rb)?:/ && exc.class.to_s !~ /^IRB/ &&
+ if exc.backtrace[0] =~ /\/irb(2)?(\/.*|-.*|\.rb)?:/ && exc.class.to_s !~ /^IRB/ &&
!(SyntaxError === exc) && !(EncodingError === exc)
# The backtrace of invalid encoding hash (ex. {"\xAE": 1}) raises EncodingError without lineno.
irb_bug = true
else
irb_bug = false
+ # To support backtrace filtering while utilizing Exception#full_message, we need to clone
+ # the exception to avoid modifying the original exception's backtrace.
+ exc = exc.clone
+ filtered_backtrace = exc.backtrace.map { |l| @context.workspace.filter_backtrace(l) }.compact
+ backtrace_filter = IRB.conf[:BACKTRACE_FILTER]
+
+ if backtrace_filter
+ if backtrace_filter.respond_to?(:call)
+ filtered_backtrace = backtrace_filter.call(filtered_backtrace)
+ else
+ warn "IRB.conf[:BACKTRACE_FILTER] #{backtrace_filter} should respond to `call` method"
+ end
+ end
+
+ exc.set_backtrace(filtered_backtrace)
end
- if exc.backtrace
- order = nil
+ highlight = Color.colorable?
+
+ order =
if RUBY_VERSION < '3.0.0'
- if STDOUT.tty?
- message = exc.full_message(order: :bottom)
- order = :bottom
- else
- message = exc.full_message(order: :top)
- order = :top
- end
+ STDOUT.tty? ? :bottom : :top
else # '3.0.0' <= RUBY_VERSION
- message = exc.full_message(order: :top)
- order = :top
+ :top
end
- message = convert_invalid_byte_sequence(message, exc.message.encoding)
- message = encode_with_invalid_byte_sequence(message, IRB.conf[:LC_MESSAGES].encoding) unless message.encoding.to_s.casecmp?(IRB.conf[:LC_MESSAGES].encoding.to_s)
- message = message.gsub(/((?:^\t.+$\n)+)/) { |m|
- case order
- when :top
- lines = m.split("\n")
- when :bottom
- lines = m.split("\n").reverse
- end
- unless irb_bug
- lines = lines.map { |l| @context.workspace.filter_backtrace(l) }.compact
- if lines.size > @context.back_trace_limit
- omit = lines.size - @context.back_trace_limit
- lines = lines[0..(@context.back_trace_limit - 1)]
- lines << "\t... %d levels..." % omit
- end
+
+ message = exc.full_message(order: order, highlight: highlight)
+ message = convert_invalid_byte_sequence(message, exc.message.encoding)
+ message = encode_with_invalid_byte_sequence(message, IRB.conf[:LC_MESSAGES].encoding) unless message.encoding.to_s.casecmp?(IRB.conf[:LC_MESSAGES].encoding.to_s)
+ message = message.gsub(/((?:^\t.+$\n)+)/) { |m|
+ case order
+ when :top
+ lines = m.split("\n")
+ when :bottom
+ lines = m.split("\n").reverse
+ end
+ unless irb_bug
+ if lines.size > @context.back_trace_limit
+ omit = lines.size - @context.back_trace_limit
+ lines = lines[0..(@context.back_trace_limit - 1)]
+ lines << "\t... %d levels..." % omit
end
- lines = lines.reverse if order == :bottom
- lines.map{ |l| l + "\n" }.join
- }
- # The "<top (required)>" in "(irb)" may be the top level of IRB so imitate the main object.
- message = message.gsub(/\(irb\):(?<num>\d+):in `<(?<frame>top \(required\))>'/) { "(irb):#{$~[:num]}:in `<main>'" }
- puts message
+ end
+ lines = lines.reverse if order == :bottom
+ lines.map{ |l| l + "\n" }.join
+ }
+ # The "<top (required)>" in "(irb)" may be the top level of IRB so imitate the main object.
+ message = message.gsub(/\(irb\):(?<num>\d+):in (?<open_quote>[`'])<(?<frame>top \(required\))>'/) { "(irb):#{$~[:num]}:in #{$~[:open_quote]}<main>'" }
+ puts message
+ puts 'Maybe IRB bug!' if irb_bug
+ rescue Exception => handler_exc
+ begin
+ puts exc.inspect
+ puts "backtraces are hidden because #{handler_exc} was raised when processing them"
+ rescue Exception
+ puts 'Uninspectable exception occurred'
end
- print "Maybe IRB bug!\n" if irb_bug
end
- # Evaluates the given block using the given +path+ as the Context#irb_path
- # and +name+ as the Context#irb_name.
+ # Evaluates the given block using the given `path` as the Context#irb_path and
+ # `name` as the Context#irb_name.
#
- # Used by the irb command +source+, see IRB@IRB+Sessions for more
- # information.
+ # Used by the irb command `source`, see IRB@IRB+Sessions for more information.
def suspend_name(path = nil, name = nil)
@context.irb_path, back_path = path, @context.irb_path if path
@context.irb_name, back_name = name, @context.irb_name if name
@@ -762,25 +1322,22 @@ module IRB
end
end
- # Evaluates the given block using the given +workspace+ as the
+ # Evaluates the given block using the given `workspace` as the
# Context#workspace.
#
- # Used by the irb command +irb_load+, see IRB@IRB+Sessions for more
- # information.
+ # Used by the irb command `irb_load`, see IRB@IRB+Sessions for more information.
def suspend_workspace(workspace)
- @context.workspace, back_workspace = workspace, @context.workspace
- begin
- yield back_workspace
- ensure
- @context.workspace = back_workspace
- end
+ current_workspace = @context.workspace
+ @context.replace_workspace(workspace)
+ yield
+ ensure
+ @context.replace_workspace current_workspace
end
- # Evaluates the given block using the given +input_method+ as the
- # Context#io.
+ # Evaluates the given block using the given `input_method` as the Context#io.
#
- # Used by the irb commands +source+ and +irb_load+, see IRB@IRB+Sessions
- # for more information.
+ # Used by the irb commands `source` and `irb_load`, see IRB@IRB+Sessions for
+ # more information.
def suspend_input_method(input_method)
back_io = @context.io
@context.instance_eval{@io = input_method}
@@ -813,7 +1370,7 @@ module IRB
end
end
- # Evaluates the given block using the given +status+.
+ # Evaluates the given block using the given `status`.
def signal_status(status)
return yield if @signal_status == :IN_LOAD
@@ -855,15 +1412,16 @@ module IRB
end
end
end
+
if multiline_p && @context.newline_before_multiline_output?
- printf @context.return_format, "\n#{str}"
- else
- printf @context.return_format, str
+ str = "\n" + str
end
+
+ Pager.page_content(format(@context.return_format, str), retain_content: true)
end
- # Outputs the local variables to this current session, including
- # #signal_status and #context, using IRB::Locale.
+ # Outputs the local variables to this current session, including #signal_status
+ # and #context, using IRB::Locale.
def inspect
ary = []
for iv in instance_variables
@@ -921,14 +1479,16 @@ module IRB
end
def format_prompt(format, ltype, indent, line_no) # :nodoc:
- format.gsub(/%([0-9]+)?([a-zA-Z])/) do
+ format.gsub(/%([0-9]+)?([a-zA-Z%])/) do
case $2
when "N"
@context.irb_name
when "m"
- truncate_prompt_main(@context.main.to_s)
+ main_str = @context.main.to_s rescue "!#{$!.class}"
+ truncate_prompt_main(main_str)
when "M"
- truncate_prompt_main(@context.main.inspect)
+ main_str = @context.main.inspect rescue "!#{$!.class}"
+ truncate_prompt_main(main_str)
when "l"
ltype
when "i"
@@ -952,7 +1512,7 @@ module IRB
line_no.to_s
end
when "%"
- "%"
+ "%" unless $1
end
end
end
@@ -960,12 +1520,11 @@ module IRB
end
class Binding
- # Opens an IRB session where +binding.irb+ is called which allows for
- # interactive debugging. You can call any methods or variables available in
- # the current scope, and mutate state if you need to.
+ # Opens an IRB session where `binding.irb` is called which allows for
+ # interactive debugging. You can call any methods or variables available in the
+ # current scope, and mutate state if you need to.
#
- #
- # Given a Ruby file called +potato.rb+ containing the following code:
+ # Given a Ruby file called `potato.rb` containing the following code:
#
# class Potato
# def initialize
@@ -977,8 +1536,8 @@ class Binding
#
# Potato.new
#
- # Running <code>ruby potato.rb</code> will open an IRB session where
- # +binding.irb+ is called, and you will see the following:
+ # Running `ruby potato.rb` will open an IRB session where `binding.irb` is
+ # called, and you will see the following:
#
# $ ruby potato.rb
#
@@ -1008,18 +1567,17 @@ class Binding
# irb(#<Potato:0x00007feea1916670>):004:0> @cooked = true
# => true
#
- # You can exit the IRB session with the +exit+ command. Note that exiting will
- # resume execution where +binding.irb+ had paused it, as you can see from the
+ # You can exit the IRB session with the `exit` command. Note that exiting will
+ # resume execution where `binding.irb` had paused it, as you can see from the
# output printed to standard output in this example:
#
# irb(#<Potato:0x00007feea1916670>):005:0> exit
# Cooked potato: true
#
- #
- # See IRB@Usage for more information.
+ # See IRB for more information.
def irb(show_code: true)
# Setup IRB with the current file's path and no command line arguments
- IRB.setup(source_location[0], argv: [])
+ IRB.setup(source_location[0], argv: []) unless IRB.initialized?
# Create a new workspace using the current binding
workspace = IRB::WorkSpace.new(self)
# Print the code around the binding if show_code is true
@@ -1031,16 +1589,17 @@ class Binding
if debugger_irb
# If we're already in a debugger session, set the workspace and irb_path for the original IRB instance
- debugger_irb.context.workspace = workspace
+ debugger_irb.context.replace_workspace(workspace)
debugger_irb.context.irb_path = irb_path
- # If we've started a debugger session and hit another binding.irb, we don't want to start an IRB session
- # instead, we want to resume the irb:rdbg session.
+ # If we've started a debugger session and hit another binding.irb, we don't want
+ # to start an IRB session instead, we want to resume the irb:rdbg session.
IRB::Debug.setup(debugger_irb)
IRB::Debug.insert_debug_break
debugger_irb.debug_break
else
- # If we're not in a debugger session, create a new IRB instance with the current workspace
- binding_irb = IRB::Irb.new(workspace)
+ # If we're not in a debugger session, create a new IRB instance with the current
+ # workspace
+ binding_irb = IRB::Irb.new(workspace, from_binding: true)
binding_irb.context.irb_path = irb_path
binding_irb.run(IRB.conf)
binding_irb.debug_break
diff --git a/lib/irb/cmd/backtrace.rb b/lib/irb/cmd/backtrace.rb
deleted file mode 100644
index f632894618..0000000000
--- a/lib/irb/cmd/backtrace.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Backtrace < DebugCommand
- def self.transform_args(args)
- args&.dump
- end
-
- def execute(*args)
- super(pre_cmds: ["backtrace", *args].join(" "))
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/break.rb b/lib/irb/cmd/break.rb
deleted file mode 100644
index df259a90ca..0000000000
--- a/lib/irb/cmd/break.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Break < DebugCommand
- def self.transform_args(args)
- args&.dump
- end
-
- def execute(args = nil)
- super(pre_cmds: "break #{args}")
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/catch.rb b/lib/irb/cmd/catch.rb
deleted file mode 100644
index 40b62c7533..0000000000
--- a/lib/irb/cmd/catch.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Catch < DebugCommand
- def self.transform_args(args)
- args&.dump
- end
-
- def execute(*args)
- super(pre_cmds: ["catch", *args].join(" "))
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/chws.rb b/lib/irb/cmd/chws.rb
deleted file mode 100644
index 31045f9bbb..0000000000
--- a/lib/irb/cmd/chws.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: false
-#
-# change-ws.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-require_relative "nop"
-require_relative "../ext/change-ws"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
-
- class CurrentWorkingWorkspace < Nop
- category "Workspace"
- description "Show the current workspace."
-
- def execute(*obj)
- irb_context.main
- end
- end
-
- class ChangeWorkspace < Nop
- category "Workspace"
- description "Change the current workspace to an object."
-
- def execute(*obj)
- irb_context.change_workspace(*obj)
- irb_context.main
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/continue.rb b/lib/irb/cmd/continue.rb
deleted file mode 100644
index 9136177eef..0000000000
--- a/lib/irb/cmd/continue.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Continue < DebugCommand
- def execute(*args)
- super(do_cmds: ["continue", *args].join(" "))
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/debug.rb b/lib/irb/cmd/debug.rb
deleted file mode 100644
index 9eca964218..0000000000
--- a/lib/irb/cmd/debug.rb
+++ /dev/null
@@ -1,80 +0,0 @@
-require_relative "nop"
-require_relative "../debug"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Debug < Nop
- category "Debugging"
- description "Start the debugger of debug.gem."
-
- BINDING_IRB_FRAME_REGEXPS = [
- '<internal:prelude>',
- binding.method(:irb).source_location.first,
- ].map { |file| /\A#{Regexp.escape(file)}:\d+:in `irb'\z/ }
-
- def execute(pre_cmds: nil, do_cmds: nil)
- if irb_context.with_debugger
- # If IRB is already running with a debug session, throw the command and IRB.debug_readline will pass it to the debugger.
- if cmd = pre_cmds || do_cmds
- throw :IRB_EXIT, cmd
- else
- puts "IRB is already running with a debug session."
- return
- end
- else
- # If IRB is not running with a debug session yet, then:
- # 1. Check if the debugging command is run from a `binding.irb` call.
- # 2. If so, try setting up the debug gem.
- # 3. Insert a debug breakpoint at `Irb#debug_break` with the intended command.
- # 4. Exit the current Irb#run call via `throw :IRB_EXIT`.
- # 5. `Irb#debug_break` will be called and trigger the breakpoint, which will run the intended command.
- unless binding_irb?
- puts "`debug` command is only available when IRB is started with binding.irb"
- return
- end
-
- if IRB.respond_to?(:JobManager)
- warn "Can't start the debugger when IRB is running in a multi-IRB session."
- return
- end
-
- unless IRB::Debug.setup(irb_context.irb)
- puts <<~MSG
- You need to install the debug gem before using this command.
- If you use `bundle exec`, please add `gem "debug"` into your Gemfile.
- MSG
- return
- end
-
- IRB::Debug.insert_debug_break(pre_cmds: pre_cmds, do_cmds: do_cmds)
-
- # exit current Irb#run call
- throw :IRB_EXIT
- end
- end
-
- private
-
- def binding_irb?
- caller.any? do |frame|
- BINDING_IRB_FRAME_REGEXPS.any? do |regexp|
- frame.match?(regexp)
- end
- end
- end
- end
-
- class DebugCommand < Debug
- def self.category
- "Debugging"
- end
-
- def self.description
- command_name = self.name.split("::").last.downcase
- "Start the debugger of debug.gem and run its `#{command_name}` command."
- end
- end
- end
-end
diff --git a/lib/irb/cmd/delete.rb b/lib/irb/cmd/delete.rb
deleted file mode 100644
index aeb26d2572..0000000000
--- a/lib/irb/cmd/delete.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Delete < DebugCommand
- def execute(*args)
- super(pre_cmds: ["delete", *args].join(" "))
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/edit.rb b/lib/irb/cmd/edit.rb
deleted file mode 100644
index 69606beea0..0000000000
--- a/lib/irb/cmd/edit.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-require 'shellwords'
-require_relative "nop"
-require_relative "../source_finder"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Edit < Nop
- category "Misc"
- description 'Open a file with the editor command defined with `ENV["VISUAL"]` or `ENV["EDITOR"]`.'
-
- class << self
- def transform_args(args)
- # Return a string literal as is for backward compatibility
- if args.nil? || args.empty? || string_literal?(args)
- args
- else # Otherwise, consider the input as a String for convenience
- args.strip.dump
- end
- end
- end
-
- def execute(*args)
- path = args.first
-
- if path.nil? && (irb_path = @irb_context.irb_path)
- path = irb_path
- end
-
- if !File.exist?(path)
- source =
- begin
- SourceFinder.new(@irb_context).find_source(path)
- rescue NameError
- # if user enters a path that doesn't exist, it'll cause NameError when passed here because find_source would try to evaluate it as well
- # in this case, we should just ignore the error
- end
-
- if source
- path = source.file
- else
- puts "Can not find file: #{path}"
- return
- end
- end
-
- if editor = (ENV['VISUAL'] || ENV['EDITOR'])
- puts "command: '#{editor}'"
- puts " path: #{path}"
- system(*Shellwords.split(editor), path)
- else
- puts "Can not find editor setting: ENV['VISUAL'] or ENV['EDITOR']"
- end
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/finish.rb b/lib/irb/cmd/finish.rb
deleted file mode 100644
index 29f100feb5..0000000000
--- a/lib/irb/cmd/finish.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Finish < DebugCommand
- def execute(*args)
- super(do_cmds: ["finish", *args].join(" "))
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/help.rb b/lib/irb/cmd/help.rb
deleted file mode 100644
index 64b885c383..0000000000
--- a/lib/irb/cmd/help.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "show_doc"
-
-module IRB
- module ExtendCommand
- class Help < ShowDoc
- category "Context"
- description "[DEPRECATED] Enter the mode to look up RI documents."
-
- DEPRECATION_MESSAGE = <<~MSG
- [Deprecation] The `help` command will be repurposed to display command help in the future.
- For RI document lookup, please use the `show_doc` command instead.
- For command help, please use `show_cmds` for now.
- MSG
-
- def execute(*names)
- warn DEPRECATION_MESSAGE
- super
- end
- end
- end
-end
diff --git a/lib/irb/cmd/info.rb b/lib/irb/cmd/info.rb
deleted file mode 100644
index 2c0a32b34f..0000000000
--- a/lib/irb/cmd/info.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Info < DebugCommand
- def self.transform_args(args)
- args&.dump
- end
-
- def execute(*args)
- super(pre_cmds: ["info", *args].join(" "))
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/irb_info.rb b/lib/irb/cmd/irb_info.rb
deleted file mode 100644
index 5b905a09bd..0000000000
--- a/lib/irb/cmd/irb_info.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: false
-
-require_relative "nop"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class IrbInfo < Nop
- category "IRB"
- description "Show information about IRB."
-
- def execute
- str = "Ruby version: #{RUBY_VERSION}\n"
- str += "IRB version: #{IRB.version}\n"
- str += "InputMethod: #{IRB.CurrentContext.io.inspect}\n"
- str += "Completion: #{IRB.CurrentContext.io.respond_to?(:completion_info) ? IRB.CurrentContext.io.completion_info : 'off'}\n"
- str += ".irbrc path: #{IRB.rc_file}\n" if File.exist?(IRB.rc_file)
- str += "RUBY_PLATFORM: #{RUBY_PLATFORM}\n"
- str += "LANG env: #{ENV["LANG"]}\n" if ENV["LANG"] && !ENV["LANG"].empty?
- str += "LC_ALL env: #{ENV["LC_ALL"]}\n" if ENV["LC_ALL"] && !ENV["LC_ALL"].empty?
- str += "East Asian Ambiguous Width: #{Reline.ambiguous_width.inspect}\n"
- if RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/
- codepage = `chcp`.b.sub(/.*: (\d+)\n/, '\1')
- str += "Code page: #{codepage}\n"
- end
- puts str
- nil
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/load.rb b/lib/irb/cmd/load.rb
deleted file mode 100644
index a3e797a7e0..0000000000
--- a/lib/irb/cmd/load.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-# frozen_string_literal: false
-#
-# load.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-require_relative "nop"
-require_relative "../ext/loader"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class LoaderCommand < Nop
- include IrbLoader
-
- def raise_cmd_argument_error
- raise CommandArgumentError.new("Please specify the file name.")
- end
- end
-
- class Load < LoaderCommand
- category "IRB"
- description "Load a Ruby file."
-
- def execute(file_name = nil, priv = nil)
- raise_cmd_argument_error unless file_name
- irb_load(file_name, priv)
- end
- end
-
- class Require < LoaderCommand
- category "IRB"
- description "Require a Ruby file."
- def execute(file_name = nil)
- raise_cmd_argument_error unless file_name
-
- rex = Regexp.new("#{Regexp.quote(file_name)}(\.o|\.rb)?")
- return false if $".find{|f| f =~ rex}
-
- case file_name
- when /\.rb$/
- begin
- if irb_load(file_name)
- $".push file_name
- return true
- end
- rescue LoadError
- end
- when /\.(so|o|sl)$/
- return ruby_require(file_name)
- end
-
- begin
- irb_load(f = file_name + ".rb")
- $".push f
- return true
- rescue LoadError
- return ruby_require(file_name)
- end
- end
- end
-
- class Source < LoaderCommand
- category "IRB"
- description "Loads a given file in the current session."
-
- def execute(file_name = nil)
- raise_cmd_argument_error unless file_name
-
- source_file(file_name)
- end
- end
- end
- # :startdoc:
-end
diff --git a/lib/irb/cmd/ls.rb b/lib/irb/cmd/ls.rb
deleted file mode 100644
index 791b1c1b21..0000000000
--- a/lib/irb/cmd/ls.rb
+++ /dev/null
@@ -1,139 +0,0 @@
-# frozen_string_literal: true
-
-require "reline"
-require "stringio"
-require_relative "nop"
-require_relative "../pager"
-require_relative "../color"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Ls < Nop
- category "Context"
- description "Show methods, constants, and variables. `-g [query]` or `-G [query]` allows you to filter out the output."
-
- def self.transform_args(args)
- if match = args&.match(/\A(?<args>.+\s|)(-g|-G)\s+(?<grep>[^\s]+)\s*\n\z/)
- args = match[:args]
- "#{args}#{',' unless args.chomp.empty?} grep: /#{match[:grep]}/"
- else
- args
- end
- end
-
- def execute(*arg, grep: nil)
- o = Output.new(grep: grep)
-
- obj = arg.empty? ? irb_context.workspace.main : arg.first
- locals = arg.empty? ? irb_context.workspace.binding.local_variables : []
- klass = (obj.class == Class || obj.class == Module ? obj : obj.class)
-
- o.dump("constants", obj.constants) if obj.respond_to?(:constants)
- dump_methods(o, klass, obj)
- o.dump("instance variables", obj.instance_variables)
- o.dump("class variables", klass.class_variables)
- o.dump("locals", locals)
- o.print_result
- end
-
- def dump_methods(o, klass, obj)
- singleton_class = begin obj.singleton_class; rescue TypeError; nil end
- dumped_mods = Array.new
- ancestors = klass.ancestors
- ancestors = ancestors.reject { |c| c >= Object } if klass < Object
- singleton_ancestors = (singleton_class&.ancestors || []).reject { |c| c >= Class }
-
- # singleton_class' ancestors should be at the front
- maps = class_method_map(singleton_ancestors, dumped_mods) + class_method_map(ancestors, dumped_mods)
- maps.each do |mod, methods|
- name = mod == singleton_class ? "#{klass}.methods" : "#{mod}#methods"
- o.dump(name, methods)
- end
- end
-
- def class_method_map(classes, dumped_mods)
- dumped_methods = Array.new
- classes.map do |mod|
- next if dumped_mods.include? mod
-
- dumped_mods << mod
-
- methods = mod.public_instance_methods(false).select do |method|
- if dumped_methods.include? method
- false
- else
- dumped_methods << method
- true
- end
- end
-
- [mod, methods]
- end.compact
- end
-
- class Output
- MARGIN = " "
-
- def initialize(grep: nil)
- @grep = grep
- @line_width = screen_width - MARGIN.length # right padding
- @io = StringIO.new
- end
-
- def print_result
- Pager.page_content(@io.string)
- end
-
- def dump(name, strs)
- strs = strs.grep(@grep) if @grep
- strs = strs.sort
- return if strs.empty?
-
- # Attempt a single line
- @io.print "#{Color.colorize(name, [:BOLD, :BLUE])}: "
- if fits_on_line?(strs, cols: strs.size, offset: "#{name}: ".length)
- @io.puts strs.join(MARGIN)
- return
- end
- @io.puts
-
- # Dump with the largest # of columns that fits on a line
- cols = strs.size
- until fits_on_line?(strs, cols: cols, offset: MARGIN.length) || cols == 1
- cols -= 1
- end
- widths = col_widths(strs, cols: cols)
- strs.each_slice(cols) do |ss|
- @io.puts ss.map.with_index { |s, i| "#{MARGIN}%-#{widths[i]}s" % s }.join
- end
- end
-
- private
-
- def fits_on_line?(strs, cols:, offset: 0)
- width = col_widths(strs, cols: cols).sum + MARGIN.length * (cols - 1)
- width <= @line_width - offset
- end
-
- def col_widths(strs, cols:)
- cols.times.map do |col|
- (col...strs.size).step(cols).map do |i|
- strs[i].length
- end.max
- end
- end
-
- def screen_width
- Reline.get_screen_size.last
- rescue Errno::EINVAL # in `winsize': Invalid argument - <STDIN>
- 80
- end
- end
- private_constant :Output
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/measure.rb b/lib/irb/cmd/measure.rb
deleted file mode 100644
index 9122e2dac9..0000000000
--- a/lib/irb/cmd/measure.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-require_relative "nop"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Measure < Nop
- category "Misc"
- description "`measure` enables the mode to measure processing time. `measure :off` disables it."
-
- def initialize(*args)
- super(*args)
- end
-
- def execute(type = nil, arg = nil, &block)
- # Please check IRB.init_config in lib/irb/init.rb that sets
- # IRB.conf[:MEASURE_PROC] to register default "measure" methods,
- # "measure :time" (abbreviated as "measure") and "measure :stackprof".
- case type
- when :off
- IRB.conf[:MEASURE] = nil
- IRB.unset_measure_callback(arg)
- when :list
- IRB.conf[:MEASURE_CALLBACKS].each do |type_name, _, arg_val|
- puts "- #{type_name}" + (arg_val ? "(#{arg_val.inspect})" : '')
- end
- when :on
- IRB.conf[:MEASURE] = true
- added = IRB.set_measure_callback(type, arg)
- puts "#{added[0]} is added." if added
- else
- if block_given?
- IRB.conf[:MEASURE] = true
- added = IRB.set_measure_callback(&block)
- puts "#{added[0]} is added." if added
- else
- IRB.conf[:MEASURE] = true
- added = IRB.set_measure_callback(type, arg)
- puts "#{added[0]} is added." if added
- end
- end
- nil
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/next.rb b/lib/irb/cmd/next.rb
deleted file mode 100644
index d29c82e7fc..0000000000
--- a/lib/irb/cmd/next.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Next < DebugCommand
- def execute(*args)
- super(do_cmds: ["next", *args].join(" "))
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/nop.rb b/lib/irb/cmd/nop.rb
index 7fb197c51f..9d2e3c4d47 100644
--- a/lib/irb/cmd/nop.rb
+++ b/lib/irb/cmd/nop.rb
@@ -1,53 +1,4 @@
-# frozen_string_literal: false
-#
-# nop.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
+# frozen_string_literal: true
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class CommandArgumentError < StandardError; end
-
- class Nop
- class << self
- def category(category = nil)
- @category = category if category
- @category
- end
-
- def description(description = nil)
- @description = description if description
- @description
- end
-
- private
-
- def string_literal?(args)
- sexp = Ripper.sexp(args)
- sexp && sexp.size == 2 && sexp.last&.first&.first == :string_literal
- end
- end
-
- def self.execute(irb_context, *opts, **kwargs, &block)
- command = new(irb_context)
- command.execute(*opts, **kwargs, &block)
- rescue CommandArgumentError => e
- puts e.message
- end
-
- def initialize(irb_context)
- @irb_context = irb_context
- end
-
- attr_reader :irb_context
-
- def execute(*opts)
- #nop
- end
- end
- end
-
- # :startdoc:
-end
+# This file is just a placeholder for backward-compatibility.
+# Please require 'irb' and inherit your command from `IRB::Command::Base` instead.
diff --git a/lib/irb/cmd/pushws.rb b/lib/irb/cmd/pushws.rb
deleted file mode 100644
index 59996ceb0c..0000000000
--- a/lib/irb/cmd/pushws.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: false
-#
-# change-ws.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-require_relative "nop"
-require_relative "../ext/workspaces"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Workspaces < Nop
- category "Workspace"
- description "Show workspaces."
-
- def execute(*obj)
- irb_context.workspaces.collect{|ws| ws.main}
- end
- end
-
- class PushWorkspace < Workspaces
- category "Workspace"
- description "Push an object to the workspace stack."
-
- def execute(*obj)
- irb_context.push_workspace(*obj)
- super
- end
- end
-
- class PopWorkspace < Workspaces
- category "Workspace"
- description "Pop a workspace from the workspace stack."
-
- def execute(*obj)
- irb_context.pop_workspace(*obj)
- super
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/show_cmds.rb b/lib/irb/cmd/show_cmds.rb
deleted file mode 100644
index 7d6b3ec266..0000000000
--- a/lib/irb/cmd/show_cmds.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-
-require "stringio"
-require_relative "nop"
-require_relative "../pager"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class ShowCmds < Nop
- category "IRB"
- description "List all available commands and their description."
-
- def execute(*args)
- commands_info = IRB::ExtendCommandBundle.all_commands_info
- commands_grouped_by_categories = commands_info.group_by { |cmd| cmd[:category] }
-
- if irb_context.with_debugger
- # Remove the original "Debugging" category
- commands_grouped_by_categories.delete("Debugging")
- # Remove the `help` command as it's delegated to the debugger
- commands_grouped_by_categories["Context"].delete_if { |cmd| cmd[:display_name] == :help }
- # Add an empty "Debugging (from debug.gem)" category at the end
- commands_grouped_by_categories["Debugging (from debug.gem)"] = []
- end
-
- longest_cmd_name_length = commands_info.map { |c| c[:display_name].length }.max
-
- output = StringIO.new
-
- commands_grouped_by_categories.each do |category, cmds|
- output.puts Color.colorize(category, [:BOLD])
-
- cmds.each do |cmd|
- output.puts " #{cmd[:display_name].to_s.ljust(longest_cmd_name_length)} #{cmd[:description]}"
- end
-
- output.puts
- end
-
- # Append the debugger help at the end
- if irb_context.with_debugger
- output.puts DEBUGGER__.help
- end
-
- Pager.page_content(output.string)
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/show_doc.rb b/lib/irb/cmd/show_doc.rb
deleted file mode 100644
index 99dd9ab95a..0000000000
--- a/lib/irb/cmd/show_doc.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "nop"
-
-module IRB
- module ExtendCommand
- class ShowDoc < Nop
- class << self
- def transform_args(args)
- # Return a string literal as is for backward compatibility
- if args.empty? || string_literal?(args)
- args
- else # Otherwise, consider the input as a String for convenience
- args.strip.dump
- end
- end
- end
-
- category "Context"
- description "Enter the mode to look up RI documents."
-
- def execute(*names)
- require 'rdoc/ri/driver'
-
- unless ShowDoc.const_defined?(:Ri)
- opts = RDoc::RI::Driver.process_args([])
- ShowDoc.const_set(:Ri, RDoc::RI::Driver.new(opts))
- end
-
- if names.empty?
- Ri.interactive
- else
- names.each do |name|
- begin
- Ri.display_name(name.to_s)
- rescue RDoc::RI::Error
- puts $!.message
- end
- end
- end
-
- nil
- rescue LoadError, SystemExit
- warn "Can't display document because `rdoc` is not installed."
- end
- end
- end
-end
diff --git a/lib/irb/cmd/show_source.rb b/lib/irb/cmd/show_source.rb
deleted file mode 100644
index 49cab43fab..0000000000
--- a/lib/irb/cmd/show_source.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "nop"
-require_relative "../source_finder"
-require_relative "../pager"
-require_relative "../color"
-
-module IRB
- module ExtendCommand
- class ShowSource < Nop
- category "Context"
- description "Show the source code of a given method or constant."
-
- class << self
- def transform_args(args)
- # Return a string literal as is for backward compatibility
- if args.empty? || string_literal?(args)
- args
- else # Otherwise, consider the input as a String for convenience
- args.strip.dump
- end
- end
- end
-
- def execute(str = nil)
- unless str.is_a?(String)
- puts "Error: Expected a string but got #{str.inspect}"
- return
- end
-
- source = SourceFinder.new(@irb_context).find_source(str)
-
- if source
- show_source(source)
- else
- puts "Error: Couldn't locate a definition for #{str}"
- end
- nil
- end
-
- private
-
- def show_source(source)
- file_content = IRB::Color.colorize_code(File.read(source.file))
- code = file_content.lines[(source.first_line - 1)...source.last_line].join
- content = <<~CONTENT
-
- #{bold("From")}: #{source.file}:#{source.first_line}
-
- #{code}
- CONTENT
-
- Pager.page_content(content)
- end
-
- def bold(str)
- Color.colorize(str, [:BOLD])
- end
- end
- end
-end
diff --git a/lib/irb/cmd/step.rb b/lib/irb/cmd/step.rb
deleted file mode 100644
index 2bc74a9d79..0000000000
--- a/lib/irb/cmd/step.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Step < DebugCommand
- def execute(*args)
- super(do_cmds: ["step", *args].join(" "))
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/subirb.rb b/lib/irb/cmd/subirb.rb
deleted file mode 100644
index 5ffd646416..0000000000
--- a/lib/irb/cmd/subirb.rb
+++ /dev/null
@@ -1,109 +0,0 @@
-# frozen_string_literal: false
-#
-# multi.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-require_relative "nop"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class MultiIRBCommand < Nop
- def execute(*args)
- extend_irb_context
- end
-
- private
-
- def print_deprecated_warning
- warn <<~MSG
- Multi-irb commands are deprecated and will be removed in IRB 2.0.0. Please use workspace commands instead.
- If you have any use case for multi-irb, please leave a comment at https://github.com/ruby/irb/issues/653
- MSG
- end
-
- def extend_irb_context
- # this extension patches IRB context like IRB.CurrentContext
- require_relative "../ext/multi-irb"
- end
-
- def print_debugger_warning
- warn "Multi-IRB commands are not available when the debugger is enabled."
- end
- end
-
- class IrbCommand < MultiIRBCommand
- category "Multi-irb (DEPRECATED)"
- description "Start a child IRB."
-
- def execute(*obj)
- print_deprecated_warning
-
- if irb_context.with_debugger
- print_debugger_warning
- return
- end
-
- super
- IRB.irb(nil, *obj)
- end
- end
-
- class Jobs < MultiIRBCommand
- category "Multi-irb (DEPRECATED)"
- description "List of current sessions."
-
- def execute
- print_deprecated_warning
-
- if irb_context.with_debugger
- print_debugger_warning
- return
- end
-
- super
- IRB.JobManager
- end
- end
-
- class Foreground < MultiIRBCommand
- category "Multi-irb (DEPRECATED)"
- description "Switches to the session of the given number."
-
- def execute(key = nil)
- print_deprecated_warning
-
- if irb_context.with_debugger
- print_debugger_warning
- return
- end
-
- super
-
- raise CommandArgumentError.new("Please specify the id of target IRB job (listed in the `jobs` command).") unless key
- IRB.JobManager.switch(key)
- end
- end
-
- class Kill < MultiIRBCommand
- category "Multi-irb (DEPRECATED)"
- description "Kills the session with the given number."
-
- def execute(*keys)
- print_deprecated_warning
-
- if irb_context.with_debugger
- print_debugger_warning
- return
- end
-
- super
- IRB.JobManager.kill(*keys)
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/cmd/whereami.rb b/lib/irb/cmd/whereami.rb
deleted file mode 100644
index 8f56ba073d..0000000000
--- a/lib/irb/cmd/whereami.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "nop"
-
-module IRB
- # :stopdoc:
-
- module ExtendCommand
- class Whereami < Nop
- category "Context"
- description "Show the source code around binding.irb again."
-
- def execute(*)
- code = irb_context.workspace.code_around_binding
- if code
- puts code
- else
- puts "The current context doesn't have code."
- end
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/color.rb b/lib/irb/color.rb
index ad8670160c..fca942b28b 100644
--- a/lib/irb/color.rb
+++ b/lib/irb/color.rb
@@ -79,12 +79,12 @@ module IRB # :nodoc:
class << self
def colorable?
- supported = $stdout.tty? && (/mswin|mingw/ =~ RUBY_PLATFORM || (ENV.key?('TERM') && ENV['TERM'] != 'dumb'))
+ supported = $stdout.tty? && (/mswin|mingw/.match?(RUBY_PLATFORM) || (ENV.key?('TERM') && ENV['TERM'] != 'dumb'))
# because ruby/debug also uses irb's color module selectively,
# irb won't be activated in that case.
if IRB.respond_to?(:conf)
- supported && IRB.conf.fetch(:USE_COLORIZE, true)
+ supported && !!IRB.conf.fetch(:USE_COLORIZE, true)
else
supported
end
diff --git a/lib/irb/command.rb b/lib/irb/command.rb
new file mode 100644
index 0000000000..68a4b52727
--- /dev/null
+++ b/lib/irb/command.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+#
+# irb/command.rb - irb command
+# by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+
+require_relative "command/base"
+
+module IRB # :nodoc:
+ module Command
+ @commands = {}
+
+ class << self
+ attr_reader :commands
+
+ # Registers a command with the given name.
+ # Aliasing is intentionally not supported at the moment.
+ def register(name, command_class)
+ @commands[name.to_sym] = [command_class, []]
+ end
+ end
+ end
+end
diff --git a/lib/irb/command/backtrace.rb b/lib/irb/command/backtrace.rb
new file mode 100644
index 0000000000..687bb075ac
--- /dev/null
+++ b/lib/irb/command/backtrace.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require_relative "debug"
+
+module IRB
+ # :stopdoc:
+
+ module Command
+ class Backtrace < DebugCommand
+ def execute(arg)
+ execute_debug_command(pre_cmds: "backtrace #{arg}")
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/command/base.rb b/lib/irb/command/base.rb
new file mode 100644
index 0000000000..1d406630a2
--- /dev/null
+++ b/lib/irb/command/base.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+#
+# nop.rb -
+# by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+
+module IRB
+ # :stopdoc:
+
+ module Command
+ class CommandArgumentError < StandardError; end
+
+ def self.extract_ruby_args(*args, **kwargs)
+ throw :EXTRACT_RUBY_ARGS, [args, kwargs]
+ end
+
+ class Base
+ class << self
+ def category(category = nil)
+ @category = category if category
+ @category || "No category"
+ end
+
+ def description(description = nil)
+ @description = description if description
+ @description || "No description provided."
+ end
+
+ def help_message(help_message = nil)
+ @help_message = help_message if help_message
+ @help_message
+ end
+
+ private
+
+ def highlight(text)
+ Color.colorize(text, [:BOLD, :BLUE])
+ end
+ end
+
+ def self.execute(irb_context, arg)
+ new(irb_context).execute(arg)
+ rescue CommandArgumentError => e
+ puts e.message
+ end
+
+ def initialize(irb_context)
+ @irb_context = irb_context
+ end
+
+ attr_reader :irb_context
+
+ def execute(arg)
+ #nop
+ end
+ end
+
+ Nop = Base
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/command/break.rb b/lib/irb/command/break.rb
new file mode 100644
index 0000000000..a8f81fe665
--- /dev/null
+++ b/lib/irb/command/break.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require_relative "debug"
+
+module IRB
+ # :stopdoc:
+
+ module Command
+ class Break < DebugCommand
+ def execute(arg)
+ execute_debug_command(pre_cmds: "break #{arg}")
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/command/catch.rb b/lib/irb/command/catch.rb
new file mode 100644
index 0000000000..529dcbca5a
--- /dev/null
+++ b/lib/irb/command/catch.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require_relative "debug"
+
+module IRB
+ # :stopdoc:
+
+ module Command
+ class Catch < DebugCommand
+ def execute(arg)
+ execute_debug_command(pre_cmds: "catch #{arg}")
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/command/chws.rb b/lib/irb/command/chws.rb
new file mode 100644
index 0000000000..ef456d0961
--- /dev/null
+++ b/lib/irb/command/chws.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+#
+# change-ws.rb -
+# by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+require_relative "../ext/change-ws"
+
+module IRB
+ # :stopdoc:
+
+ module Command
+
+ class CurrentWorkingWorkspace < Base
+ category "Workspace"
+ description "Show the current workspace."
+
+ def execute(_arg)
+ puts "Current workspace: #{irb_context.main}"
+ end
+ end
+
+ class ChangeWorkspace < Base
+ category "Workspace"
+ description "Change the current workspace to an object."
+
+ def execute(arg)
+ if arg.empty?
+ irb_context.change_workspace
+ else
+ obj = eval(arg, irb_context.workspace.binding)
+ irb_context.change_workspace(obj)
+ end
+
+ puts "Current workspace: #{irb_context.main}"
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/command/context.rb b/lib/irb/command/context.rb
new file mode 100644
index 0000000000..b4fc807343
--- /dev/null
+++ b/lib/irb/command/context.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module IRB
+ module Command
+ class Context < Base
+ category "IRB"
+ description "Displays current configuration."
+
+ def execute(_arg)
+ # This command just displays the configuration.
+ # Modifying the configuration is achieved by sending a message to IRB.conf.
+ Pager.page_content(IRB.CurrentContext.inspect)
+ end
+ end
+ end
+end
diff --git a/lib/irb/command/continue.rb b/lib/irb/command/continue.rb
new file mode 100644
index 0000000000..0daa029b15
--- /dev/null
+++ b/lib/irb/command/continue.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require_relative "debug"
+
+module IRB
+ # :stopdoc:
+
+ module Command
+ class Continue < DebugCommand
+ def execute(arg)
+ execute_debug_command(do_cmds: "continue #{arg}")
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/command/debug.rb b/lib/irb/command/debug.rb
new file mode 100644
index 0000000000..8a091a49ed
--- /dev/null
+++ b/lib/irb/command/debug.rb
@@ -0,0 +1,71 @@
+require_relative "../debug"
+
+module IRB
+ # :stopdoc:
+
+ module Command
+ class Debug < Base
+ category "Debugging"
+ description "Start the debugger of debug.gem."
+
+ def execute(_arg)
+ execute_debug_command
+ end
+
+ def execute_debug_command(pre_cmds: nil, do_cmds: nil)
+ pre_cmds = pre_cmds&.rstrip
+ do_cmds = do_cmds&.rstrip
+
+ if irb_context.with_debugger
+ # If IRB is already running with a debug session, throw the command and IRB.debug_readline will pass it to the debugger.
+ if cmd = pre_cmds || do_cmds
+ throw :IRB_EXIT, cmd
+ else
+ puts "IRB is already running with a debug session."
+ return
+ end
+ else
+ # If IRB is not running with a debug session yet, then:
+ # 1. Check if the debugging command is run from a `binding.irb` call.
+ # 2. If so, try setting up the debug gem.
+ # 3. Insert a debug breakpoint at `Irb#debug_break` with the intended command.
+ # 4. Exit the current Irb#run call via `throw :IRB_EXIT`.
+ # 5. `Irb#debug_break` will be called and trigger the breakpoint, which will run the intended command.
+ unless irb_context.from_binding?
+ puts "Debugging commands are only available when IRB is started with binding.irb"
+ return
+ end
+
+ if IRB.respond_to?(:JobManager)
+ warn "Can't start the debugger when IRB is running in a multi-IRB session."
+ return
+ end
+
+ unless IRB::Debug.setup(irb_context.irb)
+ puts <<~MSG
+ You need to install the debug gem before using this command.
+ If you use `bundle exec`, please add `gem "debug"` into your Gemfile.
+ MSG
+ return
+ end
+
+ IRB::Debug.insert_debug_break(pre_cmds: pre_cmds, do_cmds: do_cmds)
+
+ # exit current Irb#run call
+ throw :IRB_EXIT
+ end
+ end
+ end
+
+ class DebugCommand < Debug
+ def self.category
+ "Debugging"
+ end
+
+ def self.description
+ command_name = self.name.split("::").last.downcase
+ "Start the debugger of debug.gem and run its `#{command_name}` command."
+ end
+ end
+ end
+end
diff --git a/lib/irb/command/delete.rb b/lib/irb/command/delete.rb
new file mode 100644
index 0000000000..2a57a4a3de
--- /dev/null
+++ b/lib/irb/command/delete.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require_relative "debug"
+
+module IRB
+ # :stopdoc:
+
+ module Command
+ class Delete < DebugCommand
+ def execute(arg)
+ execute_debug_command(pre_cmds: "delete #{arg}")
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/command/disable_irb.rb b/lib/irb/command/disable_irb.rb
new file mode 100644
index 0000000000..0b00d0302b
--- /dev/null
+++ b/lib/irb/command/disable_irb.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module IRB
+ # :stopdoc:
+
+ module Command
+ class DisableIrb < Base
+ category "IRB"
+ description "Disable binding.irb."
+
+ def execute(*)
+ ::Binding.define_method(:irb) {}
+ IRB.irb_exit
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/command/edit.rb b/lib/irb/command/edit.rb
new file mode 100644
index 0000000000..cb7e0c4873
--- /dev/null
+++ b/lib/irb/command/edit.rb
@@ -0,0 +1,63 @@
+require 'shellwords'
+
+require_relative "../color"
+require_relative "../source_finder"
+
+module IRB
+ # :stopdoc:
+
+ module Command
+ class Edit < Base
+ include RubyArgsExtractor
+
+ category "Misc"
+ description 'Open a file or source location.'
+ help_message <<~HELP_MESSAGE
+ Usage: edit [FILE or constant or method signature]
+
+ Open a file in the editor specified in #{highlight('ENV["VISUAL"]')} or #{highlight('ENV["EDITOR"]')}
+
+ - If no arguments are provided, IRB will attempt to open the file the current context was defined in.
+ - If FILE is provided, IRB will open the file.
+ - If a constant or method signature is provided, IRB will attempt to locate the source file and open it.
+
+ Examples:
+
+ edit
+ edit foo.rb
+ edit Foo
+ edit Foo#bar
+ HELP_MESSAGE
+
+ def execute(arg)
+ # Accept string literal for backward compatibility
+ path = unwrap_string_literal(arg)
+
+ if path.nil?
+ path = @irb_context.irb_path
+ elsif !File.exist?(path)
+ source = SourceFinder.new(@irb_context).find_source(path)
+
+ if source&.file_exist? && !source.binary_file?
+ path = source.file
+ end
+ end
+
+ unless File.exist?(path)
+ puts "Can not find file: #{path}"
+ return
+ end
+
+ if editor = (ENV['VISUAL'] || ENV['EDITOR'])
+ puts "command: '#{editor}'"
+ puts " path: #{path}"
+ system(*Shellwords.split(editor), path)
+ else
+ puts "Can not find editor setting: ENV['VISUAL'] or ENV['EDITOR']"
+ end
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/command/exit.rb b/lib/irb/command/exit.rb
new file mode 100644
index 0000000000..b4436f0343
--- /dev/null
+++ b/lib/irb/command/exit.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module IRB
+ # :stopdoc:
+
+ module Command
+ class Exit < Base
+ category "IRB"
+ description "Exit the current irb session."
+
+ def execute(_arg)
+ IRB.irb_exit
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/command/finish.rb b/lib/irb/command/finish.rb
new file mode 100644
index 0000000000..3311a0e6e9
--- /dev/null
+++ b/lib/irb/command/finish.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require_relative "debug"
+
+module IRB
+ # :stopdoc:
+
+ module Command
+ class Finish < DebugCommand
+ def execute(arg)
+ execute_debug_command(do_cmds: "finish #{arg}")
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/command/force_exit.rb b/lib/irb/command/force_exit.rb
new file mode 100644
index 0000000000..14086aa849
--- /dev/null
+++ b/lib/irb/command/force_exit.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module IRB
+ # :stopdoc:
+
+ module Command
+ class ForceExit < Base
+ category "IRB"
+ description "Exit the current process."
+
+ def execute(_arg)
+ throw :IRB_EXIT, true
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/command/help.rb b/lib/irb/command/help.rb
new file mode 100644
index 0000000000..c2018f9b30
--- /dev/null
+++ b/lib/irb/command/help.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+module IRB
+ module Command
+ class Help < Base
+ category "Help"
+ description "List all available commands. Use `help <command>` to get information about a specific command."
+
+ def execute(command_name)
+ content =
+ if command_name.empty?
+ help_message
+ else
+ if command_class = Command.load_command(command_name)
+ command_class.help_message || command_class.description
+ else
+ "Can't find command `#{command_name}`. Please check the command name and try again.\n\n"
+ end
+ end
+ Pager.page_content(content)
+ end
+
+ private
+
+ def help_message
+ commands_info = IRB::Command.all_commands_info
+ helper_methods_info = IRB::HelperMethod.all_helper_methods_info
+ commands_grouped_by_categories = commands_info.group_by { |cmd| cmd[:category] }
+ commands_grouped_by_categories["Helper methods"] = helper_methods_info
+
+ if irb_context.with_debugger
+ # Remove the original "Debugging" category
+ commands_grouped_by_categories.delete("Debugging")
+ end
+
+ longest_cmd_name_length = commands_info.map { |c| c[:display_name].length }.max
+
+ output = StringIO.new
+
+ help_cmds = commands_grouped_by_categories.delete("Help")
+ no_category_cmds = commands_grouped_by_categories.delete("No category")
+ aliases = irb_context.instance_variable_get(:@user_aliases).map do |alias_name, target|
+ { display_name: alias_name, description: "Alias for `#{target}`" }
+ end
+
+ # Display help commands first
+ add_category_to_output("Help", help_cmds, output, longest_cmd_name_length)
+
+ # Display the rest of the commands grouped by categories
+ commands_grouped_by_categories.each do |category, cmds|
+ add_category_to_output(category, cmds, output, longest_cmd_name_length)
+ end
+
+ # Display commands without a category
+ if no_category_cmds
+ add_category_to_output("No category", no_category_cmds, output, longest_cmd_name_length)
+ end
+
+ # Display aliases
+ add_category_to_output("Aliases", aliases, output, longest_cmd_name_length)
+
+ # Append the debugger help at the end
+ if irb_context.with_debugger
+ # Add "Debugging (from debug.gem)" category as title
+ add_category_to_output("Debugging (from debug.gem)", [], output, longest_cmd_name_length)
+ output.puts DEBUGGER__.help
+ end
+
+ output.string
+ end
+
+ def add_category_to_output(category, cmds, output, longest_cmd_name_length)
+ output.puts Color.colorize(category, [:BOLD])
+
+ cmds.each do |cmd|
+ output.puts " #{cmd[:display_name].to_s.ljust(longest_cmd_name_length)} #{cmd[:description]}"
+ end
+
+ output.puts
+ end
+ end
+ end
+end
diff --git a/lib/irb/command/history.rb b/lib/irb/command/history.rb
new file mode 100644
index 0000000000..90f87f9102
--- /dev/null
+++ b/lib/irb/command/history.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require "stringio"
+
+require_relative "../pager"
+
+module IRB
+ # :stopdoc:
+
+ module Command
+ class History < Base
+ category "IRB"
+ description "Shows the input history. `-g [query]` or `-G [query]` allows you to filter the output."
+
+ def execute(arg)
+
+ if (match = arg&.match(/(-g|-G)\s+(?<grep>.+)\s*\n\z/))
+ grep = Regexp.new(match[:grep])
+ end
+
+ formatted_inputs = irb_context.io.class::HISTORY.each_with_index.reverse_each.filter_map do |input, index|
+ next if grep && !input.match?(grep)
+
+ header = "#{index}: "
+
+ first_line, *other_lines = input.split("\n")
+ first_line = "#{header}#{first_line}"
+
+ truncated_lines = other_lines.slice!(1..) # Show 1 additional line (2 total)
+ other_lines << "..." if truncated_lines&.any?
+
+ other_lines.map! do |line|
+ " " * header.length + line
+ end
+
+ [first_line, *other_lines].join("\n") + "\n"
+ end
+
+ Pager.page_content(formatted_inputs.join)
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/command/info.rb b/lib/irb/command/info.rb
new file mode 100644
index 0000000000..d08ce00a32
--- /dev/null
+++ b/lib/irb/command/info.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require_relative "debug"
+
+module IRB
+ # :stopdoc:
+
+ module Command
+ class Info < DebugCommand
+ def execute(arg)
+ execute_debug_command(pre_cmds: "info #{arg}")
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/command/internal_helpers.rb b/lib/irb/command/internal_helpers.rb
new file mode 100644
index 0000000000..249b5cdede
--- /dev/null
+++ b/lib/irb/command/internal_helpers.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module IRB
+ module Command
+ # Internal use only, for default command's backward compatibility.
+ module RubyArgsExtractor # :nodoc:
+ def unwrap_string_literal(str)
+ return if str.empty?
+
+ sexp = Ripper.sexp(str)
+ if sexp && sexp.size == 2 && sexp.last&.first&.first == :string_literal
+ @irb_context.workspace.binding.eval(str).to_s
+ else
+ str
+ end
+ end
+
+ def ruby_args(arg)
+ # Use throw and catch to handle arg that includes `;`
+ # For example: "1, kw: (2; 3); 4" will be parsed to [[1], { kw: 3 }]
+ catch(:EXTRACT_RUBY_ARGS) do
+ @irb_context.workspace.binding.eval "IRB::Command.extract_ruby_args #{arg}"
+ end || [[], {}]
+ end
+ end
+ end
+end
diff --git a/lib/irb/command/irb_info.rb b/lib/irb/command/irb_info.rb
new file mode 100644
index 0000000000..6d868de94c
--- /dev/null
+++ b/lib/irb/command/irb_info.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module IRB
+ # :stopdoc:
+
+ module Command
+ class IrbInfo < Base
+ category "IRB"
+ description "Show information about IRB."
+
+ def execute(_arg)
+ str = "Ruby version: #{RUBY_VERSION}\n"
+ str += "IRB version: #{IRB.version}\n"
+ str += "InputMethod: #{IRB.CurrentContext.io.inspect}\n"
+ str += "Completion: #{IRB.CurrentContext.io.respond_to?(:completion_info) ? IRB.CurrentContext.io.completion_info : 'off'}\n"
+ rc_files = IRB.irbrc_files
+ str += ".irbrc paths: #{rc_files.join(", ")}\n" if rc_files.any?
+ str += "RUBY_PLATFORM: #{RUBY_PLATFORM}\n"
+ str += "LANG env: #{ENV["LANG"]}\n" if ENV["LANG"] && !ENV["LANG"].empty?
+ str += "LC_ALL env: #{ENV["LC_ALL"]}\n" if ENV["LC_ALL"] && !ENV["LC_ALL"].empty?
+ str += "East Asian Ambiguous Width: #{Reline.ambiguous_width.inspect}\n"
+ if RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/
+ codepage = `chcp`.b.sub(/.*: (\d+)\n/, '\1')
+ str += "Code page: #{codepage}\n"
+ end
+ puts str
+ nil
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/command/load.rb b/lib/irb/command/load.rb
new file mode 100644
index 0000000000..1cd3f279d1
--- /dev/null
+++ b/lib/irb/command/load.rb
@@ -0,0 +1,91 @@
+# frozen_string_literal: true
+#
+# load.rb -
+# by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+require_relative "../ext/loader"
+
+module IRB
+ # :stopdoc:
+
+ module Command
+ class LoaderCommand < Base
+ include RubyArgsExtractor
+ include IrbLoader
+
+ def raise_cmd_argument_error
+ raise CommandArgumentError.new("Please specify the file name.")
+ end
+ end
+
+ class Load < LoaderCommand
+ category "IRB"
+ description "Load a Ruby file."
+
+ def execute(arg)
+ args, kwargs = ruby_args(arg)
+ execute_internal(*args, **kwargs)
+ end
+
+ def execute_internal(file_name = nil, priv = nil)
+ raise_cmd_argument_error unless file_name
+ irb_load(file_name, priv)
+ end
+ end
+
+ class Require < LoaderCommand
+ category "IRB"
+ description "Require a Ruby file."
+
+ def execute(arg)
+ args, kwargs = ruby_args(arg)
+ execute_internal(*args, **kwargs)
+ end
+
+ def execute_internal(file_name = nil)
+ raise_cmd_argument_error unless file_name
+
+ rex = Regexp.new("#{Regexp.quote(file_name)}(\.o|\.rb)?")
+ return false if $".find{|f| f =~ rex}
+
+ case file_name
+ when /\.rb$/
+ begin
+ if irb_load(file_name)
+ $".push file_name
+ return true
+ end
+ rescue LoadError
+ end
+ when /\.(so|o|sl)$/
+ return ruby_require(file_name)
+ end
+
+ begin
+ irb_load(f = file_name + ".rb")
+ $".push f
+ return true
+ rescue LoadError
+ return ruby_require(file_name)
+ end
+ end
+ end
+
+ class Source < LoaderCommand
+ category "IRB"
+ description "Loads a given file in the current session."
+
+ def execute(arg)
+ args, kwargs = ruby_args(arg)
+ execute_internal(*args, **kwargs)
+ end
+
+ def execute_internal(file_name = nil)
+ raise_cmd_argument_error unless file_name
+
+ source_file(file_name)
+ end
+ end
+ end
+ # :startdoc:
+end
diff --git a/lib/irb/command/ls.rb b/lib/irb/command/ls.rb
new file mode 100644
index 0000000000..cbd9998bc4
--- /dev/null
+++ b/lib/irb/command/ls.rb
@@ -0,0 +1,155 @@
+# frozen_string_literal: true
+
+require "reline"
+require "stringio"
+
+require_relative "../pager"
+require_relative "../color"
+
+module IRB
+ # :stopdoc:
+
+ module Command
+ class Ls < Base
+ include RubyArgsExtractor
+
+ category "Context"
+ description "Show methods, constants, and variables."
+
+ help_message <<~HELP_MESSAGE
+ Usage: ls [obj] [-g [query]]
+
+ -g [query] Filter the output with a query.
+ HELP_MESSAGE
+
+ def execute(arg)
+ if match = arg.match(/\A(?<target>.+\s|)(-g|-G)\s+(?<grep>.+)$/)
+ if match[:target].empty?
+ use_main = true
+ else
+ obj = @irb_context.workspace.binding.eval(match[:target])
+ end
+ grep = Regexp.new(match[:grep])
+ else
+ args, kwargs = ruby_args(arg)
+ use_main = args.empty?
+ obj = args.first
+ grep = kwargs[:grep]
+ end
+
+ if use_main
+ obj = irb_context.workspace.main
+ locals = irb_context.workspace.binding.local_variables
+ end
+
+ o = Output.new(grep: grep)
+
+ klass = (obj.class == Class || obj.class == Module ? obj : obj.class)
+
+ o.dump("constants", obj.constants) if obj.respond_to?(:constants)
+ dump_methods(o, klass, obj)
+ o.dump("instance variables", obj.instance_variables)
+ o.dump("class variables", klass.class_variables)
+ o.dump("locals", locals) if locals
+ o.print_result
+ end
+
+ def dump_methods(o, klass, obj)
+ singleton_class = begin obj.singleton_class; rescue TypeError; nil end
+ dumped_mods = Array.new
+ ancestors = klass.ancestors
+ ancestors = ancestors.reject { |c| c >= Object } if klass < Object
+ singleton_ancestors = (singleton_class&.ancestors || []).reject { |c| c >= Class }
+
+ # singleton_class' ancestors should be at the front
+ maps = class_method_map(singleton_ancestors, dumped_mods) + class_method_map(ancestors, dumped_mods)
+ maps.each do |mod, methods|
+ name = mod == singleton_class ? "#{klass}.methods" : "#{mod}#methods"
+ o.dump(name, methods)
+ end
+ end
+
+ def class_method_map(classes, dumped_mods)
+ dumped_methods = Array.new
+ classes.map do |mod|
+ next if dumped_mods.include? mod
+
+ dumped_mods << mod
+
+ methods = mod.public_instance_methods(false).select do |method|
+ if dumped_methods.include? method
+ false
+ else
+ dumped_methods << method
+ true
+ end
+ end
+
+ [mod, methods]
+ end.compact
+ end
+
+ class Output
+ MARGIN = " "
+
+ def initialize(grep: nil)
+ @grep = grep
+ @line_width = screen_width - MARGIN.length # right padding
+ @io = StringIO.new
+ end
+
+ def print_result
+ Pager.page_content(@io.string)
+ end
+
+ def dump(name, strs)
+ strs = strs.grep(@grep) if @grep
+ strs = strs.sort
+ return if strs.empty?
+
+ # Attempt a single line
+ @io.print "#{Color.colorize(name, [:BOLD, :BLUE])}: "
+ if fits_on_line?(strs, cols: strs.size, offset: "#{name}: ".length)
+ @io.puts strs.join(MARGIN)
+ return
+ end
+ @io.puts
+
+ # Dump with the largest # of columns that fits on a line
+ cols = strs.size
+ until fits_on_line?(strs, cols: cols, offset: MARGIN.length) || cols == 1
+ cols -= 1
+ end
+ widths = col_widths(strs, cols: cols)
+ strs.each_slice(cols) do |ss|
+ @io.puts ss.map.with_index { |s, i| "#{MARGIN}%-#{widths[i]}s" % s }.join
+ end
+ end
+
+ private
+
+ def fits_on_line?(strs, cols:, offset: 0)
+ width = col_widths(strs, cols: cols).sum + MARGIN.length * (cols - 1)
+ width <= @line_width - offset
+ end
+
+ def col_widths(strs, cols:)
+ cols.times.map do |col|
+ (col...strs.size).step(cols).map do |i|
+ strs[i].length
+ end.max
+ end
+ end
+
+ def screen_width
+ Reline.get_screen_size.last
+ rescue Errno::EINVAL # in `winsize': Invalid argument - <STDIN>
+ 80
+ end
+ end
+ private_constant :Output
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/command/measure.rb b/lib/irb/command/measure.rb
new file mode 100644
index 0000000000..f96be20de8
--- /dev/null
+++ b/lib/irb/command/measure.rb
@@ -0,0 +1,49 @@
+module IRB
+ # :stopdoc:
+
+ module Command
+ class Measure < Base
+ include RubyArgsExtractor
+
+ category "Misc"
+ description "`measure` enables the mode to measure processing time. `measure :off` disables it."
+
+ def initialize(*args)
+ super(*args)
+ end
+
+ def execute(arg)
+ if arg&.match?(/^do$|^do[^\w]|^\{/)
+ warn 'Configure IRB.conf[:MEASURE_PROC] to add custom measure methods.'
+ return
+ end
+ args, kwargs = ruby_args(arg)
+ execute_internal(*args, **kwargs)
+ end
+
+ def execute_internal(type = nil, arg = nil)
+ # Please check IRB.init_config in lib/irb/init.rb that sets
+ # IRB.conf[:MEASURE_PROC] to register default "measure" methods,
+ # "measure :time" (abbreviated as "measure") and "measure :stackprof".
+
+ case type
+ when :off
+ IRB.unset_measure_callback(arg)
+ when :list
+ IRB.conf[:MEASURE_CALLBACKS].each do |type_name, _, arg_val|
+ puts "- #{type_name}" + (arg_val ? "(#{arg_val.inspect})" : '')
+ end
+ when :on
+ added = IRB.set_measure_callback(arg)
+ puts "#{added[0]} is added." if added
+ else
+ added = IRB.set_measure_callback(type, arg)
+ puts "#{added[0]} is added." if added
+ end
+ nil
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/command/next.rb b/lib/irb/command/next.rb
new file mode 100644
index 0000000000..3fc6b68d21
--- /dev/null
+++ b/lib/irb/command/next.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require_relative "debug"
+
+module IRB
+ # :stopdoc:
+
+ module Command
+ class Next < DebugCommand
+ def execute(arg)
+ execute_debug_command(do_cmds: "next #{arg}")
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/command/pushws.rb b/lib/irb/command/pushws.rb
new file mode 100644
index 0000000000..b51928c650
--- /dev/null
+++ b/lib/irb/command/pushws.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+#
+# change-ws.rb -
+# by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+
+require_relative "../ext/workspaces"
+
+module IRB
+ # :stopdoc:
+
+ module Command
+ class Workspaces < Base
+ category "Workspace"
+ description "Show workspaces."
+
+ def execute(_arg)
+ inspection_resuls = irb_context.instance_variable_get(:@workspace_stack).map do |ws|
+ truncated_inspect(ws.main)
+ end
+
+ puts "[" + inspection_resuls.join(", ") + "]"
+ end
+
+ private
+
+ def truncated_inspect(obj)
+ obj_inspection = obj.inspect
+
+ if obj_inspection.size > 20
+ obj_inspection = obj_inspection[0, 19] + "...>"
+ end
+
+ obj_inspection
+ end
+ end
+
+ class PushWorkspace < Workspaces
+ category "Workspace"
+ description "Push an object to the workspace stack."
+
+ def execute(arg)
+ if arg.empty?
+ irb_context.push_workspace
+ else
+ obj = eval(arg, irb_context.workspace.binding)
+ irb_context.push_workspace(obj)
+ end
+ super
+ end
+ end
+
+ class PopWorkspace < Workspaces
+ category "Workspace"
+ description "Pop a workspace from the workspace stack."
+
+ def execute(_arg)
+ irb_context.pop_workspace
+ super
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/command/show_doc.rb b/lib/irb/command/show_doc.rb
new file mode 100644
index 0000000000..8a2188e4eb
--- /dev/null
+++ b/lib/irb/command/show_doc.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+module IRB
+ module Command
+ class ShowDoc < Base
+ include RubyArgsExtractor
+
+ category "Context"
+ description "Look up documentation with RI."
+
+ help_message <<~HELP_MESSAGE
+ Usage: show_doc [name]
+
+ When name is provided, IRB will look up the documentation for the given name.
+ When no name is provided, a RI session will be started.
+
+ Examples:
+
+ show_doc
+ show_doc Array
+ show_doc Array#each
+
+ HELP_MESSAGE
+
+ def execute(arg)
+ # Accept string literal for backward compatibility
+ name = unwrap_string_literal(arg)
+ require 'rdoc/ri/driver'
+
+ unless ShowDoc.const_defined?(:Ri)
+ opts = RDoc::RI::Driver.process_args([])
+ ShowDoc.const_set(:Ri, RDoc::RI::Driver.new(opts))
+ end
+
+ if name.nil?
+ Ri.interactive
+ else
+ begin
+ Ri.display_name(name)
+ rescue RDoc::RI::Error
+ puts $!.message
+ end
+ end
+
+ nil
+ rescue LoadError, SystemExit
+ warn "Can't display document because `rdoc` is not installed."
+ end
+ end
+ end
+end
diff --git a/lib/irb/command/show_source.rb b/lib/irb/command/show_source.rb
new file mode 100644
index 0000000000..f4c6f104a2
--- /dev/null
+++ b/lib/irb/command/show_source.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+require_relative "../source_finder"
+require_relative "../pager"
+require_relative "../color"
+
+module IRB
+ module Command
+ class ShowSource < Base
+ include RubyArgsExtractor
+
+ category "Context"
+ description "Show the source code of a given method, class/module, or constant."
+
+ help_message <<~HELP_MESSAGE
+ Usage: show_source [target] [-s]
+
+ -s Show the super method. You can stack it like `-ss` to show the super of the super, etc.
+
+ Examples:
+
+ show_source Foo
+ show_source Foo#bar
+ show_source Foo#bar -s
+ show_source Foo.baz
+ show_source Foo::BAR
+ HELP_MESSAGE
+
+ def execute(arg)
+ # Accept string literal for backward compatibility
+ str = unwrap_string_literal(arg)
+ unless str.is_a?(String)
+ puts "Error: Expected a string but got #{str.inspect}"
+ return
+ end
+
+ str, esses = str.split(" -")
+ super_level = esses ? esses.count("s") : 0
+ source = SourceFinder.new(@irb_context).find_source(str, super_level)
+
+ if source
+ show_source(source)
+ elsif super_level > 0
+ puts "Error: Couldn't locate a super definition for #{str}"
+ else
+ puts "Error: Couldn't locate a definition for #{str}"
+ end
+ nil
+ end
+
+ private
+
+ def show_source(source)
+ if source.binary_file?
+ content = "\n#{bold('Defined in binary file')}: #{source.file}\n\n"
+ else
+ code = source.colorized_content || 'Source not available'
+ content = <<~CONTENT
+
+ #{bold("From")}: #{source.file}:#{source.line}
+
+ #{code.chomp}
+
+ CONTENT
+ end
+ Pager.page_content(content)
+ end
+
+ def bold(str)
+ Color.colorize(str, [:BOLD])
+ end
+ end
+ end
+end
diff --git a/lib/irb/command/step.rb b/lib/irb/command/step.rb
new file mode 100644
index 0000000000..29e5e35ac0
--- /dev/null
+++ b/lib/irb/command/step.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require_relative "debug"
+
+module IRB
+ # :stopdoc:
+
+ module Command
+ class Step < DebugCommand
+ def execute(arg)
+ execute_debug_command(do_cmds: "step #{arg}")
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/command/subirb.rb b/lib/irb/command/subirb.rb
new file mode 100644
index 0000000000..85af28c1a5
--- /dev/null
+++ b/lib/irb/command/subirb.rb
@@ -0,0 +1,123 @@
+# frozen_string_literal: true
+#
+# multi.rb -
+# by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+
+module IRB
+ # :stopdoc:
+
+ module Command
+ class MultiIRBCommand < Base
+ include RubyArgsExtractor
+
+ private
+
+ def print_deprecated_warning
+ warn <<~MSG
+ Multi-irb commands are deprecated and will be removed in IRB 2.0.0. Please use workspace commands instead.
+ If you have any use case for multi-irb, please leave a comment at https://github.com/ruby/irb/issues/653
+ MSG
+ end
+
+ def extend_irb_context
+ # this extension patches IRB context like IRB.CurrentContext
+ require_relative "../ext/multi-irb"
+ end
+
+ def print_debugger_warning
+ warn "Multi-IRB commands are not available when the debugger is enabled."
+ end
+ end
+
+ class IrbCommand < MultiIRBCommand
+ category "Multi-irb (DEPRECATED)"
+ description "Start a child IRB."
+
+ def execute(arg)
+ args, kwargs = ruby_args(arg)
+ execute_internal(*args, **kwargs)
+ end
+
+ def execute_internal(*obj)
+ print_deprecated_warning
+
+ if irb_context.with_debugger
+ print_debugger_warning
+ return
+ end
+
+ extend_irb_context
+ IRB.irb(nil, *obj)
+ puts IRB.JobManager.inspect
+ end
+ end
+
+ class Jobs < MultiIRBCommand
+ category "Multi-irb (DEPRECATED)"
+ description "List of current sessions."
+
+ def execute(_arg)
+ print_deprecated_warning
+
+ if irb_context.with_debugger
+ print_debugger_warning
+ return
+ end
+
+ extend_irb_context
+ puts IRB.JobManager.inspect
+ end
+ end
+
+ class Foreground < MultiIRBCommand
+ category "Multi-irb (DEPRECATED)"
+ description "Switches to the session of the given number."
+
+ def execute(arg)
+ args, kwargs = ruby_args(arg)
+ execute_internal(*args, **kwargs)
+ end
+
+ def execute_internal(key = nil)
+ print_deprecated_warning
+
+ if irb_context.with_debugger
+ print_debugger_warning
+ return
+ end
+
+ extend_irb_context
+
+ raise CommandArgumentError.new("Please specify the id of target IRB job (listed in the `jobs` command).") unless key
+ IRB.JobManager.switch(key)
+ puts IRB.JobManager.inspect
+ end
+ end
+
+ class Kill < MultiIRBCommand
+ category "Multi-irb (DEPRECATED)"
+ description "Kills the session with the given number."
+
+ def execute(arg)
+ args, kwargs = ruby_args(arg)
+ execute_internal(*args, **kwargs)
+ end
+
+ def execute_internal(*keys)
+ print_deprecated_warning
+
+ if irb_context.with_debugger
+ print_debugger_warning
+ return
+ end
+
+ extend_irb_context
+ IRB.JobManager.kill(*keys)
+ puts IRB.JobManager.inspect
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/command/whereami.rb b/lib/irb/command/whereami.rb
new file mode 100644
index 0000000000..c8439f1212
--- /dev/null
+++ b/lib/irb/command/whereami.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module IRB
+ # :stopdoc:
+
+ module Command
+ class Whereami < Base
+ category "Context"
+ description "Show the source code around binding.irb again."
+
+ def execute(_arg)
+ code = irb_context.workspace.code_around_binding
+ if code
+ puts code
+ else
+ puts "The current context doesn't have code."
+ end
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/completion.rb b/lib/irb/completion.rb
index e3ebe4abff..a3d89373c3 100644
--- a/lib/irb/completion.rb
+++ b/lib/irb/completion.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#
# irb/completion.rb -
# by Keiju ISHITSUKA(keiju@ishitsuka.com)
@@ -86,6 +86,14 @@ module IRB
)
end
+ def command_completions(preposing, target)
+ if preposing.empty? && !target.empty?
+ IRB::Command.command_names.select { _1.start_with?(target) }
+ else
+ []
+ end
+ end
+
def retrieve_files_to_require_relative_from_current_dir
@files_from_current_dir ||= Dir.glob("**/*.{rb,#{RbConfig::CONFIG['DLEXT']}}", base: '.').map { |path|
path.sub(/\.(rb|#{RbConfig::CONFIG['DLEXT']})\z/, '')
@@ -93,6 +101,29 @@ module IRB
end
end
+ class TypeCompletor < BaseCompletor # :nodoc:
+ def initialize(context)
+ @context = context
+ end
+
+ def inspect
+ ReplTypeCompletor.info
+ end
+
+ def completion_candidates(preposing, target, _postposing, bind:)
+ commands = command_completions(preposing, target)
+ result = ReplTypeCompletor.analyze(preposing + target, binding: bind, filename: @context.irb_path)
+ return commands unless result
+
+ commands | result.completion_candidates.map { target + _1 }
+ end
+
+ def doc_namespace(preposing, matched, _postposing, bind:)
+ result = ReplTypeCompletor.analyze(preposing + matched, binding: bind, filename: @context.irb_path)
+ result&.doc_namespace('')
+ end
+ end
+
class RegexpCompletor < BaseCompletor # :nodoc:
using Module.new {
refine ::Binding do
@@ -160,7 +191,8 @@ module IRB
result = complete_require_path(target, preposing, postposing)
return result if result
end
- retrieve_completion_data(target, bind: bind, doc_namespace: false).compact.map{ |i| i.encode(Encoding.default_external) }
+ commands = command_completions(preposing || '', target)
+ commands | retrieve_completion_data(target, bind: bind, doc_namespace: false).compact.map{ |i| i.encode(Encoding.default_external) }
end
def doc_namespace(_preposing, matched, _postposing, bind:)
@@ -210,16 +242,16 @@ module IRB
end
when /^([^\}]*\})\.([^.]*)$/
- # Proc or Hash
+ # Hash or Proc
receiver = $1
message = $2
if doc_namespace
- ["Proc.#{message}", "Hash.#{message}"]
+ ["Hash.#{message}", "Proc.#{message}"]
else
- proc_candidates = Proc.instance_methods.collect{|m| m.to_s}
hash_candidates = Hash.instance_methods.collect{|m| m.to_s}
- select_message(receiver, message, proc_candidates | hash_candidates)
+ proc_candidates = Proc.instance_methods.collect{|m| m.to_s}
+ select_message(receiver, message, hash_candidates | proc_candidates)
end
when /^(:[^:.]+)$/
@@ -367,7 +399,7 @@ module IRB
if doc_namespace
rec_class = rec.is_a?(Module) ? rec : rec.class
- "#{rec_class.name}#{sep}#{candidates.find{ |i| i == message }}"
+ "#{rec_class.name}#{sep}#{candidates.find{ |i| i == message }}" rescue nil
else
select_message(receiver, message, candidates, sep)
end
@@ -385,13 +417,19 @@ module IRB
else
select_message(receiver, message, candidates.sort)
end
-
+ when /^\s*$/
+ # empty input
+ if doc_namespace
+ nil
+ else
+ []
+ end
else
if doc_namespace
vars = (bind.local_variables | bind.eval_instance_variables).collect{|m| m.to_s}
perfect_match_var = vars.find{|m| m.to_s == input}
if perfect_match_var
- eval("#{perfect_match_var}.class.name", bind)
+ eval("#{perfect_match_var}.class.name", bind) rescue nil
else
candidates = (bind.eval_methods | bind.eval_private_methods | bind.local_variables | bind.eval_instance_variables | bind.eval_class_constants).collect{|m| m.to_s}
candidates |= ReservedWords
diff --git a/lib/irb/context.rb b/lib/irb/context.rb
index 5dfe9d0d71..aafce7aade 100644
--- a/lib/irb/context.rb
+++ b/lib/irb/context.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#
# irb/context.rb - irb context
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
@@ -22,10 +22,11 @@ module IRB
# +other+:: uses this as InputMethod
def initialize(irb, workspace = nil, input_method = nil)
@irb = irb
+ @workspace_stack = []
if workspace
- @workspace = workspace
+ @workspace_stack << workspace
else
- @workspace = WorkSpace.new
+ @workspace_stack << WorkSpace.new
end
@thread = Thread.current
@@ -61,7 +62,7 @@ module IRB
@io = nil
self.inspect_mode = IRB.conf[:INSPECT_MODE]
- self.use_tracer = IRB.conf[:USE_TRACER] if IRB.conf[:USE_TRACER]
+ self.use_tracer = IRB.conf[:USE_TRACER]
self.use_loader = IRB.conf[:USE_LOADER] if IRB.conf[:USE_LOADER]
self.eval_history = IRB.conf[:EVAL_HISTORY] if IRB.conf[:EVAL_HISTORY]
@@ -72,19 +73,20 @@ module IRB
self.prompt_mode = IRB.conf[:PROMPT_MODE]
- if IRB.conf[:SINGLE_IRB] or !defined?(IRB::JobManager)
- @irb_name = IRB.conf[:IRB_NAME]
- else
- @irb_name = IRB.conf[:IRB_NAME]+"#"+IRB.JobManager.n_jobs.to_s
+ @irb_name = IRB.conf[:IRB_NAME]
+
+ unless IRB.conf[:SINGLE_IRB] or !defined?(IRB::JobManager)
+ @irb_name = @irb_name + "#" + IRB.JobManager.n_jobs.to_s
end
- @irb_path = "(" + @irb_name + ")"
+
+ self.irb_path = "(" + @irb_name + ")"
case input_method
when nil
@io = nil
case use_multiline?
when nil
- if STDIN.tty? && IRB.conf[:PROMPT_MODE] != :INF_RUBY && !use_singleline?
+ if term_interactive? && IRB.conf[:PROMPT_MODE] != :INF_RUBY && !use_singleline?
# Both of multiline mode and singleline mode aren't specified.
@io = RelineInputMethod.new(build_completor)
else
@@ -98,7 +100,7 @@ module IRB
unless @io
case use_singleline?
when nil
- if (defined?(ReadlineInputMethod) && STDIN.tty? &&
+ if (defined?(ReadlineInputMethod) && term_interactive? &&
IRB.conf[:PROMPT_MODE] != :INF_RUBY)
@io = ReadlineInputMethod.new
else
@@ -121,11 +123,11 @@ module IRB
when '-'
@io = FileInputMethod.new($stdin)
@irb_name = '-'
- @irb_path = '-'
+ self.irb_path = '-'
when String
@io = FileInputMethod.new(input_method)
@irb_name = File.basename(input_method)
- @irb_path = input_method
+ self.irb_path = input_method
else
@io = input_method
end
@@ -146,7 +148,41 @@ module IRB
@newline_before_multiline_output = true
end
- @command_aliases = IRB.conf[:COMMAND_ALIASES]
+ @user_aliases = IRB.conf[:COMMAND_ALIASES].dup
+ @command_aliases = @user_aliases.merge(KEYWORD_ALIASES)
+ end
+
+ private def term_interactive?
+ return true if ENV['TEST_IRB_FORCE_INTERACTIVE']
+ STDIN.tty? && ENV['TERM'] != 'dumb'
+ end
+
+ # because all input will eventually be evaluated as Ruby code,
+ # command names that conflict with Ruby keywords need special workaround
+ # we can remove them once we implemented a better command system for IRB
+ KEYWORD_ALIASES = {
+ :break => :irb_break,
+ :catch => :irb_catch,
+ :next => :irb_next,
+ }.freeze
+
+ private_constant :KEYWORD_ALIASES
+
+ def use_tracer=(val)
+ require_relative "ext/tracer" if val
+ IRB.conf[:USE_TRACER] = val
+ end
+
+ def eval_history=(val)
+ self.class.remove_method(__method__)
+ require_relative "ext/eval_history"
+ __send__(__method__, val)
+ end
+
+ def use_loader=(val)
+ self.class.remove_method(__method__)
+ require_relative "ext/use-loader"
+ __send__(__method__, val)
end
private def build_completor
@@ -164,26 +200,22 @@ module IRB
RegexpCompletor.new
end
- TYPE_COMPLETION_REQUIRED_PRISM_VERSION = '0.17.1'
-
private def build_type_completor
- unless Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.0.0') && RUBY_ENGINE != 'truffleruby'
- warn 'TypeCompletion requires RUBY_VERSION >= 3.0.0'
+ if RUBY_ENGINE == 'truffleruby'
+ # Avoid SyntaxError. truffleruby does not support endless method definition yet.
+ warn 'TypeCompletor is not supported on TruffleRuby yet'
return
end
+
begin
- require 'prism'
+ require 'repl_type_completor'
rescue LoadError => e
- warn "TypeCompletion requires Prism: #{e.message}"
- return
- end
- unless Gem::Version.new(Prism::VERSION) >= Gem::Version.new(TYPE_COMPLETION_REQUIRED_PRISM_VERSION)
- warn "TypeCompletion requires Prism::VERSION >= #{TYPE_COMPLETION_REQUIRED_PRISM_VERSION}"
+ warn "TypeCompletor requires `gem repl_type_completor`: #{e.message}"
return
end
- require 'irb/type_completion/completor'
- TypeCompletion::Types.preload_in_thread
- TypeCompletion::Completor.new
+
+ ReplTypeCompletor.preload_rbs
+ TypeCompletor.new(self)
end
def save_history=(val)
@@ -204,15 +236,24 @@ module IRB
IRB.conf[:HISTORY_FILE] = hist
end
+ # Workspace in the current context.
+ def workspace
+ @workspace_stack.last
+ end
+
+ # Replace the current workspace with the given +workspace+.
+ def replace_workspace(workspace)
+ @workspace_stack.pop
+ @workspace_stack.push(workspace)
+ end
+
# The top-level workspace, see WorkSpace#main
def main
- @workspace.main
+ workspace.main
end
# The toplevel workspace, see #home_workspace
attr_reader :workspace_home
- # WorkSpace in the current context.
- attr_accessor :workspace
# The current thread in this context.
attr_reader :thread
# The current input method.
@@ -233,9 +274,27 @@ module IRB
# Can be either name from <code>IRB.conf[:IRB_NAME]</code>, or the number of
# the current job set by JobManager, such as <code>irb#2</code>
attr_accessor :irb_name
- # Can be either the #irb_name surrounded by parenthesis, or the
- # +input_method+ passed to Context.new
- attr_accessor :irb_path
+
+ # Can be one of the following:
+ # - the #irb_name surrounded by parenthesis
+ # - the +input_method+ passed to Context.new
+ # - the file path of the current IRB context in a binding.irb session
+ attr_reader :irb_path
+
+ # Sets @irb_path to the given +path+ as well as @eval_path
+ # @eval_path is used for evaluating code in the context of IRB session
+ # It's the same as irb_path, but with the IRB name postfix
+ # This makes sure users can distinguish the methods defined in the IRB session
+ # from the methods defined in the current file's context, especially with binding.irb
+ def irb_path=(path)
+ @irb_path = path
+
+ if File.exist?(path)
+ @eval_path = "#{path}(#{IRB.conf[:IRB_NAME]})"
+ else
+ @eval_path = path
+ end
+ end
# Whether multiline editor mode is enabled or not.
#
@@ -256,15 +315,15 @@ module IRB
attr_reader :prompt_mode
# Standard IRB prompt.
#
- # See IRB@Customizing+the+IRB+Prompt for more information.
+ # See {Custom Prompts}[rdoc-ref:IRB@Custom+Prompts] for more information.
attr_accessor :prompt_i
# IRB prompt for continuated strings.
#
- # See IRB@Customizing+the+IRB+Prompt for more information.
+ # See {Custom Prompts}[rdoc-ref:IRB@Custom+Prompts] for more information.
attr_accessor :prompt_s
# IRB prompt for continuated statement. (e.g. immediately after an +if+)
#
- # See IRB@Customizing+the+IRB+Prompt for more information.
+ # See {Custom Prompts}[rdoc-ref:IRB@Custom+Prompts] for more information.
attr_accessor :prompt_c
# TODO: Remove this when developing v2.0
@@ -386,8 +445,6 @@ module IRB
# The default value is 16.
#
# Can also be set using the +--back-trace-limit+ command line option.
- #
- # See IRB@Command+line+options for more command line options.
attr_accessor :back_trace_limit
# User-defined IRB command aliases
@@ -438,9 +495,7 @@ module IRB
# StdioInputMethod or RelineInputMethod or ReadlineInputMethod, see #io
# for more information.
def prompting?
- verbose? || (STDIN.tty? && @io.kind_of?(StdioInputMethod) ||
- @io.kind_of?(RelineInputMethod) ||
- (defined?(ReadlineInputMethod) && @io.kind_of?(ReadlineInputMethod)))
+ verbose? || @io.prompting?
end
# The return value of the last statement evaluated.
@@ -450,12 +505,12 @@ module IRB
# to #last_value.
def set_last_value(value)
@last_value = value
- @workspace.local_variable_set :_, value
+ workspace.local_variable_set :_, value
end
# Sets the +mode+ of the prompt in this context.
#
- # See IRB@Customizing+the+IRB+Prompt for more information.
+ # See {Custom Prompts}[rdoc-ref:IRB@Custom+Prompts] for more information.
def prompt_mode=(mode)
@prompt_mode = mode
pconf = IRB.conf[:PROMPT][mode]
@@ -493,8 +548,6 @@ module IRB
#
# Can also be set using the +--inspect+ and +--noinspect+ command line
# options.
- #
- # See IRB@Command+line+options for more command line options.
def inspect_mode=(opt)
if i = Inspector::INSPECTORS[opt]
@@ -538,45 +591,55 @@ module IRB
@inspect_mode
end
- def evaluate(line, line_no) # :nodoc:
+ def evaluate(statement, line_no) # :nodoc:
@line_no = line_no
- result = nil
+ case statement
+ when Statement::EmptyInput
+ return
+ when Statement::Expression
+ result = evaluate_expression(statement.code, line_no)
+ set_last_value(result)
+ when Statement::Command
+ statement.command_class.execute(self, statement.arg)
+ set_last_value(nil)
+ end
+
+ nil
+ end
+
+ def from_binding?
+ @irb.from_binding
+ end
+
+ def evaluate_expression(code, line_no) # :nodoc:
+ result = nil
if IRB.conf[:MEASURE] && IRB.conf[:MEASURE_CALLBACKS].empty?
IRB.set_measure_callback
end
if IRB.conf[:MEASURE] && !IRB.conf[:MEASURE_CALLBACKS].empty?
last_proc = proc do
- result = @workspace.evaluate(line, irb_path, line_no)
+ result = workspace.evaluate(code, @eval_path, line_no)
end
IRB.conf[:MEASURE_CALLBACKS].inject(last_proc) do |chain, item|
_name, callback, arg = item
proc do
- callback.(self, line, line_no, arg) do
+ callback.(self, code, line_no, arg) do
chain.call
end
end
end.call
else
- result = @workspace.evaluate(line, irb_path, line_no)
+ result = workspace.evaluate(code, @eval_path, line_no)
end
-
- set_last_value(result)
+ result
end
def inspect_last_value # :nodoc:
@inspect_method.inspect_value(@last_value)
end
- alias __exit__ exit
- # Exits the current session, see IRB.irb_exit
- def exit(ret = 0)
- IRB.irb_exit(@irb, ret)
- rescue UncaughtThrowError
- super
- end
-
NOPRINTING_IVARS = ["@last_value"] # :nodoc:
NO_INSPECTING_IVARS = ["@irb", "@io"] # :nodoc:
IDNAME_IVARS = ["@prompt_mode"] # :nodoc:
@@ -607,17 +670,5 @@ module IRB
def local_variables # :nodoc:
workspace.binding.local_variables
end
-
- # Return true if it's aliased from the argument and it's not an identifier.
- def symbol_alias?(command)
- return nil if command.match?(/\A\w+\z/)
- command_aliases.key?(command.to_sym)
- end
-
- # Return true if the command supports transforming args
- def transform_args?(command)
- command = command_aliases.fetch(command.to_sym, command)
- ExtendCommandBundle.load_command(command)&.respond_to?(:transform_args)
- end
end
end
diff --git a/lib/irb/debug.rb b/lib/irb/debug.rb
index e522d39300..1ec2335a8e 100644
--- a/lib/irb/debug.rb
+++ b/lib/irb/debug.rb
@@ -57,6 +57,24 @@ module IRB
DEBUGGER__::ThreadClient.prepend(SkipPathHelperForIRB)
end
+ if !@output_modifier_defined && !DEBUGGER__::CONFIG[:no_hint]
+ irb_output_modifier_proc = Reline.output_modifier_proc
+
+ Reline.output_modifier_proc = proc do |output, complete:|
+ unless output.strip.empty?
+ cmd = output.split(/\s/, 2).first
+
+ if !complete && DEBUGGER__.commands.key?(cmd)
+ output = output.sub(/\n$/, " # debug command\n")
+ end
+ end
+
+ irb_output_modifier_proc.call(output, complete: complete)
+ end
+
+ @output_modifier_defined = true
+ end
+
true
end
diff --git a/lib/irb/default_commands.rb b/lib/irb/default_commands.rb
new file mode 100644
index 0000000000..91c6b2d041
--- /dev/null
+++ b/lib/irb/default_commands.rb
@@ -0,0 +1,265 @@
+# frozen_string_literal: true
+
+require_relative "command"
+require_relative "command/internal_helpers"
+require_relative "command/backtrace"
+require_relative "command/break"
+require_relative "command/catch"
+require_relative "command/chws"
+require_relative "command/context"
+require_relative "command/continue"
+require_relative "command/debug"
+require_relative "command/delete"
+require_relative "command/disable_irb"
+require_relative "command/edit"
+require_relative "command/exit"
+require_relative "command/finish"
+require_relative "command/force_exit"
+require_relative "command/help"
+require_relative "command/history"
+require_relative "command/info"
+require_relative "command/irb_info"
+require_relative "command/load"
+require_relative "command/ls"
+require_relative "command/measure"
+require_relative "command/next"
+require_relative "command/pushws"
+require_relative "command/show_doc"
+require_relative "command/show_source"
+require_relative "command/step"
+require_relative "command/subirb"
+require_relative "command/whereami"
+
+module IRB
+ module Command
+ NO_OVERRIDE = 0
+ OVERRIDE_PRIVATE_ONLY = 0x01
+ OVERRIDE_ALL = 0x02
+
+ class << self
+ # This API is for IRB's internal use only and may change at any time.
+ # Please do NOT use it.
+ def _register_with_aliases(name, command_class, *aliases)
+ @commands[name.to_sym] = [command_class, aliases]
+ end
+
+ def all_commands_info
+ user_aliases = IRB.CurrentContext.command_aliases.each_with_object({}) do |(alias_name, target), result|
+ result[target] ||= []
+ result[target] << alias_name
+ end
+
+ commands.map do |command_name, (command_class, aliases)|
+ aliases = aliases.map { |a| a.first }
+
+ if additional_aliases = user_aliases[command_name]
+ aliases += additional_aliases
+ end
+
+ display_name = aliases.shift || command_name
+ {
+ display_name: display_name,
+ description: command_class.description,
+ category: command_class.category
+ }
+ end
+ end
+
+ def command_override_policies
+ @@command_override_policies ||= commands.flat_map do |cmd_name, (cmd_class, aliases)|
+ [[cmd_name, OVERRIDE_ALL]] + aliases
+ end.to_h
+ end
+
+ def execute_as_command?(name, public_method:, private_method:)
+ case command_override_policies[name]
+ when OVERRIDE_ALL
+ true
+ when OVERRIDE_PRIVATE_ONLY
+ !public_method
+ when NO_OVERRIDE
+ !public_method && !private_method
+ end
+ end
+
+ def command_names
+ command_override_policies.keys.map(&:to_s)
+ end
+
+ # Convert a command name to its implementation class if such command exists
+ def load_command(command)
+ command = command.to_sym
+ commands.each do |command_name, (command_class, aliases)|
+ if command_name == command || aliases.any? { |alias_name, _| alias_name == command }
+ return command_class
+ end
+ end
+ nil
+ end
+ end
+
+ _register_with_aliases(:irb_context, Command::Context,
+ [:context, NO_OVERRIDE]
+ )
+
+ _register_with_aliases(:irb_exit, Command::Exit,
+ [:exit, OVERRIDE_PRIVATE_ONLY],
+ [:quit, OVERRIDE_PRIVATE_ONLY],
+ [:irb_quit, OVERRIDE_PRIVATE_ONLY]
+ )
+
+ _register_with_aliases(:irb_exit!, Command::ForceExit,
+ [:exit!, OVERRIDE_PRIVATE_ONLY]
+ )
+
+ _register_with_aliases(:irb_current_working_workspace, Command::CurrentWorkingWorkspace,
+ [:cwws, NO_OVERRIDE],
+ [:pwws, NO_OVERRIDE],
+ [:irb_print_working_workspace, OVERRIDE_ALL],
+ [:irb_cwws, OVERRIDE_ALL],
+ [:irb_pwws, OVERRIDE_ALL],
+ [:irb_current_working_binding, OVERRIDE_ALL],
+ [:irb_print_working_binding, OVERRIDE_ALL],
+ [:irb_cwb, OVERRIDE_ALL],
+ [:irb_pwb, OVERRIDE_ALL],
+ )
+
+ _register_with_aliases(:irb_change_workspace, Command::ChangeWorkspace,
+ [:chws, NO_OVERRIDE],
+ [:cws, NO_OVERRIDE],
+ [:irb_chws, OVERRIDE_ALL],
+ [:irb_cws, OVERRIDE_ALL],
+ [:irb_change_binding, OVERRIDE_ALL],
+ [:irb_cb, OVERRIDE_ALL],
+ [:cb, NO_OVERRIDE],
+ )
+
+ _register_with_aliases(:irb_workspaces, Command::Workspaces,
+ [:workspaces, NO_OVERRIDE],
+ [:irb_bindings, OVERRIDE_ALL],
+ [:bindings, NO_OVERRIDE],
+ )
+
+ _register_with_aliases(:irb_push_workspace, Command::PushWorkspace,
+ [:pushws, NO_OVERRIDE],
+ [:irb_pushws, OVERRIDE_ALL],
+ [:irb_push_binding, OVERRIDE_ALL],
+ [:irb_pushb, OVERRIDE_ALL],
+ [:pushb, NO_OVERRIDE],
+ )
+
+ _register_with_aliases(:irb_pop_workspace, Command::PopWorkspace,
+ [:popws, NO_OVERRIDE],
+ [:irb_popws, OVERRIDE_ALL],
+ [:irb_pop_binding, OVERRIDE_ALL],
+ [:irb_popb, OVERRIDE_ALL],
+ [:popb, NO_OVERRIDE],
+ )
+
+ _register_with_aliases(:irb_load, Command::Load)
+ _register_with_aliases(:irb_require, Command::Require)
+ _register_with_aliases(:irb_source, Command::Source,
+ [:source, NO_OVERRIDE]
+ )
+
+ _register_with_aliases(:irb, Command::IrbCommand)
+ _register_with_aliases(:irb_jobs, Command::Jobs,
+ [:jobs, NO_OVERRIDE]
+ )
+ _register_with_aliases(:irb_fg, Command::Foreground,
+ [:fg, NO_OVERRIDE]
+ )
+ _register_with_aliases(:irb_kill, Command::Kill,
+ [:kill, OVERRIDE_PRIVATE_ONLY]
+ )
+
+ _register_with_aliases(:irb_debug, Command::Debug,
+ [:debug, NO_OVERRIDE]
+ )
+ _register_with_aliases(:irb_edit, Command::Edit,
+ [:edit, NO_OVERRIDE]
+ )
+
+ _register_with_aliases(:irb_break, Command::Break)
+ _register_with_aliases(:irb_catch, Command::Catch)
+ _register_with_aliases(:irb_next, Command::Next)
+ _register_with_aliases(:irb_delete, Command::Delete,
+ [:delete, NO_OVERRIDE]
+ )
+
+ _register_with_aliases(:irb_step, Command::Step,
+ [:step, NO_OVERRIDE]
+ )
+ _register_with_aliases(:irb_continue, Command::Continue,
+ [:continue, NO_OVERRIDE]
+ )
+ _register_with_aliases(:irb_finish, Command::Finish,
+ [:finish, NO_OVERRIDE]
+ )
+ _register_with_aliases(:irb_backtrace, Command::Backtrace,
+ [:backtrace, NO_OVERRIDE],
+ [:bt, NO_OVERRIDE]
+ )
+
+ _register_with_aliases(:irb_debug_info, Command::Info,
+ [:info, NO_OVERRIDE]
+ )
+
+ _register_with_aliases(:irb_help, Command::Help,
+ [:help, NO_OVERRIDE],
+ [:show_cmds, NO_OVERRIDE]
+ )
+
+ _register_with_aliases(:irb_show_doc, Command::ShowDoc,
+ [:show_doc, NO_OVERRIDE]
+ )
+
+ _register_with_aliases(:irb_info, Command::IrbInfo)
+
+ _register_with_aliases(:irb_ls, Command::Ls,
+ [:ls, NO_OVERRIDE]
+ )
+
+ _register_with_aliases(:irb_measure, Command::Measure,
+ [:measure, NO_OVERRIDE]
+ )
+
+ _register_with_aliases(:irb_show_source, Command::ShowSource,
+ [:show_source, NO_OVERRIDE]
+ )
+
+ _register_with_aliases(:irb_whereami, Command::Whereami,
+ [:whereami, NO_OVERRIDE]
+ )
+
+ _register_with_aliases(:irb_history, Command::History,
+ [:history, NO_OVERRIDE],
+ [:hist, NO_OVERRIDE]
+ )
+
+ _register_with_aliases(:irb_disable_irb, Command::DisableIrb,
+ [:disable_irb, NO_OVERRIDE]
+ )
+ end
+
+ ExtendCommand = Command
+
+ # For backward compatibility, we need to keep this module:
+ # - As a container of helper methods
+ # - As a place to register commands with the deprecated def_extend_command method
+ module ExtendCommandBundle
+ # For backward compatibility
+ NO_OVERRIDE = Command::NO_OVERRIDE
+ OVERRIDE_PRIVATE_ONLY = Command::OVERRIDE_PRIVATE_ONLY
+ OVERRIDE_ALL = Command::OVERRIDE_ALL
+
+ # Deprecated. Doesn't have any effect.
+ @EXTEND_COMMANDS = []
+
+ # Drepcated. Use Command.regiser instead.
+ def self.def_extend_command(cmd_name, cmd_class, _, *aliases)
+ Command._register_with_aliases(cmd_name, cmd_class, *aliases)
+ Command.class_variable_set(:@@command_override_policies, nil)
+ end
+ end
+end
diff --git a/lib/irb/ext/change-ws.rb b/lib/irb/ext/change-ws.rb
index c0f810a4c8..60e8afe31f 100644
--- a/lib/irb/ext/change-ws.rb
+++ b/lib/irb/ext/change-ws.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#
# irb/ext/cb.rb -
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
@@ -12,7 +12,7 @@ module IRB # :nodoc:
if defined? @home_workspace
@home_workspace
else
- @home_workspace = @workspace
+ @home_workspace = workspace
end
end
@@ -25,15 +25,13 @@ module IRB # :nodoc:
# See IRB::WorkSpace.new for more information.
def change_workspace(*_main)
if _main.empty?
- @workspace = home_workspace
+ replace_workspace(home_workspace)
return main
end
- @workspace = WorkSpace.new(_main[0])
-
- if !(class<<main;ancestors;end).include?(ExtendCommandBundle)
- main.extend ExtendCommandBundle
- end
+ workspace = WorkSpace.new(_main[0])
+ replace_workspace(workspace)
+ workspace.load_helper_methods_to_main
end
end
end
diff --git a/lib/irb/ext/eval_history.rb b/lib/irb/ext/eval_history.rb
index 1a04178b40..6c21ff00ee 100644
--- a/lib/irb/ext/eval_history.rb
+++ b/lib/irb/ext/eval_history.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#
# history.rb -
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
@@ -18,7 +18,7 @@ module IRB # :nodoc:
if defined?(@eval_history) && @eval_history
@eval_history_values.push @line_no, @last_value
- @workspace.evaluate "__ = IRB.CurrentContext.instance_eval{@eval_history_values}"
+ workspace.evaluate "__ = IRB.CurrentContext.instance_eval{@eval_history_values}"
end
@last_value
@@ -49,7 +49,7 @@ module IRB # :nodoc:
else
@eval_history_values = EvalHistory.new(no)
IRB.conf[:__TMP__EHV__] = @eval_history_values
- @workspace.evaluate("__ = IRB.conf[:__TMP__EHV__]")
+ workspace.evaluate("__ = IRB.conf[:__TMP__EHV__]")
IRB.conf.delete(:__TMP_EHV__)
end
else
diff --git a/lib/irb/ext/loader.rb b/lib/irb/ext/loader.rb
index d65695df3b..df5aaa8e5a 100644
--- a/lib/irb/ext/loader.rb
+++ b/lib/irb/ext/loader.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#
# loader.rb -
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
@@ -98,13 +98,13 @@ module IRB # :nodoc:
def old # :nodoc:
back_io = @io
- back_path = @irb_path
+ back_path = irb_path
back_name = @irb_name
back_scanner = @irb.scanner
begin
@io = FileInputMethod.new(path)
@irb_name = File.basename(path)
- @irb_path = path
+ self.irb_path = path
@irb.signal_status(:IN_LOAD) do
if back_io.kind_of?(FileInputMethod)
@irb.eval_input
@@ -119,7 +119,7 @@ module IRB # :nodoc:
ensure
@io = back_io
@irb_name = back_name
- @irb_path = back_path
+ self.irb_path = back_path
@irb.scanner = back_scanner
end
end
diff --git a/lib/irb/ext/multi-irb.rb b/lib/irb/ext/multi-irb.rb
index 1c20489137..9f234f0cdc 100644
--- a/lib/irb/ext/multi-irb.rb
+++ b/lib/irb/ext/multi-irb.rb
@@ -1,11 +1,11 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#
# irb/multi-irb.rb - multiple irb module
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
#
module IRB
- class JobManager
+ class JobManager # :nodoc:
# Creates a new JobManager object
def initialize
@@ -166,12 +166,12 @@ module IRB
@JobManager = JobManager.new
# The current JobManager in the session
- def IRB.JobManager
+ def IRB.JobManager # :nodoc:
@JobManager
end
# The current Context in this session
- def IRB.CurrentContext
+ def IRB.CurrentContext # :nodoc:
IRB.JobManager.irb(Thread.current).context
end
@@ -179,7 +179,7 @@ module IRB
#
# The optional +file+ argument is given to Context.new, along with the
# workspace created with the remaining arguments, see WorkSpace.new
- def IRB.irb(file = nil, *main)
+ def IRB.irb(file = nil, *main) # :nodoc:
workspace = WorkSpace.new(*main)
parent_thread = Thread.current
Thread.start do
diff --git a/lib/irb/ext/tracer.rb b/lib/irb/ext/tracer.rb
index 3eaeb70ef2..fd6daa88ae 100644
--- a/lib/irb/ext/tracer.rb
+++ b/lib/irb/ext/tracer.rb
@@ -1,78 +1,39 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#
# irb/lib/tracer.rb -
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
#
-
+# Loading the gem "tracer" will cause it to extend IRB commands with:
+# https://github.com/ruby/tracer/blob/v0.2.2/lib/tracer/irb.rb
begin
require "tracer"
rescue LoadError
$stderr.puts "Tracer extension of IRB is enabled but tracer gem wasn't found."
- module IRB
- class Context
- def use_tracer=(opt)
- # do nothing
- end
- end
- end
return # This is about to disable loading below
end
module IRB
+ class CallTracer < ::CallTracer
+ IRB_DIR = File.expand_path('../..', __dir__)
- # initialize tracing function
- def IRB.initialize_tracer
- Tracer.verbose = false
- Tracer.add_filter {
- |event, file, line, id, binding, *rests|
- /^#{Regexp.quote(@CONF[:IRB_LIB_PATH])}/ !~ file and
- File::basename(file) != "irb.rb"
- }
- end
-
- class Context
- # Whether Tracer is used when evaluating statements in this context.
- #
- # See +lib/tracer.rb+ for more information.
- attr_reader :use_tracer
- alias use_tracer? use_tracer
-
- # Sets whether or not to use the Tracer library when evaluating statements
- # in this context.
- #
- # See +lib/tracer.rb+ for more information.
- def use_tracer=(opt)
- if opt
- Tracer.set_get_line_procs(@irb_path) {
- |line_no, *rests|
- @io.line(line_no)
- }
- elsif !opt && @use_tracer
- Tracer.off
- end
- @use_tracer=opt
+ def skip?(tp)
+ super || tp.path.match?(IRB_DIR) || tp.path.match?('<internal:prelude>')
end
end
-
class WorkSpace
alias __evaluate__ evaluate
# Evaluate the context of this workspace and use the Tracer library to
# output the exact lines of code are being executed in chronological order.
#
- # See +lib/tracer.rb+ for more information.
- def evaluate(context, statements, file = nil, line = nil)
- if context.use_tracer? && file != nil && line != nil
- Tracer.on
- begin
+ # See https://github.com/ruby/tracer for more information.
+ def evaluate(statements, file = __FILE__, line = __LINE__)
+ if IRB.conf[:USE_TRACER] == true
+ CallTracer.new(colorize: Color.colorable?).start do
__evaluate__(statements, file, line)
- ensure
- Tracer.off
end
else
- __evaluate__(statements, file || __FILE__, line || __LINE__)
+ __evaluate__(statements, file, line)
end
end
end
-
- IRB.initialize_tracer
end
diff --git a/lib/irb/ext/use-loader.rb b/lib/irb/ext/use-loader.rb
index d0b8c2d4f4..c8a3ea1fe8 100644
--- a/lib/irb/ext/use-loader.rb
+++ b/lib/irb/ext/use-loader.rb
@@ -1,10 +1,10 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#
# use-loader.rb -
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
#
-require_relative "../cmd/load"
+require_relative "../command/load"
require_relative "loader"
class Object
@@ -17,12 +17,12 @@ module IRB
remove_method :irb_load if method_defined?(:irb_load)
# Loads the given file similarly to Kernel#load, see IrbLoader#irb_load
def irb_load(*opts, &b)
- ExtendCommand::Load.execute(irb_context, *opts, &b)
+ Command::Load.execute(irb_context, *opts, &b)
end
remove_method :irb_require if method_defined?(:irb_require)
# Loads the given file similarly to Kernel#require
def irb_require(*opts, &b)
- ExtendCommand::Require.execute(irb_context, *opts, &b)
+ Command::Require.execute(irb_context, *opts, &b)
end
end
@@ -49,14 +49,12 @@ module IRB
if IRB.conf[:USE_LOADER] != opt
IRB.conf[:USE_LOADER] = opt
if opt
- if !$".include?("irb/cmd/load")
- end
- (class<<@workspace.main;self;end).instance_eval {
+ (class<<workspace.main;self;end).instance_eval {
alias_method :load, :irb_load
alias_method :require, :irb_require
}
else
- (class<<@workspace.main;self;end).instance_eval {
+ (class<<workspace.main;self;end).instance_eval {
alias_method :load, :__original__load__IRB_use_loader__
alias_method :require, :__original__require__IRB_use_loader__
}
diff --git a/lib/irb/ext/workspaces.rb b/lib/irb/ext/workspaces.rb
index 9defc3e17b..da09faa83e 100644
--- a/lib/irb/ext/workspaces.rb
+++ b/lib/irb/ext/workspaces.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#
# push-ws.rb -
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
@@ -6,21 +6,6 @@
module IRB # :nodoc:
class Context
-
- # Size of the current WorkSpace stack
- def irb_level
- workspace_stack.size
- end
-
- # WorkSpaces in the current stack
- def workspaces
- if defined? @workspaces
- @workspaces
- else
- @workspaces = []
- end
- end
-
# Creates a new workspace with the given object or binding, and appends it
# onto the current #workspaces stack.
#
@@ -28,20 +13,15 @@ module IRB # :nodoc:
# information.
def push_workspace(*_main)
if _main.empty?
- if workspaces.empty?
- print "No other workspace\n"
- return nil
+ if @workspace_stack.size > 1
+ # swap the top two workspaces
+ previous_workspace, current_workspace = @workspace_stack.pop(2)
+ @workspace_stack.push current_workspace, previous_workspace
end
- ws = workspaces.pop
- workspaces.push @workspace
- @workspace = ws
- return workspaces
- end
-
- workspaces.push @workspace
- @workspace = WorkSpace.new(@workspace.binding, _main[0])
- if !(class<<main;ancestors;end).include?(ExtendCommandBundle)
- main.extend ExtendCommandBundle
+ else
+ new_workspace = WorkSpace.new(workspace.binding, _main[0])
+ @workspace_stack.push new_workspace
+ new_workspace.load_helper_methods_to_main
end
end
@@ -50,11 +30,7 @@ module IRB # :nodoc:
#
# Also, see #push_workspace.
def pop_workspace
- if workspaces.empty?
- print "workspace stack empty\n"
- return
- end
- @workspace = workspaces.pop
+ @workspace_stack.pop if @workspace_stack.size > 1
end
end
end
diff --git a/lib/irb/extend-command.rb b/lib/irb/extend-command.rb
deleted file mode 100644
index 514293a438..0000000000
--- a/lib/irb/extend-command.rb
+++ /dev/null
@@ -1,354 +0,0 @@
-# frozen_string_literal: false
-#
-# irb/extend-command.rb - irb extend command
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-module IRB # :nodoc:
- # Installs the default irb extensions command bundle.
- module ExtendCommandBundle
- EXCB = ExtendCommandBundle # :nodoc:
-
- # See #install_alias_method.
- NO_OVERRIDE = 0
- # See #install_alias_method.
- OVERRIDE_PRIVATE_ONLY = 0x01
- # See #install_alias_method.
- OVERRIDE_ALL = 0x02
-
- # Quits the current irb context
- #
- # +ret+ is the optional signal or message to send to Context#exit
- #
- # Same as <code>IRB.CurrentContext.exit</code>.
- def irb_exit(ret = 0)
- irb_context.exit(ret)
- end
-
- # Displays current configuration.
- #
- # Modifying the configuration is achieved by sending a message to IRB.conf.
- def irb_context
- IRB.CurrentContext
- end
-
- @ALIASES = [
- [:context, :irb_context, NO_OVERRIDE],
- [:conf, :irb_context, NO_OVERRIDE],
- [:irb_quit, :irb_exit, OVERRIDE_PRIVATE_ONLY],
- [:exit, :irb_exit, OVERRIDE_PRIVATE_ONLY],
- [:quit, :irb_exit, OVERRIDE_PRIVATE_ONLY],
- ]
-
-
- @EXTEND_COMMANDS = [
- [
- :irb_current_working_workspace, :CurrentWorkingWorkspace, "cmd/chws",
- [:cwws, NO_OVERRIDE],
- [:pwws, NO_OVERRIDE],
- [:irb_print_working_workspace, OVERRIDE_ALL],
- [:irb_cwws, OVERRIDE_ALL],
- [:irb_pwws, OVERRIDE_ALL],
- [:irb_current_working_binding, OVERRIDE_ALL],
- [:irb_print_working_binding, OVERRIDE_ALL],
- [:irb_cwb, OVERRIDE_ALL],
- [:irb_pwb, OVERRIDE_ALL],
- ],
- [
- :irb_change_workspace, :ChangeWorkspace, "cmd/chws",
- [:chws, NO_OVERRIDE],
- [:cws, NO_OVERRIDE],
- [:irb_chws, OVERRIDE_ALL],
- [:irb_cws, OVERRIDE_ALL],
- [:irb_change_binding, OVERRIDE_ALL],
- [:irb_cb, OVERRIDE_ALL],
- [:cb, NO_OVERRIDE],
- ],
-
- [
- :irb_workspaces, :Workspaces, "cmd/pushws",
- [:workspaces, NO_OVERRIDE],
- [:irb_bindings, OVERRIDE_ALL],
- [:bindings, NO_OVERRIDE],
- ],
- [
- :irb_push_workspace, :PushWorkspace, "cmd/pushws",
- [:pushws, NO_OVERRIDE],
- [:irb_pushws, OVERRIDE_ALL],
- [:irb_push_binding, OVERRIDE_ALL],
- [:irb_pushb, OVERRIDE_ALL],
- [:pushb, NO_OVERRIDE],
- ],
- [
- :irb_pop_workspace, :PopWorkspace, "cmd/pushws",
- [:popws, NO_OVERRIDE],
- [:irb_popws, OVERRIDE_ALL],
- [:irb_pop_binding, OVERRIDE_ALL],
- [:irb_popb, OVERRIDE_ALL],
- [:popb, NO_OVERRIDE],
- ],
-
- [
- :irb_load, :Load, "cmd/load"],
- [
- :irb_require, :Require, "cmd/load"],
- [
- :irb_source, :Source, "cmd/load",
- [:source, NO_OVERRIDE],
- ],
-
- [
- :irb, :IrbCommand, "cmd/subirb"],
- [
- :irb_jobs, :Jobs, "cmd/subirb",
- [:jobs, NO_OVERRIDE],
- ],
- [
- :irb_fg, :Foreground, "cmd/subirb",
- [:fg, NO_OVERRIDE],
- ],
- [
- :irb_kill, :Kill, "cmd/subirb",
- [:kill, OVERRIDE_PRIVATE_ONLY],
- ],
-
- [
- :irb_debug, :Debug, "cmd/debug",
- [:debug, NO_OVERRIDE],
- ],
- [
- :irb_edit, :Edit, "cmd/edit",
- [:edit, NO_OVERRIDE],
- ],
- [
- :irb_break, :Break, "cmd/break",
- ],
- [
- :irb_catch, :Catch, "cmd/catch",
- ],
- [
- :irb_next, :Next, "cmd/next"
- ],
- [
- :irb_delete, :Delete, "cmd/delete",
- [:delete, NO_OVERRIDE],
- ],
- [
- :irb_step, :Step, "cmd/step",
- [:step, NO_OVERRIDE],
- ],
- [
- :irb_continue, :Continue, "cmd/continue",
- [:continue, NO_OVERRIDE],
- ],
- [
- :irb_finish, :Finish, "cmd/finish",
- [:finish, NO_OVERRIDE],
- ],
- [
- :irb_backtrace, :Backtrace, "cmd/backtrace",
- [:backtrace, NO_OVERRIDE],
- [:bt, NO_OVERRIDE],
- ],
- [
- :irb_debug_info, :Info, "cmd/info",
- [:info, NO_OVERRIDE],
- ],
-
- [
- :irb_help, :Help, "cmd/help",
- [:help, NO_OVERRIDE],
- ],
-
- [
- :irb_show_doc, :ShowDoc, "cmd/show_doc",
- [:show_doc, NO_OVERRIDE],
- ],
-
- [
- :irb_info, :IrbInfo, "cmd/irb_info"
- ],
-
- [
- :irb_ls, :Ls, "cmd/ls",
- [:ls, NO_OVERRIDE],
- ],
-
- [
- :irb_measure, :Measure, "cmd/measure",
- [:measure, NO_OVERRIDE],
- ],
-
- [
- :irb_show_source, :ShowSource, "cmd/show_source",
- [:show_source, NO_OVERRIDE],
- ],
-
- [
- :irb_whereami, :Whereami, "cmd/whereami",
- [:whereami, NO_OVERRIDE],
- ],
- [
- :irb_show_cmds, :ShowCmds, "cmd/show_cmds",
- [:show_cmds, NO_OVERRIDE],
- ]
- ]
-
-
- @@commands = []
-
- def self.all_commands_info
- return @@commands unless @@commands.empty?
- user_aliases = IRB.CurrentContext.command_aliases.each_with_object({}) do |(alias_name, target), result|
- result[target] ||= []
- result[target] << alias_name
- end
-
- @EXTEND_COMMANDS.each do |cmd_name, cmd_class, load_file, *aliases|
- if !defined?(ExtendCommand) || !ExtendCommand.const_defined?(cmd_class, false)
- require_relative load_file
- end
-
- klass = ExtendCommand.const_get(cmd_class, false)
- aliases = aliases.map { |a| a.first }
-
- if additional_aliases = user_aliases[cmd_name]
- aliases += additional_aliases
- end
-
- display_name = aliases.shift || cmd_name
- @@commands << { display_name: display_name, description: klass.description, category: klass.category }
- end
-
- @@commands
- end
-
- # Convert a command name to its implementation class if such command exists
- def self.load_command(command)
- command = command.to_sym
- @EXTEND_COMMANDS.each do |cmd_name, cmd_class, load_file, *aliases|
- next if cmd_name != command && aliases.all? { |alias_name, _| alias_name != command }
-
- if !defined?(ExtendCommand) || !ExtendCommand.const_defined?(cmd_class, false)
- require_relative load_file
- end
- return ExtendCommand.const_get(cmd_class, false)
- end
- nil
- end
-
- # Installs the default irb commands.
- def self.install_extend_commands
- for args in @EXTEND_COMMANDS
- def_extend_command(*args)
- end
- end
-
- # Evaluate the given +cmd_name+ on the given +cmd_class+ Class.
- #
- # Will also define any given +aliases+ for the method.
- #
- # The optional +load_file+ parameter will be required within the method
- # definition.
- def self.def_extend_command(cmd_name, cmd_class, load_file, *aliases)
- case cmd_class
- when Symbol
- cmd_class = cmd_class.id2name
- when String
- when Class
- cmd_class = cmd_class.name
- end
-
- line = __LINE__; eval %[
- def #{cmd_name}(*opts, **kwargs, &b)
- Kernel.require_relative "#{load_file}"
- ::IRB::ExtendCommand::#{cmd_class}.execute(irb_context, *opts, **kwargs, &b)
- end
- ], nil, __FILE__, line
-
- for ali, flag in aliases
- @ALIASES.push [ali, cmd_name, flag]
- end
- end
-
- # Installs alias methods for the default irb commands, see
- # ::install_extend_commands.
- def install_alias_method(to, from, override = NO_OVERRIDE)
- to = to.id2name unless to.kind_of?(String)
- from = from.id2name unless from.kind_of?(String)
-
- if override == OVERRIDE_ALL or
- (override == OVERRIDE_PRIVATE_ONLY) && !respond_to?(to) or
- (override == NO_OVERRIDE) && !respond_to?(to, true)
- target = self
- (class << self; self; end).instance_eval{
- if target.respond_to?(to, true) &&
- !target.respond_to?(EXCB.irb_original_method_name(to), true)
- alias_method(EXCB.irb_original_method_name(to), to)
- end
- alias_method to, from
- }
- else
- Kernel.warn "irb: warn: can't alias #{to} from #{from}.\n"
- end
- end
-
- def self.irb_original_method_name(method_name) # :nodoc:
- "irb_" + method_name + "_org"
- end
-
- # Installs alias methods for the default irb commands on the given object
- # using #install_alias_method.
- def self.extend_object(obj)
- unless (class << obj; ancestors; end).include?(EXCB)
- super
- for ali, com, flg in @ALIASES
- obj.install_alias_method(ali, com, flg)
- end
- end
- end
-
- install_extend_commands
- end
-
- # Extends methods for the Context module
- module ContextExtender
- CE = ContextExtender # :nodoc:
-
- @EXTEND_COMMANDS = [
- [:eval_history=, "ext/eval_history.rb"],
- [:use_tracer=, "ext/tracer.rb"],
- [:use_loader=, "ext/use-loader.rb"],
- ]
-
- # Installs the default context extensions as irb commands:
- #
- # Context#eval_history=:: +irb/ext/history.rb+
- # Context#use_tracer=:: +irb/ext/tracer.rb+
- # Context#use_loader=:: +irb/ext/use-loader.rb+
- def self.install_extend_commands
- for args in @EXTEND_COMMANDS
- def_extend_command(*args)
- end
- end
-
- # Evaluate the given +command+ from the given +load_file+ on the Context
- # module.
- #
- # Will also define any given +aliases+ for the method.
- def self.def_extend_command(cmd_name, load_file, *aliases)
- line = __LINE__; Context.module_eval %[
- def #{cmd_name}(*opts, &b)
- Context.module_eval {remove_method(:#{cmd_name})}
- require_relative "#{load_file}"
- __send__ :#{cmd_name}, *opts, &b
- end
- for ali in aliases
- alias_method ali, cmd_name
- end
- ], __FILE__, line
- end
-
- CE.install_extend_commands
- end
-end
diff --git a/lib/irb/frame.rb b/lib/irb/frame.rb
index 14768bd8f6..4b697c8719 100644
--- a/lib/irb/frame.rb
+++ b/lib/irb/frame.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#
# frame.rb -
# by Keiju ISHITSUKA(Nihon Rational Software Co.,Ltd)
diff --git a/lib/irb/help.rb b/lib/irb/help.rb
index ca12810de1..a24bc10a15 100644
--- a/lib/irb/help.rb
+++ b/lib/irb/help.rb
@@ -1,12 +1,12 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#
# irb/help.rb - print usage module
# by Keiju ISHITSUKA(keiju@ishitsuka.com)
#
module IRB
- # Outputs the irb help message, see IRB@Command+line+options.
- def IRB.print_usage
+ # Outputs the irb help message, see IRB@Command-Line+Options.
+ def IRB.print_usage # :nodoc:
lc = IRB.conf[:LC_MESSAGES]
path = lc.find("irb/help-message")
space_line = false
diff --git a/lib/irb/helper_method.rb b/lib/irb/helper_method.rb
new file mode 100644
index 0000000000..f1f6fff915
--- /dev/null
+++ b/lib/irb/helper_method.rb
@@ -0,0 +1,29 @@
+require_relative "helper_method/base"
+
+module IRB
+ module HelperMethod
+ @helper_methods = {}
+
+ class << self
+ attr_reader :helper_methods
+
+ def register(name, helper_class)
+ @helper_methods[name] = helper_class
+
+ if defined?(HelpersContainer)
+ HelpersContainer.install_helper_methods
+ end
+ end
+
+ def all_helper_methods_info
+ @helper_methods.map do |name, helper_class|
+ { display_name: name, description: helper_class.description }
+ end
+ end
+ end
+
+ # Default helper_methods
+ require_relative "helper_method/conf"
+ register(:conf, HelperMethod::Conf)
+ end
+end
diff --git a/lib/irb/helper_method/base.rb b/lib/irb/helper_method/base.rb
new file mode 100644
index 0000000000..a68001ed28
--- /dev/null
+++ b/lib/irb/helper_method/base.rb
@@ -0,0 +1,16 @@
+require "singleton"
+
+module IRB
+ module HelperMethod
+ class Base
+ include Singleton
+
+ class << self
+ def description(description = nil)
+ @description = description if description
+ @description
+ end
+ end
+ end
+ end
+end
diff --git a/lib/irb/helper_method/conf.rb b/lib/irb/helper_method/conf.rb
new file mode 100644
index 0000000000..718ed279c0
--- /dev/null
+++ b/lib/irb/helper_method/conf.rb
@@ -0,0 +1,11 @@
+module IRB
+ module HelperMethod
+ class Conf < Base
+ description "Returns the current IRB context."
+
+ def execute
+ IRB.CurrentContext
+ end
+ end
+ end
+end
diff --git a/lib/irb/history.rb b/lib/irb/history.rb
index 84d69e19cd..685354b2d8 100644
--- a/lib/irb/history.rb
+++ b/lib/irb/history.rb
@@ -1,3 +1,5 @@
+require "pathname"
+
module IRB
module HistorySavingAbility # :nodoc:
def support_history_saving?
@@ -5,7 +7,7 @@ module IRB
end
def reset_history_counter
- @loaded_history_lines = self.class::HISTORY.size if defined? @loaded_history_lines
+ @loaded_history_lines = self.class::HISTORY.size
end
def load_history
@@ -15,7 +17,7 @@ module IRB
history_file = File.expand_path(history_file)
end
history_file = IRB.rc_file("_history") unless history_file
- if File.exist?(history_file)
+ if history_file && File.exist?(history_file)
File.open(history_file, "r:#{IRB.conf[:LC_MESSAGES].encoding}") do |f|
f.each { |l|
l = l.chomp
@@ -41,6 +43,9 @@ module IRB
end
history_file = IRB.rc_file("_history") unless history_file
+ # When HOME and XDG_CONFIG_HOME are not available, history_file might be nil
+ return unless history_file
+
# Change the permission of a file that already exists[BUG #7694]
begin
if File.stat(history_file).mode & 066 != 0
@@ -59,13 +64,19 @@ module IRB
append_history = true
end
+ pathname = Pathname.new(history_file)
+ unless Dir.exist?(pathname.dirname)
+ warn "Warning: The directory to save IRB's history file does not exist. Please double check `IRB.conf[:HISTORY_FILE]`'s value."
+ return
+ end
+
File.open(history_file, (append_history ? 'a' : 'w'), 0o600, encoding: IRB.conf[:LC_MESSAGES]&.encoding) do |f|
- hist = history.map{ |l| l.split("\n").join("\\\n") }
+ hist = history.map{ |l| l.scrub.split("\n").join("\\\n") }
unless append_history
begin
hist = hist.last(num) if hist.size > num and num > 0
rescue RangeError # bignum too big to convert into `long'
- # Do nothing because the bignum should be treated as inifinity
+ # Do nothing because the bignum should be treated as infinity
end
end
f.puts(hist)
diff --git a/lib/irb/init.rb b/lib/irb/init.rb
index 470903b451..7dc08912ef 100644
--- a/lib/irb/init.rb
+++ b/lib/irb/init.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#
# irb/init.rb - irb initialize module
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
@@ -6,6 +6,7 @@
module IRB # :nodoc:
@CONF = {}
+ @INITIALIZED = false
# Displays current configuration.
#
# Modifying the configuration is achieved by sending a message to IRB.conf.
@@ -41,24 +42,27 @@ module IRB # :nodoc:
format("irb %s (%s)", @RELEASE_VERSION, @LAST_UPDATE_DATE)
end
+ def IRB.initialized?
+ !!@INITIALIZED
+ end
+
# initialize config
def IRB.setup(ap_path, argv: ::ARGV)
IRB.init_config(ap_path)
IRB.init_error
IRB.parse_opts(argv: argv)
IRB.run_config
+ IRB.validate_config
IRB.load_modules
unless @CONF[:PROMPT][@CONF[:PROMPT_MODE]]
fail UndefinedPromptMode, @CONF[:PROMPT_MODE]
end
+ @INITIALIZED = true
end
# @CONF default setting
def IRB.init_config(ap_path)
- # class instance variables
- @TRACER_INITIALIZED = false
-
# default configurations
unless ap_path and @CONF[:AP_NAME]
ap_path = File.join(File.dirname(File.dirname(__FILE__)), "irb.rb")
@@ -76,12 +80,13 @@ module IRB # :nodoc:
@CONF[:USE_SINGLELINE] = false unless defined?(ReadlineInputMethod)
@CONF[:USE_COLORIZE] = (nc = ENV['NO_COLOR']).nil? || nc.empty?
@CONF[:USE_AUTOCOMPLETE] = ENV.fetch("IRB_USE_AUTOCOMPLETE", "true") != "false"
- @CONF[:COMPLETOR] = :regexp
+ @CONF[:COMPLETOR] = ENV.fetch("IRB_COMPLETOR", "regexp").to_sym
@CONF[:INSPECT_MODE] = true
@CONF[:USE_TRACER] = false
@CONF[:USE_LOADER] = false
@CONF[:IGNORE_SIGINT] = true
@CONF[:IGNORE_EOF] = false
+ @CONF[:USE_PAGER] = true
@CONF[:EXTRA_DOC_DIRS] = []
@CONF[:ECHO] = nil
@CONF[:ECHO_ON_ASSIGNMENT] = nil
@@ -188,10 +193,6 @@ module IRB # :nodoc:
# Symbol aliases
:'$' => :show_source,
:'@' => :whereami,
- # Keyword aliases
- :break => :irb_break,
- :catch => :irb_catch,
- :next => :irb_next,
}
end
@@ -218,6 +219,7 @@ module IRB # :nodoc:
added = [:TIME, IRB.conf[:MEASURE_PROC][:TIME], arg]
end
if added
+ IRB.conf[:MEASURE] = true
found = IRB.conf[:MEASURE_CALLBACKS].find{ |m| m[0] == added[0] && m[2] == added[2] }
if found
# already added
@@ -238,6 +240,7 @@ module IRB # :nodoc:
type_sym = type.upcase.to_sym
IRB.conf[:MEASURE_CALLBACKS].reject!{ |t, | t == type_sym }
end
+ IRB.conf[:MEASURE] = nil if IRB.conf[:MEASURE_CALLBACKS].empty?
end
def IRB.init_error
@@ -285,6 +288,8 @@ module IRB # :nodoc:
end
when "--noinspect"
@CONF[:INSPECT_MODE] = false
+ when "--no-pager"
+ @CONF[:USE_PAGER] = false
when "--singleline", "--readline", "--legacy"
@CONF[:USE_SINGLELINE] = true
when "--nosingleline", "--noreadline"
@@ -388,61 +393,73 @@ module IRB # :nodoc:
$LOAD_PATH.unshift(*load_path)
end
- # running config
+ # Run the config file
def IRB.run_config
if @CONF[:RC]
- begin
- load rc_file
- rescue LoadError, Errno::ENOENT
- rescue # StandardError, ScriptError
- print "load error: #{rc_file}\n"
- print $!.class, ": ", $!, "\n"
- for err in $@[0, $@.size - 2]
- print "\t", err, "\n"
- end
+ irbrc_files.each do |rc|
+ load rc
+ rescue StandardError, ScriptError => e
+ warn "Error loading RC file '#{rc}':\n#{e.full_message(highlight: false)}"
end
end
end
IRBRC_EXT = "rc"
- def IRB.rc_file(ext = IRBRC_EXT)
- if !@CONF[:RC_NAME_GENERATOR]
- rc_file_generators do |rcgen|
- @CONF[:RC_NAME_GENERATOR] ||= rcgen
- if File.exist?(rcgen.call(IRBRC_EXT))
- @CONF[:RC_NAME_GENERATOR] = rcgen
- break
- end
- end
+
+ def IRB.rc_file(ext)
+ prepare_irbrc_name_generators
+
+ # When irbrc exist in default location
+ if (rcgen = @existing_rc_name_generators.first)
+ return rcgen.call(ext)
end
- case rc_file = @CONF[:RC_NAME_GENERATOR].call(ext)
- when String
- return rc_file
- else
- fail IllegalRCNameGenerator
+
+ # When irbrc does not exist in default location
+ rc_file_generators do |rcgen|
+ return rcgen.call(ext)
end
+
+ # When HOME and XDG_CONFIG_HOME are not available
+ nil
end
- # enumerate possible rc-file base name generators
- def IRB.rc_file_generators
- if irbrc = ENV["IRBRC"]
- yield proc{|rc| rc == "rc" ? irbrc : irbrc+rc}
+ def IRB.irbrc_files
+ prepare_irbrc_name_generators
+ @irbrc_files
+ end
+
+ def IRB.validate_config
+ conf[:IRB_NAME] = conf[:IRB_NAME].to_s
+
+ irb_rc = conf[:IRB_RC]
+ unless irb_rc.nil? || irb_rc.respond_to?(:call)
+ raise_validation_error "IRB.conf[:IRB_RC] should be a callable object. Got #{irb_rc.inspect}."
end
- if xdg_config_home = ENV["XDG_CONFIG_HOME"]
- irb_home = File.join(xdg_config_home, "irb")
- if File.directory?(irb_home)
- yield proc{|rc| irb_home + "/irb#{rc}"}
+
+ back_trace_limit = conf[:BACK_TRACE_LIMIT]
+ unless back_trace_limit.is_a?(Integer)
+ raise_validation_error "IRB.conf[:BACK_TRACE_LIMIT] should be an integer. Got #{back_trace_limit.inspect}."
+ end
+
+ prompt = conf[:PROMPT]
+ unless prompt.is_a?(Hash)
+ msg = "IRB.conf[:PROMPT] should be a Hash. Got #{prompt.inspect}."
+
+ if prompt.is_a?(Symbol)
+ msg += " Did you mean to set `IRB.conf[:PROMPT_MODE]`?"
end
+
+ raise_validation_error msg
end
- if home = ENV["HOME"]
- yield proc{|rc| home+"/.irb#{rc}"}
- yield proc{|rc| home+"/.config/irb/irb#{rc}"}
+
+ eval_history = conf[:EVAL_HISTORY]
+ unless eval_history.nil? || eval_history.is_a?(Integer)
+ raise_validation_error "IRB.conf[:EVAL_HISTORY] should be an integer. Got #{eval_history.inspect}."
end
- current_dir = Dir.pwd
- yield proc{|rc| current_dir+"/.irb#{rc}"}
- yield proc{|rc| current_dir+"/irb#{rc.sub(/\A_?/, '.')}"}
- yield proc{|rc| current_dir+"/_irb#{rc}"}
- yield proc{|rc| current_dir+"/$irb#{rc}"}
+ end
+
+ def IRB.raise_validation_error(msg)
+ raise TypeError, msg, @irbrc_files
end
# loading modules
@@ -458,6 +475,50 @@ module IRB # :nodoc:
class << IRB
private
+
+ def prepare_irbrc_name_generators
+ return if @existing_rc_name_generators
+
+ @existing_rc_name_generators = []
+ @irbrc_files = []
+ rc_file_generators do |rcgen|
+ irbrc = rcgen.call(IRBRC_EXT)
+ if File.exist?(irbrc)
+ @irbrc_files << irbrc
+ @existing_rc_name_generators << rcgen
+ end
+ end
+ generate_current_dir_irbrc_files.each do |irbrc|
+ @irbrc_files << irbrc if File.exist?(irbrc)
+ end
+ @irbrc_files.uniq!
+ end
+
+ # enumerate possible rc-file base name generators
+ def rc_file_generators
+ if irbrc = ENV["IRBRC"]
+ yield proc{|rc| rc == "rc" ? irbrc : irbrc+rc}
+ end
+ if xdg_config_home = ENV["XDG_CONFIG_HOME"]
+ irb_home = File.join(xdg_config_home, "irb")
+ if File.directory?(irb_home)
+ yield proc{|rc| irb_home + "/irb#{rc}"}
+ end
+ end
+ if home = ENV["HOME"]
+ yield proc{|rc| home+"/.irb#{rc}"}
+ if xdg_config_home.nil? || xdg_config_home.empty?
+ yield proc{|rc| home+"/.config/irb/irb#{rc}"}
+ end
+ end
+ end
+
+ # possible irbrc files in current directory
+ def generate_current_dir_irbrc_files
+ current_dir = Dir.pwd
+ %w[.irbrc irbrc _irbrc $irbrc].map { |file| "#{current_dir}/#{file}" }
+ end
+
def set_encoding(extern, intern = nil, override: true)
verbose, $VERBOSE = $VERBOSE, nil
Encoding.default_external = extern unless extern.nil? || extern.empty?
diff --git a/lib/irb/input-method.rb b/lib/irb/input-method.rb
index 94ad28cd63..ced35a2c5a 100644
--- a/lib/irb/input-method.rb
+++ b/lib/irb/input-method.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#
# irb/input-method.rb - input methods used irb
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
@@ -20,7 +20,7 @@ module IRB
#
# See IO#gets for more information.
def gets
- fail NotImplementedError, "gets"
+ fail NotImplementedError
end
public :gets
@@ -44,6 +44,10 @@ module IRB
false
end
+ def prompting?
+ false
+ end
+
# For debug message
def inspect
'Abstract InputMethod'
@@ -63,6 +67,7 @@ module IRB
#
# See IO#gets for more information.
def gets
+ puts if @stdout.tty? # workaround for debug compatibility test
print @prompt
line = @stdin.gets
@line[@line_no += 1] = line
@@ -91,6 +96,10 @@ module IRB
true
end
+ def prompting?
+ STDIN.tty?
+ end
+
# Returns the current line number for #io.
#
# #line counts the number of times #gets is called.
@@ -220,6 +229,10 @@ module IRB
@eof
end
+ def prompting?
+ true
+ end
+
# For debug message
def inspect
readline_impl = (defined?(Reline) && Readline == Reline) ? 'Reline' : 'ext/readline'
@@ -291,18 +304,35 @@ module IRB
@auto_indent_proc = block
end
+ def retrieve_doc_namespace(matched)
+ preposing, _target, postposing, bind = @completion_params
+ @completor.doc_namespace(preposing, matched, postposing, bind: bind)
+ end
+
+ def rdoc_ri_driver
+ return @rdoc_ri_driver if defined?(@rdoc_ri_driver)
+
+ begin
+ require 'rdoc'
+ rescue LoadError
+ @rdoc_ri_driver = nil
+ else
+ options = {}
+ options[:extra_doc_dirs] = IRB.conf[:EXTRA_DOC_DIRS] unless IRB.conf[:EXTRA_DOC_DIRS].empty?
+ @rdoc_ri_driver = RDoc::RI::Driver.new(options)
+ end
+ end
+
def show_doc_dialog_proc
- doc_namespace = ->(matched) {
- preposing, _target, postposing, bind = @completion_params
- @completor.doc_namespace(preposing, matched, postposing, bind: bind)
- }
+ input_method = self # self is changed in the lambda below.
->() {
dialog.trap_key = nil
alt_d = [
- [Reline::Key.new(nil, 0xE4, true)], # Normal Alt+d.
[27, 100], # Normal Alt+d when convert-meta isn't used.
- [195, 164], # The "ä" that appears when Alt+d is pressed on xterm.
- [226, 136, 130] # The "∂" that appears when Alt+d in pressed on iTerm2.
+ # When option/alt is not configured as a meta key in terminal emulator,
+ # option/alt + d will send a unicode character depend on OS keyboard setting.
+ [195, 164], # "ä" in somewhere (FIXME: environment information is unknown).
+ [226, 136, 130] # "∂" Alt+d on Mac keyboard.
]
if just_cursor_moving and completion_journey_data.nil?
@@ -311,12 +341,13 @@ module IRB
cursor_pos_to_render, result, pointer, autocomplete_dialog = context.pop(4)
return nil if result.nil? or pointer.nil? or pointer < 0
- name = doc_namespace.call(result[pointer])
+ name = input_method.retrieve_doc_namespace(result[pointer])
+ # Use first one because document dialog does not support multiple namespaces.
+ name = name.first if name.is_a?(Array)
+
show_easter_egg = name&.match?(/\ARubyVM/) && !ENV['RUBY_YES_I_AM_NOT_A_NORMAL_USER']
- options = {}
- options[:extra_doc_dirs] = IRB.conf[:EXTRA_DOC_DIRS] unless IRB.conf[:EXTRA_DOC_DIRS].empty?
- driver = RDoc::RI::Driver.new(options)
+ driver = input_method.rdoc_ri_driver
if key.match?(dialog.name)
if show_easter_egg
@@ -404,23 +435,18 @@ module IRB
}
end
- def display_document(matched, driver: nil)
- begin
- require 'rdoc'
- rescue LoadError
- return
- end
+ def display_document(matched)
+ driver = rdoc_ri_driver
+ return unless driver
if matched =~ /\A(?:::)?RubyVM/ and not ENV['RUBY_YES_I_AM_NOT_A_NORMAL_USER']
IRB.__send__(:easter_egg)
return
end
- _target, preposing, postposing, bind = @completion_params
- namespace = @completor.doc_namespace(preposing, matched, postposing, bind: bind)
+ namespace = retrieve_doc_namespace(matched)
return unless namespace
- driver ||= RDoc::RI::Driver.new
if namespace.is_a?(Array)
out = RDoc::Markup::Document.new
namespace.each do |m|
@@ -463,6 +489,10 @@ module IRB
@eof
end
+ def prompting?
+ true
+ end
+
# For debug message
def inspect
config = Reline::Config.new
diff --git a/lib/irb/inspector.rb b/lib/irb/inspector.rb
index ee3b19efdc..667087ccba 100644
--- a/lib/irb/inspector.rb
+++ b/lib/irb/inspector.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#
# irb/inspector.rb - inspect methods
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
@@ -46,7 +46,7 @@ module IRB # :nodoc:
# Determines the inspector to use where +inspector+ is one of the keys passed
# during inspector definition.
def self.keys_with_inspector(inspector)
- INSPECTORS.select{|k,v| v == inspector}.collect{|k, v| k}
+ INSPECTORS.select{|k, v| v == inspector}.collect{|k, v| k}
end
# Example
@@ -113,7 +113,7 @@ module IRB # :nodoc:
Color.colorize_code(v.inspect, colorable: Color.colorable? && Color.inspect_colorable?(v))
}
Inspector.def_inspector([true, :pp, :pretty_inspect], proc{require_relative "color_printer"}){|v|
- IRB::ColorPrinter.pp(v, '').chomp
+ IRB::ColorPrinter.pp(v, +'').chomp
}
Inspector.def_inspector([:yaml, :YAML], proc{require "yaml"}){|v|
begin
diff --git a/lib/irb/irb.gemspec b/lib/irb/irb.gemspec
index a008a39f9d..b29002f593 100644
--- a/lib/irb/irb.gemspec
+++ b/lib/irb/irb.gemspec
@@ -41,6 +41,6 @@ Gem::Specification.new do |spec|
spec.required_ruby_version = Gem::Requirement.new(">= 2.7")
- spec.add_dependency "reline", ">= 0.3.8"
- spec.add_dependency "rdoc"
+ spec.add_dependency "reline", ">= 0.4.2"
+ spec.add_dependency "rdoc", ">= 4.0.0"
end
diff --git a/lib/irb/lc/error.rb b/lib/irb/lc/error.rb
index a5ec150865..ee0f047822 100644
--- a/lib/irb/lc/error.rb
+++ b/lib/irb/lc/error.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#
# irb/lc/error.rb -
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
@@ -12,11 +12,6 @@ module IRB
super("Unrecognized switch: #{val}")
end
end
- class NotImplementedError < StandardError
- def initialize(val)
- super("Need to define `#{val}'")
- end
- end
class CantReturnToNormalMode < StandardError
def initialize
super("Can't return to normal mode.")
@@ -52,11 +47,6 @@ module IRB
super("Undefined prompt mode(#{val}).")
end
end
- class IllegalRCGenerator < StandardError
- def initialize
- super("Define illegal RC_NAME_GENERATOR.")
- end
- end
# :startdoc:
end
diff --git a/lib/irb/lc/help-message b/lib/irb/lc/help-message
index c7846b755d..37347306e8 100644
--- a/lib/irb/lc/help-message
+++ b/lib/irb/lc/help-message
@@ -22,6 +22,7 @@ Usage: irb.rb [options] [programfile] [arguments]
Show truncated result on assignment (default).
--inspect Use 'inspect' for output.
--noinspect Don't use 'inspect' for output.
+ --no-pager Don't use pager.
--multiline Use multiline editor module (default).
--nomultiline Don't use multiline editor module.
--singleline Use single line editor module.
diff --git a/lib/irb/lc/ja/error.rb b/lib/irb/lc/ja/error.rb
index 50d72c4a10..9e2e5b8870 100644
--- a/lib/irb/lc/ja/error.rb
+++ b/lib/irb/lc/ja/error.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#
# irb/lc/ja/error.rb -
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
@@ -12,11 +12,6 @@ module IRB
super("スイッãƒ(#{val})ãŒåˆ†ã‚Šã¾ã›ã‚“")
end
end
- class NotImplementedError < StandardError
- def initialize(val)
- super("`#{val}'ã®å®šç¾©ãŒå¿…è¦ã§ã™")
- end
- end
class CantReturnToNormalMode < StandardError
def initialize
super("Normalモードã«æˆ»ã‚Œã¾ã›ã‚“.")
@@ -52,11 +47,6 @@ module IRB
super("プロンプトモード(#{val})ã¯å®šç¾©ã•ã‚Œã¦ã„ã¾ã›ã‚“.")
end
end
- class IllegalRCGenerator < StandardError
- def initialize
- super("RC_NAME_GENERATORãŒæ­£ã—ã定義ã•ã‚Œã¦ã„ã¾ã›ã‚“.")
- end
- end
# :startdoc:
end
diff --git a/lib/irb/lc/ja/help-message b/lib/irb/lc/ja/help-message
index cec339cf2f..99f4449b3b 100644
--- a/lib/irb/lc/ja/help-message
+++ b/lib/irb/lc/ja/help-message
@@ -9,10 +9,18 @@ Usage: irb.rb [options] [programfile] [arguments]
-W[level=2] ruby -W ã¨åŒã˜.
--context-mode n æ–°ã—ã„ワークスペースを作æˆã—ãŸæ™‚ã«é–¢é€£ã™ã‚‹ Binding
オブジェクトã®ä½œæˆæ–¹æ³•ã‚’ 0 ã‹ã‚‰ 3 ã®ã„ãšã‚Œã‹ã«è¨­å®šã™ã‚‹.
+ --extra-doc-dir 指定ã—ãŸãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã‚’追加ã§èª­ã¿è¾¼ã‚€.
--echo 実行çµæžœã‚’表示ã™ã‚‹(デフォルト).
--noecho 実行çµæžœã‚’表示ã—ãªã„.
+ --echo-on-assignment
+ 代入çµæžœã‚’表示ã™ã‚‹.
+ --noecho-on-assignment
+ 代入çµæžœã‚’表示ã—ãªã„.
+ --truncate-echo-on-assignment
+ truncateã•ã‚ŒãŸä»£å…¥çµæžœã‚’表示ã™ã‚‹(デフォルト).
--inspect çµæžœå‡ºåŠ›ã«inspectを用ã„ã‚‹.
--noinspect çµæžœå‡ºåŠ›ã«inspectを用ã„ãªã„.
+ --no-pager ページャを使用ã—ãªã„.
--multiline マルãƒãƒ©ã‚¤ãƒ³ã‚¨ãƒ‡ã‚£ã‚¿ã‚’利用ã™ã‚‹.
--nomultiline マルãƒãƒ©ã‚¤ãƒ³ã‚¨ãƒ‡ã‚£ã‚¿ã‚’利用ã—ãªã„.
--singleline シングルラインエディタを利用ã™ã‚‹.
@@ -34,6 +42,8 @@ Usage: irb.rb [options] [programfile] [arguments]
--sample-book-mode/--simple-prompt
éžå¸¸ã«ã‚·ãƒ³ãƒ—ルãªãƒ—ロンプトを用ã„るモードã§ã™.
--noprompt プロンプト表示を行ãªã‚ãªã„.
+ --script スクリプトモード(最åˆã®å¼•æ•°ã‚’スクリプトファイルã¨ã—ã¦æ‰±ã†ã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆ)
+ --noscript 引数をargvã¨ã—ã¦æ‰±ã†.
--single-irb irb 中㧠self を実行ã—ã¦å¾—られるオブジェクトをサ
ブ irb ã¨å…±æœ‰ã™ã‚‹.
--tracer コマンド実行時ã«ãƒˆãƒ¬ãƒ¼ã‚¹ã‚’è¡Œãªã†.
diff --git a/lib/irb/locale.rb b/lib/irb/locale.rb
index f94aa0f40b..2abcc7354b 100644
--- a/lib/irb/locale.rb
+++ b/lib/irb/locale.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#
# irb/locale.rb - internationalization module
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
@@ -94,7 +94,7 @@ module IRB # :nodoc:
end
end
- def find(file , paths = $:)
+ def find(file, paths = $:)
dir = File.dirname(file)
dir = "" if dir == "."
base = File.basename(file)
diff --git a/lib/irb/nesting_parser.rb b/lib/irb/nesting_parser.rb
index 3d4db82444..5aa940cc28 100644
--- a/lib/irb/nesting_parser.rb
+++ b/lib/irb/nesting_parser.rb
@@ -12,6 +12,8 @@ module IRB
skip = false
last_tok, state, args = opens.last
case state
+ when :in_alias_undef
+ skip = t.event == :on_kw
when :in_unquoted_symbol
unless IGNORE_TOKENS.include?(t.event)
opens.pop
@@ -61,17 +63,17 @@ module IRB
if args.include?(:arg)
case t.event
when :on_nl, :on_semicolon
- # def recever.f;
+ # def receiver.f;
body = :normal
when :on_lparen
- # def recever.f()
+ # def receiver.f()
next_args << :eq
else
if t.event == :on_op && t.tok == '='
# def receiver.f =
body = :oneliner
else
- # def recever.f arg
+ # def receiver.f arg
next_args << :arg_without_paren
end
end
@@ -130,6 +132,10 @@ module IRB
opens.pop
opens << [t, nil]
end
+ when 'alias'
+ opens << [t, :in_alias_undef, 2]
+ when 'undef'
+ opens << [t, :in_alias_undef, 1]
when 'elsif', 'else', 'when'
opens.pop
opens << [t, nil]
@@ -174,6 +180,10 @@ module IRB
pending_heredocs.reverse_each { |t| opens << [t, nil] }
pending_heredocs = []
end
+ if opens.last && opens.last[1] == :in_alias_undef && !IGNORE_TOKENS.include?(t.event) && t.event != :on_heredoc_end
+ tok, state, arg = opens.pop
+ opens << [tok, state, arg - 1] if arg >= 1
+ end
yield t, opens if block_given?
end
opens.map(&:first) + pending_heredocs.reverse
diff --git a/lib/irb/notifier.rb b/lib/irb/notifier.rb
index 612de3df16..dc1b9ef14b 100644
--- a/lib/irb/notifier.rb
+++ b/lib/irb/notifier.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#
# notifier.rb - output methods used by irb
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
diff --git a/lib/irb/output-method.rb b/lib/irb/output-method.rb
index f5ea57111d..69942f47a2 100644
--- a/lib/irb/output-method.rb
+++ b/lib/irb/output-method.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#
# output-method.rb - output methods used by irb
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
@@ -9,16 +9,10 @@ module IRB
# IRB::Notifier. You can define your own output method to use with Irb.new,
# or Context.new
class OutputMethod
- class NotImplementedError < StandardError
- def initialize(val)
- super("Need to define `#{val}'")
- end
- end
-
# Open this method to implement your own output method, raises a
# NotImplementedError if you don't define #print in your own class.
def print(*opts)
- raise NotImplementedError, "print"
+ raise NotImplementedError
end
# Prints the given +opts+, with a newline delimiter.
diff --git a/lib/irb/pager.rb b/lib/irb/pager.rb
index 1194e41f6f..3391b32c66 100644
--- a/lib/irb/pager.rb
+++ b/lib/irb/pager.rb
@@ -7,9 +7,9 @@ module IRB
PAGE_COMMANDS = [ENV['RI_PAGER'], ENV['PAGER'], 'less', 'more'].compact.uniq
class << self
- def page_content(content)
+ def page_content(content, **options)
if content_exceeds_screen_height?(content)
- page do |io|
+ page(**options) do |io|
io.puts content
end
else
@@ -17,8 +17,8 @@ module IRB
end
end
- def page
- if STDIN.tty? && pager = setup_pager
+ def page(retain_content: false)
+ if should_page? && pager = setup_pager(retain_content: retain_content)
begin
pid = pager.pid
yield pager
@@ -40,6 +40,10 @@ module IRB
private
+ def should_page?
+ IRB.conf[:USE_PAGER] && STDIN.tty? && (ENV.key?("TERM") && ENV["TERM"] != "dumb")
+ end
+
def content_exceeds_screen_height?(content)
screen_height, screen_width = begin
Reline.get_screen_size
@@ -55,19 +59,20 @@ module IRB
pageable_height * screen_width < Reline::Unicode.calculate_width(content, true)
end
- def setup_pager
+ def setup_pager(retain_content:)
require 'shellwords'
- PAGE_COMMANDS.each do |pager|
- pager = Shellwords.split(pager)
- next if pager.empty?
+ PAGE_COMMANDS.each do |pager_cmd|
+ cmd = Shellwords.split(pager_cmd)
+ next if cmd.empty?
- if pager.first == 'less' || pager.first == 'more'
- pager << '-R' unless pager.include?('-R')
+ if cmd.first == 'less'
+ cmd << '-R' unless cmd.include?('-R')
+ cmd << '-X' if retain_content && !cmd.include?('-X')
end
begin
- io = IO.popen(pager, 'w')
+ io = IO.popen(cmd, 'w')
rescue
next
end
diff --git a/lib/irb/ruby-lex.rb b/lib/irb/ruby-lex.rb
index 4bce2aa6b2..f6ac7f0f5f 100644
--- a/lib/irb/ruby-lex.rb
+++ b/lib/irb/ruby-lex.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#
# irb/ruby-lex.rb - ruby lexcal analyzer
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
@@ -219,28 +219,7 @@ module IRB
:unrecoverable_error
rescue SyntaxError => e
case e.message
- when /unterminated (?:string|regexp) meets end of file/
- # "unterminated regexp meets end of file"
- #
- # example:
- # /
- #
- # "unterminated string meets end of file"
- #
- # example:
- # '
- return :recoverable_error
- when /syntax error, unexpected end-of-input/
- # "syntax error, unexpected end-of-input, expecting keyword_end"
- #
- # example:
- # if true
- # hoge
- # if false
- # fuga
- # end
- return :recoverable_error
- when /syntax error, unexpected keyword_end/
+ when /unexpected keyword_end/
# "syntax error, unexpected keyword_end"
#
# example:
@@ -250,7 +229,7 @@ module IRB
# example:
# end
return :unrecoverable_error
- when /syntax error, unexpected '\.'/
+ when /unexpected '\.'/
# "syntax error, unexpected '.'"
#
# example:
@@ -262,6 +241,27 @@ module IRB
# example:
# method / f /
return :unrecoverable_error
+ when /unterminated (?:string|regexp) meets end of file/
+ # "unterminated regexp meets end of file"
+ #
+ # example:
+ # /
+ #
+ # "unterminated string meets end of file"
+ #
+ # example:
+ # '
+ return :recoverable_error
+ when /unexpected end-of-input/
+ # "syntax error, unexpected end-of-input, expecting keyword_end"
+ #
+ # example:
+ # if true
+ # hoge
+ # if false
+ # fuga
+ # end
+ return :recoverable_error
else
return :other_error
end
@@ -290,7 +290,7 @@ module IRB
when :on_embdoc_beg
indent_level = 0
else
- indent_level += 1
+ indent_level += 1 unless t.tok == 'alias' || t.tok == 'undef'
end
end
indent_level
diff --git a/lib/irb/source_finder.rb b/lib/irb/source_finder.rb
index 959919e8ac..5d7d729d19 100644
--- a/lib/irb/source_finder.rb
+++ b/lib/irb/source_finder.rb
@@ -4,61 +4,136 @@ require_relative "ruby-lex"
module IRB
class SourceFinder
- Source = Struct.new(
- :file, # @param [String] - file name
- :first_line, # @param [String] - first line
- :last_line, # @param [String] - last line
- keyword_init: true,
- )
+ class EvaluationError < StandardError; end
+
+ class Source
+ attr_reader :file, :line
+ def initialize(file, line, ast_source = nil)
+ @file = file
+ @line = line
+ @ast_source = ast_source
+ end
+
+ def file_exist?
+ File.exist?(@file)
+ end
+
+ def binary_file?
+ # If the line is zero, it means that the target's source is probably in a binary file.
+ @line.zero?
+ end
+
+ def file_content
+ @file_content ||= File.read(@file)
+ end
+
+ def colorized_content
+ if !binary_file? && file_exist?
+ end_line = find_end
+ # To correctly colorize, we need to colorize full content and extract the relevant lines.
+ colored = IRB::Color.colorize_code(file_content)
+ colored.lines[@line - 1...end_line].join
+ elsif @ast_source
+ IRB::Color.colorize_code(@ast_source)
+ end
+ end
+
+ private
+
+ def find_end
+ lex = RubyLex.new
+ code = file_content
+ lines = code.lines[(@line - 1)..-1]
+ tokens = RubyLex.ripper_lex_without_warning(lines.join)
+ prev_tokens = []
+
+ # chunk with line number
+ tokens.chunk { |tok| tok.pos[0] }.each do |lnum, chunk|
+ code = lines[0..lnum].join
+ prev_tokens.concat chunk
+ continue = lex.should_continue?(prev_tokens)
+ syntax = lex.check_code_syntax(code, local_variables: [])
+ if !continue && syntax == :valid
+ return @line + lnum
+ end
+ end
+ @line
+ end
+ end
+
private_constant :Source
def initialize(irb_context)
@irb_context = irb_context
end
- def find_source(signature)
- context_binding = @irb_context.workspace.binding
+ def find_source(signature, super_level = 0)
case signature
- when /\A[A-Z]\w*(::[A-Z]\w*)*\z/ # Const::Name
- eval(signature, context_binding) # trigger autoload
- base = context_binding.receiver.yield_self { |r| r.is_a?(Module) ? r : Object }
- file, line = base.const_source_location(signature)
+ when /\A(::)?[A-Z]\w*(::[A-Z]\w*)*\z/ # ConstName, ::ConstName, ConstPath::ConstName
+ eval_receiver_or_owner(signature) # trigger autoload
+ *parts, name = signature.split('::', -1)
+ base =
+ if parts.empty? # ConstName
+ find_const_owner(name)
+ elsif parts == [''] # ::ConstName
+ Object
+ else # ConstPath::ConstName
+ eval_receiver_or_owner(parts.join('::'))
+ end
+ file, line = base.const_source_location(name)
when /\A(?<owner>[A-Z]\w*(::[A-Z]\w*)*)#(?<method>[^ :.]+)\z/ # Class#method
- owner = eval(Regexp.last_match[:owner], context_binding)
+ owner = eval_receiver_or_owner(Regexp.last_match[:owner])
method = Regexp.last_match[:method]
- if owner.respond_to?(:instance_method)
- methods = owner.instance_methods + owner.private_instance_methods
- file, line = owner.instance_method(method).source_location if methods.include?(method.to_sym)
- end
+ return unless owner.respond_to?(:instance_method)
+ method = method_target(owner, super_level, method, "owner")
+ file, line = method&.source_location
when /\A((?<receiver>.+)(\.|::))?(?<method>[^ :.]+)\z/ # method, receiver.method, receiver::method
- receiver = eval(Regexp.last_match[:receiver] || 'self', context_binding)
+ receiver = eval_receiver_or_owner(Regexp.last_match[:receiver] || 'self')
method = Regexp.last_match[:method]
- file, line = receiver.method(method).source_location if receiver.respond_to?(method, true)
+ return unless receiver.respond_to?(method, true)
+ method = method_target(receiver, super_level, method, "receiver")
+ file, line = method&.source_location
end
- if file && line && File.exist?(file)
- Source.new(file: file, first_line: line, last_line: find_end(file, line))
+ return unless file && line
+
+ if File.exist?(file)
+ Source.new(file, line)
+ elsif method
+ # Method defined with eval, probably in IRB session
+ source = RubyVM::AbstractSyntaxTree.of(method)&.source rescue nil
+ Source.new(file, line, source)
end
+ rescue EvaluationError
+ nil
end
private
- def find_end(file, first_line)
- lex = RubyLex.new
- lines = File.read(file).lines[(first_line - 1)..-1]
- tokens = RubyLex.ripper_lex_without_warning(lines.join)
- prev_tokens = []
-
- # chunk with line number
- tokens.chunk { |tok| tok.pos[0] }.each do |lnum, chunk|
- code = lines[0..lnum].join
- prev_tokens.concat chunk
- continue = lex.should_continue?(prev_tokens)
- syntax = lex.check_code_syntax(code, local_variables: [])
- if !continue && syntax == :valid
- return first_line + lnum
- end
+ def method_target(owner_receiver, super_level, method, type)
+ case type
+ when "owner"
+ target_method = owner_receiver.instance_method(method)
+ when "receiver"
+ target_method = owner_receiver.method(method)
+ end
+ super_level.times do |s|
+ target_method = target_method.super_method if target_method
end
- first_line
+ target_method
+ rescue NameError
+ nil
+ end
+
+ def eval_receiver_or_owner(code)
+ context_binding = @irb_context.workspace.binding
+ eval(code, context_binding)
+ rescue NameError
+ raise EvaluationError
+ end
+
+ def find_const_owner(name)
+ module_nesting = @irb_context.workspace.binding.eval('::Module.nesting')
+ module_nesting.find { |mod| mod.const_defined?(name, false) } || module_nesting.find { |mod| mod.const_defined?(name) } || Object
end
end
end
diff --git a/lib/irb/statement.rb b/lib/irb/statement.rb
index b12110600c..a3391c12a3 100644
--- a/lib/irb/statement.rb
+++ b/lib/irb/statement.rb
@@ -16,8 +16,23 @@ module IRB
raise NotImplementedError
end
- def evaluable_code
- raise NotImplementedError
+ class EmptyInput < Statement
+ def is_assignment?
+ false
+ end
+
+ def suppresses_echo?
+ true
+ end
+
+ # Debugger takes empty input to repeat the last command
+ def should_be_handled_by_debugger?
+ true
+ end
+
+ def code
+ ""
+ end
end
class Expression < Statement
@@ -37,18 +52,15 @@ module IRB
def is_assignment?
@is_assignment
end
-
- def evaluable_code
- @code
- end
end
class Command < Statement
- def initialize(code, command, arg, command_class)
- @code = code
- @command = command
- @arg = arg
+ attr_reader :command_class, :arg
+
+ def initialize(original_code, command_class, arg)
+ @code = original_code
@command_class = command_class
+ @arg = arg
end
def is_assignment?
@@ -60,20 +72,8 @@ module IRB
end
def should_be_handled_by_debugger?
- require_relative 'cmd/help'
- require_relative 'cmd/debug'
- IRB::ExtendCommand::DebugCommand > @command_class || IRB::ExtendCommand::Help == @command_class
- end
-
- def evaluable_code
- # Hook command-specific transformation to return valid Ruby code
- if @command_class.respond_to?(:transform_args)
- arg = @command_class.transform_args(@arg)
- else
- arg = @arg
- end
-
- [@command, arg].compact.join(' ')
+ require_relative 'command/debug'
+ IRB::Command::DebugCommand > @command_class
end
end
end
diff --git a/lib/irb/type_completion/completor.rb b/lib/irb/type_completion/completor.rb
deleted file mode 100644
index e893fd8adc..0000000000
--- a/lib/irb/type_completion/completor.rb
+++ /dev/null
@@ -1,235 +0,0 @@
-# frozen_string_literal: true
-
-require 'prism'
-require 'irb/completion'
-require_relative 'type_analyzer'
-
-module IRB
- module TypeCompletion
- class Completor < BaseCompletor # :nodoc:
- HIDDEN_METHODS = %w[Namespace TypeName] # defined by rbs, should be hidden
-
- class << self
- attr_accessor :last_completion_error
- end
-
- def inspect
- name = 'TypeCompletion::Completor'
- prism_info = "Prism: #{Prism::VERSION}"
- if Types.rbs_builder
- "#{name}(#{prism_info}, RBS: #{RBS::VERSION})"
- elsif Types.rbs_load_error
- "#{name}(#{prism_info}, RBS: #{Types.rbs_load_error.inspect})"
- else
- "#{name}(#{prism_info}, RBS: loading)"
- end
- end
-
- def completion_candidates(preposing, target, _postposing, bind:)
- @preposing = preposing
- verbose, $VERBOSE = $VERBOSE, nil
- code = "#{preposing}#{target}"
- @result = analyze code, bind
- name, candidates = candidates_from_result(@result)
-
- all_symbols_pattern = /\A[ -\/:-@\[-`\{-~]*\z/
- candidates.map(&:to_s).select { !_1.match?(all_symbols_pattern) && _1.start_with?(name) }.uniq.sort.map do
- target + _1[name.size..]
- end
- rescue SyntaxError, StandardError => e
- Completor.last_completion_error = e
- handle_error(e)
- []
- ensure
- $VERBOSE = verbose
- end
-
- def doc_namespace(preposing, matched, postposing, bind:)
- name = matched[/[a-zA-Z_0-9]*[!?=]?\z/]
- method_doc = -> type do
- type = type.types.find { _1.all_methods.include? name.to_sym }
- case type
- when Types::SingletonType
- "#{Types.class_name_of(type.module_or_class)}.#{name}"
- when Types::InstanceType
- "#{Types.class_name_of(type.klass)}##{name}"
- end
- end
- call_or_const_doc = -> type do
- if name =~ /\A[A-Z]/
- type = type.types.grep(Types::SingletonType).find { _1.module_or_class.const_defined?(name) }
- type.module_or_class == Object ? name : "#{Types.class_name_of(type.module_or_class)}::#{name}" if type
- else
- method_doc.call(type)
- end
- end
-
- value_doc = -> type do
- return unless type
- type.types.each do |t|
- case t
- when Types::SingletonType
- return Types.class_name_of(t.module_or_class)
- when Types::InstanceType
- return Types.class_name_of(t.klass)
- end
- end
- nil
- end
-
- case @result
- in [:call_or_const, type, _name, _self_call]
- call_or_const_doc.call type
- in [:const, type, _name, scope]
- if type
- call_or_const_doc.call type
- else
- value_doc.call scope[name]
- end
- in [:gvar, _name, scope]
- value_doc.call scope["$#{name}"]
- in [:ivar, _name, scope]
- value_doc.call scope["@#{name}"]
- in [:cvar, _name, scope]
- value_doc.call scope["@@#{name}"]
- in [:call, type, _name, _self_call]
- method_doc.call type
- in [:lvar_or_method, _name, scope]
- if scope.local_variables.include?(name)
- value_doc.call scope[name]
- else
- method_doc.call scope.self_type
- end
- else
- end
- end
-
- def candidates_from_result(result)
- candidates = case result
- in [:require, name]
- retrieve_files_to_require_from_load_path
- in [:require_relative, name]
- retrieve_files_to_require_relative_from_current_dir
- in [:call_or_const, type, name, self_call]
- ((self_call ? type.all_methods : type.methods).map(&:to_s) - HIDDEN_METHODS) | type.constants
- in [:const, type, name, scope]
- if type
- scope_constants = type.types.flat_map do |t|
- scope.table_module_constants(t.module_or_class) if t.is_a?(Types::SingletonType)
- end
- (scope_constants.compact | type.constants.map(&:to_s)).sort
- else
- scope.constants.sort | ReservedWords
- end
- in [:ivar, name, scope]
- ivars = scope.instance_variables.sort
- name == '@' ? ivars + scope.class_variables.sort : ivars
- in [:cvar, name, scope]
- scope.class_variables
- in [:gvar, name, scope]
- scope.global_variables
- in [:symbol, name]
- Symbol.all_symbols.map { _1.inspect[1..] }
- in [:call, type, name, self_call]
- (self_call ? type.all_methods : type.methods).map(&:to_s) - HIDDEN_METHODS
- in [:lvar_or_method, name, scope]
- scope.self_type.all_methods.map(&:to_s) | scope.local_variables | ReservedWords
- else
- []
- end
- [name || '', candidates]
- end
-
- def analyze(code, binding = Object::TOPLEVEL_BINDING)
- # Workaround for https://github.com/ruby/prism/issues/1592
- return if code.match?(/%[qQ]\z/)
-
- ast = Prism.parse(code, scopes: [binding.local_variables]).value
- name = code[/(@@|@|\$)?\w*[!?=]?\z/]
- *parents, target_node = find_target ast, code.bytesize - name.bytesize
- return unless target_node
-
- calculate_scope = -> { TypeAnalyzer.calculate_target_type_scope(binding, parents, target_node).last }
- calculate_type_scope = ->(node) { TypeAnalyzer.calculate_target_type_scope binding, [*parents, target_node], node }
-
- case target_node
- when Prism::StringNode, Prism::InterpolatedStringNode
- call_node, args_node = parents.last(2)
- return unless call_node.is_a?(Prism::CallNode) && call_node.receiver.nil?
- return unless args_node.is_a?(Prism::ArgumentsNode) && args_node.arguments.size == 1
-
- case call_node.name
- when :require
- [:require, name.rstrip]
- when :require_relative
- [:require_relative, name.rstrip]
- end
- when Prism::SymbolNode
- if parents.last.is_a? Prism::BlockArgumentNode # method(&:target)
- receiver_type, _scope = calculate_type_scope.call target_node
- [:call, receiver_type, name, false]
- else
- [:symbol, name] unless name.empty?
- end
- when Prism::CallNode
- return [:lvar_or_method, name, calculate_scope.call] if target_node.receiver.nil?
-
- self_call = target_node.receiver.is_a? Prism::SelfNode
- op = target_node.call_operator
- receiver_type, _scope = calculate_type_scope.call target_node.receiver
- receiver_type = receiver_type.nonnillable if op == '&.'
- [op == '::' ? :call_or_const : :call, receiver_type, name, self_call]
- when Prism::LocalVariableReadNode, Prism::LocalVariableTargetNode
- [:lvar_or_method, name, calculate_scope.call]
- when Prism::ConstantReadNode, Prism::ConstantTargetNode
- if parents.last.is_a? Prism::ConstantPathNode
- path_node = parents.last
- if path_node.parent # A::B
- receiver, scope = calculate_type_scope.call(path_node.parent)
- [:const, receiver, name, scope]
- else # ::A
- scope = calculate_scope.call
- [:const, Types::SingletonType.new(Object), name, scope]
- end
- else
- [:const, nil, name, calculate_scope.call]
- end
- when Prism::GlobalVariableReadNode, Prism::GlobalVariableTargetNode
- [:gvar, name, calculate_scope.call]
- when Prism::InstanceVariableReadNode, Prism::InstanceVariableTargetNode
- [:ivar, name, calculate_scope.call]
- when Prism::ClassVariableReadNode, Prism::ClassVariableTargetNode
- [:cvar, name, calculate_scope.call]
- end
- end
-
- def find_target(node, position)
- location = (
- case node
- when Prism::CallNode
- node.message_loc
- when Prism::SymbolNode
- node.value_loc
- when Prism::StringNode
- node.content_loc
- when Prism::InterpolatedStringNode
- node.closing_loc if node.parts.empty?
- end
- )
- return [node] if location&.start_offset == position
-
- node.compact_child_nodes.each do |n|
- match = find_target(n, position)
- next unless match
- match.unshift node
- return match
- end
-
- [node] if node.location.start_offset == position
- end
-
- def handle_error(e)
- end
- end
- end
-end
diff --git a/lib/irb/type_completion/methods.rb b/lib/irb/type_completion/methods.rb
deleted file mode 100644
index 8a88b6d0f9..0000000000
--- a/lib/irb/type_completion/methods.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module IRB
- module TypeCompletion
- module Methods
- OBJECT_SINGLETON_CLASS_METHOD = Object.instance_method(:singleton_class)
- OBJECT_INSTANCE_VARIABLES_METHOD = Object.instance_method(:instance_variables)
- OBJECT_INSTANCE_VARIABLE_GET_METHOD = Object.instance_method(:instance_variable_get)
- OBJECT_CLASS_METHOD = Object.instance_method(:class)
- MODULE_NAME_METHOD = Module.instance_method(:name)
- end
- end
-end
diff --git a/lib/irb/type_completion/scope.rb b/lib/irb/type_completion/scope.rb
deleted file mode 100644
index 5a58a0ed65..0000000000
--- a/lib/irb/type_completion/scope.rb
+++ /dev/null
@@ -1,412 +0,0 @@
-# frozen_string_literal: true
-
-require 'set'
-require_relative 'types'
-
-module IRB
- module TypeCompletion
-
- class RootScope
- attr_reader :module_nesting, :self_object
-
- def initialize(binding, self_object, local_variables)
- @binding = binding
- @self_object = self_object
- @cache = {}
- modules = [*binding.eval('::Module.nesting'), Object]
- @module_nesting = modules.map { [_1, []] }
- binding_local_variables = binding.local_variables
- uninitialized_locals = local_variables - binding_local_variables
- uninitialized_locals.each { @cache[_1] = Types::NIL }
- @local_variables = (local_variables | binding_local_variables).map(&:to_s).to_set
- @global_variables = Kernel.global_variables.map(&:to_s).to_set
- @owned_constants_cache = {}
- end
-
- def level() = 0
-
- def level_of(_name, _var_type) = 0
-
- def mutable?() = false
-
- def module_own_constant?(mod, name)
- set = (@owned_constants_cache[mod] ||= Set.new(mod.constants.map(&:to_s)))
- set.include? name
- end
-
- def get_const(nesting, path, _key = nil)
- return unless nesting
-
- result = path.reduce nesting do |mod, name|
- return nil unless mod.is_a?(Module) && module_own_constant?(mod, name)
- mod.const_get name
- end
- Types.type_from_object result
- end
-
- def get_cvar(nesting, path, name, _key = nil)
- return Types::NIL unless nesting
-
- result = path.reduce nesting do |mod, n|
- return Types::NIL unless mod.is_a?(Module) && module_own_constant?(mod, n)
- mod.const_get n
- end
- value = result.class_variable_get name if result.is_a?(Module) && name.size >= 3 && result.class_variable_defined?(name)
- Types.type_from_object value
- end
-
- def [](name)
- @cache[name] ||= (
- value = case RootScope.type_by_name name
- when :ivar
- begin
- Methods::OBJECT_INSTANCE_VARIABLE_GET_METHOD.bind_call(@self_object, name)
- rescue NameError
- end
- when :lvar
- begin
- @binding.local_variable_get(name)
- rescue NameError
- end
- when :gvar
- @binding.eval name if @global_variables.include? name
- end
- Types.type_from_object(value)
- )
- end
-
- def self_type
- Types.type_from_object @self_object
- end
-
- def local_variables() = @local_variables.to_a
-
- def global_variables() = @global_variables.to_a
-
- def self.type_by_name(name)
- if name.start_with? '@@'
- # "@@cvar" or "@@cvar::[module_id]::[module_path]"
- :cvar
- elsif name.start_with? '@'
- :ivar
- elsif name.start_with? '$'
- :gvar
- elsif name.start_with? '%'
- :internal
- elsif name[0].downcase != name[0] || name[0].match?(/\d/)
- # "ConstName" or "[module_id]::[const_path]"
- :const
- else
- :lvar
- end
- end
- end
-
- class Scope
- BREAK_RESULT = '%break'
- NEXT_RESULT = '%next'
- RETURN_RESULT = '%return'
- PATTERNMATCH_BREAK = '%match'
-
- attr_reader :parent, :mergeable_changes, :level, :module_nesting
-
- def self.from_binding(binding, locals) = new(RootScope.new(binding, binding.receiver, locals))
-
- def initialize(parent, table = {}, trace_ivar: true, trace_lvar: true, self_type: nil, nesting: nil)
- @parent = parent
- @level = parent.level + 1
- @trace_ivar = trace_ivar
- @trace_lvar = trace_lvar
- @module_nesting = nesting ? [nesting, *parent.module_nesting] : parent.module_nesting
- @self_type = self_type
- @terminated = false
- @jump_branches = []
- @mergeable_changes = @table = table.transform_values { [level, _1] }
- end
-
- def mutable? = true
-
- def terminated?
- @terminated
- end
-
- def terminate_with(type, value)
- return if terminated?
- store_jump type, value, @mergeable_changes
- terminate
- end
-
- def store_jump(type, value, changes)
- return if terminated?
- if has_own?(type)
- changes[type] = [level, value]
- @jump_branches << changes
- elsif @parent.mutable?
- @parent.store_jump(type, value, changes)
- end
- end
-
- def terminate
- return if terminated?
- @terminated = true
- @table = @mergeable_changes.dup
- end
-
- def trace?(name)
- return false unless @parent
- type = RootScope.type_by_name(name)
- type == :ivar ? @trace_ivar : type == :lvar ? @trace_lvar : true
- end
-
- def level_of(name, var_type)
- case var_type
- when :ivar
- return level unless @trace_ivar
- when :gvar
- return 0
- end
- variable_level, = @table[name]
- variable_level || parent.level_of(name, var_type)
- end
-
- def get_const(nesting, path, key = nil)
- key ||= [nesting.__id__, path].join('::')
- _l, value = @table[key]
- value || @parent.get_const(nesting, path, key)
- end
-
- def get_cvar(nesting, path, name, key = nil)
- key ||= [name, nesting.__id__, path].join('::')
- _l, value = @table[key]
- value || @parent.get_cvar(nesting, path, name, key)
- end
-
- def [](name)
- type = RootScope.type_by_name(name)
- if type == :const
- return get_const(nil, nil, name) || Types::NIL if name.include?('::')
-
- module_nesting.each do |(nesting, path)|
- value = get_const nesting, [*path, name]
- return value if value
- end
- return Types::NIL
- elsif type == :cvar
- return get_cvar(nil, nil, nil, name) if name.include?('::')
-
- nesting, path = module_nesting.first
- return get_cvar(nesting, path, name)
- end
- level, value = @table[name]
- if level
- value
- elsif trace? name
- @parent[name]
- elsif type == :ivar
- self_instance_variable_get name
- end
- end
-
- def set_const(nesting, path, value)
- key = [nesting.__id__, path].join('::')
- @table[key] = [0, value]
- end
-
- def set_cvar(nesting, path, name, value)
- key = [name, nesting.__id__, path].join('::')
- @table[key] = [0, value]
- end
-
- def []=(name, value)
- type = RootScope.type_by_name(name)
- if type == :const
- if name.include?('::')
- @table[name] = [0, value]
- else
- parent_module, parent_path = module_nesting.first
- set_const parent_module, [*parent_path, name], value
- end
- return
- elsif type == :cvar
- if name.include?('::')
- @table[name] = [0, value]
- else
- parent_module, parent_path = module_nesting.first
- set_cvar parent_module, parent_path, name, value
- end
- return
- end
- variable_level = level_of name, type
- @table[name] = [variable_level, value] if variable_level
- end
-
- def self_type
- @self_type || @parent.self_type
- end
-
- def global_variables
- gvar_keys = @table.keys.select do |name|
- RootScope.type_by_name(name) == :gvar
- end
- gvar_keys | @parent.global_variables
- end
-
- def local_variables
- lvar_keys = @table.keys.select do |name|
- RootScope.type_by_name(name) == :lvar
- end
- lvar_keys |= @parent.local_variables if @trace_lvar
- lvar_keys
- end
-
- def table_constants
- constants = module_nesting.flat_map do |mod, path|
- prefix = [mod.__id__, *path].join('::') + '::'
- @table.keys.select { _1.start_with? prefix }.map { _1.delete_prefix(prefix).split('::').first }
- end.uniq
- constants |= @parent.table_constants if @parent.mutable?
- constants
- end
-
- def table_module_constants(mod)
- prefix = "#{mod.__id__}::"
- constants = @table.keys.select { _1.start_with? prefix }.map { _1.delete_prefix(prefix).split('::').first }
- constants |= @parent.table_constants if @parent.mutable?
- constants
- end
-
- def base_scope
- @parent.mutable? ? @parent.base_scope : @parent
- end
-
- def table_instance_variables
- ivars = @table.keys.select { RootScope.type_by_name(_1) == :ivar }
- ivars |= @parent.table_instance_variables if @parent.mutable? && @trace_ivar
- ivars
- end
-
- def instance_variables
- self_singleton_types = self_type.types.grep(Types::SingletonType)
- singleton_classes = self_type.types.grep(Types::InstanceType).map(&:klass).select(&:singleton_class?)
- base_self = base_scope.self_object
- self_instance_variables = singleton_classes.flat_map do |singleton_class|
- if singleton_class.respond_to? :attached_object
- Methods::OBJECT_INSTANCE_VARIABLES_METHOD.bind_call(singleton_class.attached_object).map(&:to_s)
- elsif singleton_class == Methods::OBJECT_SINGLETON_CLASS_METHOD.bind_call(base_self)
- Methods::OBJECT_INSTANCE_VARIABLES_METHOD.bind_call(base_self).map(&:to_s)
- else
- []
- end
- end
- [
- self_singleton_types.flat_map { _1.module_or_class.instance_variables.map(&:to_s) },
- self_instance_variables || [],
- table_instance_variables
- ].inject(:|)
- end
-
- def self_instance_variable_get(name)
- self_objects = self_type.types.grep(Types::SingletonType).map(&:module_or_class)
- singleton_classes = self_type.types.grep(Types::InstanceType).map(&:klass).select(&:singleton_class?)
- base_self = base_scope.self_object
- singleton_classes.each do |singleton_class|
- if singleton_class.respond_to? :attached_object
- self_objects << singleton_class.attached_object
- elsif singleton_class == base_self.singleton_class
- self_objects << base_self
- end
- end
- types = self_objects.map do |object|
- value = begin
- Methods::OBJECT_INSTANCE_VARIABLE_GET_METHOD.bind_call(object, name)
- rescue NameError
- end
- Types.type_from_object value
- end
- Types::UnionType[*types]
- end
-
- def table_class_variables
- cvars = @table.keys.filter_map { _1.split('::', 2).first if RootScope.type_by_name(_1) == :cvar }
- cvars |= @parent.table_class_variables if @parent.mutable?
- cvars
- end
-
- def class_variables
- cvars = table_class_variables
- m, = module_nesting.first
- cvars |= m.class_variables.map(&:to_s) if m.is_a? Module
- cvars
- end
-
- def constants
- module_nesting.flat_map do |nest,|
- nest.constants
- end.map(&:to_s) | table_constants
- end
-
- def merge_jumps
- if terminated?
- @terminated = false
- @table = @mergeable_changes
- merge @jump_branches
- @terminated = true
- else
- merge [*@jump_branches, {}]
- end
- end
-
- def conditional(&block)
- run_branches(block, ->(_s) {}).first || Types::NIL
- end
-
- def never(&block)
- block.call Scope.new(self, { BREAK_RESULT => nil, NEXT_RESULT => nil, PATTERNMATCH_BREAK => nil, RETURN_RESULT => nil })
- end
-
- def run_branches(*blocks)
- results = []
- branches = []
- blocks.each do |block|
- scope = Scope.new self
- result = block.call scope
- next if scope.terminated?
- results << result
- branches << scope.mergeable_changes
- end
- terminate if branches.empty?
- merge branches
- results
- end
-
- def has_own?(name)
- @table.key? name
- end
-
- def update(child_scope)
- current_level = level
- child_scope.mergeable_changes.each do |name, (level, value)|
- self[name] = value if level <= current_level
- end
- end
-
- protected
-
- def merge(branches)
- current_level = level
- merge = {}
- branches.each do |changes|
- changes.each do |name, (level, value)|
- next if current_level < level
- (merge[name] ||= []) << value
- end
- end
- merge.each do |name, values|
- values << self[name] unless values.size == branches.size
- values.compact!
- self[name] = Types::UnionType[*values.compact] unless values.empty?
- end
- end
- end
- end
-end
diff --git a/lib/irb/type_completion/type_analyzer.rb b/lib/irb/type_completion/type_analyzer.rb
deleted file mode 100644
index c4a41e4999..0000000000
--- a/lib/irb/type_completion/type_analyzer.rb
+++ /dev/null
@@ -1,1169 +0,0 @@
-# frozen_string_literal: true
-
-require 'set'
-require_relative 'types'
-require_relative 'scope'
-require 'prism'
-
-module IRB
- module TypeCompletion
- class TypeAnalyzer
- class DigTarget
- def initialize(parents, receiver, &block)
- @dig_ids = parents.to_h { [_1.__id__, true] }
- @target_id = receiver.__id__
- @block = block
- end
-
- def dig?(node) = @dig_ids[node.__id__]
- def target?(node) = @target_id == node.__id__
- def resolve(type, scope)
- @block.call type, scope
- end
- end
-
- OBJECT_METHODS = {
- to_s: Types::STRING,
- to_str: Types::STRING,
- to_a: Types::ARRAY,
- to_ary: Types::ARRAY,
- to_h: Types::HASH,
- to_hash: Types::HASH,
- to_i: Types::INTEGER,
- to_int: Types::INTEGER,
- to_f: Types::FLOAT,
- to_c: Types::COMPLEX,
- to_r: Types::RATIONAL
- }
-
- def initialize(dig_targets)
- @dig_targets = dig_targets
- end
-
- def evaluate(node, scope)
- method = "evaluate_#{node.type}"
- if respond_to? method
- result = send method, node, scope
- else
- result = Types::NIL
- end
- @dig_targets.resolve result, scope if @dig_targets.target? node
- result
- end
-
- def evaluate_program_node(node, scope)
- evaluate node.statements, scope
- end
-
- def evaluate_statements_node(node, scope)
- if node.body.empty?
- Types::NIL
- else
- node.body.map { evaluate _1, scope }.last
- end
- end
-
- def evaluate_def_node(node, scope)
- if node.receiver
- self_type = evaluate node.receiver, scope
- else
- current_self_types = scope.self_type.types
- self_types = current_self_types.map do |type|
- if type.is_a?(Types::SingletonType) && type.module_or_class.is_a?(Class)
- Types::InstanceType.new type.module_or_class
- else
- type
- end
- end
- self_type = Types::UnionType[*self_types]
- end
- if @dig_targets.dig?(node.body) || @dig_targets.dig?(node.parameters)
- params_table = node.locals.to_h { [_1.to_s, Types::NIL] }
- method_scope = Scope.new(
- scope,
- { **params_table, Scope::BREAK_RESULT => nil, Scope::NEXT_RESULT => nil, Scope::RETURN_RESULT => nil },
- self_type: self_type,
- trace_lvar: false,
- trace_ivar: false
- )
- if node.parameters
- # node.parameters is Prism::ParametersNode
- assign_parameters node.parameters, method_scope, [], {}
- end
-
- if @dig_targets.dig?(node.body)
- method_scope.conditional do |s|
- evaluate node.body, s
- end
- end
- method_scope.merge_jumps
- scope.update method_scope
- end
- Types::SYMBOL
- end
-
- def evaluate_integer_node(_node, _scope) = Types::INTEGER
-
- def evaluate_float_node(_node, _scope) = Types::FLOAT
-
- def evaluate_rational_node(_node, _scope) = Types::RATIONAL
-
- def evaluate_imaginary_node(_node, _scope) = Types::COMPLEX
-
- def evaluate_string_node(_node, _scope) = Types::STRING
-
- def evaluate_x_string_node(_node, _scope)
- Types::UnionType[Types::STRING, Types::NIL]
- end
-
- def evaluate_symbol_node(_node, _scope) = Types::SYMBOL
-
- def evaluate_regular_expression_node(_node, _scope) = Types::REGEXP
-
- def evaluate_string_concat_node(node, scope)
- evaluate node.left, scope
- evaluate node.right, scope
- Types::STRING
- end
-
- def evaluate_interpolated_string_node(node, scope)
- node.parts.each { evaluate _1, scope }
- Types::STRING
- end
-
- def evaluate_interpolated_x_string_node(node, scope)
- node.parts.each { evaluate _1, scope }
- Types::STRING
- end
-
- def evaluate_interpolated_symbol_node(node, scope)
- node.parts.each { evaluate _1, scope }
- Types::SYMBOL
- end
-
- def evaluate_interpolated_regular_expression_node(node, scope)
- node.parts.each { evaluate _1, scope }
- Types::REGEXP
- end
-
- def evaluate_embedded_statements_node(node, scope)
- node.statements ? evaluate(node.statements, scope) : Types::NIL
- Types::STRING
- end
-
- def evaluate_embedded_variable_node(node, scope)
- evaluate node.variable, scope
- Types::STRING
- end
-
- def evaluate_array_node(node, scope)
- Types.array_of evaluate_list_splat_items(node.elements, scope)
- end
-
- def evaluate_hash_node(node, scope) = evaluate_hash(node, scope)
- def evaluate_keyword_hash_node(node, scope) = evaluate_hash(node, scope)
- def evaluate_hash(node, scope)
- keys = []
- values = []
- node.elements.each do |assoc|
- case assoc
- when Prism::AssocNode
- keys << evaluate(assoc.key, scope)
- values << evaluate(assoc.value, scope)
- when Prism::AssocSplatNode
- next unless assoc.value # def f(**); {**}
-
- hash = evaluate assoc.value, scope
- unless hash.is_a?(Types::InstanceType) && hash.klass == Hash
- hash = method_call hash, :to_hash, [], nil, nil, scope
- end
- if hash.is_a?(Types::InstanceType) && hash.klass == Hash
- keys << hash.params[:K] if hash.params[:K]
- values << hash.params[:V] if hash.params[:V]
- end
- end
- end
- if keys.empty? && values.empty?
- Types::InstanceType.new Hash
- else
- Types::InstanceType.new Hash, K: Types::UnionType[*keys], V: Types::UnionType[*values]
- end
- end
-
- def evaluate_parentheses_node(node, scope)
- node.body ? evaluate(node.body, scope) : Types::NIL
- end
-
- def evaluate_constant_path_node(node, scope)
- type, = evaluate_constant_node_info node, scope
- type
- end
-
- def evaluate_self_node(_node, scope) = scope.self_type
-
- def evaluate_true_node(_node, _scope) = Types::TRUE
-
- def evaluate_false_node(_node, _scope) = Types::FALSE
-
- def evaluate_nil_node(_node, _scope) = Types::NIL
-
- def evaluate_source_file_node(_node, _scope) = Types::STRING
-
- def evaluate_source_line_node(_node, _scope) = Types::INTEGER
-
- def evaluate_source_encoding_node(_node, _scope) = Types::InstanceType.new(Encoding)
-
- def evaluate_numbered_reference_read_node(_node, _scope)
- Types::UnionType[Types::STRING, Types::NIL]
- end
-
- def evaluate_back_reference_read_node(_node, _scope)
- Types::UnionType[Types::STRING, Types::NIL]
- end
-
- def evaluate_reference_read(node, scope)
- scope[node.name.to_s] || Types::NIL
- end
- alias evaluate_constant_read_node evaluate_reference_read
- alias evaluate_global_variable_read_node evaluate_reference_read
- alias evaluate_local_variable_read_node evaluate_reference_read
- alias evaluate_class_variable_read_node evaluate_reference_read
- alias evaluate_instance_variable_read_node evaluate_reference_read
-
-
- def evaluate_call_node(node, scope)
- is_field_assign = node.name.match?(/[^<>=!\]]=\z/) || (node.name == :[]= && !node.call_operator)
- receiver_type = node.receiver ? evaluate(node.receiver, scope) : scope.self_type
- evaluate_method = lambda do |scope|
- args_types, kwargs_types, block_sym_node, has_block = evaluate_call_node_arguments node, scope
-
- if block_sym_node
- block_sym = block_sym_node.value
- if @dig_targets.target? block_sym_node
- # method(args, &:completion_target)
- call_block_proc = ->(block_args, _self_type) do
- block_receiver = block_args.first || Types::OBJECT
- @dig_targets.resolve block_receiver, scope
- Types::OBJECT
- end
- else
- call_block_proc = ->(block_args, _self_type) do
- block_receiver, *rest = block_args
- block_receiver ? method_call(block_receiver || Types::OBJECT, block_sym, rest, nil, nil, scope) : Types::OBJECT
- end
- end
- elsif node.block.is_a? Prism::BlockNode
- call_block_proc = ->(block_args, block_self_type) do
- scope.conditional do |s|
- numbered_parameters = node.block.locals.grep(/\A_[1-9]/).map(&:to_s)
- params_table = node.block.locals.to_h { [_1.to_s, Types::NIL] }
- table = { **params_table, Scope::BREAK_RESULT => nil, Scope::NEXT_RESULT => nil }
- block_scope = Scope.new s, table, self_type: block_self_type, trace_ivar: !block_self_type
- # TODO kwargs
- if node.block.parameters&.parameters
- # node.block.parameters is Prism::BlockParametersNode
- assign_parameters node.block.parameters.parameters, block_scope, block_args, {}
- elsif !numbered_parameters.empty?
- assign_numbered_parameters numbered_parameters, block_scope, block_args, {}
- end
- result = node.block.body ? evaluate(node.block.body, block_scope) : Types::NIL
- block_scope.merge_jumps
- s.update block_scope
- nexts = block_scope[Scope::NEXT_RESULT]
- breaks = block_scope[Scope::BREAK_RESULT]
- if block_scope.terminated?
- [Types::UnionType[*nexts], breaks]
- else
- [Types::UnionType[result, *nexts], breaks]
- end
- end
- end
- elsif has_block
- call_block_proc = ->(_block_args, _self_type) { Types::OBJECT }
- end
- result = method_call receiver_type, node.name, args_types, kwargs_types, call_block_proc, scope
- if is_field_assign
- args_types.last || Types::NIL
- else
- result
- end
- end
- if node.call_operator == '&.'
- result = scope.conditional { evaluate_method.call _1 }
- if receiver_type.nillable?
- Types::UnionType[result, Types::NIL]
- else
- result
- end
- else
- evaluate_method.call scope
- end
- end
-
- def evaluate_and_node(node, scope) = evaluate_and_or(node, scope, and_op: true)
- def evaluate_or_node(node, scope) = evaluate_and_or(node, scope, and_op: false)
- def evaluate_and_or(node, scope, and_op:)
- left = evaluate node.left, scope
- right = scope.conditional { evaluate node.right, _1 }
- if and_op
- Types::UnionType[right, Types::NIL, Types::FALSE]
- else
- Types::UnionType[left, right]
- end
- end
-
- def evaluate_call_operator_write_node(node, scope) = evaluate_call_write(node, scope, :operator, node.write_name)
- def evaluate_call_and_write_node(node, scope) = evaluate_call_write(node, scope, :and, node.write_name)
- def evaluate_call_or_write_node(node, scope) = evaluate_call_write(node, scope, :or, node.write_name)
- def evaluate_index_operator_write_node(node, scope) = evaluate_call_write(node, scope, :operator, :[]=)
- def evaluate_index_and_write_node(node, scope) = evaluate_call_write(node, scope, :and, :[]=)
- def evaluate_index_or_write_node(node, scope) = evaluate_call_write(node, scope, :or, :[]=)
- def evaluate_call_write(node, scope, operator, write_name)
- receiver_type = evaluate node.receiver, scope
- if write_name == :[]=
- args_types, kwargs_types, block_sym_node, has_block = evaluate_call_node_arguments node, scope
- else
- args_types = []
- end
- if block_sym_node
- block_sym = block_sym_node.value
- call_block_proc = ->(block_args, _self_type) do
- block_receiver, *rest = block_args
- block_receiver ? method_call(block_receiver || Types::OBJECT, block_sym, rest, nil, nil, scope) : Types::OBJECT
- end
- elsif has_block
- call_block_proc = ->(_block_args, _self_type) { Types::OBJECT }
- end
- method = write_name.to_s.delete_suffix('=')
- left = method_call receiver_type, method, args_types, kwargs_types, call_block_proc, scope
- case operator
- when :and
- right = scope.conditional { evaluate node.value, _1 }
- Types::UnionType[right, Types::NIL, Types::FALSE]
- when :or
- right = scope.conditional { evaluate node.value, _1 }
- Types::UnionType[left, right]
- else
- right = evaluate node.value, scope
- method_call left, node.operator, [right], nil, nil, scope, name_match: false
- end
- end
-
- def evaluate_variable_operator_write(node, scope)
- left = scope[node.name.to_s] || Types::OBJECT
- right = evaluate node.value, scope
- scope[node.name.to_s] = method_call left, node.operator, [right], nil, nil, scope, name_match: false
- end
- alias evaluate_global_variable_operator_write_node evaluate_variable_operator_write
- alias evaluate_local_variable_operator_write_node evaluate_variable_operator_write
- alias evaluate_class_variable_operator_write_node evaluate_variable_operator_write
- alias evaluate_instance_variable_operator_write_node evaluate_variable_operator_write
-
- def evaluate_variable_and_write(node, scope)
- right = scope.conditional { evaluate node.value, scope }
- scope[node.name.to_s] = Types::UnionType[right, Types::NIL, Types::FALSE]
- end
- alias evaluate_global_variable_and_write_node evaluate_variable_and_write
- alias evaluate_local_variable_and_write_node evaluate_variable_and_write
- alias evaluate_class_variable_and_write_node evaluate_variable_and_write
- alias evaluate_instance_variable_and_write_node evaluate_variable_and_write
-
- def evaluate_variable_or_write(node, scope)
- left = scope[node.name.to_s] || Types::OBJECT
- right = scope.conditional { evaluate node.value, scope }
- scope[node.name.to_s] = Types::UnionType[left, right]
- end
- alias evaluate_global_variable_or_write_node evaluate_variable_or_write
- alias evaluate_local_variable_or_write_node evaluate_variable_or_write
- alias evaluate_class_variable_or_write_node evaluate_variable_or_write
- alias evaluate_instance_variable_or_write_node evaluate_variable_or_write
-
- def evaluate_constant_operator_write_node(node, scope)
- left = scope[node.name.to_s] || Types::OBJECT
- right = evaluate node.value, scope
- scope[node.name.to_s] = method_call left, node.operator, [right], nil, nil, scope, name_match: false
- end
-
- def evaluate_constant_and_write_node(node, scope)
- right = scope.conditional { evaluate node.value, scope }
- scope[node.name.to_s] = Types::UnionType[right, Types::NIL, Types::FALSE]
- end
-
- def evaluate_constant_or_write_node(node, scope)
- left = scope[node.name.to_s] || Types::OBJECT
- right = scope.conditional { evaluate node.value, scope }
- scope[node.name.to_s] = Types::UnionType[left, right]
- end
-
- def evaluate_constant_path_operator_write_node(node, scope)
- left, receiver, _parent_module, name = evaluate_constant_node_info node.target, scope
- right = evaluate node.value, scope
- value = method_call left, node.operator, [right], nil, nil, scope, name_match: false
- const_path_write receiver, name, value, scope
- value
- end
-
- def evaluate_constant_path_and_write_node(node, scope)
- _left, receiver, _parent_module, name = evaluate_constant_node_info node.target, scope
- right = scope.conditional { evaluate node.value, scope }
- value = Types::UnionType[right, Types::NIL, Types::FALSE]
- const_path_write receiver, name, value, scope
- value
- end
-
- def evaluate_constant_path_or_write_node(node, scope)
- left, receiver, _parent_module, name = evaluate_constant_node_info node.target, scope
- right = scope.conditional { evaluate node.value, scope }
- value = Types::UnionType[left, right]
- const_path_write receiver, name, value, scope
- value
- end
-
- def evaluate_constant_path_write_node(node, scope)
- receiver = evaluate node.target.parent, scope if node.target.parent
- value = evaluate node.value, scope
- const_path_write receiver, node.target.child.name.to_s, value, scope
- value
- end
-
- def evaluate_lambda_node(node, scope)
- local_table = node.locals.to_h { [_1.to_s, Types::OBJECT] }
- block_scope = Scope.new scope, { **local_table, Scope::BREAK_RESULT => nil, Scope::NEXT_RESULT => nil, Scope::RETURN_RESULT => nil }
- block_scope.conditional do |s|
- assign_parameters node.parameters.parameters, s, [], {} if node.parameters&.parameters
- evaluate node.body, s if node.body
- end
- block_scope.merge_jumps
- scope.update block_scope
- Types::PROC
- end
-
- def evaluate_reference_write(node, scope)
- scope[node.name.to_s] = evaluate node.value, scope
- end
- alias evaluate_constant_write_node evaluate_reference_write
- alias evaluate_global_variable_write_node evaluate_reference_write
- alias evaluate_local_variable_write_node evaluate_reference_write
- alias evaluate_class_variable_write_node evaluate_reference_write
- alias evaluate_instance_variable_write_node evaluate_reference_write
-
- def evaluate_multi_write_node(node, scope)
- evaluated_receivers = {}
- evaluate_multi_write_receiver node, scope, evaluated_receivers
- value = (
- if node.value.is_a? Prism::ArrayNode
- if node.value.elements.any?(Prism::SplatNode)
- evaluate node.value, scope
- else
- node.value.elements.map do |n|
- evaluate n, scope
- end
- end
- elsif node.value
- evaluate node.value, scope
- else
- Types::NIL
- end
- )
- evaluate_multi_write node, value, scope, evaluated_receivers
- value.is_a?(Array) ? Types.array_of(*value) : value
- end
-
- def evaluate_if_node(node, scope) = evaluate_if_unless(node, scope)
- def evaluate_unless_node(node, scope) = evaluate_if_unless(node, scope)
- def evaluate_if_unless(node, scope)
- evaluate node.predicate, scope
- Types::UnionType[*scope.run_branches(
- -> { node.statements ? evaluate(node.statements, _1) : Types::NIL },
- -> { node.consequent ? evaluate(node.consequent, _1) : Types::NIL }
- )]
- end
-
- def evaluate_else_node(node, scope)
- node.statements ? evaluate(node.statements, scope) : Types::NIL
- end
-
- def evaluate_while_until(node, scope)
- inner_scope = Scope.new scope, { Scope::BREAK_RESULT => nil }
- evaluate node.predicate, inner_scope
- if node.statements
- inner_scope.conditional do |s|
- evaluate node.statements, s
- end
- end
- inner_scope.merge_jumps
- scope.update inner_scope
- breaks = inner_scope[Scope::BREAK_RESULT]
- breaks ? Types::UnionType[breaks, Types::NIL] : Types::NIL
- end
- alias evaluate_while_node evaluate_while_until
- alias evaluate_until_node evaluate_while_until
-
- def evaluate_break_node(node, scope) = evaluate_jump(node, scope, :break)
- def evaluate_next_node(node, scope) = evaluate_jump(node, scope, :next)
- def evaluate_return_node(node, scope) = evaluate_jump(node, scope, :return)
- def evaluate_jump(node, scope, mode)
- internal_key = (
- case mode
- when :break
- Scope::BREAK_RESULT
- when :next
- Scope::NEXT_RESULT
- when :return
- Scope::RETURN_RESULT
- end
- )
- jump_value = (
- arguments = node.arguments&.arguments
- if arguments.nil? || arguments.empty?
- Types::NIL
- elsif arguments.size == 1 && !arguments.first.is_a?(Prism::SplatNode)
- evaluate arguments.first, scope
- else
- Types.array_of evaluate_list_splat_items(arguments, scope)
- end
- )
- scope.terminate_with internal_key, jump_value
- Types::NIL
- end
-
- def evaluate_yield_node(node, scope)
- evaluate_list_splat_items node.arguments.arguments, scope if node.arguments
- Types::OBJECT
- end
-
- def evaluate_redo_node(_node, scope)
- scope.terminate
- Types::NIL
- end
-
- def evaluate_retry_node(_node, scope)
- scope.terminate
- Types::NIL
- end
-
- def evaluate_forwarding_super_node(_node, _scope) = Types::OBJECT
-
- def evaluate_super_node(node, scope)
- evaluate_list_splat_items node.arguments.arguments, scope if node.arguments
- Types::OBJECT
- end
-
- def evaluate_begin_node(node, scope)
- return_type = node.statements ? evaluate(node.statements, scope) : Types::NIL
- if node.rescue_clause
- if node.else_clause
- return_types = scope.run_branches(
- ->{ evaluate node.rescue_clause, _1 },
- ->{ evaluate node.else_clause, _1 }
- )
- else
- return_types = [
- return_type,
- scope.conditional { evaluate node.rescue_clause, _1 }
- ]
- end
- return_type = Types::UnionType[*return_types]
- end
- if node.ensure_clause&.statements
- # ensure_clause is Prism::EnsureNode
- evaluate node.ensure_clause.statements, scope
- end
- return_type
- end
-
- def evaluate_rescue_node(node, scope)
- run_rescue = lambda do |s|
- if node.reference
- error_classes_type = evaluate_list_splat_items node.exceptions, s
- error_types = error_classes_type.types.filter_map do
- Types::InstanceType.new _1.module_or_class if _1.is_a?(Types::SingletonType)
- end
- error_types << Types::InstanceType.new(StandardError) if error_types.empty?
- error_type = Types::UnionType[*error_types]
- case node.reference
- when Prism::LocalVariableTargetNode, Prism::InstanceVariableTargetNode, Prism::ClassVariableTargetNode, Prism::GlobalVariableTargetNode, Prism::ConstantTargetNode
- s[node.reference.name.to_s] = error_type
- when Prism::CallNode
- evaluate node.reference, s
- end
- end
- node.statements ? evaluate(node.statements, s) : Types::NIL
- end
- if node.consequent # begin; rescue A; rescue B; end
- types = scope.run_branches(
- run_rescue,
- -> { evaluate node.consequent, _1 }
- )
- Types::UnionType[*types]
- else
- run_rescue.call scope
- end
- end
-
- def evaluate_rescue_modifier_node(node, scope)
- a = evaluate node.expression, scope
- b = scope.conditional { evaluate node.rescue_expression, _1 }
- Types::UnionType[a, b]
- end
-
- def evaluate_singleton_class_node(node, scope)
- klass_types = evaluate(node.expression, scope).types.filter_map do |type|
- Types::SingletonType.new type.klass if type.is_a? Types::InstanceType
- end
- klass_types = [Types::CLASS] if klass_types.empty?
- table = node.locals.to_h { [_1.to_s, Types::NIL] }
- sclass_scope = Scope.new(
- scope,
- { **table, Scope::BREAK_RESULT => nil, Scope::NEXT_RESULT => nil, Scope::RETURN_RESULT => nil },
- trace_ivar: false,
- trace_lvar: false,
- self_type: Types::UnionType[*klass_types]
- )
- result = node.body ? evaluate(node.body, sclass_scope) : Types::NIL
- scope.update sclass_scope
- result
- end
-
- def evaluate_class_node(node, scope) = evaluate_class_module(node, scope, true)
- def evaluate_module_node(node, scope) = evaluate_class_module(node, scope, false)
- def evaluate_class_module(node, scope, is_class)
- unless node.constant_path.is_a?(Prism::ConstantReadNode) || node.constant_path.is_a?(Prism::ConstantPathNode)
- # Incomplete class/module `class (statement[cursor_here])::Name; end`
- evaluate node.constant_path, scope
- return Types::NIL
- end
- const_type, _receiver, parent_module, name = evaluate_constant_node_info node.constant_path, scope
- if is_class
- select_class_type = -> { _1.is_a?(Types::SingletonType) && _1.module_or_class.is_a?(Class) }
- module_types = const_type.types.select(&select_class_type)
- module_types += evaluate(node.superclass, scope).types.select(&select_class_type) if node.superclass
- module_types << Types::CLASS if module_types.empty?
- else
- module_types = const_type.types.select { _1.is_a?(Types::SingletonType) && !_1.module_or_class.is_a?(Class) }
- module_types << Types::MODULE if module_types.empty?
- end
- return Types::NIL unless node.body
-
- table = node.locals.to_h { [_1.to_s, Types::NIL] }
- if !name.empty? && (parent_module.is_a?(Module) || parent_module.nil?)
- value = parent_module.const_get name if parent_module&.const_defined? name
- unless value
- value_type = scope[name]
- value = value_type.module_or_class if value_type.is_a? Types::SingletonType
- end
-
- if value.is_a? Module
- nesting = [value, []]
- else
- if parent_module
- nesting = [parent_module, [name]]
- else
- parent_nesting, parent_path = scope.module_nesting.first
- nesting = [parent_nesting, parent_path + [name]]
- end
- nesting_key = [nesting[0].__id__, nesting[1]].join('::')
- nesting_value = is_class ? Types::CLASS : Types::MODULE
- end
- else
- # parent_module == :unknown
- # TODO: dummy module
- end
- module_scope = Scope.new(
- scope,
- { **table, Scope::BREAK_RESULT => nil, Scope::NEXT_RESULT => nil, Scope::RETURN_RESULT => nil },
- trace_ivar: false,
- trace_lvar: false,
- self_type: Types::UnionType[*module_types],
- nesting: nesting
- )
- module_scope[nesting_key] = nesting_value if nesting_value
- result = evaluate(node.body, module_scope)
- scope.update module_scope
- result
- end
-
- def evaluate_for_node(node, scope)
- node.statements
- collection = evaluate node.collection, scope
- inner_scope = Scope.new scope, { Scope::BREAK_RESULT => nil }
- ary_type = method_call collection, :to_ary, [], nil, nil, nil, name_match: false
- element_types = ary_type.types.filter_map do |ary|
- ary.params[:Elem] if ary.is_a?(Types::InstanceType) && ary.klass == Array
- end
- element_type = Types::UnionType[*element_types]
- inner_scope.conditional do |s|
- evaluate_write node.index, element_type, s, nil
- evaluate node.statements, s if node.statements
- end
- inner_scope.merge_jumps
- scope.update inner_scope
- breaks = inner_scope[Scope::BREAK_RESULT]
- breaks ? Types::UnionType[breaks, collection] : collection
- end
-
- def evaluate_case_node(node, scope)
- target = evaluate(node.predicate, scope) if node.predicate
- # TODO
- branches = node.conditions.map do |condition|
- ->(s) { evaluate_case_match target, condition, s }
- end
- if node.consequent
- branches << ->(s) { evaluate node.consequent, s }
- elsif node.conditions.any? { _1.is_a? Prism::WhenNode }
- branches << ->(_s) { Types::NIL }
- end
- Types::UnionType[*scope.run_branches(*branches)]
- end
-
- def evaluate_match_required_node(node, scope)
- value_type = evaluate node.value, scope
- evaluate_match_pattern value_type, node.pattern, scope
- Types::NIL # void value
- end
-
- def evaluate_match_predicate_node(node, scope)
- value_type = evaluate node.value, scope
- scope.conditional { evaluate_match_pattern value_type, node.pattern, _1 }
- Types::BOOLEAN
- end
-
- def evaluate_range_node(node, scope)
- beg_type = evaluate node.left, scope if node.left
- end_type = evaluate node.right, scope if node.right
- elem = (Types::UnionType[*[beg_type, end_type].compact]).nonnillable
- Types::InstanceType.new Range, Elem: elem
- end
-
- def evaluate_defined_node(node, scope)
- scope.conditional { evaluate node.value, _1 }
- Types::UnionType[Types::STRING, Types::NIL]
- end
-
- def evaluate_flip_flop_node(node, scope)
- scope.conditional { evaluate node.left, _1 } if node.left
- scope.conditional { evaluate node.right, _1 } if node.right
- Types::BOOLEAN
- end
-
- def evaluate_multi_target_node(node, scope)
- # Raw MultiTargetNode, incomplete code like `a,b`, `*a`.
- evaluate_multi_write_receiver node, scope, nil
- Types::NIL
- end
-
- def evaluate_splat_node(node, scope)
- # Raw SplatNode, incomplete code like `*a.`
- evaluate_multi_write_receiver node.expression, scope, nil if node.expression
- Types::NIL
- end
-
- def evaluate_implicit_node(node, scope)
- evaluate node.value, scope
- end
-
- def evaluate_match_write_node(node, scope)
- # /(?<a>)(?<b>)/ =~ string
- evaluate node.call, scope
- node.locals.each { scope[_1.to_s] = Types::UnionType[Types::STRING, Types::NIL] }
- Types::BOOLEAN
- end
-
- def evaluate_match_last_line_node(_node, _scope)
- Types::BOOLEAN
- end
-
- def evaluate_interpolated_match_last_line_node(node, scope)
- node.parts.each { evaluate _1, scope }
- Types::BOOLEAN
- end
-
- def evaluate_pre_execution_node(node, scope)
- node.statements ? evaluate(node.statements, scope) : Types::NIL
- end
-
- def evaluate_post_execution_node(node, scope)
- node.statements && @dig_targets.dig?(node.statements) ? evaluate(node.statements, scope) : Types::NIL
- end
-
- def evaluate_alias_method_node(_node, _scope) = Types::NIL
- def evaluate_alias_global_variable_node(_node, _scope) = Types::NIL
- def evaluate_undef_node(_node, _scope) = Types::NIL
- def evaluate_missing_node(_node, _scope) = Types::NIL
-
- def evaluate_call_node_arguments(call_node, scope)
- # call_node.arguments is Prism::ArgumentsNode
- arguments = call_node.arguments&.arguments&.dup || []
- block_arg = call_node.block.expression if call_node.block.is_a?(Prism::BlockArgumentNode)
- kwargs = arguments.pop.elements if arguments.last.is_a?(Prism::KeywordHashNode)
- args_types = arguments.map do |arg|
- case arg
- when Prism::ForwardingArgumentsNode
- # `f(a, ...)` treat like splat
- nil
- when Prism::SplatNode
- evaluate arg.expression, scope if arg.expression
- nil # TODO: splat
- else
- evaluate arg, scope
- end
- end
- if kwargs
- kwargs_types = kwargs.map do |arg|
- case arg
- when Prism::AssocNode
- if arg.key.is_a?(Prism::SymbolNode)
- [arg.key.value, evaluate(arg.value, scope)]
- else
- evaluate arg.key, scope
- evaluate arg.value, scope
- nil
- end
- when Prism::AssocSplatNode
- evaluate arg.value, scope if arg.value
- nil
- end
- end.compact.to_h
- end
- if block_arg.is_a? Prism::SymbolNode
- block_sym_node = block_arg
- elsif block_arg
- evaluate block_arg, scope
- end
- [args_types, kwargs_types, block_sym_node, !!block_arg]
- end
-
- def const_path_write(receiver, name, value, scope)
- if receiver # receiver::A = value
- singleton_type = receiver.types.find { _1.is_a? Types::SingletonType }
- scope.set_const singleton_type.module_or_class, name, value if singleton_type
- else # ::A = value
- scope.set_const Object, name, value
- end
- end
-
- def assign_required_parameter(node, value, scope)
- case node
- when Prism::RequiredParameterNode
- scope[node.name.to_s] = value || Types::OBJECT
- when Prism::MultiTargetNode
- parameters = [*node.lefts, *node.rest, *node.rights]
- values = value ? sized_splat(value, :to_ary, parameters.size) : []
- parameters.zip values do |n, v|
- assign_required_parameter n, v, scope
- end
- when Prism::SplatNode
- splat_value = value ? Types.array_of(value) : Types::ARRAY
- assign_required_parameter node.expression, splat_value, scope if node.expression
- end
- end
-
- def evaluate_constant_node_info(node, scope)
- case node
- when Prism::ConstantPathNode
- name = node.child.name.to_s
- if node.parent
- receiver = evaluate node.parent, scope
- if receiver.is_a? Types::SingletonType
- parent_module = receiver.module_or_class
- end
- else
- parent_module = Object
- end
- if parent_module
- type = scope.get_const(parent_module, [name]) || Types::NIL
- else
- parent_module = :unknown
- type = Types::NIL
- end
- when Prism::ConstantReadNode
- name = node.name.to_s
- type = scope[name]
- end
- @dig_targets.resolve type, scope if @dig_targets.target? node
- [type, receiver, parent_module, name]
- end
-
-
- def assign_parameters(node, scope, args, kwargs)
- args = args.dup
- kwargs = kwargs.dup
- size = node.requireds.size + node.optionals.size + (node.rest ? 1 : 0) + node.posts.size
- args = sized_splat(args.first, :to_ary, size) if size >= 2 && args.size == 1
- reqs = args.shift node.requireds.size
- if node.rest
- # node.rest is Prism::RestParameterNode
- posts = []
- opts = args.shift node.optionals.size
- rest = args
- else
- posts = args.pop node.posts.size
- opts = args
- rest = []
- end
- node.requireds.zip reqs do |n, v|
- assign_required_parameter n, v, scope
- end
- node.optionals.zip opts do |n, v|
- # n is Prism::OptionalParameterNode
- values = [v]
- values << evaluate(n.value, scope) if n.value
- scope[n.name.to_s] = Types::UnionType[*values.compact]
- end
- node.posts.zip posts do |n, v|
- assign_required_parameter n, v, scope
- end
- if node.rest&.name
- # node.rest is Prism::RestParameterNode
- scope[node.rest.name.to_s] = Types.array_of(*rest)
- end
- node.keywords.each do |n|
- name = n.name.to_s.delete(':')
- values = [kwargs.delete(name)]
- # n is Prism::OptionalKeywordParameterNode (has n.value) or Prism::RequiredKeywordParameterNode (does not have n.value)
- values << evaluate(n.value, scope) if n.respond_to?(:value)
- scope[name] = Types::UnionType[*values.compact]
- end
- # node.keyword_rest is Prism::KeywordRestParameterNode or Prism::ForwardingParameterNode or Prism::NoKeywordsParameterNode
- if node.keyword_rest.is_a?(Prism::KeywordRestParameterNode) && node.keyword_rest.name
- scope[node.keyword_rest.name.to_s] = Types::InstanceType.new(Hash, K: Types::SYMBOL, V: Types::UnionType[*kwargs.values])
- end
- if node.block&.name
- # node.block is Prism::BlockParameterNode
- scope[node.block.name.to_s] = Types::PROC
- end
- end
-
- def assign_numbered_parameters(numbered_parameters, scope, args, _kwargs)
- return if numbered_parameters.empty?
- max_num = numbered_parameters.map { _1[1].to_i }.max
- if max_num == 1
- scope['_1'] = args.first || Types::NIL
- else
- args = sized_splat(args.first, :to_ary, max_num) if args.size == 1
- numbered_parameters.each do |name|
- index = name[1].to_i - 1
- scope[name] = args[index] || Types::NIL
- end
- end
- end
-
- def evaluate_case_match(target, node, scope)
- case node
- when Prism::WhenNode
- node.conditions.each { evaluate _1, scope }
- node.statements ? evaluate(node.statements, scope) : Types::NIL
- when Prism::InNode
- pattern = node.pattern
- if pattern.is_a?(Prism::IfNode) || pattern.is_a?(Prism::UnlessNode)
- cond_node = pattern.predicate
- pattern = pattern.statements.body.first
- end
- evaluate_match_pattern(target, pattern, scope)
- evaluate cond_node, scope if cond_node # TODO: conditional branch
- node.statements ? evaluate(node.statements, scope) : Types::NIL
- end
- end
-
- def evaluate_match_pattern(value, pattern, scope)
- # TODO: scope.terminate_with Scope::PATTERNMATCH_BREAK, Types::NIL
- case pattern
- when Prism::FindPatternNode
- # TODO
- evaluate_match_pattern Types::OBJECT, pattern.left, scope
- pattern.requireds.each { evaluate_match_pattern Types::OBJECT, _1, scope }
- evaluate_match_pattern Types::OBJECT, pattern.right, scope
- when Prism::ArrayPatternNode
- # TODO
- pattern.requireds.each { evaluate_match_pattern Types::OBJECT, _1, scope }
- evaluate_match_pattern Types::OBJECT, pattern.rest, scope if pattern.rest
- pattern.posts.each { evaluate_match_pattern Types::OBJECT, _1, scope }
- Types::ARRAY
- when Prism::HashPatternNode
- # TODO
- pattern.elements.each { evaluate_match_pattern Types::OBJECT, _1, scope }
- if pattern.respond_to?(:rest) && pattern.rest
- evaluate_match_pattern Types::OBJECT, pattern.rest, scope
- end
- Types::HASH
- when Prism::AssocNode
- evaluate_match_pattern value, pattern.value, scope if pattern.value
- Types::OBJECT
- when Prism::AssocSplatNode
- # TODO
- evaluate_match_pattern Types::HASH, pattern.value, scope
- Types::OBJECT
- when Prism::PinnedVariableNode
- evaluate pattern.variable, scope
- when Prism::PinnedExpressionNode
- evaluate pattern.expression, scope
- when Prism::LocalVariableTargetNode
- scope[pattern.name.to_s] = value
- when Prism::AlternationPatternNode
- Types::UnionType[evaluate_match_pattern(value, pattern.left, scope), evaluate_match_pattern(value, pattern.right, scope)]
- when Prism::CapturePatternNode
- capture_type = class_or_value_to_instance evaluate_match_pattern(value, pattern.value, scope)
- value = capture_type unless capture_type.types.empty? || capture_type.types == [Types::OBJECT]
- evaluate_match_pattern value, pattern.target, scope
- when Prism::SplatNode
- value = Types.array_of value
- evaluate_match_pattern value, pattern.expression, scope if pattern.expression
- value
- else
- # literal node
- type = evaluate(pattern, scope)
- class_or_value_to_instance(type)
- end
- end
-
- def class_or_value_to_instance(type)
- instance_types = type.types.map do |t|
- t.is_a?(Types::SingletonType) ? Types::InstanceType.new(t.module_or_class) : t
- end
- Types::UnionType[*instance_types]
- end
-
- def evaluate_write(node, value, scope, evaluated_receivers)
- case node
- when Prism::MultiTargetNode
- evaluate_multi_write node, value, scope, evaluated_receivers
- when Prism::CallNode
- evaluated_receivers&.[](node.receiver) || evaluate(node.receiver, scope) if node.receiver
- when Prism::SplatNode
- evaluate_write node.expression, Types.array_of(value), scope, evaluated_receivers if node.expression
- when Prism::LocalVariableTargetNode, Prism::GlobalVariableTargetNode, Prism::InstanceVariableTargetNode, Prism::ClassVariableTargetNode, Prism::ConstantTargetNode
- scope[node.name.to_s] = value
- when Prism::ConstantPathTargetNode
- receiver = evaluated_receivers&.[](node.parent) || evaluate(node.parent, scope) if node.parent
- const_path_write receiver, node.child.name.to_s, value, scope
- value
- end
- end
-
- def evaluate_multi_write(node, values, scope, evaluated_receivers)
- pre_targets = node.lefts
- splat_target = node.rest
- post_targets = node.rights
- size = pre_targets.size + (splat_target ? 1 : 0) + post_targets.size
- values = values.is_a?(Array) ? values.dup : sized_splat(values, :to_ary, size)
- pre_pairs = pre_targets.zip(values.shift(pre_targets.size))
- post_pairs = post_targets.zip(values.pop(post_targets.size))
- splat_pairs = splat_target ? [[splat_target, Types::UnionType[*values]]] : []
- (pre_pairs + splat_pairs + post_pairs).each do |target, value|
- evaluate_write target, value || Types::NIL, scope, evaluated_receivers
- end
- end
-
- def evaluate_multi_write_receiver(node, scope, evaluated_receivers)
- case node
- when Prism::MultiWriteNode, Prism::MultiTargetNode
- targets = [*node.lefts, *node.rest, *node.rights]
- targets.each { evaluate_multi_write_receiver _1, scope, evaluated_receivers }
- when Prism::CallNode
- if node.receiver
- receiver = evaluate(node.receiver, scope)
- evaluated_receivers[node.receiver] = receiver if evaluated_receivers
- end
- if node.arguments
- node.arguments.arguments&.each do |arg|
- if arg.is_a? Prism::SplatNode
- evaluate arg.expression, scope
- else
- evaluate arg, scope
- end
- end
- end
- when Prism::SplatNode
- evaluate_multi_write_receiver node.expression, scope, evaluated_receivers if node.expression
- end
- end
-
- def evaluate_list_splat_items(list, scope)
- items = list.flat_map do |node|
- if node.is_a? Prism::SplatNode
- next unless node.expression # def f(*); [*]
-
- splat = evaluate node.expression, scope
- array_elem, non_array = partition_to_array splat.nonnillable, :to_a
- [*array_elem, *non_array]
- else
- evaluate node, scope
- end
- end.compact.uniq
- Types::UnionType[*items]
- end
-
- def sized_splat(value, method, size)
- array_elem, non_array = partition_to_array value, method
- values = [Types::UnionType[*array_elem, *non_array]]
- values += [array_elem] * (size - 1) if array_elem && size >= 1
- values
- end
-
- def partition_to_array(value, method)
- arrays, non_arrays = value.types.partition { _1.is_a?(Types::InstanceType) && _1.klass == Array }
- non_arrays.select! do |type|
- to_array_result = method_call type, method, [], nil, nil, nil, name_match: false
- if to_array_result.is_a?(Types::InstanceType) && to_array_result.klass == Array
- arrays << to_array_result
- false
- else
- true
- end
- end
- array_elem = arrays.empty? ? nil : Types::UnionType[*arrays.map { _1.params[:Elem] || Types::OBJECT }]
- non_array = non_arrays.empty? ? nil : Types::UnionType[*non_arrays]
- [array_elem, non_array]
- end
-
- def method_call(receiver, method_name, args, kwargs, block, scope, name_match: true)
- methods = Types.rbs_methods receiver, method_name.to_sym, args, kwargs, !!block
- block_called = false
- type_breaks = methods.map do |method, given_params, method_params|
- receiver_vars = receiver.is_a?(Types::InstanceType) ? receiver.params : {}
- free_vars = method.type.free_variables - receiver_vars.keys.to_set
- vars = receiver_vars.merge Types.match_free_variables(free_vars, method_params, given_params)
- if block && method.block
- params_type = method.block.type.required_positionals.map do |func_param|
- Types.from_rbs_type func_param.type, receiver, vars
- end
- self_type = Types.from_rbs_type method.block.self_type, receiver, vars if method.block.self_type
- block_response, breaks = block.call params_type, self_type
- block_called = true
- vars.merge! Types.match_free_variables(free_vars - vars.keys.to_set, [method.block.type.return_type], [block_response])
- end
- if Types.method_return_bottom?(method)
- [nil, breaks]
- else
- [Types.from_rbs_type(method.type.return_type, receiver, vars || {}), breaks]
- end
- end
- block&.call [], nil unless block_called
- terminates = !type_breaks.empty? && type_breaks.map(&:first).all?(&:nil?)
- types = type_breaks.map(&:first).compact
- breaks = type_breaks.map(&:last).compact
- types << OBJECT_METHODS[method_name.to_sym] if name_match && OBJECT_METHODS.has_key?(method_name.to_sym)
-
- if method_name.to_sym == :new
- receiver.types.each do |type|
- if type.is_a?(Types::SingletonType) && type.module_or_class.is_a?(Class)
- types << Types::InstanceType.new(type.module_or_class)
- end
- end
- end
- scope&.terminate if terminates && breaks.empty?
- Types::UnionType[*types, *breaks]
- end
-
- def self.calculate_target_type_scope(binding, parents, target)
- dig_targets = DigTarget.new(parents, target) do |type, scope|
- return type, scope
- end
- program = parents.first
- scope = Scope.from_binding(binding, program.locals)
- new(dig_targets).evaluate program, scope
- [Types::NIL, scope]
- end
- end
- end
-end
diff --git a/lib/irb/type_completion/types.rb b/lib/irb/type_completion/types.rb
deleted file mode 100644
index f0f2342ffe..0000000000
--- a/lib/irb/type_completion/types.rb
+++ /dev/null
@@ -1,426 +0,0 @@
-# frozen_string_literal: true
-
-require_relative 'methods'
-
-module IRB
- module TypeCompletion
- module Types
- OBJECT_TO_TYPE_SAMPLE_SIZE = 50
-
- singleton_class.attr_reader :rbs_builder, :rbs_load_error
-
- def self.preload_in_thread
- return if @preload_started
-
- @preload_started = true
- Thread.new do
- load_rbs_builder
- end
- end
-
- def self.load_rbs_builder
- require 'rbs'
- require 'rbs/cli'
- loader = RBS::CLI::LibraryOptions.new.loader
- loader.add path: Pathname('sig')
- @rbs_builder = RBS::DefinitionBuilder.new env: RBS::Environment.from_loader(loader).resolve_type_names
- rescue LoadError, StandardError => e
- @rbs_load_error = e
- nil
- end
-
- def self.class_name_of(klass)
- klass = klass.superclass if klass.singleton_class?
- Methods::MODULE_NAME_METHOD.bind_call klass
- end
-
- def self.rbs_search_method(klass, method_name, singleton)
- klass.ancestors.each do |ancestor|
- name = class_name_of ancestor
- next unless name && rbs_builder
- type_name = RBS::TypeName(name).absolute!
- definition = (singleton ? rbs_builder.build_singleton(type_name) : rbs_builder.build_instance(type_name)) rescue nil
- method = definition.methods[method_name] if definition
- return method if method
- end
- nil
- end
-
- def self.method_return_type(type, method_name)
- receivers = type.types.map do |t|
- case t
- in SingletonType
- [t, t.module_or_class, true]
- in InstanceType
- [t, t.klass, false]
- end
- end
- types = receivers.flat_map do |receiver_type, klass, singleton|
- method = rbs_search_method klass, method_name, singleton
- next [] unless method
- method.method_types.map do |method|
- from_rbs_type(method.type.return_type, receiver_type, {})
- end
- end
- UnionType[*types]
- end
-
- def self.rbs_methods(type, method_name, args_types, kwargs_type, has_block)
- return [] unless rbs_builder
-
- receivers = type.types.map do |t|
- case t
- in SingletonType
- [t, t.module_or_class, true]
- in InstanceType
- [t, t.klass, false]
- end
- end
- has_splat = args_types.include?(nil)
- methods_with_score = receivers.flat_map do |receiver_type, klass, singleton|
- method = rbs_search_method klass, method_name, singleton
- next [] unless method
- method.method_types.map do |method_type|
- score = 0
- score += 2 if !!method_type.block == has_block
- reqs = method_type.type.required_positionals
- opts = method_type.type.optional_positionals
- rest = method_type.type.rest_positionals
- trailings = method_type.type.trailing_positionals
- keyreqs = method_type.type.required_keywords
- keyopts = method_type.type.optional_keywords
- keyrest = method_type.type.rest_keywords
- args = args_types
- if kwargs_type&.any? && keyreqs.empty? && keyopts.empty? && keyrest.nil?
- kw_value_type = UnionType[*kwargs_type.values]
- args += [InstanceType.new(Hash, K: SYMBOL, V: kw_value_type)]
- end
- if has_splat
- score += 1 if args.count(&:itself) <= reqs.size + opts.size + trailings.size
- elsif reqs.size + trailings.size <= args.size && (rest || args.size <= reqs.size + opts.size + trailings.size)
- score += 2
- centers = args[reqs.size...-trailings.size]
- given = args.first(reqs.size) + centers.take(opts.size) + args.last(trailings.size)
- expected = (reqs + opts.take(centers.size) + trailings).map(&:type)
- if rest
- given << UnionType[*centers.drop(opts.size)]
- expected << rest.type
- end
- if given.any?
- score += given.zip(expected).count do |t, e|
- e = from_rbs_type e, receiver_type
- intersect?(t, e) || (intersect?(STRING, e) && t.methods.include?(:to_str)) || (intersect?(INTEGER, e) && t.methods.include?(:to_int)) || (intersect?(ARRAY, e) && t.methods.include?(:to_ary))
- end.fdiv(given.size)
- end
- end
- [[method_type, given || [], expected || []], score]
- end
- end
- max_score = methods_with_score.map(&:last).max
- methods_with_score.select { _2 == max_score }.map(&:first)
- end
-
- def self.intersect?(a, b)
- atypes = a.types.group_by(&:class)
- btypes = b.types.group_by(&:class)
- if atypes[SingletonType] && btypes[SingletonType]
- aa, bb = [atypes, btypes].map {|types| types[SingletonType].map(&:module_or_class) }
- return true if (aa & bb).any?
- end
-
- aa, bb = [atypes, btypes].map {|types| (types[InstanceType] || []).map(&:klass) }
- (aa.flat_map(&:ancestors) & bb).any?
- end
-
- def self.type_from_object(object)
- case object
- when Array
- InstanceType.new Array, { Elem: union_type_from_objects(object) }
- when Hash
- InstanceType.new Hash, { K: union_type_from_objects(object.keys), V: union_type_from_objects(object.values) }
- when Module
- SingletonType.new object
- else
- klass = Methods::OBJECT_SINGLETON_CLASS_METHOD.bind_call(object) rescue Methods::OBJECT_CLASS_METHOD.bind_call(object)
- InstanceType.new klass
- end
- end
-
- def self.union_type_from_objects(objects)
- values = objects.size <= OBJECT_TO_TYPE_SAMPLE_SIZE ? objects : objects.sample(OBJECT_TO_TYPE_SAMPLE_SIZE)
- klasses = values.map { Methods::OBJECT_CLASS_METHOD.bind_call(_1) }
- UnionType[*klasses.uniq.map { InstanceType.new _1 }]
- end
-
- class SingletonType
- attr_reader :module_or_class
- def initialize(module_or_class)
- @module_or_class = module_or_class
- end
- def transform() = yield(self)
- def methods() = @module_or_class.methods
- def all_methods() = methods | Kernel.methods
- def constants() = @module_or_class.constants
- def types() = [self]
- def nillable?() = false
- def nonnillable() = self
- def inspect
- "#{module_or_class}.itself"
- end
- end
-
- class InstanceType
- attr_reader :klass, :params
- def initialize(klass, params = {})
- @klass = klass
- @params = params
- end
- def transform() = yield(self)
- def methods() = rbs_methods.select { _2.public? }.keys | @klass.instance_methods
- def all_methods() = rbs_methods.keys | @klass.instance_methods | @klass.private_instance_methods
- def constants() = []
- def types() = [self]
- def nillable?() = (@klass == NilClass)
- def nonnillable() = self
- def rbs_methods
- name = Types.class_name_of(@klass)
- return {} unless name && Types.rbs_builder
-
- type_name = RBS::TypeName(name).absolute!
- Types.rbs_builder.build_instance(type_name).methods rescue {}
- end
- def inspect
- if params.empty?
- inspect_without_params
- else
- params_string = "[#{params.map { "#{_1}: #{_2.inspect}" }.join(', ')}]"
- "#{inspect_without_params}#{params_string}"
- end
- end
- def inspect_without_params
- if klass == NilClass
- 'nil'
- elsif klass == TrueClass
- 'true'
- elsif klass == FalseClass
- 'false'
- else
- klass.singleton_class? ? klass.superclass.to_s : klass.to_s
- end
- end
- end
-
- NIL = InstanceType.new NilClass
- OBJECT = InstanceType.new Object
- TRUE = InstanceType.new TrueClass
- FALSE = InstanceType.new FalseClass
- SYMBOL = InstanceType.new Symbol
- STRING = InstanceType.new String
- INTEGER = InstanceType.new Integer
- RANGE = InstanceType.new Range
- REGEXP = InstanceType.new Regexp
- FLOAT = InstanceType.new Float
- RATIONAL = InstanceType.new Rational
- COMPLEX = InstanceType.new Complex
- ARRAY = InstanceType.new Array
- HASH = InstanceType.new Hash
- CLASS = InstanceType.new Class
- MODULE = InstanceType.new Module
- PROC = InstanceType.new Proc
-
- class UnionType
- attr_reader :types
-
- def initialize(*types)
- @types = []
- singletons = []
- instances = {}
- collect = -> type do
- case type
- in UnionType
- type.types.each(&collect)
- in InstanceType
- params = (instances[type.klass] ||= {})
- type.params.each do |k, v|
- (params[k] ||= []) << v
- end
- in SingletonType
- singletons << type
- end
- end
- types.each(&collect)
- @types = singletons.uniq + instances.map do |klass, params|
- InstanceType.new(klass, params.transform_values { |v| UnionType[*v] })
- end
- end
-
- def transform(&block)
- UnionType[*types.map(&block)]
- end
-
- def nillable?
- types.any?(&:nillable?)
- end
-
- def nonnillable
- UnionType[*types.reject { _1.is_a?(InstanceType) && _1.klass == NilClass }]
- end
-
- def self.[](*types)
- type = new(*types)
- if type.types.empty?
- OBJECT
- elsif type.types.size == 1
- type.types.first
- else
- type
- end
- end
-
- def methods() = @types.flat_map(&:methods).uniq
- def all_methods() = @types.flat_map(&:all_methods).uniq
- def constants() = @types.flat_map(&:constants).uniq
- def inspect() = @types.map(&:inspect).join(' | ')
- end
-
- BOOLEAN = UnionType[TRUE, FALSE]
-
- def self.array_of(*types)
- type = types.size >= 2 ? UnionType[*types] : types.first || OBJECT
- InstanceType.new Array, Elem: type
- end
-
- def self.from_rbs_type(return_type, self_type, extra_vars = {})
- case return_type
- when RBS::Types::Bases::Self
- self_type
- when RBS::Types::Bases::Bottom, RBS::Types::Bases::Nil
- NIL
- when RBS::Types::Bases::Any, RBS::Types::Bases::Void
- OBJECT
- when RBS::Types::Bases::Class
- self_type.transform do |type|
- case type
- in SingletonType
- InstanceType.new(self_type.module_or_class.is_a?(Class) ? Class : Module)
- in InstanceType
- SingletonType.new type.klass
- end
- end
- UnionType[*types]
- when RBS::Types::Bases::Bool
- BOOLEAN
- when RBS::Types::Bases::Instance
- self_type.transform do |type|
- if type.is_a?(SingletonType) && type.module_or_class.is_a?(Class)
- InstanceType.new type.module_or_class
- else
- OBJECT
- end
- end
- when RBS::Types::Union
- UnionType[*return_type.types.map { from_rbs_type _1, self_type, extra_vars }]
- when RBS::Types::Proc
- PROC
- when RBS::Types::Tuple
- elem = UnionType[*return_type.types.map { from_rbs_type _1, self_type, extra_vars }]
- InstanceType.new Array, Elem: elem
- when RBS::Types::Record
- InstanceType.new Hash, K: SYMBOL, V: OBJECT
- when RBS::Types::Literal
- InstanceType.new return_type.literal.class
- when RBS::Types::Variable
- if extra_vars.key? return_type.name
- extra_vars[return_type.name]
- elsif self_type.is_a? InstanceType
- self_type.params[return_type.name] || OBJECT
- elsif self_type.is_a? UnionType
- types = self_type.types.filter_map do |t|
- t.params[return_type.name] if t.is_a? InstanceType
- end
- UnionType[*types]
- else
- OBJECT
- end
- when RBS::Types::Optional
- UnionType[from_rbs_type(return_type.type, self_type, extra_vars), NIL]
- when RBS::Types::Alias
- case return_type.name.name
- when :int
- INTEGER
- when :boolish
- BOOLEAN
- when :string
- STRING
- else
- # TODO: ???
- OBJECT
- end
- when RBS::Types::Interface
- # unimplemented
- OBJECT
- when RBS::Types::ClassInstance
- klass = return_type.name.to_namespace.path.reduce(Object) { _1.const_get _2 }
- if return_type.args
- args = return_type.args.map { from_rbs_type _1, self_type, extra_vars }
- names = rbs_builder.build_singleton(return_type.name).type_params
- params = names.map.with_index { [_1, args[_2] || OBJECT] }.to_h
- end
- InstanceType.new klass, params || {}
- end
- end
-
- def self.method_return_bottom?(method)
- method.type.return_type.is_a? RBS::Types::Bases::Bottom
- end
-
- def self.match_free_variables(vars, types, values)
- accumulator = {}
- types.zip values do |t, v|
- _match_free_variable(vars, t, v, accumulator) if v
- end
- accumulator.transform_values { UnionType[*_1] }
- end
-
- def self._match_free_variable(vars, rbs_type, value, accumulator)
- case [rbs_type, value]
- in [RBS::Types::Variable,]
- (accumulator[rbs_type.name] ||= []) << value if vars.include? rbs_type.name
- in [RBS::Types::ClassInstance, InstanceType]
- names = rbs_builder.build_singleton(rbs_type.name).type_params
- names.zip(rbs_type.args).each do |name, arg|
- v = value.params[name]
- _match_free_variable vars, arg, v, accumulator if v
- end
- in [RBS::Types::Tuple, InstanceType] if value.klass == Array
- v = value.params[:Elem]
- rbs_type.types.each do |t|
- _match_free_variable vars, t, v, accumulator
- end
- in [RBS::Types::Record, InstanceType] if value.klass == Hash
- # TODO
- in [RBS::Types::Interface,]
- definition = rbs_builder.build_interface rbs_type.name
- convert = {}
- definition.type_params.zip(rbs_type.args).each do |from, arg|
- convert[from] = arg.name if arg.is_a? RBS::Types::Variable
- end
- return if convert.empty?
- ac = {}
- definition.methods.each do |method_name, method|
- return_type = method_return_type value, method_name
- method.defs.each do |method_def|
- interface_return_type = method_def.type.type.return_type
- _match_free_variable convert, interface_return_type, return_type, ac
- end
- end
- convert.each do |from, to|
- values = ac[from]
- (accumulator[to] ||= []).concat values if values
- end
- else
- end
- end
- end
- end
-end
diff --git a/lib/irb/version.rb b/lib/irb/version.rb
index c33c4f798c..c41917329c 100644
--- a/lib/irb/version.rb
+++ b/lib/irb/version.rb
@@ -1,11 +1,11 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#
# irb/version.rb - irb version definition file
# by Keiju ISHITSUKA(keiju@ishitsuka.com)
#
module IRB # :nodoc:
- VERSION = "1.9.0"
+ VERSION = "1.13.1"
@RELEASE_VERSION = VERSION
- @LAST_UPDATE_DATE = "2023-11-11"
+ @LAST_UPDATE_DATE = "2024-05-05"
end
diff --git a/lib/irb/workspace.rb b/lib/irb/workspace.rb
index 2bf3d5e0f1..d24d1cc38d 100644
--- a/lib/irb/workspace.rb
+++ b/lib/irb/workspace.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#
# irb/workspace-binding.rb -
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
@@ -6,6 +6,8 @@
require "delegate"
+require_relative "helper_method"
+
IRB::TOPLEVEL_BINDING = binding
module IRB # :nodoc:
class WorkSpace
@@ -90,11 +92,11 @@ EOF
IRB.conf[:__MAIN__] = @main
@main.singleton_class.class_eval do
private
- define_method(:exit) do |*a, &b|
- # Do nothing, will be overridden
- end
define_method(:binding, Kernel.instance_method(:binding))
define_method(:local_variables, Kernel.instance_method(:local_variables))
+ # Define empty method to avoid delegator warning, will be overridden.
+ define_method(:exit) {|*a, &b| }
+ define_method(:exit!) {|*a, &b| }
end
@binding = eval("IRB.conf[:__MAIN__].instance_eval('binding', __FILE__, __LINE__)", @binding, *@binding.source_location)
end
@@ -108,8 +110,10 @@ EOF
# <code>IRB.conf[:__MAIN__]</code>
attr_reader :main
- def load_commands_to_main
- main.extend ExtendCommandBundle
+ def load_helper_methods_to_main
+ ancestors = class<<main;ancestors;end
+ main.extend ExtendCommandBundle if !ancestors.include?(ExtendCommandBundle)
+ main.extend HelpersContainer if !ancestors.include?(HelpersContainer)
end
# Evaluate the given +statements+ within the context of this workspace.
@@ -170,4 +174,16 @@ EOF
"\nFrom: #{file} @ line #{pos + 1} :\n\n#{body}#{Color.clear}\n"
end
end
+
+ module HelpersContainer
+ def self.install_helper_methods
+ HelperMethod.helper_methods.each do |name, helper_method_class|
+ define_method name do |*args, **opts, &block|
+ helper_method_class.instance.execute(*args, **opts, &block)
+ end unless method_defined?(name)
+ end
+ end
+
+ install_helper_methods
+ end
end
diff --git a/lib/irb/ws-for-case-2.rb b/lib/irb/ws-for-case-2.rb
index a0f617e4ed..03f42d73d9 100644
--- a/lib/irb/ws-for-case-2.rb
+++ b/lib/irb/ws-for-case-2.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#
# irb/ws-for-case-2.rb -
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
diff --git a/lib/irb/xmp.rb b/lib/irb/xmp.rb
index 94c700b484..b1bc53283e 100644
--- a/lib/irb/xmp.rb
+++ b/lib/irb/xmp.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#
# xmp.rb - irb version of gotoken xmp
# by Keiju ISHITSUKA(Nippon Rational Inc.)
@@ -44,8 +44,8 @@ class XMP
# The top-level binding or, optional +bind+ parameter will be used when
# creating the workspace. See WorkSpace.new for more information.
#
- # This uses the +:XMP+ prompt mode, see IRB@Customizing+the+IRB+Prompt for
- # full detail.
+ # This uses the +:XMP+ prompt mode.
+ # See {Custom Prompts}[rdoc-ref:IRB@Custom+Prompts] for more information.
def initialize(bind = nil)
IRB.init_config(nil)
diff --git a/lib/logger/period.rb b/lib/logger/period.rb
index 0a291dbbbe..a0359defe3 100644
--- a/lib/logger/period.rb
+++ b/lib/logger/period.rb
@@ -8,14 +8,14 @@ class Logger
def next_rotate_time(now, shift_age)
case shift_age
- when 'daily'
+ when 'daily', :daily
t = Time.mktime(now.year, now.month, now.mday) + SiD
- when 'weekly'
+ when 'weekly', :weekly
t = Time.mktime(now.year, now.month, now.mday) + SiD * (7 - now.wday)
- when 'monthly'
+ when 'monthly', :monthly
t = Time.mktime(now.year, now.month, 1) + SiD * 32
return Time.mktime(t.year, t.month, 1)
- when 'now', 'everytime'
+ when 'now', 'everytime', :now, :everytime
return now
else
raise ArgumentError, "invalid :shift_age #{shift_age.inspect}, should be daily, weekly, monthly, or everytime"
@@ -30,13 +30,13 @@ class Logger
def previous_period_end(now, shift_age)
case shift_age
- when 'daily'
+ when 'daily', :daily
t = Time.mktime(now.year, now.month, now.mday) - SiD / 2
- when 'weekly'
+ when 'weekly', :weekly
t = Time.mktime(now.year, now.month, now.mday) - (SiD * now.wday + SiD / 2)
- when 'monthly'
+ when 'monthly', :monthly
t = Time.mktime(now.year, now.month, 1) - SiD / 2
- when 'now', 'everytime'
+ when 'now', 'everytime', :now, :everytime
return now
else
raise ArgumentError, "invalid :shift_age #{shift_age.inspect}, should be daily, weekly, monthly, or everytime"
diff --git a/lib/mkmf.rb b/lib/mkmf.rb
index 6da7dde5f1..73459ffeb9 100644
--- a/lib/mkmf.rb
+++ b/lib/mkmf.rb
@@ -44,6 +44,23 @@ end
# correctly compile and link the C extension to Ruby and a third-party
# library.
module MakeMakefile
+
+ target_rbconfig = nil
+ ARGV.delete_if do |arg|
+ opt = arg.delete_prefix("--target-rbconfig=")
+ unless opt == arg
+ target_rbconfig = opt
+ end
+ end
+ if target_rbconfig
+ # Load the RbConfig for the target platform into this module.
+ # Cross-compiling needs the same version of Ruby.
+ Kernel.load target_rbconfig, self
+ else
+ # The RbConfig for the target platform where the built extension runs.
+ RbConfig = ::RbConfig
+ end
+
#### defer until this module become global-state free.
# def self.extended(obj)
# obj.init_mkmf
@@ -59,6 +76,9 @@ module MakeMakefile
# The makefile configuration using the defaults from when Ruby was built.
CONFIG = RbConfig::MAKEFILE_CONFIG
+
+ ##
+ # The saved original value of +LIB+ environment variable
ORIG_LIBPATH = ENV['LIB']
##
@@ -245,12 +265,16 @@ MESSAGE
CSRCFLAG = CONFIG['CSRCFLAG']
CPPOUTFILE = config_string('CPPOUTFILE') {|str| str.sub(/\bconftest\b/, CONFTEST)}
+ # :startdoc:
+
+ # Removes _files_.
def rm_f(*files)
opt = (Hash === files.last ? [files.pop] : [])
FileUtils.rm_f(Dir[*files.flatten], *opt)
end
module_function :rm_f
+ # Removes _files_ recursively.
def rm_rf(*files)
opt = (Hash === files.last ? [files.pop] : [])
FileUtils.rm_rf(Dir[*files.flatten], *opt)
@@ -265,6 +289,8 @@ MESSAGE
t if times.all? {|n| n <= t}
end
+ # :stopdoc:
+
def split_libs(*strs)
sep = $mswin ? /\s+/ : /\s+(?=-|\z)/
strs.flat_map {|s| s.lstrip.split(sep)}
@@ -390,6 +416,11 @@ MESSAGE
env, *commands = commands if Hash === commands.first
envs.merge!(env) if env
end
+
+ # disable ASAN leak reporting - conftest programs almost always don't bother
+ # to free their memory.
+ envs['ASAN_OPTIONS'] = "detect_leaks=0" unless ENV.key?('ASAN_OPTIONS')
+
return envs, expand[commands]
end
@@ -397,11 +428,19 @@ MESSAGE
envs.map {|e, v| "#{e}=#{v.quote}"}
end
- def xsystem command, opts = nil
+ # :startdoc:
+
+ # call-seq:
+ # xsystem(command, werror: false) -> true or false
+ #
+ # Executes _command_ with expanding variables, and returns the exit
+ # status like as Kernel#system. If _werror_ is true and the error
+ # output is not empty, returns +false+. The output will logged.
+ def xsystem(command, werror: false)
env, command = expand_command(command)
Logging::open do
puts [env_quote(env), command.quote].join(' ')
- if opts and opts[:werror]
+ if werror
result = nil
Logging.postpone do |log|
output = IO.popen(env, command, &:read)
@@ -415,6 +454,7 @@ MESSAGE
end
end
+ # Executes _command_ similarly to xsystem, but yields opened pipe.
def xpopen command, *mode, &block
env, commands = expand_command(command)
command = [env_quote(env), command].join(' ')
@@ -429,6 +469,7 @@ MESSAGE
end
end
+ # Logs _src_
def log_src(src, heading="checked program was")
src = src.split(/^/)
fmt = "%#{src.size.to_s.size}d: %s"
@@ -443,10 +484,15 @@ EOM
EOM
end
+ # Returns the language-dependent source file name for configuration
+ # checks.
def conftest_source
CONFTEST_C
end
+ # Creats temporary source file from +COMMON_HEADERS+ and _src_.
+ # Yields the created source string and uses the returned string as
+ # the source code, if the block is given.
def create_tmpsrc(src)
src = "#{COMMON_HEADERS}\n#{src}"
src = yield(src) if block_given?
@@ -467,6 +513,8 @@ EOM
src
end
+ # :stopdoc:
+
def have_devel?
unless defined? $have_devel
$have_devel = true
@@ -475,7 +523,7 @@ EOM
$have_devel
end
- def try_do(src, command, *opts, &b)
+ def try_do(src, command, **opts, &b)
unless have_devel?
raise <<MSG
The compiler failed to generate an executable file.
@@ -484,7 +532,7 @@ MSG
end
begin
src = create_tmpsrc(src, &b)
- xsystem(command, *opts)
+ xsystem(command, **opts)
ensure
log_src(src)
end
@@ -545,18 +593,17 @@ MSG
}.join
end
+ def werror_flag(opt = nil)
+ config_string("WERRORFLAG") {|flag| opt = opt && !opt.empty? ? "#{opt} #{flag}" : flag}
+ opt
+ end
+
def with_werror(opt, opts = nil)
- if opts
- if opts[:werror] and config_string("WERRORFLAG") {|flag| opt = opt ? "#{opt} #{flag}" : flag}
- (opts = opts.dup).delete(:werror)
- end
- yield(opt, opts)
- else
- yield(opt)
- end
+ opt = werror_flag(opt) if opts and (opts = opts.dup).delete(:werror)
+ yield(opt, opts)
end
- def try_link0(src, opt="", *opts, &b) # :nodoc:
+ def try_link0(src, opt = "", **opts, &b) # :nodoc:
exe = CONFTEST+$EXEEXT
cmd = link_command("", opt)
if $universal
@@ -564,13 +611,13 @@ MSG
Dir.mktmpdir("mkmf_", oldtmpdir = ENV["TMPDIR"]) do |tmpdir|
begin
ENV["TMPDIR"] = tmpdir
- try_do(src, cmd, *opts, &b)
+ try_do(src, cmd, **opts, &b)
ensure
ENV["TMPDIR"] = oldtmpdir
end
end
else
- try_do(src, cmd, *opts, &b)
+ try_do(src, cmd, **opts, &b)
end and File.executable?(exe) or return nil
exe
ensure
@@ -579,31 +626,32 @@ MSG
# Returns whether or not the +src+ can be compiled as a C source and linked
# with its depending libraries successfully. +opt+ is passed to the linker
- # as options. Note that +$CFLAGS+ and +$LDFLAGS+ are also passed to the
- # linker.
+ # as options. Note that <tt>$CFLAGS</tt> and <tt>$LDFLAGS</tt> are also
+ # passed to the linker.
#
# If a block given, it is called with the source before compilation. You can
# modify the source in the block.
#
# [+src+] a String which contains a C source
# [+opt+] a String which contains linker options
- def try_link(src, opt="", *opts, &b)
- exe = try_link0(src, opt, *opts, &b) or return false
+ def try_link(src, opt = "", **opts, &b)
+ exe = try_link0(src, opt, **opts, &b) or return false
MakeMakefile.rm_f exe
true
end
# Returns whether or not the +src+ can be compiled as a C source. +opt+ is
- # passed to the C compiler as options. Note that +$CFLAGS+ is also passed to
- # the compiler.
+ # passed to the C compiler as options. Note that <tt>$CFLAGS</tt> is also
+ # passed to the compiler.
#
# If a block given, it is called with the source before compilation. You can
# modify the source in the block.
#
# [+src+] a String which contains a C source
# [+opt+] a String which contains compiler options
- def try_compile(src, opt="", *opts, &b)
- with_werror(opt, *opts) {|_opt, *| try_do(src, cc_command(_opt), *opts, &b)} and
+ def try_compile(src, opt = "", werror: nil, **opts, &b)
+ opt = werror_flag(opt) if werror
+ try_do(src, cc_command(opt), werror: werror, **opts, &b) and
File.file?("#{CONFTEST}.#{$OBJEXT}")
ensure
MakeMakefile.rm_f "#{CONFTEST}*"
@@ -611,15 +659,15 @@ MSG
# Returns whether or not the +src+ can be preprocessed with the C
# preprocessor. +opt+ is passed to the preprocessor as options. Note that
- # +$CFLAGS+ is also passed to the preprocessor.
+ # <tt>$CFLAGS</tt> is also passed to the preprocessor.
#
# If a block given, it is called with the source before preprocessing. You
# can modify the source in the block.
#
# [+src+] a String which contains a C source
# [+opt+] a String which contains preprocessor options
- def try_cpp(src, opt="", *opts, &b)
- try_do(src, cpp_command(CPPOUTFILE, opt), *opts, &b) and
+ def try_cpp(src, opt = "", **opts, &b)
+ try_do(src, cpp_command(CPPOUTFILE, opt), **opts, &b) and
File.file?("#{CONFTEST}.i")
ensure
MakeMakefile.rm_f "#{CONFTEST}*"
@@ -636,6 +684,14 @@ MSG
end
end
+ # :startdoc:
+
+ # Sets <tt>$CPPFLAGS</tt> to _flags_ and yields. If the block returns a
+ # falsy value, <tt>$CPPFLAGS</tt> is reset to its previous value, remains
+ # set to _flags_ otherwise.
+ #
+ # [+flags+] a C preprocessor flag as a +String+
+ #
def with_cppflags(flags)
cppflags = $CPPFLAGS
$CPPFLAGS = flags.dup
@@ -644,20 +700,29 @@ MSG
$CPPFLAGS = cppflags unless ret
end
- def try_cppflags(flags, opts = {})
- try_header(MAIN_DOES_NOTHING, flags, {:werror => true}.update(opts))
+ # :nodoc:
+ def try_cppflags(flags, werror: true, **opts)
+ try_header(MAIN_DOES_NOTHING, flags, werror: werror, **opts)
end
- def append_cppflags(flags, *opts)
+ # Check whether each given C preprocessor flag is acceptable and append it
+ # to <tt>$CPPFLAGS</tt> if so.
+ #
+ # [+flags+] a C preprocessor flag as a +String+ or an +Array+ of them
+ #
+ def append_cppflags(flags, **opts)
Array(flags).each do |flag|
if checking_for("whether #{flag} is accepted as CPPFLAGS") {
- try_cppflags(flag, *opts)
+ try_cppflags(flag, **opts)
}
$CPPFLAGS << " " << flag
end
end
end
+ # Sets <tt>$CFLAGS</tt> to _flags_ and yields. If the block returns a falsy
+ # value, <tt>$CFLAGS</tt> is reset to its previous value, remains set to
+ # _flags_ otherwise.
def with_cflags(flags)
cflags = $CFLAGS
$CFLAGS = flags.dup
@@ -666,10 +731,14 @@ MSG
$CFLAGS = cflags unless ret
end
- def try_cflags(flags, opts = {})
- try_compile(MAIN_DOES_NOTHING, flags, {:werror => true}.update(opts))
+ # :nodoc:
+ def try_cflags(flags, werror: true, **opts)
+ try_compile(MAIN_DOES_NOTHING, flags, werror: werror, **opts)
end
+ # Sets <tt>$LDFLAGS</tt> to _flags_ and yields. If the block returns a
+ # falsy value, <tt>$LDFLAGS</tt> is reset to its previous value, remains set
+ # to _flags_ otherwise.
def with_ldflags(flags)
ldflags = $LDFLAGS
$LDFLAGS = flags.dup
@@ -678,21 +747,30 @@ MSG
$LDFLAGS = ldflags unless ret
end
- def try_ldflags(flags, opts = {})
- opts = {:werror => true}.update(opts) if $mswin
- try_link(MAIN_DOES_NOTHING, flags, opts)
+ # :nodoc:
+ def try_ldflags(flags, werror: $mswin, **opts)
+ try_link(MAIN_DOES_NOTHING, flags, werror: werror, **opts)
end
- def append_ldflags(flags, *opts)
+ # :startdoc:
+
+ # Check whether each given linker flag is acceptable and append it to
+ # <tt>$LDFLAGS</tt> if so.
+ #
+ # [+flags+] a linker flag as a +String+ or an +Array+ of them
+ #
+ def append_ldflags(flags, **opts)
Array(flags).each do |flag|
if checking_for("whether #{flag} is accepted as LDFLAGS") {
- try_ldflags(flag, *opts)
+ try_ldflags(flag, **opts)
}
$LDFLAGS << " " << flag
end
end
end
+ # :stopdoc:
+
def try_static_assert(expr, headers = nil, opt = "", &b)
headers = cpp_include(headers)
try_compile(<<SRC, opt, &b)
@@ -828,6 +906,8 @@ int t(void) { const volatile void *volatile p; p = &(&#{var})[0]; return !p; }
SRC
end
+ # :startdoc:
+
# Returns whether or not the +src+ can be preprocessed with the C
# preprocessor and matches with +pat+.
#
@@ -866,6 +946,8 @@ SRC
log_src(src)
end
+ # :stopdoc:
+
# This is used internally by the have_macro? method.
def macro_defined?(macro, src, opt = "", &b)
src = src.sub(/[^\n]\z/, "\\&\n")
@@ -885,8 +967,8 @@ SRC
# * the linked file can be invoked as an executable
# * and the executable exits successfully
#
- # +opt+ is passed to the linker as options. Note that +$CFLAGS+ and
- # +$LDFLAGS+ are also passed to the linker.
+ # +opt+ is passed to the linker as options. Note that <tt>$CFLAGS</tt> and
+ # <tt>$LDFLAGS</tt> are also passed to the linker.
#
# If a block given, it is called with the source before compilation. You can
# modify the source in the block.
@@ -958,6 +1040,10 @@ SRC
format(LIBARG, lib) + " " + libs
end
+ # Prints messages to $stdout, if verbose mode.
+ #
+ # Internal use only.
+ #
def message(*s)
unless Logging.quiet and not $VERBOSE
printf(*s)
@@ -989,6 +1075,10 @@ SRC
r
end
+ # Build a message for checking.
+ #
+ # Internal use only.
+ #
def checking_message(target, place = nil, opt = nil)
[["in", place], ["with", opt]].inject("#{target}") do |msg, (pre, noun)|
if noun
@@ -1013,10 +1103,10 @@ SRC
#
# [+flags+] a C compiler flag as a +String+ or an +Array+ of them
#
- def append_cflags(flags, *opts)
+ def append_cflags(flags, **opts)
Array(flags).each do |flag|
if checking_for("whether #{flag} is accepted as CFLAGS") {
- try_cflags(flag, *opts)
+ try_cflags(flag, **opts)
}
$CFLAGS << " " << flag
end
@@ -1250,6 +1340,7 @@ SRC
end
end
+ # :nodoc:
# Returns whether or not the static type +type+ is defined.
#
# See also +have_type+
@@ -1307,6 +1398,7 @@ SRC
end
end
+ # :nodoc:
# Returns whether or not the constant +const+ is defined.
#
# See also +have_const+
@@ -1466,7 +1558,7 @@ SRC
u = "unsigned " if signed > 0
prelude << "extern rbcv_typedef_ foo();"
compat = UNIVERSAL_INTS.find {|t|
- try_compile([prelude, "extern #{u}#{t} foo();"].join("\n"), opts, :werror=>true, &b)
+ try_compile([prelude, "extern #{u}#{t} foo();"].join("\n"), opts, werror: true, &b)
}
end
if compat
@@ -1490,7 +1582,7 @@ SRC
# Used internally by the what_type? method to determine if +type+ is a scalar
# pointer.
def scalar_ptr_type?(type, member = nil, headers = nil, &b)
- try_compile(<<"SRC", &b) # pointer
+ try_compile(<<"SRC", &b)
#{cpp_include(headers)}
/*top*/
volatile #{type} conftestval;
@@ -1503,7 +1595,7 @@ SRC
# Used internally by the what_type? method to determine if +type+ is a scalar
# pointer.
def scalar_type?(type, member = nil, headers = nil, &b)
- try_compile(<<"SRC", &b) # pointer
+ try_compile(<<"SRC", &b)
#{cpp_include(headers)}
/*top*/
volatile #{type} conftestval;
@@ -1525,6 +1617,10 @@ SRC
end
end
+ # :startdoc:
+
+ # Returns a string represents the type of _type_, or _member_ of
+ # _type_ if _member_ is not +nil+.
def what_type?(type, member = nil, headers = nil, &b)
m = "#{type}"
var = val = "*rbcv_var_"
@@ -1584,6 +1680,8 @@ SRC
end
end
+ # :nodoc:
+ #
# This method is used internally by the find_executable method.
#
# Internal use only.
@@ -1622,8 +1720,6 @@ SRC
nil
end
- # :startdoc:
-
# Searches for the executable +bin+ on +path+. The default path is your
# +PATH+ environment variable. If that isn't defined, it will resort to
# searching /usr/local/bin, /usr/ucb, /usr/bin and /bin.
@@ -2069,7 +2165,9 @@ ARCH_FLAG = #{$ARCH_FLAG}
DLDFLAGS = $(ldflags) $(dldflags) $(ARCH_FLAG)
LDSHARED = #{CONFIG['LDSHARED']}
LDSHAREDXX = #{config_string('LDSHAREDXX') || '$(LDSHARED)'}
+POSTLINK = #{config_string('POSTLINK', RbConfig::CONFIG)}
AR = #{CONFIG['AR']}
+LD = #{CONFIG['LD']}
EXEEXT = #{CONFIG['EXEEXT']}
}
@@ -2377,7 +2475,7 @@ TARGET_ENTRY = #{EXPORT_PREFIX || ''}Init_$(TARGET_NAME)
DLLIB = #{dllib}
EXTSTATIC = #{$static || ""}
STATIC_LIB = #{staticlib unless $static.nil?}
-#{!$extout && defined?($installed_list) ? "INSTALLED_LIST = #{$installed_list}\n" : ""}
+#{!$extout && defined?($installed_list) ? %[INSTALLED_LIST = #{$installed_list}\n] : ""}
TIMESTAMP_DIR = #{$extout && $extmk ? '$(extout)/.timestamp' : '.'}
" #"
# TODO: fixme
@@ -2404,7 +2502,7 @@ TARGET_SO_DIR_TIMESTAMP = #{timestamp_file(sodir, target_prefix)}
mfile.puts(conf)
mfile.print "
all: #{$extout ? "install" : target ? "$(DLLIB)" : "Makefile"}
-static: #{$extmk && !$static ? "all" : "$(STATIC_LIB)#{$extout ? " install-rb" : ""}"}
+static: #{$extmk && !$static ? "all" : %[$(STATIC_LIB)#{$extout ? " install-rb" : ""}]}
.PHONY: all install static install-so install-rb
.PHONY: clean clean-so clean-static clean-rb
" #"
@@ -2435,6 +2533,7 @@ static: #{$extmk && !$static ? "all" : "$(STATIC_LIB)#{$extout ? " install-rb" :
mfile.puts dest
mfile.print "clean-so::\n"
mfile.print "\t-$(Q)$(RM) #{fseprepl[dest]} #{fseprepl[stamp]}\n"
+ mfile.print "\t-$(Q)$(RM_RF) #{fseprepl['$(CLEANLIBS)']}\n"
mfile.print "\t-$(Q)$(RMDIRS) #{fseprepl[dir]}#{$ignore_error}\n"
else
mfile.print "#{f} #{stamp}\n"
@@ -2727,6 +2826,9 @@ MESSAGE
split = Shellwords.method(:shellwords).to_proc
+ ##
+ # The prefix added to exported symbols automatically
+
EXPORT_PREFIX = config_string('EXPORT_PREFIX') {|s| s.strip}
hdr = ['#include "ruby.h"' "\n"]
@@ -2756,6 +2858,10 @@ MESSAGE
# make compile rules
COMPILE_RULES = config_string('COMPILE_RULES', &split) || %w[.%s.%s:]
+
+ ##
+ # Substitution in rules for NMake
+
RULE_SUBST = config_string('RULE_SUBST')
##
@@ -2801,6 +2907,10 @@ MESSAGE
# Argument which will add a library path to the linker
LIBPATHFLAG = config_string('LIBPATHFLAG') || ' -L%s'
+
+ ##
+ # Argument which will add a runtime library path to the linker
+
RPATHFLAG = config_string('RPATHFLAG') || ''
##
@@ -2812,6 +2922,10 @@ MESSAGE
# A C main function which does no work
MAIN_DOES_NOTHING = config_string('MAIN_DOES_NOTHING') || "int main(int argc, char **argv)\n{\n return !!argv[argc];\n}"
+
+ ##
+ # The type names for convertible_int
+
UNIVERSAL_INTS = config_string('UNIVERSAL_INTS') {|s| Shellwords.shellwords(s)} ||
%w[int short long long\ long]
@@ -2842,18 +2956,32 @@ realclean: distclean
@lang = Hash.new(self)
+ ##
+ # Retrieves the module for _name_ language.
def self.[](name)
@lang.fetch(name)
end
+ ##
+ # Defines the module for _name_ language.
def self.[]=(name, mod)
@lang[name] = mod
end
- self["C++"] = Module.new do
+ ##
+ # The language that this module is for
+ LANGUAGE = -"C"
+
+ self[self::LANGUAGE] = self
+
+ cxx = Module.new do
+ # Module for C++
+
include MakeMakefile
extend self
+ # :stopdoc:
+
CONFTEST_CXX = "#{CONFTEST}.#{config_string('CXX_EXT') || CXX_EXT[0]}"
TRY_LINK_CXX = config_string('TRY_LINK_CXX') ||
@@ -2883,7 +3011,12 @@ realclean: distclean
conf = link_config(ldflags, *opts)
RbConfig::expand(TRY_LINK_CXX.dup, conf)
end
+
+ # :startdoc:
end
+
+ cxx::LANGUAGE = -"C++"
+ self[cxx::LANGUAGE] = cxx
end
# MakeMakefile::Global = #
diff --git a/lib/mutex_m.gemspec b/lib/mutex_m.gemspec
deleted file mode 100644
index ebbda2606c..0000000000
--- a/lib/mutex_m.gemspec
+++ /dev/null
@@ -1,28 +0,0 @@
-begin
- require_relative "lib/mutex_m"
-rescue LoadError
- # for Ruby core repository
- require_relative "mutex_m"
-end
-
-Gem::Specification.new do |spec|
- spec.name = "mutex_m"
- spec.version = Mutex_m::VERSION
- spec.authors = ["Keiju ISHITSUKA"]
- spec.email = ["keiju@ruby-lang.org"]
-
- spec.summary = %q{Mixin to extend objects to be handled like a Mutex.}
- spec.description = %q{Mixin to extend objects to be handled like a Mutex.}
- spec.homepage = "https://github.com/ruby/mutex_m"
- spec.licenses = ["Ruby", "BSD-2-Clause"]
-
- spec.files = ["Gemfile", "LICENSE.txt", "README.md", "Rakefile", "lib/mutex_m.rb", "mutex_m.gemspec"]
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
- spec.require_paths = ["lib"]
- spec.required_ruby_version = '>= 2.5'
-
- spec.add_development_dependency "bundler"
- spec.add_development_dependency "rake"
- spec.add_development_dependency "test-unit"
-end
diff --git a/lib/mutex_m.rb b/lib/mutex_m.rb
deleted file mode 100644
index 7e55181881..0000000000
--- a/lib/mutex_m.rb
+++ /dev/null
@@ -1,116 +0,0 @@
-# frozen_string_literal: false
-#
-# mutex_m.rb -
-# $Release Version: 3.0$
-# $Revision: 1.7 $
-# Original from mutex.rb
-# by Keiju ISHITSUKA(keiju@ishitsuka.com)
-# modified by matz
-# patched by akira yamada
-#
-# --
-
-# = mutex_m.rb
-#
-# When 'mutex_m' is required, any object that extends or includes Mutex_m will
-# be treated like a Mutex.
-#
-# Start by requiring the standard library Mutex_m:
-#
-# require "mutex_m.rb"
-#
-# From here you can extend an object with Mutex instance methods:
-#
-# obj = Object.new
-# obj.extend Mutex_m
-#
-# Or mixin Mutex_m into your module to your class inherit Mutex instance
-# methods --- remember to call super() in your class initialize method.
-#
-# class Foo
-# include Mutex_m
-# def initialize
-# # ...
-# super()
-# end
-# # ...
-# end
-# obj = Foo.new
-# # this obj can be handled like Mutex
-#
-module Mutex_m
-
- VERSION = "0.2.0"
- Ractor.make_shareable(VERSION) if defined?(Ractor)
-
- def Mutex_m.define_aliases(cl) # :nodoc:
- cl.alias_method(:locked?, :mu_locked?)
- cl.alias_method(:lock, :mu_lock)
- cl.alias_method(:unlock, :mu_unlock)
- cl.alias_method(:try_lock, :mu_try_lock)
- cl.alias_method(:synchronize, :mu_synchronize)
- end
-
- def Mutex_m.append_features(cl) # :nodoc:
- super
- define_aliases(cl) unless cl.instance_of?(Module)
- end
-
- def Mutex_m.extend_object(obj) # :nodoc:
- super
- obj.mu_extended
- end
-
- def mu_extended # :nodoc:
- unless (defined? locked? and
- defined? lock and
- defined? unlock and
- defined? try_lock and
- defined? synchronize)
- Mutex_m.define_aliases(singleton_class)
- end
- mu_initialize
- end
-
- # See Thread::Mutex#synchronize
- def mu_synchronize(&block)
- @_mutex.synchronize(&block)
- end
-
- # See Thread::Mutex#locked?
- def mu_locked?
- @_mutex.locked?
- end
-
- # See Thread::Mutex#try_lock
- def mu_try_lock
- @_mutex.try_lock
- end
-
- # See Thread::Mutex#lock
- def mu_lock
- @_mutex.lock
- end
-
- # See Thread::Mutex#unlock
- def mu_unlock
- @_mutex.unlock
- end
-
- # See Thread::Mutex#sleep
- def sleep(timeout = nil)
- @_mutex.sleep(timeout)
- end
-
- private
-
- def mu_initialize # :nodoc:
- @_mutex = Thread::Mutex.new
- end
-
- def initialize(*args) # :nodoc:
- mu_initialize
- super
- end
- ruby2_keywords(:initialize) if respond_to?(:ruby2_keywords, true)
-end
diff --git a/lib/net/http.rb b/lib/net/http.rb
index 34ca0669eb..958ff09f0e 100644
--- a/lib/net/http.rb
+++ b/lib/net/http.rb
@@ -67,6 +67,8 @@ module Net #:nodoc:
# Net::HTTP.post(uri, data)
# params = {title: 'foo', body: 'bar', userId: 1}
# Net::HTTP.post_form(uri, params)
+ # data = '{"title": "foo", "body": "bar", "userId": 1}'
+ # Net::HTTP.put(uri, data)
#
# - If performance is important, consider using sessions, which lower request overhead.
# This {session}[rdoc-ref:Net::HTTP@Sessions] has multiple requests for
@@ -456,6 +458,10 @@ module Net #:nodoc:
#
# == What's Here
#
+ # First, what's elsewhere. Class Net::HTTP:
+ #
+ # - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
+ #
# This is a categorized summary of methods and attributes.
#
# === \Net::HTTP Objects
@@ -520,6 +526,8 @@ module Net #:nodoc:
# Sends a POST request with form data and returns a response object.
# - {::post}[rdoc-ref:Net::HTTP.post]:
# Sends a POST request with data and returns a response object.
+ # - {::put}[rdoc-ref:Net::HTTP.put]:
+ # Sends a PUT request with data and returns a response object.
# - {#copy}[rdoc-ref:Net::HTTP#copy]:
# Sends a COPY request and returns a response object.
# - {#delete}[rdoc-ref:Net::HTTP#delete]:
@@ -722,7 +730,7 @@ module Net #:nodoc:
class HTTP < Protocol
# :stopdoc:
- VERSION = "0.4.0"
+ VERSION = "0.4.1"
HTTPVersion = '1.1'
begin
require 'zlib'
@@ -889,6 +897,39 @@ module Net #:nodoc:
}
end
+ # Sends a PUT request to the server; returns a Net::HTTPResponse object.
+ #
+ # Argument +url+ must be a URL;
+ # argument +data+ must be a string:
+ #
+ # _uri = uri.dup
+ # _uri.path = '/posts'
+ # data = '{"title": "foo", "body": "bar", "userId": 1}'
+ # headers = {'content-type': 'application/json'}
+ # res = Net::HTTP.put(_uri, data, headers) # => #<Net::HTTPCreated 201 Created readbody=true>
+ # puts res.body
+ #
+ # Output:
+ #
+ # {
+ # "title": "foo",
+ # "body": "bar",
+ # "userId": 1,
+ # "id": 101
+ # }
+ #
+ # Related:
+ #
+ # - Net::HTTP::Put: request class for \HTTP method +PUT+.
+ # - Net::HTTP#put: convenience method for \HTTP method +PUT+.
+ #
+ def HTTP.put(url, data, header = nil)
+ start(url.hostname, url.port,
+ :use_ssl => url.scheme == 'https' ) {|http|
+ http.put(url, data, header)
+ }
+ end
+
#
# \HTTP session management
#
@@ -2012,6 +2053,11 @@ module Net #:nodoc:
# http = Net::HTTP.new(hostname)
# http.put('/todos/1', data) # => #<Net::HTTPOK 200 OK readbody=true>
#
+ # Related:
+ #
+ # - Net::HTTP::Put: request class for \HTTP method PUT.
+ # - Net::HTTP.put: sends PUT request, returns response body.
+ #
def put(path, data, initheader = nil)
request(Put.new(path, initheader), data)
end
@@ -2350,7 +2396,10 @@ module Net #:nodoc:
res
}
res.reading_body(@socket, req.response_body_permitted?) {
- yield res if block_given?
+ if block_given?
+ count = max_retries # Don't restart in the middle of a download
+ yield res
+ end
}
rescue Net::OpenTimeout
raise
diff --git a/lib/net/http/header.rb b/lib/net/http/header.rb
index 6660c8075a..f6c36f1b5e 100644
--- a/lib/net/http/header.rb
+++ b/lib/net/http/header.rb
@@ -491,7 +491,7 @@ module Net::HTTPHeader
alias canonical_each each_capitalized
def capitalize(name)
- name.to_s.split(/-/).map {|s| s.capitalize }.join('-')
+ name.to_s.split('-'.freeze).map {|s| s.capitalize }.join('-'.freeze)
end
private :capitalize
diff --git a/lib/net/http/requests.rb b/lib/net/http/requests.rb
index 5724164205..e58057adf1 100644
--- a/lib/net/http/requests.rb
+++ b/lib/net/http/requests.rb
@@ -124,6 +124,11 @@ end
# - {Idempotent}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Idempotent_methods]: yes.
# - {Cacheable}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Cacheable_methods]: no.
#
+# Related:
+#
+# - Net::HTTP.put: sends +PUT+ request, returns response object.
+# - Net::HTTP#put: sends +PUT+ request, returns response object.
+#
class Net::HTTP::Put < Net::HTTPRequest
METHOD = 'PUT'
REQUEST_HAS_BODY = true
diff --git a/lib/net/net-protocol.gemspec b/lib/net/net-protocol.gemspec
index 29ad2504eb..f9fd83f12b 100644
--- a/lib/net/net-protocol.gemspec
+++ b/lib/net/net-protocol.gemspec
@@ -21,6 +21,7 @@ Gem::Specification.new do |spec|
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
+ spec.metadata["changelog_uri"] = spec.homepage + "/releases"
# Specify which files should be added to the gem when it is released.
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
diff --git a/lib/observer.gemspec b/lib/observer.gemspec
deleted file mode 100644
index 93e61b8c84..0000000000
--- a/lib/observer.gemspec
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-name = File.basename(__FILE__, ".gemspec")
-version = ["lib", Array.new(name.count("-")+1, ".").join("/")].find do |dir|
- break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
- /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
- end rescue nil
-end
-
-Gem::Specification.new do |spec|
- spec.name = name
- spec.version = version
- spec.authors = ["Yukihiro Matsumoto"]
- spec.email = ["matz@ruby-lang.org"]
-
- spec.summary = %q{Implementation of the Observer object-oriented design pattern.}
- spec.description = spec.summary
- spec.homepage = "https://github.com/ruby/observer"
- spec.licenses = ["Ruby", "BSD-2-Clause"]
-
- spec.metadata["homepage_uri"] = spec.homepage
- spec.metadata["source_code_uri"] = spec.homepage
-
- # Specify which files should be added to the gem when it is released.
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
- `git ls-files -z 2>#{IO::NULL}`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
- end
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
- spec.require_paths = ["lib"]
-end
diff --git a/lib/observer.rb b/lib/observer.rb
deleted file mode 100644
index 75832cace2..0000000000
--- a/lib/observer.rb
+++ /dev/null
@@ -1,229 +0,0 @@
-# frozen_string_literal: true
-#
-# Implementation of the _Observer_ object-oriented design pattern. The
-# following documentation is copied, with modifications, from "Programming
-# Ruby", by Hunt and Thomas; http://www.ruby-doc.org/docs/ProgrammingRuby/html/lib_patterns.html.
-#
-# See Observable for more info.
-
-# The Observer pattern (also known as publish/subscribe) provides a simple
-# mechanism for one object to inform a set of interested third-party objects
-# when its state changes.
-#
-# == Mechanism
-#
-# The notifying class mixes in the +Observable+
-# module, which provides the methods for managing the associated observer
-# objects.
-#
-# The observable object must:
-# * assert that it has +#changed+
-# * call +#notify_observers+
-#
-# An observer subscribes to updates using Observable#add_observer, which also
-# specifies the method called via #notify_observers. The default method for
-# #notify_observers is #update.
-#
-# === Example
-#
-# The following example demonstrates this nicely. A +Ticker+, when run,
-# continually receives the stock +Price+ for its <tt>@symbol</tt>. A +Warner+
-# is a general observer of the price, and two warners are demonstrated, a
-# +WarnLow+ and a +WarnHigh+, which print a warning if the price is below or
-# above their set limits, respectively.
-#
-# The +update+ callback allows the warners to run without being explicitly
-# called. The system is set up with the +Ticker+ and several observers, and the
-# observers do their duty without the top-level code having to interfere.
-#
-# Note that the contract between publisher and subscriber (observable and
-# observer) is not declared or enforced. The +Ticker+ publishes a time and a
-# price, and the warners receive that. But if you don't ensure that your
-# contracts are correct, nothing else can warn you.
-#
-# require "observer"
-#
-# class Ticker ### Periodically fetch a stock price.
-# include Observable
-#
-# def initialize(symbol)
-# @symbol = symbol
-# end
-#
-# def run
-# last_price = nil
-# loop do
-# price = Price.fetch(@symbol)
-# print "Current price: #{price}\n"
-# if price != last_price
-# changed # notify observers
-# last_price = price
-# notify_observers(Time.now, price)
-# end
-# sleep 1
-# end
-# end
-# end
-#
-# class Price ### A mock class to fetch a stock price (60 - 140).
-# def self.fetch(symbol)
-# 60 + rand(80)
-# end
-# end
-#
-# class Warner ### An abstract observer of Ticker objects.
-# def initialize(ticker, limit)
-# @limit = limit
-# ticker.add_observer(self)
-# end
-# end
-#
-# class WarnLow < Warner
-# def update(time, price) # callback for observer
-# if price < @limit
-# print "--- #{time.to_s}: Price below #@limit: #{price}\n"
-# end
-# end
-# end
-#
-# class WarnHigh < Warner
-# def update(time, price) # callback for observer
-# if price > @limit
-# print "+++ #{time.to_s}: Price above #@limit: #{price}\n"
-# end
-# end
-# end
-#
-# ticker = Ticker.new("MSFT")
-# WarnLow.new(ticker, 80)
-# WarnHigh.new(ticker, 120)
-# ticker.run
-#
-# Produces:
-#
-# Current price: 83
-# Current price: 75
-# --- Sun Jun 09 00:10:25 CDT 2002: Price below 80: 75
-# Current price: 90
-# Current price: 134
-# +++ Sun Jun 09 00:10:25 CDT 2002: Price above 120: 134
-# Current price: 134
-# Current price: 112
-# Current price: 79
-# --- Sun Jun 09 00:10:25 CDT 2002: Price below 80: 79
-#
-# === Usage with procs
-#
-# The +#notify_observers+ method can also be used with +proc+s by using
-# the +:call+ as +func+ parameter.
-#
-# The following example illustrates the use of a lambda:
-#
-# require 'observer'
-#
-# class Ticker
-# include Observable
-#
-# def run
-# # logic to retrieve the price (here 77.0)
-# changed
-# notify_observers(77.0)
-# end
-# end
-#
-# ticker = Ticker.new
-# warner = ->(price) { puts "New price received: #{price}" }
-# ticker.add_observer(warner, :call)
-# ticker.run
-module Observable
- VERSION = "0.1.2"
-
- #
- # Add +observer+ as an observer on this object. So that it will receive
- # notifications.
- #
- # +observer+:: the object that will be notified of changes.
- # +func+:: Symbol naming the method that will be called when this Observable
- # has changes.
- #
- # This method must return true for +observer.respond_to?+ and will
- # receive <tt>*arg</tt> when #notify_observers is called, where
- # <tt>*arg</tt> is the value passed to #notify_observers by this
- # Observable
- def add_observer(observer, func=:update)
- @observer_peers = {} unless defined? @observer_peers
- unless observer.respond_to? func
- raise NoMethodError, "observer does not respond to `#{func}'"
- end
- @observer_peers[observer] = func
- end
-
- #
- # Remove +observer+ as an observer on this object so that it will no longer
- # receive notifications.
- #
- # +observer+:: An observer of this Observable
- def delete_observer(observer)
- @observer_peers.delete observer if defined? @observer_peers
- end
-
- #
- # Remove all observers associated with this object.
- #
- def delete_observers
- @observer_peers.clear if defined? @observer_peers
- end
-
- #
- # Return the number of observers associated with this object.
- #
- def count_observers
- if defined? @observer_peers
- @observer_peers.size
- else
- 0
- end
- end
-
- #
- # Set the changed state of this object. Notifications will be sent only if
- # the changed +state+ is +true+.
- #
- # +state+:: Boolean indicating the changed state of this Observable.
- #
- def changed(state=true)
- @observer_state = state
- end
-
- #
- # Returns true if this object's state has been changed since the last
- # #notify_observers call.
- #
- def changed?
- if defined? @observer_state and @observer_state
- true
- else
- false
- end
- end
-
- #
- # Notify observers of a change in state *if* this object's changed state is
- # +true+.
- #
- # This will invoke the method named in #add_observer, passing <tt>*arg</tt>.
- # The changed state is then set to +false+.
- #
- # <tt>*arg</tt>:: Any arguments to pass to the observers.
- def notify_observers(*arg)
- if defined? @observer_state and @observer_state
- if defined? @observer_peers
- @observer_peers.each do |k, v|
- k.__send__(v, *arg)
- end
- end
- @observer_state = false
- end
- end
-
-end
diff --git a/lib/open-uri.rb b/lib/open-uri.rb
index 00e4c2d9b8..ba2379325f 100644
--- a/lib/open-uri.rb
+++ b/lib/open-uri.rb
@@ -91,7 +91,7 @@ end
module OpenURI
- VERSION = "0.4.0"
+ VERSION = "0.4.1"
Options = {
:proxy => true,
@@ -108,6 +108,7 @@ module OpenURI
:ftp_active_mode => false,
:redirect => true,
:encoding => nil,
+ :max_redirects => 64,
}
def OpenURI.check_options(options) # :nodoc:
@@ -211,6 +212,7 @@ module OpenURI
end
uri_set = {}
+ max_redirects = options[:max_redirects]
buf = nil
while true
redirect = catch(:open_uri_redirect) {
@@ -238,6 +240,7 @@ module OpenURI
uri = redirect
raise "HTTP redirection loop: #{uri}" if uri_set.include? uri.to_s
uri_set[uri.to_s] = true
+ raise TooManyRedirects.new("Too many redirects", buf.io) if max_redirects && uri_set.size > max_redirects
else
break
end
@@ -392,6 +395,9 @@ module OpenURI
attr_reader :uri
end
+ class TooManyRedirects < HTTPError
+ end
+
class Buffer # :nodoc: all
def initialize
@io = StringIO.new
diff --git a/lib/open3.rb b/lib/open3.rb
index 72c9ae5962..74d00b86d9 100644
--- a/lib/open3.rb
+++ b/lib/open3.rb
@@ -72,11 +72,11 @@ require 'open3/version'
# Each of the methods above accepts:
#
# - An optional hash of environment variable names and values;
-# see {Execution Environment}[rdoc-ref:Process#Execution+Environment].
+# see {Execution Environment}[rdoc-ref:Process@Execution+Environment].
# - A required string argument that is a +command_line+ or +exe_path+;
-# see {Argument command_line or exe_path}[rdoc-ref:Process#Argument+command_line+or+exe_path].
+# see {Argument command_line or exe_path}[rdoc-ref:Process@Argument+command_line+or+exe_path].
# - An optional hash of execution options;
-# see {Execution Options}[rdoc-ref:Process#Execution+Options].
+# see {Execution Options}[rdoc-ref:Process@Execution+Options].
#
module Open3
@@ -86,7 +86,9 @@ module Open3
# Open3.popen3([env, ] command_line, options = {}) {|stdin, stdout, stderr, wait_thread| ... } -> object
# Open3.popen3([env, ] exe_path, *args, options = {}) {|stdin, stdout, stderr, wait_thread| ... } -> object
#
- # Basically a wrapper for Process.spawn that:
+ # Basically a wrapper for
+ # {Process.spawn}[rdoc-ref:Process.spawn]
+ # that:
#
# - Creates a child process, by calling Process.spawn with the given arguments.
# - Creates streams +stdin+, +stdout+, and +stderr+,
@@ -133,12 +135,17 @@ module Open3
#
# Like Process.spawn, this method has potential security vulnerabilities
# if called with untrusted input;
- # see {Command Injection}[rdoc-ref:command_injection.rdoc].
+ # see {Command Injection}[rdoc-ref:command_injection.rdoc@Command+Injection].
#
# Unlike Process.spawn, this method waits for the child process to exit
# before returning, so the caller need not do so.
#
- # Argument +options+ is a hash of options for the new process;
+ # If the first argument is a hash, it becomes leading argument +env+
+ # in the call to Process.spawn;
+ # see {Execution Environment}[rdoc-ref:Process@Execution+Environment].
+ #
+ # If the last argument is a hash, it becomes trailing argument +options+
+ # in the call to Process.spawn;
# see {Execution Options}[rdoc-ref:Process@Execution+Options].
#
# The single required argument is one of the following:
@@ -235,7 +242,9 @@ module Open3
# Open3.popen2([env, ] command_line, options = {}) {|stdin, stdout, wait_thread| ... } -> object
# Open3.popen2([env, ] exe_path, *args, options = {}) {|stdin, stdout, wait_thread| ... } -> object
#
- # Basically a wrapper for Process.spawn that:
+ # Basically a wrapper for
+ # {Process.spawn}[rdoc-ref:Process.spawn]
+ # that:
#
# - Creates a child process, by calling Process.spawn with the given arguments.
# - Creates streams +stdin+ and +stdout+,
@@ -279,12 +288,17 @@ module Open3
#
# Like Process.spawn, this method has potential security vulnerabilities
# if called with untrusted input;
- # see {Command Injection}[rdoc-ref:command_injection.rdoc].
+ # see {Command Injection}[rdoc-ref:command_injection.rdoc@Command+Injection].
#
# Unlike Process.spawn, this method waits for the child process to exit
# before returning, so the caller need not do so.
#
- # Argument +options+ is a hash of options for the new process;
+ # If the first argument is a hash, it becomes leading argument +env+
+ # in the call to Process.spawn;
+ # see {Execution Environment}[rdoc-ref:Process@Execution+Environment].
+ #
+ # If the last argument is a hash, it becomes trailing argument +options+
+ # in the call to Process.spawn;
# see {Execution Options}[rdoc-ref:Process@Execution+Options].
#
# The single required argument is one of the following:
@@ -372,7 +386,9 @@ module Open3
# Open3.popen2e([env, ] command_line, options = {}) {|stdin, stdout_and_stderr, wait_thread| ... } -> object
# Open3.popen2e([env, ] exe_path, *args, options = {}) {|stdin, stdout_and_stderr, wait_thread| ... } -> object
#
- # Basically a wrapper for Process.spawn that:
+ # Basically a wrapper for
+ # {Process.spawn}[rdoc-ref:Process.spawn]
+ # that:
#
# - Creates a child process, by calling Process.spawn with the given arguments.
# - Creates streams +stdin+, +stdout_and_stderr+,
@@ -416,12 +432,17 @@ module Open3
#
# Like Process.spawn, this method has potential security vulnerabilities
# if called with untrusted input;
- # see {Command Injection}[rdoc-ref:command_injection.rdoc].
+ # see {Command Injection}[rdoc-ref:command_injection.rdoc@Command+Injection].
#
# Unlike Process.spawn, this method waits for the child process to exit
# before returning, so the caller need not do so.
#
- # Argument +options+ is a hash of options for the new process;
+ # If the first argument is a hash, it becomes leading argument +env+
+ # in the call to Process.spawn;
+ # see {Execution Environment}[rdoc-ref:Process@Execution+Environment].
+ #
+ # If the last argument is a hash, it becomes trailing argument +options+
+ # in the call to Process.spawn;
# see {Execution Options}[rdoc-ref:Process@Execution+Options].
#
# The single required argument is one of the following:
@@ -549,15 +570,20 @@ module Open3
#
# Like Process.spawn, this method has potential security vulnerabilities
# if called with untrusted input;
- # see {Command Injection}[rdoc-ref:command_injection.rdoc].
+ # see {Command Injection}[rdoc-ref:command_injection.rdoc@Command+Injection].
#
# Unlike Process.spawn, this method waits for the child process to exit
# before returning, so the caller need not do so.
#
- # Argument +options+ is a hash of options for the new process;
+ # If the first argument is a hash, it becomes leading argument +env+
+ # in the call to Open3.popen3;
+ # see {Execution Environment}[rdoc-ref:Process@Execution+Environment].
+ #
+ # If the last argument is a hash, it becomes trailing argument +options+
+ # in the call to Open3.popen3;
# see {Execution Options}[rdoc-ref:Process@Execution+Options].
#
- # The hash +options+ is passed to method Open3.popen3;
+ # The hash +options+ is given;
# two options have local effect in method Open3.capture3:
#
# - If entry <tt>options[:stdin_data]</tt> exists, the entry is removed
@@ -566,7 +592,7 @@ module Open3
# Open3.capture3('tee', stdin_data: 'Foo')
# # => ["Foo", "", #<Process::Status: pid 2319575 exit 0>]
#
- # - If entry <tt>options[:binmode]</tt> exists, the entry is removed
+ # - If entry <tt>options[:binmode]</tt> exists, the entry is removed and
# the internal streams are set to binary mode.
#
# The single required argument is one of the following:
@@ -670,15 +696,20 @@ module Open3
#
# Like Process.spawn, this method has potential security vulnerabilities
# if called with untrusted input;
- # see {Command Injection}[rdoc-ref:command_injection.rdoc].
+ # see {Command Injection}[rdoc-ref:command_injection.rdoc@Command+Injection].
#
# Unlike Process.spawn, this method waits for the child process to exit
# before returning, so the caller need not do so.
#
- # Argument +options+ is a hash of options for the new process;
+ # If the first argument is a hash, it becomes leading argument +env+
+ # in the call to Open3.popen3;
+ # see {Execution Environment}[rdoc-ref:Process@Execution+Environment].
+ #
+ # If the last argument is a hash, it becomes trailing argument +options+
+ # in the call to Open3.popen3;
# see {Execution Options}[rdoc-ref:Process@Execution+Options].
#
- # The hash +options+ is passed to method Open3.popen3;
+ # The hash +options+ is given;
# two options have local effect in method Open3.capture2:
#
# - If entry <tt>options[:stdin_data]</tt> exists, the entry is removed
@@ -688,6 +719,7 @@ module Open3
#
# # => ["Foo", #<Process::Status: pid 2326087 exit 0>]
#
+ # - If entry <tt>options[:binmode]</tt> exists, the entry is removed and
# the internal streams are set to binary mode.
#
# The single required argument is one of the following:
@@ -792,15 +824,20 @@ module Open3
#
# Like Process.spawn, this method has potential security vulnerabilities
# if called with untrusted input;
- # see {Command Injection}[rdoc-ref:command_injection.rdoc].
+ # see {Command Injection}[rdoc-ref:command_injection.rdoc@Command+Injection].
#
# Unlike Process.spawn, this method waits for the child process to exit
# before returning, so the caller need not do so.
#
- # Argument +options+ is a hash of options for the new process;
+ # If the first argument is a hash, it becomes leading argument +env+
+ # in the call to Open3.popen3;
+ # see {Execution Environment}[rdoc-ref:Process@Execution+Environment].
+ #
+ # If the last argument is a hash, it becomes trailing argument +options+
+ # in the call to Open3.popen3;
# see {Execution Options}[rdoc-ref:Process@Execution+Options].
#
- # The hash +options+ is passed to method Open3.popen3;
+ # The hash +options+ is given;
# two options have local effect in method Open3.capture2e:
#
# - If entry <tt>options[:stdin_data]</tt> exists, the entry is removed
@@ -809,6 +846,7 @@ module Open3
# Open3.capture2e('tee', stdin_data: 'Foo')
# # => ["Foo", #<Process::Status: pid 2371732 exit 0>]
#
+ # - If entry <tt>options[:binmode]</tt> exists, the entry is removed and
# the internal streams are set to binary mode.
#
# The single required argument is one of the following:
@@ -893,48 +931,86 @@ module Open3
end
module_function :capture2e
- # Open3.pipeline_rw starts a list of commands as a pipeline with pipes
- # which connect to stdin of the first command and stdout of the last command.
- #
- # Open3.pipeline_rw(cmd1, cmd2, ... [, opts]) {|first_stdin, last_stdout, wait_threads|
- # ...
- # }
+ # :call-seq:
+ # Open3.pipeline_rw([env, ] *cmds, options = {}) -> [first_stdin, last_stdout, wait_threads]
#
- # first_stdin, last_stdout, wait_threads = Open3.pipeline_rw(cmd1, cmd2, ... [, opts])
- # ...
- # first_stdin.close
- # last_stdout.close
+ # Basically a wrapper for
+ # {Process.spawn}[rdoc-ref:Process.spawn]
+ # that:
#
- # Each cmd is a string or an array.
- # If it is an array, the elements are passed to Process.spawn.
+ # - Creates a child process for each of the given +cmds+
+ # by calling Process.spawn.
+ # - Pipes the +stdout+ from each child to the +stdin+ of the next child,
+ # or, for the first child, from the caller's +stdin+,
+ # or, for the last child, to the caller's +stdout+.
#
- # cmd:
- # commandline command line string which is passed to a shell
- # [env, commandline, opts] command line string which is passed to a shell
- # [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell)
- # [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell)
+ # The method does not wait for child processes to exit,
+ # so the caller must do so.
#
- # Note that env and opts are optional, as for Process.spawn.
+ # With no block given, returns a 3-element array containing:
#
- # The options to pass to Process.spawn are constructed by merging
- # +opts+, the last hash element of the array, and
- # specifications for the pipes between each of the commands.
+ # - The +stdin+ stream of the first child process.
+ # - The +stdout+ stream of the last child process.
+ # - An array of the wait threads for all of the child processes.
#
# Example:
#
- # Open3.pipeline_rw("tr -dc A-Za-z", "wc -c") {|i, o, ts|
- # i.puts "All persons more than a mile high to leave the court."
- # i.close
- # p o.gets #=> "42\n"
- # }
- #
- # Open3.pipeline_rw("sort", "cat -n") {|stdin, stdout, wait_thrs|
- # stdin.puts "foo"
- # stdin.puts "bar"
- # stdin.puts "baz"
- # stdin.close # send EOF to sort.
- # p stdout.read #=> " 1\tbar\n 2\tbaz\n 3\tfoo\n"
- # }
+ # first_stdin, last_stdout, wait_threads = Open3.pipeline_rw('sort', 'cat -n')
+ # # => [#<IO:fd 20>, #<IO:fd 21>, [#<Process::Waiter:0x000055e8de29ab40 sleep>, #<Process::Waiter:0x000055e8de29a690 sleep>]]
+ # first_stdin.puts("foo\nbar\nbaz")
+ # first_stdin.close # Send EOF to sort.
+ # puts last_stdout.read
+ # wait_threads.each do |wait_thread|
+ # wait_thread.join
+ # end
+ #
+ # Output:
+ #
+ # 1 bar
+ # 2 baz
+ # 3 foo
+ #
+ # With a block given, calls the block with the +stdin+ stream of the first child,
+ # the +stdout+ stream of the last child,
+ # and an array of the wait processes:
+ #
+ # Open3.pipeline_rw('sort', 'cat -n') do |first_stdin, last_stdout, wait_threads|
+ # first_stdin.puts "foo\nbar\nbaz"
+ # first_stdin.close # send EOF to sort.
+ # puts last_stdout.read
+ # wait_threads.each do |wait_thread|
+ # wait_thread.join
+ # end
+ # end
+ #
+ # Output:
+ #
+ # 1 bar
+ # 2 baz
+ # 3 foo
+ #
+ # Like Process.spawn, this method has potential security vulnerabilities
+ # if called with untrusted input;
+ # see {Command Injection}[rdoc-ref:command_injection.rdoc@Command+Injection].
+ #
+ # If the first argument is a hash, it becomes leading argument +env+
+ # in each call to Process.spawn;
+ # see {Execution Environment}[rdoc-ref:Process@Execution+Environment].
+ #
+ # If the last argument is a hash, it becomes trailing argument +options+
+ # in each call to Process.spawn;
+ # see {Execution Options}[rdoc-ref:Process@Execution+Options].
+ #
+ # Each remaining argument in +cmds+ is one of:
+ #
+ # - A +command_line+: a string that begins with a shell reserved word
+ # or special built-in, or contains one or more metacharacters.
+ # - An +exe_path+: the string path to an executable to be called.
+ # - An array containing a +command_line+ or an +exe_path+,
+ # along with zero or more string arguments for the command.
+ #
+ # See {Argument command_line or exe_path}[rdoc-ref:Process@Argument+command_line+or+exe_path].
+ #
def pipeline_rw(*cmds, &block)
if Hash === cmds.last
opts = cmds.pop.dup
@@ -953,43 +1029,77 @@ module Open3
end
module_function :pipeline_rw
- # Open3.pipeline_r starts a list of commands as a pipeline with a pipe
- # which connects to stdout of the last command.
+ # :call-seq:
+ # Open3.pipeline_r([env, ] *cmds, options = {}) -> [last_stdout, wait_threads]
#
- # Open3.pipeline_r(cmd1, cmd2, ... [, opts]) {|last_stdout, wait_threads|
- # ...
- # }
+ # Basically a wrapper for
+ # {Process.spawn}[rdoc-ref:Process.spawn]
+ # that:
#
- # last_stdout, wait_threads = Open3.pipeline_r(cmd1, cmd2, ... [, opts])
- # ...
- # last_stdout.close
+ # - Creates a child process for each of the given +cmds+
+ # by calling Process.spawn.
+ # - Pipes the +stdout+ from each child to the +stdin+ of the next child,
+ # or, for the last child, to the caller's +stdout+.
#
- # Each cmd is a string or an array.
- # If it is an array, the elements are passed to Process.spawn.
+ # The method does not wait for child processes to exit,
+ # so the caller must do so.
#
- # cmd:
- # commandline command line string which is passed to a shell
- # [env, commandline, opts] command line string which is passed to a shell
- # [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell)
- # [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell)
+ # With no block given, returns a 2-element array containing:
#
- # Note that env and opts are optional, as for Process.spawn.
+ # - The +stdout+ stream of the last child process.
+ # - An array of the wait threads for all of the child processes.
#
# Example:
#
- # Open3.pipeline_r("zcat /var/log/apache2/access.log.*.gz",
- # [{"LANG"=>"C"}, "grep", "GET /favicon.ico"],
- # "logresolve") {|o, ts|
- # o.each_line {|line|
- # ...
- # }
- # }
+ # last_stdout, wait_threads = Open3.pipeline_r('ls', 'grep R')
+ # # => [#<IO:fd 5>, [#<Process::Waiter:0x000055e8de2f9898 dead>, #<Process::Waiter:0x000055e8de2f94b0 sleep>]]
+ # puts last_stdout.read
+ # wait_threads.each do |wait_thread|
+ # wait_thread.join
+ # end
+ #
+ # Output:
+ #
+ # Rakefile
+ # README.md
+ #
+ # With a block given, calls the block with the +stdout+ stream
+ # of the last child process,
+ # and an array of the wait processes:
#
- # Open3.pipeline_r("yes", "head -10") {|o, ts|
- # p o.read #=> "y\ny\ny\ny\ny\ny\ny\ny\ny\ny\n"
- # p ts[0].value #=> #<Process::Status: pid 24910 SIGPIPE (signal 13)>
- # p ts[1].value #=> #<Process::Status: pid 24913 exit 0>
- # }
+ # Open3.pipeline_r('ls', 'grep R') do |last_stdout, wait_threads|
+ # puts last_stdout.read
+ # wait_threads.each do |wait_thread|
+ # wait_thread.join
+ # end
+ # end
+ #
+ # Output:
+ #
+ # Rakefile
+ # README.md
+ #
+ # Like Process.spawn, this method has potential security vulnerabilities
+ # if called with untrusted input;
+ # see {Command Injection}[rdoc-ref:command_injection.rdoc@Command+Injection].
+ #
+ # If the first argument is a hash, it becomes leading argument +env+
+ # in each call to Process.spawn;
+ # see {Execution Environment}[rdoc-ref:Process@Execution+Environment].
+ #
+ # If the last argument is a hash, it becomes trailing argument +options+
+ # in each call to Process.spawn;
+ # see {Execution Options}[rdoc-ref:Process@Execution+Options].
+ #
+ # Each remaining argument in +cmds+ is one of:
+ #
+ # - A +command_line+: a string that begins with a shell reserved word
+ # or special built-in, or contains one or more metacharacters.
+ # - An +exe_path+: the string path to an executable to be called.
+ # - An array containing a +command_line+ or an +exe_path+,
+ # along with zero or more string arguments for the command.
+ #
+ # See {Argument command_line or exe_path}[rdoc-ref:Process@Argument+command_line+or+exe_path].
#
def pipeline_r(*cmds, &block)
if Hash === cmds.last
@@ -1005,33 +1115,82 @@ module Open3
end
module_function :pipeline_r
- # Open3.pipeline_w starts a list of commands as a pipeline with a pipe
- # which connects to stdin of the first command.
+
+ # :call-seq:
+ # Open3.pipeline_w([env, ] *cmds, options = {}) -> [first_stdin, wait_threads]
#
- # Open3.pipeline_w(cmd1, cmd2, ... [, opts]) {|first_stdin, wait_threads|
- # ...
- # }
+ # Basically a wrapper for
+ # {Process.spawn}[rdoc-ref:Process.spawn]
+ # that:
#
- # first_stdin, wait_threads = Open3.pipeline_w(cmd1, cmd2, ... [, opts])
- # ...
- # first_stdin.close
+ # - Creates a child process for each of the given +cmds+
+ # by calling Process.spawn.
+ # - Pipes the +stdout+ from each child to the +stdin+ of the next child,
+ # or, for the first child, pipes the caller's +stdout+ to the child's +stdin+.
#
- # Each cmd is a string or an array.
- # If it is an array, the elements are passed to Process.spawn.
+ # The method does not wait for child processes to exit,
+ # so the caller must do so.
#
- # cmd:
- # commandline command line string which is passed to a shell
- # [env, commandline, opts] command line string which is passed to a shell
- # [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell)
- # [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell)
+ # With no block given, returns a 2-element array containing:
#
- # Note that env and opts are optional, as for Process.spawn.
+ # - The +stdin+ stream of the first child process.
+ # - An array of the wait threads for all of the child processes.
#
# Example:
#
- # Open3.pipeline_w("bzip2 -c", :out=>"/tmp/hello.bz2") {|i, ts|
- # i.puts "hello"
- # }
+ # first_stdin, wait_threads = Open3.pipeline_w('sort', 'cat -n')
+ # # => [#<IO:fd 7>, [#<Process::Waiter:0x000055e8de928278 run>, #<Process::Waiter:0x000055e8de923e80 run>]]
+ # first_stdin.puts("foo\nbar\nbaz")
+ # first_stdin.close # Send EOF to sort.
+ # wait_threads.each do |wait_thread|
+ # wait_thread.join
+ # end
+ #
+ # Output:
+ #
+ # 1 bar
+ # 2 baz
+ # 3 foo
+ #
+ # With a block given, calls the block with the +stdin+ stream
+ # of the first child process,
+ # and an array of the wait processes:
+ #
+ # Open3.pipeline_w('sort', 'cat -n') do |first_stdin, wait_threads|
+ # first_stdin.puts("foo\nbar\nbaz")
+ # first_stdin.close # Send EOF to sort.
+ # wait_threads.each do |wait_thread|
+ # wait_thread.join
+ # end
+ # end
+ #
+ # Output:
+ #
+ # 1 bar
+ # 2 baz
+ # 3 foo
+ #
+ # Like Process.spawn, this method has potential security vulnerabilities
+ # if called with untrusted input;
+ # see {Command Injection}[rdoc-ref:command_injection.rdoc@Command+Injection].
+ #
+ # If the first argument is a hash, it becomes leading argument +env+
+ # in each call to Process.spawn;
+ # see {Execution Environment}[rdoc-ref:Process@Execution+Environment].
+ #
+ # If the last argument is a hash, it becomes trailing argument +options+
+ # in each call to Process.spawn;
+ # see {Execution Options}[rdoc-ref:Process@Execution+Options].
+ #
+ # Each remaining argument in +cmds+ is one of:
+ #
+ # - A +command_line+: a string that begins with a shell reserved word
+ # or special built-in, or contains one or more metacharacters.
+ # - An +exe_path+: the string path to an executable to be called.
+ # - An array containing a +command_line+ or an +exe_path+,
+ # along with zero or more string arguments for the command.
+ #
+ # See {Argument command_line or exe_path}[rdoc-ref:Process@Argument+command_line+or+exe_path].
#
def pipeline_w(*cmds, &block)
if Hash === cmds.last
@@ -1048,49 +1207,67 @@ module Open3
end
module_function :pipeline_w
- # Open3.pipeline_start starts a list of commands as a pipeline.
- # No pipes are created for stdin of the first command and
- # stdout of the last command.
+ # :call-seq:
+ # Open3.pipeline_start([env, ] *cmds, options = {}) -> [wait_threads]
#
- # Open3.pipeline_start(cmd1, cmd2, ... [, opts]) {|wait_threads|
- # ...
- # }
+ # Basically a wrapper for
+ # {Process.spawn}[rdoc-ref:Process.spawn]
+ # that:
#
- # wait_threads = Open3.pipeline_start(cmd1, cmd2, ... [, opts])
- # ...
+ # - Creates a child process for each of the given +cmds+
+ # by calling Process.spawn.
+ # - Does not wait for child processes to exit.
#
- # Each cmd is a string or an array.
- # If it is an array, the elements are passed to Process.spawn.
+ # With no block given, returns an array of the wait threads
+ # for all of the child processes.
#
- # cmd:
- # commandline command line string which is passed to a shell
- # [env, commandline, opts] command line string which is passed to a shell
- # [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell)
- # [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell)
+ # Example:
#
- # Note that env and opts are optional, as for Process.spawn.
+ # wait_threads = Open3.pipeline_start('ls', 'grep R')
+ # # => [#<Process::Waiter:0x000055e8de9d2bb0 run>, #<Process::Waiter:0x000055e8de9d2890 run>]
+ # wait_threads.each do |wait_thread|
+ # wait_thread.join
+ # end
#
- # Example:
+ # Output:
+ #
+ # Rakefile
+ # README.md
+ #
+ # With a block given, calls the block with an array of the wait processes:
+ #
+ # Open3.pipeline_start('ls', 'grep R') do |wait_threads|
+ # wait_threads.each do |wait_thread|
+ # wait_thread.join
+ # end
+ # end
+ #
+ # Output:
+ #
+ # Rakefile
+ # README.md
#
- # # Run xeyes in 10 seconds.
- # Open3.pipeline_start("xeyes") {|ts|
- # sleep 10
- # t = ts[0]
- # Process.kill("TERM", t.pid)
- # p t.value #=> #<Process::Status: pid 911 SIGTERM (signal 15)>
- # }
- #
- # # Convert pdf to ps and send it to a printer.
- # # Collect error message of pdftops and lpr.
- # pdf_file = "paper.pdf"
- # printer = "printer-name"
- # err_r, err_w = IO.pipe
- # Open3.pipeline_start(["pdftops", pdf_file, "-"],
- # ["lpr", "-P#{printer}"],
- # :err=>err_w) {|ts|
- # err_w.close
- # p err_r.read # error messages of pdftops and lpr.
- # }
+ # Like Process.spawn, this method has potential security vulnerabilities
+ # if called with untrusted input;
+ # see {Command Injection}[rdoc-ref:command_injection.rdoc@Command+Injection].
+ #
+ # If the first argument is a hash, it becomes leading argument +env+
+ # in each call to Process.spawn;
+ # see {Execution Environment}[rdoc-ref:Process@Execution+Environment].
+ #
+ # If the last argument is a hash, it becomes trailing argument +options+
+ # in each call to Process.spawn;
+ # see {Execution Options}[rdoc-ref:Process@Execution+Options].
+ #
+ # Each remaining argument in +cmds+ is one of:
+ #
+ # - A +command_line+: a string that begins with a shell reserved word
+ # or special built-in, or contains one or more metacharacters.
+ # - An +exe_path+: the string path to an executable to be called.
+ # - An array containing a +command_line+ or an +exe_path+,
+ # along with zero or more string arguments for the command.
+ #
+ # See {Argument command_line or exe_path}[rdoc-ref:Process@Argument+command_line+or+exe_path].
#
def pipeline_start(*cmds, &block)
if Hash === cmds.last
@@ -1119,27 +1296,22 @@ module Open3
# by calling Process.spawn.
# - Pipes the +stdout+ from each child to the +stdin+ of the next child,
# or, for the last child, to the caller's +stdout+.
- # - Waits for all child processes to exit.
+ # - Waits for the child processes to exit.
# - Returns an array of Process::Status objects (one for each child).
#
- # A simple example:
+ # Example:
#
- # Open3.pipeline('ls', 'grep [A-Z]')
- # # => [#<Process::Status: pid 1343895 exit 0>, #<Process::Status: pid 1343897 exit 0>]
+ # wait_threads = Open3.pipeline('ls', 'grep R')
+ # # => [#<Process::Status: pid 2139200 exit 0>, #<Process::Status: pid 2139202 exit 0>]
#
# Output:
#
- # Gemfile
- # LICENSE.txt
# Rakefile
# README.md
#
# Like Process.spawn, this method has potential security vulnerabilities
# if called with untrusted input;
- # see {Command Injection}[rdoc-ref:command_injection.rdoc].
- #
- # Unlike Process.spawn, this method waits for the child process to exit
- # before returning, so the caller need not do so.
+ # see {Command Injection}[rdoc-ref:command_injection.rdoc@Command+Injection].
#
# If the first argument is a hash, it becomes leading argument +env+
# in each call to Process.spawn;
@@ -1157,6 +1329,8 @@ module Open3
# - An array containing a +command_line+ or an +exe_path+,
# along with zero or more string arguments for the command.
#
+ # See {Argument command_line or exe_path}[rdoc-ref:Process@Argument+command_line+or+exe_path].
+ #
def pipeline(*cmds)
if Hash === cmds.last
opts = cmds.pop.dup
diff --git a/lib/open3/version.rb b/lib/open3/version.rb
index 378b389110..bfcec44ccc 100644
--- a/lib/open3/version.rb
+++ b/lib/open3/version.rb
@@ -1,3 +1,3 @@
module Open3
- VERSION = "0.2.0"
+ VERSION = "0.2.1"
end
diff --git a/lib/optparse.rb b/lib/optparse.rb
index 832b928a2d..069c3e436e 100644
--- a/lib/optparse.rb
+++ b/lib/optparse.rb
@@ -8,7 +8,6 @@
# See OptionParser for documentation.
#
-
#--
# == Developer Documentation (not for RDoc output)
#
@@ -425,7 +424,8 @@
# If you have any questions, file a ticket at http://bugs.ruby-lang.org.
#
class OptionParser
- OptionParser::Version = "0.4.0"
+ # The version string
+ OptionParser::Version = "0.5.0"
# :stopdoc:
NoArgument = [NO_ARGUMENT = :NONE, nil].freeze
@@ -438,6 +438,8 @@ class OptionParser
# and resolved against a list of acceptable values.
#
module Completion
+ # :nodoc:
+
def self.regexp(key, icase)
Regexp.new('\A' + Regexp.quote(key).gsub(/\w+\b/, '\&\w*'), icase)
end
@@ -459,7 +461,7 @@ class OptionParser
candidates
end
- def candidate(key, icase = false, pat = nil)
+ def candidate(key, icase = false, pat = nil, &_)
Completion.candidate(key, icase, pat, &method(:each))
end
@@ -510,6 +512,8 @@ class OptionParser
# RequiredArgument, etc.
#
class Switch
+ # :nodoc:
+
attr_reader :pattern, :conv, :short, :long, :arg, :desc, :block
#
@@ -697,6 +701,11 @@ class OptionParser
q.object_group(self) {pretty_print_contents(q)}
end
+ def omitted_argument(val) # :nodoc:
+ val.pop if val.size == 3 and val.last.nil?
+ val
+ end
+
#
# Switch that takes no arguments.
#
@@ -710,10 +719,10 @@ class OptionParser
conv_arg(arg)
end
- def self.incompatible_argument_styles(*)
+ def self.incompatible_argument_styles(*) # :nodoc:
end
- def self.pattern
+ def self.pattern # :nodoc:
Object
end
@@ -730,7 +739,7 @@ class OptionParser
#
# Raises an exception if argument is not present.
#
- def parse(arg, argv)
+ def parse(arg, argv, &_)
unless arg
raise MissingArgument if argv.empty?
arg = argv.shift
@@ -755,7 +764,7 @@ class OptionParser
if arg
conv_arg(*parse_arg(arg, &error))
else
- conv_arg(arg)
+ omitted_argument conv_arg(arg)
end
end
@@ -774,13 +783,14 @@ class OptionParser
#
def parse(arg, argv, &error)
if !(val = arg) and (argv.empty? or /\A-./ =~ (val = argv[0]))
- return nil, block, nil
+ return nil, block
end
opt = (val = parse_arg(val, &error))[1]
val = conv_arg(*val)
if opt and !arg
argv.shift
else
+ omitted_argument val
val[0] = nil
end
val
@@ -798,6 +808,8 @@ class OptionParser
# matching pattern and converter pair. Also provides summary feature.
#
class List
+ # :nodoc:
+
# Map from acceptable argument types to pattern and converter pairs.
attr_reader :atype
@@ -837,7 +849,7 @@ class OptionParser
def accept(t, pat = /.*/m, &block)
if pat
pat.respond_to?(:match) or
- raise TypeError, "has no `match'", ParseError.filter_backtrace(caller(2))
+ raise TypeError, "has no 'match'", ParseError.filter_backtrace(caller(2))
else
pat = t if t.respond_to?(:match)
end
@@ -1033,11 +1045,31 @@ XXX
to << "#compdef #{name}\n"
to << COMPSYS_HEADER
visit(:compsys, {}, {}) {|o, d|
- to << %Q[ "#{o}[#{d.gsub(/[\"\[\]]/, '\\\\\&')}]" \\\n]
+ to << %Q[ "#{o}[#{d.gsub(/[\\\"\[\]]/, '\\\\\&')}]" \\\n]
}
to << " '*:file:_files' && return 0\n"
end
+ def help_exit
+ if STDOUT.tty? && (pager = ENV.values_at(*%w[RUBY_PAGER PAGER]).find {|e| e && !e.empty?})
+ less = ENV["LESS"]
+ args = [{"LESS" => "#{!less || less.empty? ? '-' : less}Fe"}, pager, "w"]
+ print = proc do |f|
+ f.puts help
+ rescue Errno::EPIPE
+ # pager terminated
+ end
+ if Process.respond_to?(:fork) and false
+ IO.popen("-") {|f| f ? Process.exec(*args, in: f) : print.call(STDOUT)}
+ # unreachable
+ end
+ IO.popen(*args, &print)
+ else
+ puts help
+ end
+ exit
+ end
+
#
# Default options for ARGV, which never appear in option summary.
#
@@ -1049,8 +1081,7 @@ XXX
#
Officious['help'] = proc do |parser|
Switch::NoArgument.new do |arg|
- puts parser.help
- exit
+ parser.help_exit
end
end
@@ -1129,6 +1160,10 @@ XXX
default.to_i + 1
end
end
+
+ #
+ # See self.inc
+ #
def inc(*args)
self.class.inc(*args)
end
@@ -1167,11 +1202,19 @@ XXX
def terminate(arg = nil)
self.class.terminate(arg)
end
+ #
+ # See #terminate.
+ #
def self.terminate(arg = nil)
throw :terminate, arg
end
@stack = [DefaultList]
+ #
+ # Returns the global top option list.
+ #
+ # Do not use directly.
+ #
def self.top() DefaultList end
#
@@ -1192,9 +1235,9 @@ XXX
#
# Directs to reject specified class argument.
#
- # +t+:: Argument class specifier, any object including Class.
+ # +type+:: Argument class specifier, any object including Class.
#
- # reject(t)
+ # reject(type)
#
def reject(*args, &blk) top.reject(*args, &blk) end
#
@@ -1284,10 +1327,24 @@ XXX
end
end
+ #
+ # Shows warning message with the program name
+ #
+ # +mesg+:: Message, defaulted to +$!+.
+ #
+ # See Kernel#warn.
+ #
def warn(mesg = $!)
super("#{program_name}: #{mesg}")
end
+ #
+ # Shows message with the program name then aborts.
+ #
+ # +mesg+:: Message, defaulted to +$!+.
+ #
+ # See Kernel#abort.
+ #
def abort(mesg = $!)
super("#{program_name}: #{mesg}")
end
@@ -1309,6 +1366,9 @@ XXX
#
# Pushes a new List.
#
+ # If a block is given, yields +self+ and returns the result of the
+ # block, otherwise returns +self+.
+ #
def new
@stack.push(List.new)
if block_given?
@@ -1532,6 +1592,12 @@ XXX
nolong
end
+ # ----
+ # Option definition phase methods
+ #
+ # These methods are used to define options, or to construct an
+ # OptionParser instance in other words.
+
# :call-seq:
# define(*params, &block)
#
@@ -1607,6 +1673,13 @@ XXX
top.append(string, nil, nil)
end
+ # ----
+ # Arguments parse phase methods
+ #
+ # These methods parse +argv+, convert, and store the results by
+ # calling handlers. As these methods do not modify +self+, +self+
+ # can be frozen.
+
#
# Parses command line arguments +argv+ in order. When a block is given,
# each non-option argument is yielded. When optional +into+ keyword
@@ -1616,21 +1689,21 @@ XXX
#
# Returns the rest of +argv+ left unparsed.
#
- def order(*argv, into: nil, &nonopt)
+ def order(*argv, **keywords, &nonopt)
argv = argv[0].dup if argv.size == 1 and Array === argv[0]
- order!(argv, into: into, &nonopt)
+ order!(argv, **keywords, &nonopt)
end
#
# Same as #order, but removes switches destructively.
# Non-option arguments remain in +argv+.
#
- def order!(argv = default_argv, into: nil, &nonopt)
+ def order!(argv = default_argv, into: nil, **keywords, &nonopt)
setter = ->(name, val) {into[name.to_sym] = val} if into
- parse_in_order(argv, setter, &nonopt)
+ parse_in_order(argv, setter, **keywords, &nonopt)
end
- def parse_in_order(argv = default_argv, setter = nil, &nonopt) # :nodoc:
+ def parse_in_order(argv = default_argv, setter = nil, exact: require_exact, **, &nonopt) # :nodoc:
opt, arg, val, rest = nil
nonopt ||= proc {|a| throw :terminate, a}
argv.unshift(arg) if arg = catch(:terminate) {
@@ -1641,19 +1714,24 @@ XXX
opt, rest = $1, $2
opt.tr!('_', '-')
begin
- sw, = complete(:long, opt, true)
- if require_exact && !sw.long.include?(arg)
- throw :terminate, arg unless raise_unknown
- raise InvalidOption, arg
+ if exact
+ sw, = search(:long, opt)
+ else
+ sw, = complete(:long, opt, true)
end
rescue ParseError
throw :terminate, arg unless raise_unknown
raise $!.set_option(arg, true)
+ else
+ unless sw
+ throw :terminate, arg unless raise_unknown
+ raise InvalidOption, arg
+ end
end
begin
- opt, cb, val = sw.parse(rest, argv) {|*exc| raise(*exc)}
- val = cb.call(val) if cb
- setter.call(sw.switch_name, val) if setter
+ opt, cb, *val = sw.parse(rest, argv) {|*exc| raise(*exc)}
+ val = callback!(cb, 1, *val) if cb
+ callback!(setter, 2, sw.switch_name, *val) if setter
rescue ParseError
raise $!.set_option(arg, rest)
end
@@ -1671,7 +1749,7 @@ XXX
val = arg.delete_prefix('-')
has_arg = true
rescue InvalidOption
- raise if require_exact
+ raise if exact
# if no short options match, try completion with long
# options.
sw, = complete(:long, opt)
@@ -1683,7 +1761,7 @@ XXX
raise $!.set_option(arg, true)
end
begin
- opt, cb, val = sw.parse(val, argv) {|*exc| raise(*exc) if eq}
+ opt, cb, *val = sw.parse(val, argv) {|*exc| raise(*exc) if eq}
rescue ParseError
raise $!.set_option(arg, arg.length > 2)
else
@@ -1691,8 +1769,8 @@ XXX
end
begin
argv.unshift(opt) if opt and (!rest or (opt = opt.sub(/\A-*/, '-')) != '-')
- val = cb.call(val) if cb
- setter.call(sw.switch_name, val) if setter
+ val = callback!(cb, 1, *val) if cb
+ callback!(setter, 2, sw.switch_name, *val) if setter
rescue ParseError
raise $!.set_option(arg, arg.length > 2)
end
@@ -1718,6 +1796,17 @@ XXX
end
private :parse_in_order
+ # Calls callback with _val_.
+ def callback!(cb, max_arity, *args) # :nodoc:
+ if (size = args.size) < max_arity and cb.to_proc.lambda?
+ (arity = cb.arity) < 0 and arity = (1-arity)
+ arity = max_arity if arity > max_arity
+ args[arity - 1] = nil if arity > size
+ end
+ cb.call(*args)
+ end
+ private :callback!
+
#
# Parses command line arguments +argv+ in permutation mode and returns
# list of non-option arguments. When optional +into+ keyword
@@ -1725,18 +1814,18 @@ XXX
# <code>[]=</code> method (so it can be Hash, or OpenStruct, or other
# similar object).
#
- def permute(*argv, into: nil)
+ def permute(*argv, **keywords)
argv = argv[0].dup if argv.size == 1 and Array === argv[0]
- permute!(argv, into: into)
+ permute!(argv, **keywords)
end
#
# Same as #permute, but removes switches destructively.
# Non-option arguments remain in +argv+.
#
- def permute!(argv = default_argv, into: nil)
+ def permute!(argv = default_argv, **keywords)
nonopts = []
- order!(argv, into: into, &nonopts.method(:<<))
+ order!(argv, **keywords, &nonopts.method(:<<))
argv[0, 0] = nonopts
argv
end
@@ -1748,20 +1837,20 @@ XXX
# values are stored there via <code>[]=</code> method (so it can be Hash,
# or OpenStruct, or other similar object).
#
- def parse(*argv, into: nil)
+ def parse(*argv, **keywords)
argv = argv[0].dup if argv.size == 1 and Array === argv[0]
- parse!(argv, into: into)
+ parse!(argv, **keywords)
end
#
# Same as #parse, but removes switches destructively.
# Non-option arguments remain in +argv+.
#
- def parse!(argv = default_argv, into: nil)
+ def parse!(argv = default_argv, **keywords)
if ENV.include?('POSIXLY_CORRECT')
- order!(argv, into: into)
+ order!(argv, **keywords)
else
- permute!(argv, into: into)
+ permute!(argv, **keywords)
end
end
@@ -1784,7 +1873,7 @@ XXX
# # params[:bar] = "x" # --bar x
# # params[:zot] = "z" # --zot Z
#
- def getopts(*args, symbolize_names: false)
+ def getopts(*args, symbolize_names: false, **keywords)
argv = Array === args.first ? args.shift : default_argv
single_options, *long_options = *args
@@ -1812,7 +1901,7 @@ XXX
end
end
- parse_in_order(argv, result.method(:[]=))
+ parse_in_order(argv, result.method(:[]=), **keywords)
symbolize_names ? result.transform_keys(&:to_sym) : result
end
@@ -1881,6 +1970,9 @@ XXX
DidYouMean.formatter.message_for(all_candidates & checker.correct(opt))
end
+ #
+ # Return candidates for +word+.
+ #
def candidate(word)
list = []
case word
@@ -1922,10 +2014,10 @@ XXX
# The optional +into+ keyword argument works exactly like that accepted in
# method #parse.
#
- def load(filename = nil, into: nil)
+ def load(filename = nil, **keywords)
unless filename
basename = File.basename($0, '.*')
- return true if load(File.expand_path(basename, '~/.options'), into: into) rescue nil
+ return true if load(File.expand_path(basename, '~/.options'), **keywords) rescue nil
basename << ".options"
return [
# XDG
@@ -1937,11 +2029,11 @@ XXX
'~/config/settings',
].any? {|dir|
next if !dir or dir.empty?
- load(File.expand_path(basename, dir), into: into) rescue nil
+ load(File.expand_path(basename, dir), **keywords) rescue nil
}
end
begin
- parse(*File.readlines(filename, chomp: true), into: into)
+ parse(*File.readlines(filename, chomp: true), **keywords)
true
rescue Errno::ENOENT, Errno::ENOTDIR
false
@@ -1954,10 +2046,10 @@ XXX
#
# +env+ defaults to the basename of the program.
#
- def environment(env = File.basename($0, '.*'))
+ def environment(env = File.basename($0, '.*'), **keywords)
env = ENV[env] || ENV[env.upcase] or return
require 'shellwords'
- parse(*Shellwords.shellwords(env))
+ parse(*Shellwords.shellwords(env), **keywords)
end
#
@@ -2123,6 +2215,7 @@ XXX
# Reason which caused the error.
Reason = 'parse error'
+ # :nodoc:
def initialize(*args, additional: nil)
@additional = additional
@arg0, = args
@@ -2273,19 +2366,19 @@ XXX
# Parses +self+ destructively in order and returns +self+ containing the
# rest arguments left unparsed.
#
- def order!(&blk) options.order!(self, &blk) end
+ def order!(**keywords, &blk) options.order!(self, **keywords, &blk) end
#
# Parses +self+ destructively in permutation mode and returns +self+
# containing the rest arguments left unparsed.
#
- def permute!() options.permute!(self) end
+ def permute!(**keywords) options.permute!(self, **keywords) end
#
# Parses +self+ destructively and returns +self+ containing the
# rest arguments left unparsed.
#
- def parse!() options.parse!(self) end
+ def parse!(**keywords) options.parse!(self, **keywords) end
#
# Substitution of getopts is possible as follows. Also see
@@ -2298,8 +2391,8 @@ XXX
# rescue OptionParser::ParseError
# end
#
- def getopts(*args, symbolize_names: false)
- options.getopts(self, *args, symbolize_names: symbolize_names)
+ def getopts(*args, symbolize_names: false, **keywords)
+ options.getopts(self, *args, symbolize_names: symbolize_names, **keywords)
end
#
@@ -2309,7 +2402,8 @@ XXX
super
obj.instance_eval {@optparse = nil}
end
- def initialize(*args)
+
+ def initialize(*args) # :nodoc:
super
@optparse = nil
end
diff --git a/lib/optparse/ac.rb b/lib/optparse/ac.rb
index 0953725e46..23fc740d10 100644
--- a/lib/optparse/ac.rb
+++ b/lib/optparse/ac.rb
@@ -1,7 +1,11 @@
# frozen_string_literal: false
require_relative '../optparse'
+#
+# autoconf-like options.
+#
class OptionParser::AC < OptionParser
+ # :stopdoc:
private
def _check_ac_args(name, block)
@@ -14,6 +18,7 @@ class OptionParser::AC < OptionParser
end
ARG_CONV = proc {|val| val.nil? ? true : val}
+ private_constant :ARG_CONV
def _ac_arg_enable(prefix, name, help_string, block)
_check_ac_args(name, block)
@@ -29,16 +34,27 @@ class OptionParser::AC < OptionParser
enable
end
+ # :startdoc:
+
public
+ # Define <tt>--enable</tt> / <tt>--disable</tt> style option
+ #
+ # Appears as <tt>--enable-<i>name</i></tt> in help message.
def ac_arg_enable(name, help_string, &block)
_ac_arg_enable("enable", name, help_string, block)
end
+ # Define <tt>--enable</tt> / <tt>--disable</tt> style option
+ #
+ # Appears as <tt>--disable-<i>name</i></tt> in help message.
def ac_arg_disable(name, help_string, &block)
_ac_arg_enable("disable", name, help_string, block)
end
+ # Define <tt>--with</tt> / <tt>--without</tt> style option
+ #
+ # Appears as <tt>--with-<i>name</i></tt> in help message.
def ac_arg_with(name, help_string, &block)
_check_ac_args(name, block)
diff --git a/lib/optparse/kwargs.rb b/lib/optparse/kwargs.rb
index 992aca467e..59a2f61544 100644
--- a/lib/optparse/kwargs.rb
+++ b/lib/optparse/kwargs.rb
@@ -7,12 +7,17 @@ class OptionParser
#
# :include: ../../doc/optparse/creates_option.rdoc
#
- def define_by_keywords(options, meth, **opts)
- meth.parameters.each do |type, name|
+ # Defines options which set in to _options_ for keyword parameters
+ # of _method_.
+ #
+ # Parameters for each keywords are given as elements of _params_.
+ #
+ def define_by_keywords(options, method, **params)
+ method.parameters.each do |type, name|
case type
when :key, :keyreq
op, cl = *(type == :key ? %w"[ ]" : ["", ""])
- define("--#{name}=#{op}#{name.upcase}#{cl}", *opts[name]) do |o|
+ define("--#{name}=#{op}#{name.upcase}#{cl}", *params[name]) do |o|
options[name] = o
end
end
diff --git a/lib/optparse/optparse.gemspec b/lib/optparse/optparse.gemspec
index a4287ddeee..1aa54aa781 100644
--- a/lib/optparse/optparse.gemspec
+++ b/lib/optparse/optparse.gemspec
@@ -22,7 +22,8 @@ Gem::Specification.new do |spec|
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
- spec.files = Dir["{doc,lib,misc}/**/*"] + %w[README.md ChangeLog COPYING]
+ spec.files = Dir["{doc,lib,misc}/**/{*,.document}"] +
+ %w[README.md ChangeLog COPYING .document .rdoc_options]
spec.rdoc_options = ["--main=README.md", "--op=rdoc", "--page-dir=doc"]
spec.bindir = "exe"
spec.executables = []
diff --git a/lib/optparse/version.rb b/lib/optparse/version.rb
index b869d8fe51..b5ed695146 100644
--- a/lib/optparse/version.rb
+++ b/lib/optparse/version.rb
@@ -2,6 +2,11 @@
# OptionParser internal utility
class << OptionParser
+ #
+ # Shows version string in packages if Version is defined.
+ #
+ # +pkgs+:: package list
+ #
def show_version(*pkgs)
progname = ARGV.options.program_name
result = false
@@ -47,6 +52,8 @@ class << OptionParser
result
end
+ # :stopdoc:
+
def each_const(path, base = ::Object)
path.split(/::|\//).inject(base) do |klass, name|
raise NameError, path unless Module === klass
@@ -68,4 +75,6 @@ class << OptionParser
end
end
end
+
+ # :startdoc:
end
diff --git a/lib/ostruct.rb b/lib/ostruct.rb
index fa882b7b9b..c762baa5a5 100644
--- a/lib/ostruct.rb
+++ b/lib/ostruct.rb
@@ -376,7 +376,7 @@ class OpenStruct
end
@table.delete(sym) do
return yield if block
- raise! NameError.new("no field `#{sym}' in #{self}", sym)
+ raise! NameError.new("no field '#{sym}' in #{self}", sym)
end
end
diff --git a/lib/pp.rb b/lib/pp.rb
index 1708dee05e..1ec5a880eb 100644
--- a/lib/pp.rb
+++ b/lib/pp.rb
@@ -93,7 +93,7 @@ class PP < PrettyPrint
#
# PP.pp returns +out+.
def PP.pp(obj, out=$>, width=width_for(out))
- q = PP.new(out, width)
+ q = new(out, width)
q.guard_inspect_key {q.pp obj}
q.flush
#$pp = q
@@ -286,16 +286,21 @@ class PP < PrettyPrint
group(1, '{', '}') {
seplist(obj, nil, :each_pair) {|k, v|
group {
- pp k
- text '=>'
- group(1) {
- breakable ''
- pp v
- }
+ pp_hash_pair k, v
}
}
}
end
+
+ # A pretty print for a pair of Hash
+ def pp_hash_pair(k, v)
+ pp k
+ text '=>'
+ group(1) {
+ breakable ''
+ pp v
+ }
+ end
end
include PPMethods
@@ -422,8 +427,10 @@ end
class Data # :nodoc:
def pretty_print(q) # :nodoc:
- q.group(1, sprintf("#<data %s", PP.mcall(self, Kernel, :class).name), '>') {
- q.seplist(PP.mcall(self, Data, :members), lambda { q.text "," }) {|member|
+ class_name = PP.mcall(self, Kernel, :class).name
+ class_name = " #{class_name}" if class_name
+ q.group(1, "#<data#{class_name}", '>') {
+ q.seplist(PP.mcall(self, Kernel, :class).members, lambda { q.text "," }) {|member|
q.breakable
q.text member.to_s
q.text '='
@@ -438,11 +445,11 @@ class Data # :nodoc:
def pretty_print_cycle(q) # :nodoc:
q.text sprintf("#<data %s:...>", PP.mcall(self, Kernel, :class).name)
end
-end if "3.2" <= RUBY_VERSION
+end if defined?(Data.define)
class Range # :nodoc:
def pretty_print(q) # :nodoc:
- q.pp self.begin
+ q.pp self.begin if self.begin
q.breakable ''
q.text(self.exclude_end? ? '...' : '..')
q.breakable ''
diff --git a/lib/prism.rb b/lib/prism.rb
index 909b71d66d..66a64e7fd0 100644
--- a/lib/prism.rb
+++ b/lib/prism.rb
@@ -13,38 +13,37 @@ module Prism
autoload :BasicVisitor, "prism/visitor"
autoload :Compiler, "prism/compiler"
- autoload :Debug, "prism/debug"
autoload :DesugarCompiler, "prism/desugar_compiler"
autoload :Dispatcher, "prism/dispatcher"
autoload :DotVisitor, "prism/dot_visitor"
autoload :DSL, "prism/dsl"
+ autoload :InspectVisitor, "prism/inspect_visitor"
autoload :LexCompat, "prism/lex_compat"
autoload :LexRipper, "prism/lex_compat"
autoload :MutationCompiler, "prism/mutation_compiler"
- autoload :NodeInspector, "prism/node_inspector"
- autoload :RipperCompat, "prism/ripper_compat"
autoload :Pack, "prism/pack"
autoload :Pattern, "prism/pattern"
+ autoload :Reflection, "prism/reflection"
autoload :Serialize, "prism/serialize"
+ autoload :Translation, "prism/translation"
autoload :Visitor, "prism/visitor"
# Some of these constants are not meant to be exposed, so marking them as
# private here.
- private_constant :Debug
private_constant :LexCompat
private_constant :LexRipper
# :call-seq:
- # Prism::lex_compat(source, **options) -> Array
+ # Prism::lex_compat(source, **options) -> LexCompat::Result
#
- # Returns an array of tokens that closely resembles that of the Ripper lexer.
- # The only difference is that since we don't keep track of lexer state in the
- # same way, it's going to always return the NONE state.
+ # Returns a parse result whose value is an array of tokens that closely
+ # resembles the return value of Ripper::lex. The main difference is that the
+ # `:on_sp` token is not emitted.
#
# For supported options, see Prism::parse.
def self.lex_compat(source, **options)
- LexCompat.new(source, **options).result
+ LexCompat.new(source, **options).result # steep:ignore
end
# :call-seq:
@@ -54,7 +53,7 @@ module Prism
# returns the same tokens. Raises SyntaxError if the syntax in source is
# invalid.
def self.lex_ripper(source)
- LexRipper.new(source).result
+ LexRipper.new(source).result # steep:ignore
end
# :call-seq:
@@ -66,11 +65,10 @@ module Prism
end
end
+require_relative "prism/polyfill/byteindex"
require_relative "prism/node"
require_relative "prism/node_ext"
require_relative "prism/parse_result"
-require_relative "prism/parse_result/comments"
-require_relative "prism/parse_result/newlines"
# This is a Ruby implementation of the prism parser. If we're running on CRuby
# and we haven't explicitly set the PRISM_FFI_BACKEND environment variable, then
@@ -78,6 +76,12 @@ require_relative "prism/parse_result/newlines"
# module that uses FFI to call into the library.
if RUBY_ENGINE == "ruby" and !ENV["PRISM_FFI_BACKEND"]
require "prism/prism"
+
+ # The C extension is the default backend on CRuby.
+ Prism::BACKEND = :CEXT
else
require_relative "prism/ffi"
+
+ # The FFI backend is used on other Ruby implementations.
+ Prism::BACKEND = :FFI
end
diff --git a/lib/prism/debug.rb b/lib/prism/debug.rb
deleted file mode 100644
index d0469adc9a..0000000000
--- a/lib/prism/debug.rb
+++ /dev/null
@@ -1,195 +0,0 @@
-# frozen_string_literal: true
-
-module Prism
- # This module is used for testing and debugging and is not meant to be used by
- # consumers of this library.
- module Debug
- # A wrapper around a RubyVM::InstructionSequence that provides a more
- # convenient interface for accessing parts of the iseq.
- class ISeq # :nodoc:
- attr_reader :parts
-
- def initialize(parts)
- @parts = parts
- end
-
- def type
- parts[0]
- end
-
- def local_table
- parts[10]
- end
-
- def instructions
- parts[13]
- end
-
- def each_child
- instructions.each do |instruction|
- # Only look at arrays. Other instructions are line numbers or
- # tracepoint events.
- next unless instruction.is_a?(Array)
-
- instruction.each do |opnd|
- # Only look at arrays. Other operands are literals.
- next unless opnd.is_a?(Array)
-
- # Only look at instruction sequences. Other operands are literals.
- next unless opnd[0] == "YARVInstructionSequence/SimpleDataFormat"
-
- yield ISeq.new(opnd)
- end
- end
- end
- end
-
- private_constant :ISeq
-
- # :call-seq:
- # Debug::cruby_locals(source) -> Array
- #
- # For the given source, compiles with CRuby and returns a list of all of the
- # sets of local variables that were encountered.
- def self.cruby_locals(source)
- verbose, $VERBOSE = $VERBOSE, nil
-
- begin
- locals = []
- stack = [ISeq.new(RubyVM::InstructionSequence.compile(source).to_a)]
-
- while (iseq = stack.pop)
- names = [*iseq.local_table]
- names.map!.with_index do |name, index|
- # When an anonymous local variable is present in the iseq's local
- # table, it is represented as the stack offset from the top.
- # However, when these are dumped to binary and read back in, they
- # are replaced with the symbol :#arg_rest. To consistently handle
- # this, we replace them here with their index.
- if name == :"#arg_rest"
- names.length - index + 1
- else
- name
- end
- end
-
- locals << names
- iseq.each_child { |child| stack << child }
- end
-
- locals
- ensure
- $VERBOSE = verbose
- end
- end
-
- # Used to hold the place of a local that will be in the local table but
- # cannot be accessed directly from the source code. For example, the
- # iteration variable in a for loop or the positional parameter on a method
- # definition that is destructured.
- AnonymousLocal = Object.new
- private_constant :AnonymousLocal
-
- # :call-seq:
- # Debug::prism_locals(source) -> Array
- #
- # For the given source, parses with prism and returns a list of all of the
- # sets of local variables that were encountered.
- def self.prism_locals(source)
- locals = []
- stack = [Prism.parse(source).value]
-
- while (node = stack.pop)
- case node
- when BlockNode, DefNode, LambdaNode
- names = node.locals
-
- params = node.parameters
- params = params&.parameters unless node.is_a?(DefNode)
-
- # prism places parameters in the same order that they appear in the
- # source. CRuby places them in the order that they need to appear
- # according to their own internal calling convention. We mimic that
- # order here so that we can compare properly.
- if params
- sorted = [
- *params.requireds.map do |required|
- if required.is_a?(RequiredParameterNode)
- required.name
- else
- AnonymousLocal
- end
- end,
- *params.optionals.map(&:name),
- *((params.rest.name || :*) if params.rest && params.rest.operator != ","),
- *params.posts.map do |post|
- if post.is_a?(RequiredParameterNode)
- post.name
- else
- AnonymousLocal
- end
- end,
- *params.keywords.grep(RequiredKeywordParameterNode).map(&:name),
- *params.keywords.grep(OptionalKeywordParameterNode).map(&:name),
- ]
-
- if params.keyword_rest.is_a?(ForwardingParameterNode)
- sorted.push(:*, :&, :"...")
- end
-
- sorted << AnonymousLocal if params.keywords.any?
-
- # Recurse down the parameter tree to find any destructured
- # parameters and add them after the other parameters.
- param_stack = params.requireds.concat(params.posts).grep(MultiTargetNode).reverse
- while (param = param_stack.pop)
- case param
- when MultiTargetNode
- param_stack.concat(param.rights.reverse)
- param_stack << param.rest
- param_stack.concat(param.lefts.reverse)
- when RequiredParameterNode
- sorted << param.name
- when SplatNode
- sorted << param.expression.name if param.expression
- end
- end
-
- names = sorted.concat(names - sorted)
- end
-
- names.map!.with_index do |name, index|
- if name == AnonymousLocal
- names.length - index + 1
- else
- name
- end
- end
-
- locals << names
- when ClassNode, ModuleNode, ProgramNode, SingletonClassNode
- locals << node.locals
- when ForNode
- locals << [2]
- when PostExecutionNode
- locals.push([], [])
- when InterpolatedRegularExpressionNode
- locals << [] if node.once?
- end
-
- stack.concat(node.compact_child_nodes)
- end
-
- locals
- end
-
- # :call-seq:
- # Debug::newlines(source) -> Array
- #
- # For the given source string, return the byte offsets of every newline in
- # the source.
- def self.newlines(source)
- Prism.parse(source).source.offsets
- end
- end
-end
diff --git a/lib/prism/desugar_compiler.rb b/lib/prism/desugar_compiler.rb
index 3624217686..de02445149 100644
--- a/lib/prism/desugar_compiler.rb
+++ b/lib/prism/desugar_compiler.rb
@@ -1,6 +1,218 @@
# frozen_string_literal: true
module Prism
+ class DesugarAndWriteNode # :nodoc:
+ attr_reader :node, :source, :read_class, :write_class, :arguments
+
+ def initialize(node, source, read_class, write_class, *arguments)
+ @node = node
+ @source = source
+ @read_class = read_class
+ @write_class = write_class
+ @arguments = arguments
+ end
+
+ # Desugar `x &&= y` to `x && x = y`
+ def compile
+ AndNode.new(
+ source,
+ read_class.new(source, *arguments, node.name_loc),
+ write_class.new(source, *arguments, node.name_loc, node.value, node.operator_loc, node.location),
+ node.operator_loc,
+ node.location
+ )
+ end
+ end
+
+ class DesugarOrWriteDefinedNode # :nodoc:
+ attr_reader :node, :source, :read_class, :write_class, :arguments
+
+ def initialize(node, source, read_class, write_class, *arguments)
+ @node = node
+ @source = source
+ @read_class = read_class
+ @write_class = write_class
+ @arguments = arguments
+ end
+
+ # Desugar `x ||= y` to `defined?(x) ? x : x = y`
+ def compile
+ IfNode.new(
+ source,
+ node.operator_loc,
+ DefinedNode.new(source, nil, read_class.new(source, *arguments, node.name_loc), nil, node.operator_loc, node.name_loc),
+ node.operator_loc,
+ StatementsNode.new(source, [read_class.new(source, *arguments, node.name_loc)], node.location),
+ ElseNode.new(
+ source,
+ node.operator_loc,
+ StatementsNode.new(
+ source,
+ [write_class.new(source, *arguments, node.name_loc, node.value, node.operator_loc, node.location)],
+ node.location
+ ),
+ node.operator_loc,
+ node.location
+ ),
+ node.operator_loc,
+ node.location
+ )
+ end
+ end
+
+ class DesugarOperatorWriteNode # :nodoc:
+ attr_reader :node, :source, :read_class, :write_class, :arguments
+
+ def initialize(node, source, read_class, write_class, *arguments)
+ @node = node
+ @source = source
+ @read_class = read_class
+ @write_class = write_class
+ @arguments = arguments
+ end
+
+ # Desugar `x += y` to `x = x + y`
+ def compile
+ binary_operator_loc = node.binary_operator_loc.chop
+
+ write_class.new(
+ source,
+ *arguments,
+ node.name_loc,
+ CallNode.new(
+ source,
+ 0,
+ read_class.new(source, *arguments, node.name_loc),
+ nil,
+ binary_operator_loc.slice.to_sym,
+ binary_operator_loc,
+ nil,
+ ArgumentsNode.new(source, 0, [node.value], node.value.location),
+ nil,
+ nil,
+ node.location
+ ),
+ node.binary_operator_loc.copy(start_offset: node.binary_operator_loc.end_offset - 1, length: 1),
+ node.location
+ )
+ end
+ end
+
+ class DesugarOrWriteNode # :nodoc:
+ attr_reader :node, :source, :read_class, :write_class, :arguments
+
+ def initialize(node, source, read_class, write_class, *arguments)
+ @node = node
+ @source = source
+ @read_class = read_class
+ @write_class = write_class
+ @arguments = arguments
+ end
+
+ # Desugar `x ||= y` to `x || x = y`
+ def compile
+ OrNode.new(
+ source,
+ read_class.new(source, *arguments, node.name_loc),
+ write_class.new(source, *arguments, node.name_loc, node.value, node.operator_loc, node.location),
+ node.operator_loc,
+ node.location
+ )
+ end
+ end
+
+ private_constant :DesugarAndWriteNode, :DesugarOrWriteNode, :DesugarOrWriteDefinedNode, :DesugarOperatorWriteNode
+
+ class ClassVariableAndWriteNode
+ def desugar # :nodoc:
+ DesugarAndWriteNode.new(self, source, ClassVariableReadNode, ClassVariableWriteNode, name).compile
+ end
+ end
+
+ class ClassVariableOrWriteNode
+ def desugar # :nodoc:
+ DesugarOrWriteDefinedNode.new(self, source, ClassVariableReadNode, ClassVariableWriteNode, name).compile
+ end
+ end
+
+ class ClassVariableOperatorWriteNode
+ def desugar # :nodoc:
+ DesugarOperatorWriteNode.new(self, source, ClassVariableReadNode, ClassVariableWriteNode, name).compile
+ end
+ end
+
+ class ConstantAndWriteNode
+ def desugar # :nodoc:
+ DesugarAndWriteNode.new(self, source, ConstantReadNode, ConstantWriteNode, name).compile
+ end
+ end
+
+ class ConstantOrWriteNode
+ def desugar # :nodoc:
+ DesugarOrWriteDefinedNode.new(self, source, ConstantReadNode, ConstantWriteNode, name).compile
+ end
+ end
+
+ class ConstantOperatorWriteNode
+ def desugar # :nodoc:
+ DesugarOperatorWriteNode.new(self, source, ConstantReadNode, ConstantWriteNode, name).compile
+ end
+ end
+
+ class GlobalVariableAndWriteNode
+ def desugar # :nodoc:
+ DesugarAndWriteNode.new(self, source, GlobalVariableReadNode, GlobalVariableWriteNode, name).compile
+ end
+ end
+
+ class GlobalVariableOrWriteNode
+ def desugar # :nodoc:
+ DesugarOrWriteDefinedNode.new(self, source, GlobalVariableReadNode, GlobalVariableWriteNode, name).compile
+ end
+ end
+
+ class GlobalVariableOperatorWriteNode
+ def desugar # :nodoc:
+ DesugarOperatorWriteNode.new(self, source, GlobalVariableReadNode, GlobalVariableWriteNode, name).compile
+ end
+ end
+
+ class InstanceVariableAndWriteNode
+ def desugar # :nodoc:
+ DesugarAndWriteNode.new(self, source, InstanceVariableReadNode, InstanceVariableWriteNode, name).compile
+ end
+ end
+
+ class InstanceVariableOrWriteNode
+ def desugar # :nodoc:
+ DesugarOrWriteNode.new(self, source, InstanceVariableReadNode, InstanceVariableWriteNode, name).compile
+ end
+ end
+
+ class InstanceVariableOperatorWriteNode
+ def desugar # :nodoc:
+ DesugarOperatorWriteNode.new(self, source, InstanceVariableReadNode, InstanceVariableWriteNode, name).compile
+ end
+ end
+
+ class LocalVariableAndWriteNode
+ def desugar # :nodoc:
+ DesugarAndWriteNode.new(self, source, LocalVariableReadNode, LocalVariableWriteNode, name, depth).compile
+ end
+ end
+
+ class LocalVariableOrWriteNode
+ def desugar # :nodoc:
+ DesugarOrWriteNode.new(self, source, LocalVariableReadNode, LocalVariableWriteNode, name, depth).compile
+ end
+ end
+
+ class LocalVariableOperatorWriteNode
+ def desugar # :nodoc:
+ DesugarOperatorWriteNode.new(self, source, LocalVariableReadNode, LocalVariableWriteNode, name, depth).compile
+ end
+ end
+
# DesugarCompiler is a compiler that desugars Ruby code into a more primitive
# form. This is useful for consumers that want to deal with fewer node types.
class DesugarCompiler < MutationCompiler
@@ -10,7 +222,7 @@ module Prism
#
# @@foo && @@foo = bar
def visit_class_variable_and_write_node(node)
- desugar_and_write_node(node, ClassVariableReadNode, ClassVariableWriteNode, node.name)
+ node.desugar
end
# @@foo ||= bar
@@ -19,7 +231,7 @@ module Prism
#
# defined?(@@foo) ? @@foo : @@foo = bar
def visit_class_variable_or_write_node(node)
- desugar_or_write_defined_node(node, ClassVariableReadNode, ClassVariableWriteNode, node.name)
+ node.desugar
end
# @@foo += bar
@@ -28,7 +240,7 @@ module Prism
#
# @@foo = @@foo + bar
def visit_class_variable_operator_write_node(node)
- desugar_operator_write_node(node, ClassVariableReadNode, ClassVariableWriteNode, node.name)
+ node.desugar
end
# Foo &&= bar
@@ -37,7 +249,7 @@ module Prism
#
# Foo && Foo = bar
def visit_constant_and_write_node(node)
- desugar_and_write_node(node, ConstantReadNode, ConstantWriteNode, node.name)
+ node.desugar
end
# Foo ||= bar
@@ -46,7 +258,7 @@ module Prism
#
# defined?(Foo) ? Foo : Foo = bar
def visit_constant_or_write_node(node)
- desugar_or_write_defined_node(node, ConstantReadNode, ConstantWriteNode, node.name)
+ node.desugar
end
# Foo += bar
@@ -55,7 +267,7 @@ module Prism
#
# Foo = Foo + bar
def visit_constant_operator_write_node(node)
- desugar_operator_write_node(node, ConstantReadNode, ConstantWriteNode, node.name)
+ node.desugar
end
# $foo &&= bar
@@ -64,7 +276,7 @@ module Prism
#
# $foo && $foo = bar
def visit_global_variable_and_write_node(node)
- desugar_and_write_node(node, GlobalVariableReadNode, GlobalVariableWriteNode, node.name)
+ node.desugar
end
# $foo ||= bar
@@ -73,7 +285,7 @@ module Prism
#
# defined?($foo) ? $foo : $foo = bar
def visit_global_variable_or_write_node(node)
- desugar_or_write_defined_node(node, GlobalVariableReadNode, GlobalVariableWriteNode, node.name)
+ node.desugar
end
# $foo += bar
@@ -82,7 +294,7 @@ module Prism
#
# $foo = $foo + bar
def visit_global_variable_operator_write_node(node)
- desugar_operator_write_node(node, GlobalVariableReadNode, GlobalVariableWriteNode, node.name)
+ node.desugar
end
# @foo &&= bar
@@ -91,7 +303,7 @@ module Prism
#
# @foo && @foo = bar
def visit_instance_variable_and_write_node(node)
- desugar_and_write_node(node, InstanceVariableReadNode, InstanceVariableWriteNode, node.name)
+ node.desugar
end
# @foo ||= bar
@@ -100,7 +312,7 @@ module Prism
#
# @foo || @foo = bar
def visit_instance_variable_or_write_node(node)
- desugar_or_write_node(node, InstanceVariableReadNode, InstanceVariableWriteNode, node.name)
+ node.desugar
end
# @foo += bar
@@ -109,7 +321,7 @@ module Prism
#
# @foo = @foo + bar
def visit_instance_variable_operator_write_node(node)
- desugar_operator_write_node(node, InstanceVariableReadNode, InstanceVariableWriteNode, node.name)
+ node.desugar
end
# foo &&= bar
@@ -118,7 +330,7 @@ module Prism
#
# foo && foo = bar
def visit_local_variable_and_write_node(node)
- desugar_and_write_node(node, LocalVariableReadNode, LocalVariableWriteNode, node.name, node.depth)
+ node.desugar
end
# foo ||= bar
@@ -127,7 +339,7 @@ module Prism
#
# foo || foo = bar
def visit_local_variable_or_write_node(node)
- desugar_or_write_node(node, LocalVariableReadNode, LocalVariableWriteNode, node.name, node.depth)
+ node.desugar
end
# foo += bar
@@ -136,71 +348,7 @@ module Prism
#
# foo = foo + bar
def visit_local_variable_operator_write_node(node)
- desugar_operator_write_node(node, LocalVariableReadNode, LocalVariableWriteNode, node.name, node.depth)
- end
-
- private
-
- # Desugar `x &&= y` to `x && x = y`
- def desugar_and_write_node(node, read_class, write_class, *arguments)
- AndNode.new(
- read_class.new(*arguments, node.name_loc),
- write_class.new(*arguments, node.name_loc, node.value, node.operator_loc, node.location),
- node.operator_loc,
- node.location
- )
- end
-
- # Desugar `x += y` to `x = x + y`
- def desugar_operator_write_node(node, read_class, write_class, *arguments)
- write_class.new(
- *arguments,
- node.name_loc,
- CallNode.new(
- read_class.new(*arguments, node.name_loc),
- nil,
- node.operator_loc.copy(length: node.operator_loc.length - 1),
- nil,
- ArgumentsNode.new([node.value], 0, node.value.location),
- nil,
- nil,
- 0,
- node.operator_loc.slice.chomp("="),
- node.location
- ),
- node.operator_loc.copy(start_offset: node.operator_loc.end_offset - 1, length: 1),
- node.location
- )
- end
-
- # Desugar `x ||= y` to `x || x = y`
- def desugar_or_write_node(node, read_class, write_class, *arguments)
- OrNode.new(
- read_class.new(*arguments, node.name_loc),
- write_class.new(*arguments, node.name_loc, node.value, node.operator_loc, node.location),
- node.operator_loc,
- node.location
- )
- end
-
- # Desugar `x ||= y` to `defined?(x) ? x : x = y`
- def desugar_or_write_defined_node(node, read_class, write_class, *arguments)
- IfNode.new(
- node.operator_loc,
- DefinedNode.new(nil, read_class.new(*arguments, node.name_loc), nil, node.operator_loc, node.name_loc),
- StatementsNode.new([read_class.new(*arguments, node.name_loc)], node.location),
- ElseNode.new(
- node.operator_loc,
- StatementsNode.new(
- [write_class.new(*arguments, node.name_loc, node.value, node.operator_loc, node.location)],
- node.location
- ),
- node.operator_loc,
- node.location
- ),
- node.operator_loc,
- node.location
- )
+ node.desugar
end
end
end
diff --git a/lib/prism/ffi.rb b/lib/prism/ffi.rb
index 96102201b3..6b48af43cc 100644
--- a/lib/prism/ffi.rb
+++ b/lib/prism/ffi.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+# typed: ignore
# This file is responsible for mirroring the API provided by the C extension by
# using FFI to call into the shared library.
@@ -7,14 +8,12 @@ require "rbconfig"
require "ffi"
module Prism
- BACKEND = :FFI
-
module LibRubyParser # :nodoc:
extend FFI::Library
# Define the library that we will be pulling functions from. Note that this
# must align with the build shared library from make/rake.
- ffi_lib File.expand_path("../../build/librubyparser.#{RbConfig::CONFIG["SOEXT"]}", __dir__)
+ ffi_lib File.expand_path("../../build/libprism.#{RbConfig::CONFIG["SOEXT"]}", __dir__)
# Convert a native C type declaration into a symbol that FFI understands.
# For example:
@@ -24,15 +23,21 @@ module Prism
# size_t -> :size_t
# void -> :void
#
- def self.resolve_type(type)
+ def self.resolve_type(type, callbacks)
type = type.strip
- type.end_with?("*") ? :pointer : type.delete_prefix("const ").to_sym
+
+ if !type.end_with?("*")
+ type.delete_prefix("const ").to_sym
+ else
+ type = type.delete_suffix("*").rstrip
+ callbacks.include?(type.to_sym) ? type.to_sym : :pointer
+ end
end
# Read through the given header file and find the declaration of each of the
# given functions. For each one, define a function with the same name and
# signature as the C function.
- def self.load_exported_functions_from(header, *functions)
+ def self.load_exported_functions_from(header, *functions, callbacks)
File.foreach(File.expand_path("../../include/#{header}", __dir__)) do |line|
# We only want to attempt to load exported functions.
next unless line.start_with?("PRISM_EXPORTED_FUNCTION ")
@@ -56,23 +61,28 @@ module Prism
# Resolve the type of the argument by dropping the name of the argument
# first if it is present.
- arg_types.map! { |type| resolve_type(type.sub(/\w+$/, "")) }
+ arg_types.map! { |type| resolve_type(type.sub(/\w+$/, ""), callbacks) }
# Attach the function using the FFI library.
- attach_function name, arg_types, resolve_type(return_type)
+ attach_function name, arg_types, resolve_type(return_type, [])
end
# If we didn't find all of the functions, raise an error.
raise "Could not find functions #{functions.inspect}" unless functions.empty?
end
+ callback :pm_parse_stream_fgets_t, [:pointer, :int, :pointer], :pointer
+
load_exported_functions_from(
"prism.h",
"pm_version",
"pm_serialize_parse",
+ "pm_serialize_parse_stream",
"pm_serialize_parse_comments",
"pm_serialize_lex",
- "pm_serialize_parse_lex"
+ "pm_serialize_parse_lex",
+ "pm_parse_success_p",
+ [:pm_parse_stream_fgets_t]
)
load_exported_functions_from(
@@ -81,7 +91,8 @@ module Prism
"pm_buffer_init",
"pm_buffer_value",
"pm_buffer_length",
- "pm_buffer_free"
+ "pm_buffer_free",
+ []
)
load_exported_functions_from(
@@ -90,7 +101,8 @@ module Prism
"pm_string_free",
"pm_string_source",
"pm_string_length",
- "pm_string_sizeof"
+ "pm_string_sizeof",
+ []
)
# This object represents a pm_buffer_t. We only use it as an opaque pointer,
@@ -118,15 +130,12 @@ module Prism
# Initialize a new buffer and yield it to the block. The buffer will be
# automatically freed when the block returns.
- def self.with(&block)
- pointer = FFI::MemoryPointer.new(SIZEOF)
-
- begin
+ def self.with
+ FFI::MemoryPointer.new(SIZEOF) do |pointer|
raise unless LibRubyParser.pm_buffer_init(pointer)
- yield new(pointer)
+ return yield new(pointer)
ensure
LibRubyParser.pm_buffer_free(pointer)
- pointer.free
end
end
end
@@ -136,34 +145,47 @@ module Prism
class PrismString # :nodoc:
SIZEOF = LibRubyParser.pm_string_sizeof
- attr_reader :pointer
+ attr_reader :pointer, :length
- def initialize(pointer)
+ def initialize(pointer, length, from_string)
@pointer = pointer
- end
-
- def source
- LibRubyParser.pm_string_source(pointer)
- end
-
- def length
- LibRubyParser.pm_string_length(pointer)
+ @length = length
+ @from_string = from_string
end
def read
- source.read_string(length)
+ raise "should use the original String instead" if @from_string
+ @pointer.read_string(@length)
end
# Yields a pm_string_t pointer to the given block.
- def self.with(filepath, &block)
- pointer = FFI::MemoryPointer.new(SIZEOF)
+ def self.with_string(string)
+ raise TypeError unless string.is_a?(String)
+
+ length = string.bytesize
+ # + 1 to never get an address of 0, which pm_parser_init() asserts
+ FFI::MemoryPointer.new(:char, length + 1, false) do |pointer|
+ pointer.write_string(string)
+ # since we have the extra byte we might as well \0-terminate
+ pointer.put_char(length, 0)
+ return yield new(pointer, length, true)
+ end
+ end
- begin
- raise unless LibRubyParser.pm_string_mapped_init(pointer, filepath)
- yield new(pointer)
+ # Yields a pm_string_t pointer to the given block.
+ def self.with_file(filepath)
+ raise TypeError unless filepath.is_a?(String)
+
+ FFI::MemoryPointer.new(SIZEOF) do |pm_string|
+ if LibRubyParser.pm_string_mapped_init(pm_string, filepath)
+ pointer = LibRubyParser.pm_string_source(pm_string)
+ length = LibRubyParser.pm_string_length(pm_string)
+ return yield new(pointer, length, false)
+ else
+ raise SystemCallError.new(filepath, FFI.errno)
+ end
ensure
- LibRubyParser.pm_string_free(pointer)
- pointer.free
+ LibRubyParser.pm_string_free(pm_string)
end
end
end
@@ -178,97 +200,202 @@ module Prism
class << self
# Mirror the Prism.dump API by using the serialization API.
- def dump(code, **options)
- LibRubyParser::PrismBuffer.with do |buffer|
- LibRubyParser.pm_serialize_parse(buffer.pointer, code, code.bytesize, dump_options(options))
- buffer.read
- end
+ def dump(source, **options)
+ LibRubyParser::PrismString.with_string(source) { |string| dump_common(string, options) }
end
# Mirror the Prism.dump_file API by using the serialization API.
def dump_file(filepath, **options)
- LibRubyParser::PrismString.with(filepath) do |string|
- dump(string.read, **options, filepath: filepath)
- end
+ options[:filepath] = filepath
+ LibRubyParser::PrismString.with_file(filepath) { |string| dump_common(string, options) }
end
# Mirror the Prism.lex API by using the serialization API.
def lex(code, **options)
- LibRubyParser::PrismBuffer.with do |buffer|
- LibRubyParser.pm_serialize_lex(buffer.pointer, code, code.bytesize, dump_options(options))
- Serialize.load_tokens(Source.new(code), buffer.read)
- end
+ LibRubyParser::PrismString.with_string(code) { |string| lex_common(string, code, options) }
end
# Mirror the Prism.lex_file API by using the serialization API.
def lex_file(filepath, **options)
- LibRubyParser::PrismString.with(filepath) do |string|
- lex(string.read, **options, filepath: filepath)
- end
+ options[:filepath] = filepath
+ LibRubyParser::PrismString.with_file(filepath) { |string| lex_common(string, string.read, options) }
end
# Mirror the Prism.parse API by using the serialization API.
def parse(code, **options)
- Prism.load(code, dump(code, **options))
+ LibRubyParser::PrismString.with_string(code) { |string| parse_common(string, code, options) }
end
# Mirror the Prism.parse_file API by using the serialization API. This uses
- # native strings instead of Ruby strings because it allows us to use mmap when
- # it is available.
+ # native strings instead of Ruby strings because it allows us to use mmap
+ # when it is available.
def parse_file(filepath, **options)
- LibRubyParser::PrismString.with(filepath) do |string|
- parse(string.read, **options, filepath: filepath)
- end
+ options[:filepath] = filepath
+ LibRubyParser::PrismString.with_file(filepath) { |string| parse_common(string, string.read, options) }
end
- # Mirror the Prism.parse_comments API by using the serialization API.
- def parse_comments(code, **options)
+ # Mirror the Prism.parse_stream API by using the serialization API.
+ def parse_stream(stream, **options)
LibRubyParser::PrismBuffer.with do |buffer|
- LibRubyParser.pm_serialize_parse_comments(buffer.pointer, code, code.bytesize, dump_options(options))
+ source = +""
+ callback = -> (string, size, _) {
+ raise "Expected size to be >= 0, got: #{size}" if size <= 0
- source = Source.new(code)
- loader = Serialize::Loader.new(source, buffer.read)
-
- loader.load_header
- loader.load_force_encoding
- loader.load_start_line
- loader.load_comments
+ if !(line = stream.gets(size - 1)).nil?
+ source << line
+ string.write_string("#{line}\x00", line.bytesize + 1)
+ end
+ }
+
+ # In the pm_serialize_parse_stream function it accepts a pointer to the
+ # IO object as a void* and then passes it through to the callback as the
+ # third argument, but it never touches it itself. As such, since we have
+ # access to the IO object already through the closure of the lambda, we
+ # can pass a null pointer here and not worry.
+ LibRubyParser.pm_serialize_parse_stream(buffer.pointer, nil, callback, dump_options(options))
+ Prism.load(source, buffer.read)
end
end
+ # Mirror the Prism.parse_comments API by using the serialization API.
+ def parse_comments(code, **options)
+ LibRubyParser::PrismString.with_string(code) { |string| parse_comments_common(string, code, options) }
+ end
+
# Mirror the Prism.parse_file_comments API by using the serialization
# API. This uses native strings instead of Ruby strings because it allows us
# to use mmap when it is available.
def parse_file_comments(filepath, **options)
- LibRubyParser::PrismString.with(filepath) do |string|
- parse_comments(string.read, **options, filepath: filepath)
- end
+ options[:filepath] = filepath
+ LibRubyParser::PrismString.with_file(filepath) { |string| parse_comments_common(string, string.read, options) }
end
# Mirror the Prism.parse_lex API by using the serialization API.
def parse_lex(code, **options)
+ LibRubyParser::PrismString.with_string(code) { |string| parse_lex_common(string, code, options) }
+ end
+
+ # Mirror the Prism.parse_lex_file API by using the serialization API.
+ def parse_lex_file(filepath, **options)
+ options[:filepath] = filepath
+ LibRubyParser::PrismString.with_file(filepath) { |string| parse_lex_common(string, string.read, options) }
+ end
+
+ # Mirror the Prism.parse_success? API by using the serialization API.
+ def parse_success?(code, **options)
+ LibRubyParser::PrismString.with_string(code) { |string| parse_file_success_common(string, options) }
+ end
+
+ # Mirror the Prism.parse_failure? API by using the serialization API.
+ def parse_failure?(code, **options)
+ !parse_success?(code, **options)
+ end
+
+ # Mirror the Prism.parse_file_success? API by using the serialization API.
+ def parse_file_success?(filepath, **options)
+ options[:filepath] = filepath
+ LibRubyParser::PrismString.with_file(filepath) { |string| parse_file_success_common(string, options) }
+ end
+
+ # Mirror the Prism.parse_file_failure? API by using the serialization API.
+ def parse_file_failure?(filepath, **options)
+ !parse_file_success?(filepath, **options)
+ end
+
+ # Mirror the Prism.profile API by using the serialization API.
+ def profile(source, **options)
+ LibRubyParser::PrismString.with_string(source) do |string|
+ LibRubyParser::PrismBuffer.with do |buffer|
+ LibRubyParser.pm_serialize_parse(buffer.pointer, string.pointer, string.length, dump_options(options))
+ nil
+ end
+ end
+ end
+
+ # Mirror the Prism.profile_file API by using the serialization API.
+ def profile_file(filepath, **options)
+ LibRubyParser::PrismString.with_file(filepath) do |string|
+ LibRubyParser::PrismBuffer.with do |buffer|
+ options[:filepath] = filepath
+ LibRubyParser.pm_serialize_parse(buffer.pointer, string.pointer, string.length, dump_options(options))
+ nil
+ end
+ end
+ end
+
+ private
+
+ def dump_common(string, options) # :nodoc:
LibRubyParser::PrismBuffer.with do |buffer|
- LibRubyParser.pm_serialize_parse_lex(buffer.pointer, code, code.bytesize, dump_options(options))
+ LibRubyParser.pm_serialize_parse(buffer.pointer, string.pointer, string.length, dump_options(options))
+ buffer.read
+ end
+ end
- source = Source.new(code)
+ def lex_common(string, code, options) # :nodoc:
+ serialized = LibRubyParser::PrismBuffer.with do |buffer|
+ LibRubyParser.pm_serialize_lex(buffer.pointer, string.pointer, string.length, dump_options(options))
+ buffer.read
+ end
+
+ Serialize.load_tokens(Source.for(code), serialized)
+ end
+
+ def parse_common(string, code, options) # :nodoc:
+ serialized = dump_common(string, options)
+ Prism.load(code, serialized)
+ end
+
+ def parse_comments_common(string, code, options) # :nodoc:
+ LibRubyParser::PrismBuffer.with do |buffer|
+ LibRubyParser.pm_serialize_parse_comments(buffer.pointer, string.pointer, string.length, dump_options(options))
+
+ source = Source.for(code)
+ loader = Serialize::Loader.new(source, buffer.read)
+
+ loader.load_header
+ loader.load_encoding
+ loader.load_start_line
+ loader.load_comments
+ end
+ end
+
+ def parse_lex_common(string, code, options) # :nodoc:
+ LibRubyParser::PrismBuffer.with do |buffer|
+ LibRubyParser.pm_serialize_parse_lex(buffer.pointer, string.pointer, string.length, dump_options(options))
+
+ source = Source.for(code)
loader = Serialize::Loader.new(source, buffer.read)
tokens = loader.load_tokens
- node, comments, magic_comments, errors, warnings = loader.load_nodes
+ node, comments, magic_comments, data_loc, errors, warnings = loader.load_nodes
tokens.each { |token,| token.value.force_encoding(loader.encoding) }
- ParseResult.new([node, tokens], comments, magic_comments, errors, warnings, source)
+ ParseLexResult.new([node, tokens], comments, magic_comments, data_loc, errors, warnings, source)
end
end
- # Mirror the Prism.parse_lex_file API by using the serialization API.
- def parse_lex_file(filepath, **options)
- LibRubyParser::PrismString.with(filepath) do |string|
- parse_lex(string.read, **options, filepath: filepath)
- end
+ def parse_file_success_common(string, options) # :nodoc:
+ LibRubyParser.pm_parse_success_p(string.pointer, string.length, dump_options(options))
end
- private
+ # Return the value that should be dumped for the command_line option.
+ def dump_options_command_line(options)
+ command_line = options.fetch(:command_line, "")
+ raise ArgumentError, "command_line must be a string" unless command_line.is_a?(String)
+
+ command_line.each_char.inject(0) do |value, char|
+ case char
+ when "a" then value | 0b000001
+ when "e" then value | 0b000010
+ when "l" then value | 0b000100
+ when "n" then value | 0b001000
+ when "p" then value | 0b010000
+ when "x" then value | 0b100000
+ else raise ArgumentError, "invalid command_line option: #{char}"
+ end
+ end
+ end
# Convert the given options into a serialized options string.
def dump_options(options)
@@ -283,12 +410,12 @@ module Prism
values << 0
end
- template << "L"
+ template << "l"
values << options.fetch(:line, 1)
template << "L"
if (encoding = options[:encoding])
- name = encoding.name
+ name = encoding.is_a?(Encoding) ? encoding.name : encoding
values.push(name.bytesize, name.b)
template << "A*"
else
@@ -299,7 +426,10 @@ module Prism
values << (options.fetch(:frozen_string_literal, false) ? 1 : 0)
template << "C"
- values << (options[:verbose] ? 0 : 1)
+ values << dump_options_command_line(options)
+
+ template << "C"
+ values << { nil => 0, "3.3.0" => 1, "3.3.1" => 1, "3.4.0" => 0, "latest" => 0 }.fetch(options[:version])
template << "L"
if (scopes = options[:scopes])
diff --git a/lib/prism/lex_compat.rb b/lib/prism/lex_compat.rb
index b6d12053a0..4f8e443a3b 100644
--- a/lib/prism/lex_compat.rb
+++ b/lib/prism/lex_compat.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require "delegate"
+require "ripper"
module Prism
# This class is responsible for lexing the source using prism and then
@@ -9,6 +10,23 @@ module Prism
# generally lines up. However, there are a few cases that require special
# handling.
class LexCompat # :nodoc:
+ # A result class specialized for holding tokens produced by the lexer.
+ class Result < Prism::Result
+ # The list of tokens that were produced by the lexer.
+ attr_reader :value
+
+ # Create a new lex compat result object with the given values.
+ def initialize(value, comments, magic_comments, data_loc, errors, warnings, source)
+ @value = value
+ super(comments, magic_comments, data_loc, errors, warnings, source)
+ end
+
+ # Implement the hash pattern matching interface for Result.
+ def deconstruct_keys(keys)
+ super.merge!(value: value)
+ end
+ end
+
# This is a mapping of prism token types to Ripper token types. This is a
# many-to-one mapping because we split up our token types, whereas Ripper
# tends to group them.
@@ -184,6 +202,8 @@ module Prism
# However, we add a couple of convenience methods onto them to make them a
# little easier to work with. We delegate all other methods to the array.
class Token < SimpleDelegator
+ # @dynamic initialize, each, []
+
# The location of the token in the source.
def location
self[0]
@@ -240,10 +260,10 @@ module Prism
def ==(other) # :nodoc:
return false unless self[0...-1] == other[0...-1]
- if self[4] == Ripper::EXPR_ARG | Ripper::EXPR_LABELED
- other[4] & Ripper::EXPR_ARG | Ripper::EXPR_LABELED > 0
+ if self[3] == Ripper::EXPR_ARG | Ripper::EXPR_LABELED
+ other[3] & Ripper::EXPR_ARG | Ripper::EXPR_LABELED != 0
else
- self[4] == other[4]
+ self[3] == other[3]
end
end
end
@@ -307,7 +327,7 @@ module Prism
def to_a
embexpr_balance = 0
- tokens.each_with_object([]) do |token, results|
+ tokens.each_with_object([]) do |token, results| #$ Array[Token]
case token.event
when :on_embexpr_beg
embexpr_balance += 1
@@ -408,7 +428,7 @@ module Prism
# If every line in the heredoc is blank, we still need to split up the
# string content token into multiple tokens.
if dedent.nil?
- results = []
+ results = [] #: Array[Token]
embexpr_balance = 0
tokens.each do |token|
@@ -443,7 +463,7 @@ module Prism
# If the minimum common whitespace is 0, then we need to concatenate
# string nodes together that are immediately adjacent.
if dedent == 0
- results = []
+ results = [] #: Array[Token]
embexpr_balance = 0
index = 0
@@ -476,7 +496,7 @@ module Prism
# insert on_ignored_sp tokens for the amount of dedent that we need to
# perform. We also need to remove the dedent from the beginning of
# each line of plain string content tokens.
- results = []
+ results = [] #: Array[Token]
dedent_next = true
embexpr_balance = 0
@@ -525,7 +545,7 @@ module Prism
# dedent from the beginning of the line.
if (dedent > 0) && (dedent_next || index > 0)
deleting = 0
- deleted_chars = []
+ deleted_chars = [] #: Array[String]
# Gather up all of the characters that we're going to
# delete, stopping when you hit a character that would put
@@ -602,14 +622,15 @@ module Prism
end
def result
- tokens = []
+ tokens = [] #: Array[LexCompat::Token]
state = :default
- heredoc_stack = [[]]
+ heredoc_stack = [[]] #: Array[Array[Heredoc::PlainHeredoc | Heredoc::DashHeredoc | Heredoc::DedentingHeredoc]]
result = Prism.lex(source, **options)
result_value = result.value
- previous_state = nil
+ previous_state = nil #: Ripper::Lexer::State?
+ last_heredoc_end = nil #: Integer?
# In previous versions of Ruby, Ripper wouldn't flush the bom before the
# first token, so we had to have a hack in place to account for that. This
@@ -664,6 +685,7 @@ module Prism
when :on_heredoc_end
# Heredoc end tokens can be emitted in an odd order, so we don't
# want to bother comparing the state on them.
+ last_heredoc_end = token.location.end_offset
IgnoreStateToken.new([[lineno, column], event, value, lex_state])
when :on_ident
if lex_state == Ripper::EXPR_END
@@ -729,16 +751,24 @@ module Prism
# comment and there is still whitespace after the comment, then
# Ripper will append a on_nl token (even though there isn't
# necessarily a newline). We mirror that here.
- start_offset = previous_token.location.end_offset
- end_offset = token.location.start_offset
+ if previous_token.type == :COMMENT
+ # If the comment is at the start of a heredoc: <<HEREDOC # comment
+ # then the comment's end_offset is up near the heredoc_beg.
+ # This is not the correct offset to use for figuring out if
+ # there is trailing whitespace after the last token.
+ # Use the greater offset of the two to determine the start of
+ # the trailing whitespace.
+ start_offset = [previous_token.location.end_offset, last_heredoc_end].compact.max
+ end_offset = token.location.start_offset
+
+ if start_offset < end_offset
+ if bom
+ start_offset += 3
+ end_offset += 3
+ end
- if previous_token.type == :COMMENT && start_offset < end_offset
- if bom
- start_offset += 3
- end_offset += 3
+ tokens << Token.new([[lineno, 0], :on_nl, source.byteslice(start_offset...end_offset), lex_state])
end
-
- tokens << Token.new([[lineno, 0], :on_nl, source.byteslice(start_offset...end_offset), lex_state])
end
Token.new([[lineno, column], event, value, lex_state])
@@ -831,7 +861,7 @@ module Prism
# We sort by location to compare against Ripper's output
tokens.sort_by!(&:location)
- ParseResult.new(tokens, result.comments, result.magic_comments, result.errors, result.warnings, [])
+ Result.new(tokens, result.comments, result.magic_comments, result.data_loc, result.errors, result.warnings, Source.for(source))
end
end
@@ -847,10 +877,10 @@ module Prism
end
def result
- previous = []
- results = []
+ previous = [] #: [[Integer, Integer], Symbol, String, untyped] | []
+ results = [] #: Array[[[Integer, Integer], Symbol, String, untyped]]
- Ripper.lex(source, raise_errors: true).each do |token|
+ lex(source).each do |token|
case token[1]
when :on_sp
# skip
@@ -876,6 +906,21 @@ module Prism
results
end
+
+ private
+
+ if Ripper.method(:lex).parameters.assoc(:keyrest)
+ def lex(source)
+ Ripper.lex(source, raise_errors: true)
+ end
+ else
+ def lex(source)
+ ripper = Ripper::Lexer.new(source)
+ ripper.lex.tap do |result|
+ raise SyntaxError, ripper.errors.map(&:message).join(' ;') if ripper.errors.any?
+ end
+ end
+ end
end
private_constant :LexRipper
diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb
index 4febc615c1..aa6a18cf29 100644
--- a/lib/prism/node_ext.rb
+++ b/lib/prism/node_ext.rb
@@ -3,6 +3,20 @@
# Here we are reopening the prism module to provide methods on nodes that aren't
# templated and are meant as convenience methods.
module Prism
+ class Node
+ def deprecated(*replacements) # :nodoc:
+ location = caller_locations(1, 1)
+ location = location[0].label if location
+ suggest = replacements.map { |replacement| "#{self.class}##{replacement}" }
+
+ warn(<<~MSG, category: :deprecated)
+ [deprecation]: #{self.class}##{location} is deprecated and will be \
+ removed in the next major version. Use #{suggest.join("/")} instead.
+ #{(caller(1, 3) || []).join("\n")}
+ MSG
+ end
+ end
+
module RegularExpressionOptions # :nodoc:
# Returns a numeric value that represents the flags that were used to create
# the regular expression.
@@ -14,50 +28,98 @@ module Prism
end
end
+ class InterpolatedMatchLastLineNode < Node
+ include RegularExpressionOptions
+ end
+
+ class InterpolatedRegularExpressionNode < Node
+ include RegularExpressionOptions
+ end
+
+ class MatchLastLineNode < Node
+ include RegularExpressionOptions
+ end
+
+ class RegularExpressionNode < Node
+ include RegularExpressionOptions
+ end
+
private_constant :RegularExpressionOptions
- class FloatNode < Node
- # Returns the value of the node as a Ruby Float.
- def value
- Float(slice)
+ module HeredocQuery # :nodoc:
+ # Returns true if this node was represented as a heredoc in the source code.
+ def heredoc?
+ opening&.start_with?("<<")
end
end
- class ImaginaryNode < Node
- # Returns the value of the node as a Ruby Complex.
- def value
- Complex(0, numeric.value)
- end
+ class InterpolatedStringNode < Node
+ include HeredocQuery
end
- class IntegerNode < Node
- # Returns the value of the node as a Ruby Integer.
- def value
- Integer(slice)
- end
+ class InterpolatedXStringNode < Node
+ include HeredocQuery
end
- class InterpolatedMatchLastLineNode < Node
- include RegularExpressionOptions
+ class StringNode < Node
+ include HeredocQuery
+
+ # Occasionally it's helpful to treat a string as if it were interpolated so
+ # that there's a consistent interface for working with strings.
+ def to_interpolated
+ InterpolatedStringNode.new(
+ source,
+ frozen? ? InterpolatedStringNodeFlags::FROZEN : 0,
+ opening_loc,
+ [copy(opening_loc: nil, closing_loc: nil, location: content_loc)],
+ closing_loc,
+ location
+ )
+ end
end
- class InterpolatedRegularExpressionNode < Node
- include RegularExpressionOptions
+ class XStringNode < Node
+ include HeredocQuery
+
+ # Occasionally it's helpful to treat a string as if it were interpolated so
+ # that there's a consistent interface for working with strings.
+ def to_interpolated
+ InterpolatedXStringNode.new(
+ source,
+ opening_loc,
+ [StringNode.new(source, 0, nil, content_loc, nil, unescaped, content_loc)],
+ closing_loc,
+ location
+ )
+ end
end
- class MatchLastLineNode < Node
- include RegularExpressionOptions
+ private_constant :HeredocQuery
+
+ class ImaginaryNode < Node
+ # Returns the value of the node as a Ruby Complex.
+ def value
+ Complex(0, numeric.value)
+ end
end
class RationalNode < Node
# Returns the value of the node as a Ruby Rational.
def value
- Rational(slice.chomp("r"))
+ Rational(numerator, denominator)
end
- end
- class RegularExpressionNode < Node
- include RegularExpressionOptions
+ # Returns the value of the node as an IntegerNode or a FloatNode. This
+ # method is deprecated in favor of #value or #numerator/#denominator.
+ def numeric
+ deprecated("value", "numerator", "denominator")
+
+ if denominator == 1
+ IntegerNode.new(source, flags, numerator, location.chop)
+ else
+ FloatNode.new(source, numerator.to_f / denominator, location.chop)
+ end
+ end
end
class ConstantReadNode < Node
@@ -69,22 +131,57 @@ module Prism
# Returns the full name of this constant. For example: "Foo"
def full_name
- name.name
+ name.to_s
+ end
+ end
+
+ class ConstantWriteNode < Node
+ # Returns the list of parts for the full name of this constant.
+ # For example: [:Foo]
+ def full_name_parts
+ [name]
+ end
+
+ # Returns the full name of this constant. For example: "Foo"
+ def full_name
+ name.to_s
end
end
class ConstantPathNode < Node
+ # An error class raised when dynamic parts are found while computing a
+ # constant path's full name. For example:
+ # Foo::Bar::Baz -> does not raise because all parts of the constant path are
+ # simple constants
+ # var::Bar::Baz -> raises because the first part of the constant path is a
+ # local variable
+ class DynamicPartsInConstantPathError < StandardError; end
+
+ # An error class raised when missing nodes are found while computing a
+ # constant path's full name. For example:
+ # Foo:: -> raises because the constant path is missing the last part
+ class MissingNodesInConstantPathError < StandardError; end
+
# Returns the list of parts for the full name of this constant path.
# For example: [:Foo, :Bar]
def full_name_parts
- parts = [child.name]
- current = parent
+ parts = [] #: Array[Symbol]
+ current = self #: node?
while current.is_a?(ConstantPathNode)
- parts.unshift(current.child.name)
+ name = current.name
+ if name.nil?
+ raise MissingNodesInConstantPathError, "Constant path contains missing nodes. Cannot compute full name"
+ end
+
+ parts.unshift(name)
current = current.parent
end
+ if !current.is_a?(ConstantReadNode) && !current.nil?
+ raise DynamicPartsInConstantPathError, "Constant path contains dynamic parts. Cannot compute full name"
+ end
+
parts.unshift(current&.name || :"")
end
@@ -92,40 +189,95 @@ module Prism
def full_name
full_name_parts.join("::")
end
+
+ # Previously, we had a child node on this class that contained either a
+ # constant read or a missing node. To not cause a breaking change, we
+ # continue to supply that API.
+ def child
+ deprecated("name", "name_loc")
+ name ? ConstantReadNode.new(source, name, name_loc) : MissingNode.new(source, location)
+ end
end
class ConstantPathTargetNode < Node
# Returns the list of parts for the full name of this constant path.
# For example: [:Foo, :Bar]
def full_name_parts
- (parent&.full_name_parts || [:""]).push(child.name)
+ parts =
+ case parent
+ when ConstantPathNode, ConstantReadNode
+ parent.full_name_parts
+ when nil
+ [:""]
+ else
+ # e.g. self::Foo, (var)::Bar = baz
+ raise ConstantPathNode::DynamicPartsInConstantPathError, "Constant target path contains dynamic parts. Cannot compute full name"
+ end
+
+ if name.nil?
+ raise ConstantPathNode::MissingNodesInConstantPathError, "Constant target path contains missing nodes. Cannot compute full name"
+ end
+
+ parts.push(name)
end
# Returns the full name of this constant path. For example: "Foo::Bar"
def full_name
full_name_parts.join("::")
end
+
+ # Previously, we had a child node on this class that contained either a
+ # constant read or a missing node. To not cause a breaking change, we
+ # continue to supply that API.
+ def child
+ deprecated("name", "name_loc")
+ name ? ConstantReadNode.new(source, name, name_loc) : MissingNode.new(source, location)
+ end
+ end
+
+ class ConstantTargetNode < Node
+ # Returns the list of parts for the full name of this constant.
+ # For example: [:Foo]
+ def full_name_parts
+ [name]
+ end
+
+ # Returns the full name of this constant. For example: "Foo"
+ def full_name
+ name.to_s
+ end
end
class ParametersNode < Node
# Mirrors the Method#parameters method.
def signature
- names = []
+ names = [] #: Array[[Symbol, Symbol] | [Symbol]]
requireds.each do |param|
names << (param.is_a?(MultiTargetNode) ? [:req] : [:req, param.name])
end
optionals.each { |param| names << [:opt, param.name] }
- names << [:rest, rest.name || :*] if rest
+
+ if rest && rest.is_a?(RestParameterNode)
+ names << [:rest, rest.name || :*]
+ end
posts.each do |param|
- names << (param.is_a?(MultiTargetNode) ? [:req] : [:req, param.name])
+ case param
+ when MultiTargetNode
+ names << [:req]
+ when NoKeywordsParameterNode, KeywordRestParameterNode, ForwardingParameterNode
+ # Invalid syntax, e.g. "def f(**nil, ...)" moves the NoKeywordsParameterNode to posts
+ raise "Invalid syntax"
+ else
+ names << [:req, param.name]
+ end
end
# Regardless of the order in which the keywords were defined, the required
# keywords always come first followed by the optional keywords.
- keyopt = []
+ keyopt = [] #: Array[OptionalKeywordParameterNode]
keywords.each do |param|
if param.is_a?(OptionalKeywordParameterNode)
keyopt << param
@@ -149,4 +301,147 @@ module Prism
names
end
end
+
+ class CallNode < Node
+ # When a call node has the attribute_write flag set, it means that the call
+ # is using the attribute write syntax. This is either a method call to []=
+ # or a method call to a method that ends with =. Either way, the = sign is
+ # present in the source.
+ #
+ # Prism returns the message_loc _without_ the = sign attached, because there
+ # can be any amount of space between the message and the = sign. However,
+ # sometimes you want the location of the full message including the inner
+ # space and the = sign. This method provides that.
+ def full_message_loc
+ attribute_write? ? message_loc&.adjoin("=") : message_loc
+ end
+ end
+
+ class CallOperatorWriteNode < Node
+ # Returns the binary operator used to modify the receiver. This method is
+ # deprecated in favor of #binary_operator.
+ def operator
+ deprecated("binary_operator")
+ binary_operator
+ end
+
+ # Returns the location of the binary operator used to modify the receiver.
+ # This method is deprecated in favor of #binary_operator_loc.
+ def operator_loc
+ deprecated("binary_operator_loc")
+ binary_operator_loc
+ end
+ end
+
+ class ClassVariableOperatorWriteNode < Node
+ # Returns the binary operator used to modify the receiver. This method is
+ # deprecated in favor of #binary_operator.
+ def operator
+ deprecated("binary_operator")
+ binary_operator
+ end
+
+ # Returns the location of the binary operator used to modify the receiver.
+ # This method is deprecated in favor of #binary_operator_loc.
+ def operator_loc
+ deprecated("binary_operator_loc")
+ binary_operator_loc
+ end
+ end
+
+ class ConstantOperatorWriteNode < Node
+ # Returns the binary operator used to modify the receiver. This method is
+ # deprecated in favor of #binary_operator.
+ def operator
+ deprecated("binary_operator")
+ binary_operator
+ end
+
+ # Returns the location of the binary operator used to modify the receiver.
+ # This method is deprecated in favor of #binary_operator_loc.
+ def operator_loc
+ deprecated("binary_operator_loc")
+ binary_operator_loc
+ end
+ end
+
+ class ConstantPathOperatorWriteNode < Node
+ # Returns the binary operator used to modify the receiver. This method is
+ # deprecated in favor of #binary_operator.
+ def operator
+ deprecated("binary_operator")
+ binary_operator
+ end
+
+ # Returns the location of the binary operator used to modify the receiver.
+ # This method is deprecated in favor of #binary_operator_loc.
+ def operator_loc
+ deprecated("binary_operator_loc")
+ binary_operator_loc
+ end
+ end
+
+ class GlobalVariableOperatorWriteNode < Node
+ # Returns the binary operator used to modify the receiver. This method is
+ # deprecated in favor of #binary_operator.
+ def operator
+ deprecated("binary_operator")
+ binary_operator
+ end
+
+ # Returns the location of the binary operator used to modify the receiver.
+ # This method is deprecated in favor of #binary_operator_loc.
+ def operator_loc
+ deprecated("binary_operator_loc")
+ binary_operator_loc
+ end
+ end
+
+ class IndexOperatorWriteNode < Node
+ # Returns the binary operator used to modify the receiver. This method is
+ # deprecated in favor of #binary_operator.
+ def operator
+ deprecated("binary_operator")
+ binary_operator
+ end
+
+ # Returns the location of the binary operator used to modify the receiver.
+ # This method is deprecated in favor of #binary_operator_loc.
+ def operator_loc
+ deprecated("binary_operator_loc")
+ binary_operator_loc
+ end
+ end
+
+ class InstanceVariableOperatorWriteNode < Node
+ # Returns the binary operator used to modify the receiver. This method is
+ # deprecated in favor of #binary_operator.
+ def operator
+ deprecated("binary_operator")
+ binary_operator
+ end
+
+ # Returns the location of the binary operator used to modify the receiver.
+ # This method is deprecated in favor of #binary_operator_loc.
+ def operator_loc
+ deprecated("binary_operator_loc")
+ binary_operator_loc
+ end
+ end
+
+ class LocalVariableOperatorWriteNode < Node
+ # Returns the binary operator used to modify the receiver. This method is
+ # deprecated in favor of #binary_operator.
+ def operator
+ deprecated("binary_operator")
+ binary_operator
+ end
+
+ # Returns the location of the binary operator used to modify the receiver.
+ # This method is deprecated in favor of #binary_operator_loc.
+ def operator_loc
+ deprecated("binary_operator_loc")
+ binary_operator_loc
+ end
+ end
end
diff --git a/lib/prism/node_inspector.rb b/lib/prism/node_inspector.rb
deleted file mode 100644
index d77af33c3a..0000000000
--- a/lib/prism/node_inspector.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-# frozen_string_literal: true
-
-module Prism
- # This object is responsible for generating the output for the inspect method
- # implementations of child nodes.
- class NodeInspector # :nodoc:
- attr_reader :prefix, :output
-
- def initialize(prefix = "")
- @prefix = prefix
- @output = +""
- end
-
- # Appends a line to the output with the current prefix.
- def <<(line)
- output << "#{prefix}#{line}"
- end
-
- # This generates a string that is used as the header of the inspect output
- # for any given node.
- def header(node)
- output = +"@ #{node.class.name.split("::").last} ("
- output << "location: (#{node.location.start_line},#{node.location.start_column})-(#{node.location.end_line},#{node.location.end_column})"
- output << ", newline: true" if node.newline?
- output << ")\n"
- output
- end
-
- # Generates a string that represents a list of nodes. It handles properly
- # using the box drawing characters to make the output look nice.
- def list(prefix, nodes)
- output = +"(length: #{nodes.length})\n"
- last_index = nodes.length - 1
-
- nodes.each_with_index do |node, index|
- pointer, preadd = (index == last_index) ? ["└── ", " "] : ["├── ", "│ "]
- node_prefix = "#{prefix}#{preadd}"
- output << node.inspect(NodeInspector.new(node_prefix)).sub(node_prefix, "#{prefix}#{pointer}")
- end
-
- output
- end
-
- # Generates a string that represents a location field on a node.
- def location(value)
- if value
- "(#{value.start_line},#{value.start_column})-(#{value.end_line},#{value.end_column}) = #{value.slice.inspect}"
- else
- "∅"
- end
- end
-
- # Generates a string that represents a child node.
- def child_node(node, append)
- node.inspect(child_inspector(append)).delete_prefix(prefix)
- end
-
- # Returns a new inspector that can be used to inspect a child node.
- def child_inspector(append)
- NodeInspector.new("#{prefix}#{append}")
- end
-
- # Returns the output as a string.
- def to_str
- output
- end
- end
-end
diff --git a/lib/prism/pack.rb b/lib/prism/pack.rb
index 00caf553c6..c0de8ab8b7 100644
--- a/lib/prism/pack.rb
+++ b/lib/prism/pack.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+# typed: ignore
module Prism
# A parser for the pack template language.
@@ -148,6 +149,8 @@ module Prism
end
when LENGTH_MAX
base + ", as many as possible"
+ else
+ raise
end
when UTF8
"UTF-8 character"
@@ -214,6 +217,7 @@ module Prism
else
source = directive.source
end
+ # @type var source_width: Integer
" #{source.ljust(source_width)} #{directive.describe}"
end
diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb
index 170a529bea..798fde09e5 100644
--- a/lib/prism/parse_result.rb
+++ b/lib/prism/parse_result.rb
@@ -5,60 +5,110 @@ module Prism
# conjunction with locations to allow them to resolve line numbers and source
# ranges.
class Source
+ # Create a new source object with the given source code. This method should
+ # be used instead of `new` and it will return either a `Source` or a
+ # specialized and more performant `ASCIISource` if no multibyte characters
+ # are present in the source code.
+ def self.for(source, start_line = 1, offsets = [])
+ source.ascii_only? ? ASCIISource.new(source, start_line, offsets): new(source, start_line, offsets)
+ end
+
# The source code that this source object represents.
attr_reader :source
# The line number where this source starts.
- attr_accessor :start_line
+ attr_reader :start_line
# The list of newline byte offsets in the source code.
attr_reader :offsets
- # Create a new source object with the given source code and newline byte
- # offsets. If no newline byte offsets are given, they will be computed from
- # the source code.
- def initialize(source, start_line = 1, offsets = compute_offsets(source))
+ # Create a new source object with the given source code.
+ def initialize(source, start_line = 1, offsets = [])
@source = source
- @start_line = start_line
- @offsets = offsets
+ @start_line = start_line # set after parsing is done
+ @offsets = offsets # set after parsing is done
+ end
+
+ # Returns the encoding of the source code, which is set by parameters to the
+ # parser or by the encoding magic comment.
+ def encoding
+ source.encoding
+ end
+
+ # Returns the lines of the source code as an array of strings.
+ def lines
+ source.lines
end
# Perform a byteslice on the source code using the given byte offset and
# byte length.
- def slice(offset, length)
- source.byteslice(offset, length)
+ def slice(byte_offset, length)
+ source.byteslice(byte_offset, length) or raise
end
# Binary search through the offsets to find the line number for the given
# byte offset.
- def line(value)
- start_line + find_line(value)
+ def line(byte_offset)
+ start_line + find_line(byte_offset)
end
# Return the byte offset of the start of the line corresponding to the given
# byte offset.
- def line_offset(value)
- offsets[find_line(value)]
+ def line_start(byte_offset)
+ offsets[find_line(byte_offset)]
+ end
+
+ # Returns the byte offset of the end of the line corresponding to the given
+ # byte offset.
+ def line_end(byte_offset)
+ offsets[find_line(byte_offset) + 1] || source.bytesize
end
# Return the column number for the given byte offset.
- def column(value)
- value - offsets[find_line(value)]
+ def column(byte_offset)
+ byte_offset - line_start(byte_offset)
+ end
+
+ # Return the character offset for the given byte offset.
+ def character_offset(byte_offset)
+ (source.byteslice(0, byte_offset) or raise).length
+ end
+
+ # Return the column number in characters for the given byte offset.
+ def character_column(byte_offset)
+ character_offset(byte_offset) - character_offset(line_start(byte_offset))
+ end
+
+ # Returns the offset from the start of the file for the given byte offset
+ # counting in code units for the given encoding.
+ #
+ # This method is tested with UTF-8, UTF-16, and UTF-32. If there is the
+ # concept of code units that differs from the number of characters in other
+ # encodings, it is not captured here.
+ def code_units_offset(byte_offset, encoding)
+ byteslice = (source.byteslice(0, byte_offset) or raise).encode(encoding)
+ (encoding == Encoding::UTF_16LE || encoding == Encoding::UTF_16BE) ? (byteslice.bytesize / 2) : byteslice.length
+ end
+
+ # Returns the column number in code units for the given encoding for the
+ # given byte offset.
+ def code_units_column(byte_offset, encoding)
+ code_units_offset(byte_offset, encoding) - code_units_offset(line_start(byte_offset), encoding)
end
private
# Binary search through the offsets to find the line number for the given
# byte offset.
- def find_line(value)
+ def find_line(byte_offset)
left = 0
right = offsets.length - 1
while left <= right
mid = left + (right - left) / 2
- return mid if offsets[mid] == value
+ return mid if (offset = offsets[mid]) == byte_offset
- if offsets[mid] < value
+ if offset < byte_offset
left = mid + 1
else
right = mid - 1
@@ -67,13 +117,38 @@ module Prism
left - 1
end
+ end
+
+ # Specialized version of Prism::Source for source code that includes ASCII
+ # characters only. This class is used to apply performance optimizations that
+ # cannot be applied to sources that include multibyte characters. Sources that
+ # include multibyte characters are represented by the Prism::Source class.
+ class ASCIISource < Source
+ # Return the character offset for the given byte offset.
+ def character_offset(byte_offset)
+ byte_offset
+ end
+
+ # Return the column number in characters for the given byte offset.
+ def character_column(byte_offset)
+ byte_offset - line_start(byte_offset)
+ end
- # Find all of the newlines in the source code and return their byte offsets
- # from the start of the string an array.
- def compute_offsets(code)
- offsets = [0]
- code.b.scan("\n") { offsets << $~.end(0) }
- offsets
+ # Returns the offset from the start of the file for the given byte offset
+ # counting in code units for the given encoding.
+ #
+ # This method is tested with UTF-8, UTF-16, and UTF-32. If there is the
+ # concept of code units that differs from the number of characters in other
+ # encodings, it is not captured here.
+ def code_units_offset(byte_offset, encoding)
+ byte_offset
+ end
+
+ # Specialized version of `code_units_column` that does not depend on
+ # `code_units_offset`, which is a more expensive operation. This is
+ # essentialy the same as `Prism::Source#column`.
+ def code_units_column(byte_offset, encoding)
+ byte_offset - line_start(byte_offset)
end
end
@@ -81,7 +156,8 @@ module Prism
class Location
# A Source object that is used to determine more information from the given
# offset and length.
- protected attr_reader :source
+ attr_reader :source
+ protected :source
# The byte offset from the beginning of the source where this location
# starts.
@@ -90,25 +166,56 @@ module Prism
# The length of this location in bytes.
attr_reader :length
- # The list of comments attached to this location
- attr_reader :comments
-
# Create a new location object with the given source, start byte offset, and
# byte length.
def initialize(source, start_offset, length)
@source = source
@start_offset = start_offset
@length = length
- @comments = []
+
+ # These are used to store comments that are associated with this location.
+ # They are initialized to `nil` to save on memory when there are no
+ # comments to be attached and/or the comment-related APIs are not used.
+ @leading_comments = nil
+ @trailing_comments = nil
+ end
+
+ # These are the comments that are associated with this location that exist
+ # before the start of this location.
+ def leading_comments
+ @leading_comments ||= []
+ end
+
+ # Attach a comment to the leading comments of this location.
+ def leading_comment(comment)
+ leading_comments << comment
+ end
+
+ # These are the comments that are associated with this location that exist
+ # after the end of this location.
+ def trailing_comments
+ @trailing_comments ||= []
+ end
+
+ # Attach a comment to the trailing comments of this location.
+ def trailing_comment(comment)
+ trailing_comments << comment
+ end
+
+ # Returns all comments that are associated with this location (both leading
+ # and trailing comments).
+ def comments
+ [*@leading_comments, *@trailing_comments]
end
# Create a new location object with the given options.
- def copy(**options)
- Location.new(
- options.fetch(:source) { source },
- options.fetch(:start_offset) { start_offset },
- options.fetch(:length) { length }
- )
+ def copy(source: self.source, start_offset: self.start_offset, length: self.length)
+ Location.new(source, start_offset, length)
+ end
+
+ # Returns a new location that is the result of chopping off the last byte.
+ def chop
+ copy(length: length == 0 ? length : length - 1)
end
# Returns a string representation of this location.
@@ -116,16 +223,52 @@ module Prism
"#<Prism::Location @start_offset=#{@start_offset} @length=#{@length} start_line=#{start_line}>"
end
+ # Returns all of the lines of the source code associated with this location.
+ def source_lines
+ source.lines
+ end
+
# The source code that this location represents.
def slice
source.slice(start_offset, length)
end
+ # The source code that this location represents starting from the beginning
+ # of the line that this location starts on to the end of the line that this
+ # location ends on.
+ def slice_lines
+ line_start = source.line_start(start_offset)
+ line_end = source.line_end(end_offset)
+ source.slice(line_start, line_end - line_start)
+ end
+
+ # The character offset from the beginning of the source where this location
+ # starts.
+ def start_character_offset
+ source.character_offset(start_offset)
+ end
+
+ # The offset from the start of the file in code units of the given encoding.
+ def start_code_units_offset(encoding = Encoding::UTF_16LE)
+ source.code_units_offset(start_offset, encoding)
+ end
+
# The byte offset from the beginning of the source where this location ends.
def end_offset
start_offset + length
end
+ # The character offset from the beginning of the source where this location
+ # ends.
+ def end_character_offset
+ source.character_offset(end_offset)
+ end
+
+ # The offset from the start of the file in code units of the given encoding.
+ def end_code_units_offset(encoding = Encoding::UTF_16LE)
+ source.code_units_offset(end_offset, encoding)
+ end
+
# The line number where this location starts.
def start_line
source.line(start_offset)
@@ -133,7 +276,7 @@ module Prism
# The content of the line where this location starts before this location.
def start_line_slice
- offset = source.line_offset(start_offset)
+ offset = source.line_start(start_offset)
source.slice(offset, start_offset - offset)
end
@@ -148,12 +291,36 @@ module Prism
source.column(start_offset)
end
+ # The column number in characters where this location ends from the start of
+ # the line.
+ def start_character_column
+ source.character_column(start_offset)
+ end
+
+ # The column number in code units of the given encoding where this location
+ # starts from the start of the line.
+ def start_code_units_column(encoding = Encoding::UTF_16LE)
+ source.code_units_column(start_offset, encoding)
+ end
+
# The column number in bytes where this location ends from the start of the
# line.
def end_column
source.column(end_offset)
end
+ # The column number in characters where this location ends from the start of
+ # the line.
+ def end_character_column
+ source.character_column(end_offset)
+ end
+
+ # The column number in code units of the given encoding where this location
+ # ends from the start of the line.
+ def end_code_units_column(encoding = Encoding::UTF_16LE)
+ source.code_units_column(end_offset, encoding)
+ end
+
# Implement the hash pattern matching interface for Location.
def deconstruct_keys(keys)
{ start_offset: start_offset, end_offset: end_offset }
@@ -166,7 +333,7 @@ module Prism
# Returns true if the given other location is equal to this location.
def ==(other)
- other.is_a?(Location) &&
+ Location === other &&
other.start_offset == start_offset &&
other.end_offset == end_offset
end
@@ -181,11 +348,16 @@ module Prism
Location.new(source, start_offset, other.end_offset - start_offset)
end
- # Returns a null location that does not correspond to a source and points to
- # the beginning of the file. Useful for when you want a location object but
- # do not care where it points.
- def self.null
- new(nil, 0, 0)
+ # Join this location with the first occurrence of the string in the source
+ # that occurs after this location on the same line, and return the new
+ # location. This will raise an error if the string does not exist.
+ def adjoin(string)
+ line_suffix = source.slice(end_offset, source.line_end(end_offset) - end_offset)
+
+ line_suffix_index = line_suffix.byteindex(string)
+ raise "Could not find #{string}" if line_suffix_index.nil?
+
+ Location.new(source, start_offset, length + line_suffix_index + string.bytesize)
end
end
@@ -205,9 +377,9 @@ module Prism
{ location: location }
end
- # This can only be true for inline comments.
- def trailing?
- false
+ # Returns the content of the comment by slicing it from the source code.
+ def slice
+ location.slice
end
end
@@ -229,18 +401,14 @@ module Prism
# EmbDocComment objects correspond to comments that are surrounded by =begin
# and =end.
class EmbDocComment < Comment
- # Returns a string representation of this comment.
- def inspect
- "#<Prism::EmbDocComment @location=#{location.inspect}>"
+ # This can only be true for inline comments.
+ def trailing?
+ false
end
- end
- # DATAComment objects correspond to comments that are after the __END__
- # keyword in a source file.
- class DATAComment < Comment
# Returns a string representation of this comment.
def inspect
- "#<Prism::DATAComment @location=#{location.inspect}>"
+ "#<Prism::EmbDocComment @location=#{location.inspect}>"
end
end
@@ -281,69 +449,87 @@ module Prism
# This represents an error that was encountered during parsing.
class ParseError
+ # The type of error. This is an _internal_ symbol that is used for
+ # communicating with translation layers. It is not meant to be public API.
+ attr_reader :type
+
# The message associated with this error.
attr_reader :message
# A Location object representing the location of this error in the source.
attr_reader :location
+ # The level of this error.
+ attr_reader :level
+
# Create a new error object with the given message and location.
- def initialize(message, location)
+ def initialize(type, message, location, level)
+ @type = type
@message = message
@location = location
+ @level = level
end
# Implement the hash pattern matching interface for ParseError.
def deconstruct_keys(keys)
- { message: message, location: location }
+ { type: type, message: message, location: location, level: level }
end
# Returns a string representation of this error.
def inspect
- "#<Prism::ParseError @message=#{@message.inspect} @location=#{@location.inspect}>"
+ "#<Prism::ParseError @type=#{@type.inspect} @message=#{@message.inspect} @location=#{@location.inspect} @level=#{@level.inspect}>"
end
end
# This represents a warning that was encountered during parsing.
class ParseWarning
+ # The type of warning. This is an _internal_ symbol that is used for
+ # communicating with translation layers. It is not meant to be public API.
+ attr_reader :type
+
# The message associated with this warning.
attr_reader :message
# A Location object representing the location of this warning in the source.
attr_reader :location
+ # The level of this warning.
+ attr_reader :level
+
# Create a new warning object with the given message and location.
- def initialize(message, location)
+ def initialize(type, message, location, level)
+ @type = type
@message = message
@location = location
+ @level = level
end
# Implement the hash pattern matching interface for ParseWarning.
def deconstruct_keys(keys)
- { message: message, location: location }
+ { type: type, message: message, location: location, level: level }
end
# Returns a string representation of this warning.
def inspect
- "#<Prism::ParseWarning @message=#{@message.inspect} @location=#{@location.inspect}>"
+ "#<Prism::ParseWarning @type=#{@type.inspect} @message=#{@message.inspect} @location=#{@location.inspect} @level=#{@level.inspect}>"
end
end
# This represents the result of a call to ::parse or ::parse_file. It contains
- # the AST, any comments that were encounters, and any errors that were
- # encountered.
- class ParseResult
- # The value that was generated by parsing. Normally this holds the AST, but
- # it can sometimes how a list of tokens or other results passed back from
- # the parser.
- attr_reader :value
-
+ # the requested structure, any comments that were encounters, and any errors
+ # that were encountered.
+ class Result
# The list of comments that were encountered during parsing.
attr_reader :comments
# The list of magic comments that were encountered during parsing.
attr_reader :magic_comments
+ # An optional location that represents the location of the __END__ marker
+ # and the rest of the content of the file. This content is loaded into the
+ # DATA constant when the file being parsed is the main file being executed.
+ attr_reader :data_loc
+
# The list of errors that were generated during parsing.
attr_reader :errors
@@ -353,19 +539,24 @@ module Prism
# A Source instance that represents the source code that was parsed.
attr_reader :source
- # Create a new parse result object with the given values.
- def initialize(value, comments, magic_comments, errors, warnings, source)
- @value = value
+ # Create a new result object with the given values.
+ def initialize(comments, magic_comments, data_loc, errors, warnings, source)
@comments = comments
@magic_comments = magic_comments
+ @data_loc = data_loc
@errors = errors
@warnings = warnings
@source = source
end
- # Implement the hash pattern matching interface for ParseResult.
+ # Implement the hash pattern matching interface for Result.
def deconstruct_keys(keys)
- { value: value, comments: comments, magic_comments: magic_comments, errors: errors, warnings: warnings }
+ { comments: comments, magic_comments: magic_comments, data_loc: data_loc, errors: errors, warnings: warnings }
+ end
+
+ # Returns the encoding of the source code that was parsed.
+ def encoding
+ source.encoding
end
# Returns true if there were no errors during parsing and false if there
@@ -381,19 +572,90 @@ module Prism
end
end
+ # This is a result specific to the `parse` and `parse_file` methods.
+ class ParseResult < Result
+ autoload :Comments, "prism/parse_result/comments"
+ autoload :Newlines, "prism/parse_result/newlines"
+
+ private_constant :Comments
+ private_constant :Newlines
+
+ # The syntax tree that was parsed from the source code.
+ attr_reader :value
+
+ # Create a new parse result object with the given values.
+ def initialize(value, comments, magic_comments, data_loc, errors, warnings, source)
+ @value = value
+ super(comments, magic_comments, data_loc, errors, warnings, source)
+ end
+
+ # Implement the hash pattern matching interface for ParseResult.
+ def deconstruct_keys(keys)
+ super.merge!(value: value)
+ end
+
+ # Attach the list of comments to their respective locations in the tree.
+ def attach_comments!
+ Comments.new(self).attach! # steep:ignore
+ end
+
+ # Walk the tree and mark nodes that are on a new line, loosely emulating
+ # the behavior of CRuby's `:line` tracepoint event.
+ def mark_newlines!
+ value.accept(Newlines.new(source.offsets.size)) # steep:ignore
+ end
+ end
+
+ # This is a result specific to the `lex` and `lex_file` methods.
+ class LexResult < Result
+ # The list of tokens that were parsed from the source code.
+ attr_reader :value
+
+ # Create a new lex result object with the given values.
+ def initialize(value, comments, magic_comments, data_loc, errors, warnings, source)
+ @value = value
+ super(comments, magic_comments, data_loc, errors, warnings, source)
+ end
+
+ # Implement the hash pattern matching interface for LexResult.
+ def deconstruct_keys(keys)
+ super.merge!(value: value)
+ end
+ end
+
+ # This is a result specific to the `parse_lex` and `parse_lex_file` methods.
+ class ParseLexResult < Result
+ # A tuple of the syntax tree and the list of tokens that were parsed from
+ # the source code.
+ attr_reader :value
+
+ # Create a new parse lex result object with the given values.
+ def initialize(value, comments, magic_comments, data_loc, errors, warnings, source)
+ @value = value
+ super(comments, magic_comments, data_loc, errors, warnings, source)
+ end
+
+ # Implement the hash pattern matching interface for ParseLexResult.
+ def deconstruct_keys(keys)
+ super.merge!(value: value)
+ end
+ end
+
# This represents a token from the Ruby source.
class Token
+ # The Source object that represents the source this token came from.
+ attr_reader :source
+ private :source
+
# The type of token that this token is.
attr_reader :type
# A byteslice of the source that this token represents.
attr_reader :value
- # A Location object representing the location of this token in the source.
- attr_reader :location
-
# Create a new token object with the given type, value, and location.
- def initialize(type, value, location)
+ def initialize(source, type, value, location)
+ @source = source
@type = type
@value = value
@location = location
@@ -404,6 +666,13 @@ module Prism
{ type: type, value: value, location: location }
end
+ # A Location object representing the location of this token in the source.
+ def location
+ location = @location
+ return location if location.is_a?(Location)
+ @location = Location.new(source, location >> 32, location & 0xFFFFFFFF)
+ end
+
# Implement the pretty print interface for Token.
def pretty_print(q)
q.group do
@@ -421,7 +690,7 @@ module Prism
# Returns true if the given other token is equal to this token.
def ==(other)
- other.is_a?(Token) &&
+ Token === other &&
other.type == type &&
other.value == value
end
diff --git a/lib/prism/parse_result/comments.rb b/lib/prism/parse_result/comments.rb
index 7a3a47de50..22c4148b2c 100644
--- a/lib/prism/parse_result/comments.rb
+++ b/lib/prism/parse_result/comments.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Prism
- class ParseResult
+ class ParseResult < Result
# When we've parsed the source, we have both the syntax tree and the list of
# comments that we found in the source. This class is responsible for
# walking the tree and finding the nearest location to attach each comment.
@@ -27,11 +27,11 @@ module Prism
end
def start_offset
- node.location.start_offset
+ node.start_offset
end
def end_offset
- node.location.end_offset
+ node.end_offset
end
def encloses?(comment)
@@ -39,8 +39,12 @@ module Prism
comment.location.end_offset <= end_offset
end
- def <<(comment)
- node.location.comments << comment
+ def leading_comment(comment)
+ node.location.leading_comment(comment)
+ end
+
+ def trailing_comment(comment)
+ node.location.trailing_comment(comment)
end
end
@@ -65,8 +69,12 @@ module Prism
false
end
- def <<(comment)
- location.comments << comment
+ def leading_comment(comment)
+ location.leading_comment(comment)
+ end
+
+ def trailing_comment(comment)
+ location.trailing_comment(comment)
end
end
@@ -84,15 +92,23 @@ module Prism
def attach!
parse_result.comments.each do |comment|
preceding, enclosing, following = nearest_targets(parse_result.value, comment)
- target =
- if comment.trailing?
- preceding || following || enclosing || NodeTarget.new(parse_result.value)
+
+ if comment.trailing?
+ if preceding
+ preceding.trailing_comment(comment)
else
- # If a comment exists on its own line, prefer a leading comment.
- following || preceding || enclosing || NodeTarget.new(parse_result.value)
+ (following || enclosing || NodeTarget.new(parse_result.value)).leading_comment(comment)
end
-
- target << comment
+ else
+ # If a comment exists on its own line, prefer a leading comment.
+ if following
+ following.leading_comment(comment)
+ elsif preceding
+ preceding.trailing_comment(comment)
+ else
+ (enclosing || NodeTarget.new(parse_result.value)).leading_comment(comment)
+ end
+ end
end
end
@@ -104,7 +120,7 @@ module Prism
comment_start = comment.location.start_offset
comment_end = comment.location.end_offset
- targets = []
+ targets = [] #: Array[_Target]
node.comment_targets.map do |value|
case value
when StatementsNode
@@ -117,8 +133,8 @@ module Prism
end
targets.sort_by!(&:start_offset)
- preceding = nil
- following = nil
+ preceding = nil #: _Target?
+ following = nil #: _Target?
left = 0
right = targets.length
@@ -134,6 +150,7 @@ module Prism
target_end = target.end_offset
if target.encloses?(comment)
+ # @type var target: NodeTarget
# The comment is completely contained by this target. Abandon the
# binary search at this level.
return nearest_targets(target.node, comment)
@@ -166,12 +183,5 @@ module Prism
[preceding, NodeTarget.new(node), following]
end
end
-
- private_constant :Comments
-
- # Attach the list of comments to their respective locations in the tree.
- def attach_comments!
- Comments.new(self).attach!
- end
end
end
diff --git a/lib/prism/parse_result/newlines.rb b/lib/prism/parse_result/newlines.rb
index ca05f5b702..808a129a6b 100644
--- a/lib/prism/parse_result/newlines.rb
+++ b/lib/prism/parse_result/newlines.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Prism
- class ParseResult
+ class ParseResult < Result
# The :line tracepoint event gets fired whenever the Ruby VM encounters an
# expression on a new line. The types of expressions that can trigger this
# event are:
@@ -17,21 +17,27 @@ module Prism
# Note that the logic in this file should be kept in sync with the Java
# MarkNewlinesVisitor, since that visitor is responsible for marking the
# newlines for JRuby/TruffleRuby.
+ #
+ # This file is autoloaded only when `mark_newlines!` is called, so the
+ # re-opening of the various nodes in this file will only be performed in
+ # that case. We do that to avoid storing the extra `@newline` instance
+ # variable on every node if we don't need it.
class Newlines < Visitor
# Create a new Newlines visitor with the given newline offsets.
- def initialize(newline_marked)
- @newline_marked = newline_marked
+ def initialize(lines)
+ # @type var lines: Integer
+ @lines = Array.new(1 + lines, false)
end
# Permit block/lambda nodes to mark newlines within themselves.
def visit_block_node(node)
- old_newline_marked = @newline_marked
- @newline_marked = Array.new(old_newline_marked.size, false)
+ old_lines = @lines
+ @lines = Array.new(old_lines.size, false)
begin
super(node)
ensure
- @newline_marked = old_newline_marked
+ @lines = old_lines
end
end
@@ -39,7 +45,7 @@ module Prism
# Mark if/unless nodes as newlines.
def visit_if_node(node)
- node.set_newline_flag(@newline_marked)
+ node.newline!(@lines)
super(node)
end
@@ -48,17 +54,101 @@ module Prism
# Permit statements lists to mark newlines within themselves.
def visit_statements_node(node)
node.body.each do |child|
- child.set_newline_flag(@newline_marked)
+ child.newline!(@lines)
end
super(node)
end
end
+ end
+
+ class Node
+ def newline? # :nodoc:
+ @newline ? true : false
+ end
+
+ def newline!(lines) # :nodoc:
+ line = location.start_line
+ unless lines[line]
+ lines[line] = true
+ @newline = true
+ end
+ end
+ end
+
+ class BeginNode < Node
+ def newline!(lines) # :nodoc:
+ # Never mark BeginNode with a newline flag, mark children instead.
+ end
+ end
+
+ class ParenthesesNode < Node
+ def newline!(lines) # :nodoc:
+ # Never mark ParenthesesNode with a newline flag, mark children instead.
+ end
+ end
+
+ class IfNode < Node
+ def newline!(lines) # :nodoc:
+ predicate.newline!(lines)
+ end
+ end
+
+ class UnlessNode < Node
+ def newline!(lines) # :nodoc:
+ predicate.newline!(lines)
+ end
+ end
+
+ class UntilNode < Node
+ def newline!(lines) # :nodoc:
+ predicate.newline!(lines)
+ end
+ end
+
+ class WhileNode < Node
+ def newline!(lines) # :nodoc:
+ predicate.newline!(lines)
+ end
+ end
+
+ class RescueModifierNode < Node
+ def newline!(lines) # :nodoc:
+ expression.newline!(lines)
+ end
+ end
+
+ class InterpolatedMatchLastLineNode < Node
+ def newline!(lines) # :nodoc:
+ first = parts.first
+ first.newline!(lines) if first
+ end
+ end
+
+ class InterpolatedRegularExpressionNode < Node
+ def newline!(lines) # :nodoc:
+ first = parts.first
+ first.newline!(lines) if first
+ end
+ end
+
+ class InterpolatedStringNode < Node
+ def newline!(lines) # :nodoc:
+ first = parts.first
+ first.newline!(lines) if first
+ end
+ end
- private_constant :Newlines
+ class InterpolatedSymbolNode < Node
+ def newline!(lines) # :nodoc:
+ first = parts.first
+ first.newline!(lines) if first
+ end
+ end
- # Walk the tree and mark nodes that are on a new line.
- def mark_newlines!
- value.accept(Newlines.new(Array.new(1 + source.offsets.size, false)))
+ class InterpolatedXStringNode < Node
+ def newline!(lines) # :nodoc:
+ first = parts.first
+ first.newline!(lines) if first
end
end
end
diff --git a/lib/prism/pattern.rb b/lib/prism/pattern.rb
index e1643671ec..03fec26789 100644
--- a/lib/prism/pattern.rb
+++ b/lib/prism/pattern.rb
@@ -69,7 +69,14 @@ module Prism
# nodes.
def compile
result = Prism.parse("case nil\nin #{query}\nend")
- compile_node(result.value.statements.body.last.conditions.last.pattern)
+
+ case_match_node = result.value.statements.body.last
+ raise CompilationError, case_match_node.inspect unless case_match_node.is_a?(CaseMatchNode)
+
+ in_node = case_match_node.conditions.last
+ raise CompilationError, in_node.inspect unless in_node.is_a?(InNode)
+
+ compile_node(in_node.pattern)
end
# Scan the given node and all of its children for nodes that match the
@@ -77,13 +84,13 @@ module Prism
# matches the pattern. If no block is given, an enumerator will be returned
# that will yield each node that matches the pattern.
def scan(root)
- return to_enum(__method__, root) unless block_given?
+ return to_enum(:scan, root) unless block_given?
@compiled ||= compile
queue = [root]
while (node = queue.shift)
- yield node if @compiled.call(node)
+ yield node if @compiled.call(node) # steep:ignore
queue.concat(node.compact_child_nodes)
end
end
@@ -142,7 +149,10 @@ module Prism
parent = node.parent
if parent.is_a?(ConstantReadNode) && parent.slice == "Prism"
- compile_node(node.child)
+ name = node.name
+ raise CompilationError, node.inspect if name.nil?
+
+ compile_constant_name(node, name)
else
compile_error(node)
end
@@ -151,14 +161,17 @@ module Prism
# in ConstantReadNode
# in String
def compile_constant_read_node(node)
- value = node.slice
+ compile_constant_name(node, node.name)
+ end
- if Prism.const_defined?(value, false)
- clazz = Prism.const_get(value)
+ # Compile a name associated with a constant.
+ def compile_constant_name(node, name)
+ if Prism.const_defined?(name, false)
+ clazz = Prism.const_get(name)
->(other) { clazz === other }
- elsif Object.const_defined?(value, false)
- clazz = Object.const_get(value)
+ elsif Object.const_defined?(name, false)
+ clazz = Object.const_get(name)
->(other) { clazz === other }
else
@@ -174,7 +187,12 @@ module Prism
preprocessed =
node.elements.to_h do |element|
- [element.key.unescaped.to_sym, compile_node(element.value)]
+ key = element.key
+ if key.is_a?(SymbolNode)
+ [key.unescaped.to_sym, compile_node(element.value)]
+ else
+ raise CompilationError, element.inspect
+ end
end
compiled_keywords = ->(other) do
diff --git a/lib/prism/polyfill/byteindex.rb b/lib/prism/polyfill/byteindex.rb
new file mode 100644
index 0000000000..98c6089f14
--- /dev/null
+++ b/lib/prism/polyfill/byteindex.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+# Polyfill for String#byteindex, which didn't exist until Ruby 3.2.
+if !("".respond_to?(:byteindex))
+ String.include(
+ Module.new {
+ def byteindex(needle, offset = 0)
+ charindex = index(needle, offset)
+ slice(0...charindex).bytesize if charindex
+ end
+ }
+ )
+end
diff --git a/lib/prism/polyfill/unpack1.rb b/lib/prism/polyfill/unpack1.rb
new file mode 100644
index 0000000000..3fa9b5a0c5
--- /dev/null
+++ b/lib/prism/polyfill/unpack1.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+# Polyfill for String#unpack1 with the offset parameter. Not all Ruby engines
+# have Method#parameters implemented, so we check the arity instead if
+# necessary.
+if (unpack1 = String.instance_method(:unpack1)).respond_to?(:parameters) ? unpack1.parameters.none? { |_, name| name == :offset } : (unpack1.arity == 1)
+ String.prepend(
+ Module.new {
+ def unpack1(format, offset: 0) # :nodoc:
+ offset == 0 ? super(format) : self[offset..].unpack1(format) # steep:ignore
+ end
+ }
+ )
+end
diff --git a/lib/prism/prism.gemspec b/lib/prism/prism.gemspec
index 65cc61a825..b39ba706dc 100644
--- a/lib/prism/prism.gemspec
+++ b/lib/prism/prism.gemspec
@@ -2,7 +2,7 @@
Gem::Specification.new do |spec|
spec.name = "prism"
- spec.version = "0.17.1"
+ spec.version = "0.30.0"
spec.authors = ["Shopify"]
spec.email = ["ruby@shopify.com"]
@@ -10,10 +10,11 @@ Gem::Specification.new do |spec|
spec.homepage = "https://github.com/ruby/prism"
spec.license = "MIT"
- spec.required_ruby_version = ">= 3.0.0"
+ spec.required_ruby_version = ">= 2.7.0"
spec.require_paths = ["lib"]
spec.files = [
+ "BSDmakefile",
"CHANGELOG.md",
"CODE_OF_CONDUCT.md",
"CONTRIBUTING.md",
@@ -22,17 +23,21 @@ Gem::Specification.new do |spec|
"README.md",
"config.yml",
"docs/build_system.md",
- "docs/building.md",
"docs/configuration.md",
+ "docs/cruby_compilation.md",
"docs/design.md",
"docs/encoding.md",
"docs/fuzzing.md",
"docs/heredocs.md",
"docs/javascript.md",
+ "docs/local_variable_depth.md",
"docs/mapping.md",
+ "docs/parser_translation.md",
+ "docs/parsing_rules.md",
"docs/releasing.md",
- "docs/ripper.md",
+ "docs/ripper_translation.md",
"docs/ruby_api.md",
+ "docs/ruby_parser_translation.md",
"docs/serialization.md",
"docs/testing.md",
"ext/prism/api_node.c",
@@ -43,78 +48,108 @@ Gem::Specification.new do |spec|
"include/prism/ast.h",
"include/prism/defines.h",
"include/prism/diagnostic.h",
- "include/prism/enc/pm_encoding.h",
+ "include/prism/encoding.h",
"include/prism/node.h",
"include/prism/options.h",
"include/prism/pack.h",
"include/prism/parser.h",
"include/prism/prettyprint.h",
"include/prism/regexp.h",
+ "include/prism/static_literals.h",
"include/prism/util/pm_buffer.h",
"include/prism/util/pm_char.h",
"include/prism/util/pm_constant_pool.h",
+ "include/prism/util/pm_integer.h",
"include/prism/util/pm_list.h",
"include/prism/util/pm_memchr.h",
"include/prism/util/pm_newline_list.h",
- "include/prism/util/pm_state_stack.h",
"include/prism/util/pm_strncasecmp.h",
"include/prism/util/pm_string.h",
- "include/prism/util/pm_string_list.h",
"include/prism/util/pm_strpbrk.h",
"include/prism/version.h",
"lib/prism.rb",
"lib/prism/compiler.rb",
- "lib/prism/debug.rb",
"lib/prism/desugar_compiler.rb",
"lib/prism/dispatcher.rb",
"lib/prism/dot_visitor.rb",
"lib/prism/dsl.rb",
"lib/prism/ffi.rb",
+ "lib/prism/inspect_visitor.rb",
"lib/prism/lex_compat.rb",
"lib/prism/mutation_compiler.rb",
- "lib/prism/node.rb",
"lib/prism/node_ext.rb",
- "lib/prism/node_inspector.rb",
+ "lib/prism/node.rb",
"lib/prism/pack.rb",
"lib/prism/parse_result.rb",
- "lib/prism/pattern.rb",
- "lib/prism/ripper_compat.rb",
- "lib/prism/serialize.rb",
"lib/prism/parse_result/comments.rb",
"lib/prism/parse_result/newlines.rb",
+ "lib/prism/pattern.rb",
+ "lib/prism/polyfill/byteindex.rb",
+ "lib/prism/polyfill/unpack1.rb",
+ "lib/prism/reflection.rb",
+ "lib/prism/serialize.rb",
+ "lib/prism/translation.rb",
+ "lib/prism/translation/parser.rb",
+ "lib/prism/translation/parser33.rb",
+ "lib/prism/translation/parser34.rb",
+ "lib/prism/translation/parser/compiler.rb",
+ "lib/prism/translation/parser/lexer.rb",
+ "lib/prism/translation/parser/rubocop.rb",
+ "lib/prism/translation/ripper.rb",
+ "lib/prism/translation/ripper/sexp.rb",
+ "lib/prism/translation/ripper/shim.rb",
+ "lib/prism/translation/ruby_parser.rb",
"lib/prism/visitor.rb",
+ "prism.gemspec",
+ "rbi/prism.rbi",
+ "rbi/prism/compiler.rbi",
+ "rbi/prism/inspect_visitor.rbi",
+ "rbi/prism/node_ext.rbi",
+ "rbi/prism/node.rbi",
+ "rbi/prism/parse_result.rbi",
+ "rbi/prism/reflection.rbi",
+ "rbi/prism/translation/parser.rbi",
+ "rbi/prism/translation/parser33.rbi",
+ "rbi/prism/translation/parser34.rbi",
+ "rbi/prism/translation/ripper.rbi",
+ "rbi/prism/visitor.rbi",
+ "sig/prism.rbs",
+ "sig/prism/compiler.rbs",
+ "sig/prism/dispatcher.rbs",
+ "sig/prism/dot_visitor.rbs",
+ "sig/prism/dsl.rbs",
+ "sig/prism/inspect_visitor.rbs",
+ "sig/prism/lex_compat.rbs",
+ "sig/prism/mutation_compiler.rbs",
+ "sig/prism/node_ext.rbs",
+ "sig/prism/node.rbs",
+ "sig/prism/pack.rbs",
+ "sig/prism/parse_result.rbs",
+ "sig/prism/pattern.rbs",
+ "sig/prism/reflection.rbs",
+ "sig/prism/serialize.rbs",
+ "sig/prism/visitor.rbs",
"src/diagnostic.c",
- "src/enc/pm_big5.c",
- "src/enc/pm_euc_jp.c",
- "src/enc/pm_gbk.c",
- "src/enc/pm_shift_jis.c",
- "src/enc/pm_tables.c",
- "src/enc/pm_unicode.c",
- "src/enc/pm_windows_31j.c",
+ "src/encoding.c",
"src/node.c",
+ "src/options.c",
"src/pack.c",
"src/prettyprint.c",
+ "src/prism.c",
"src/regexp.c",
"src/serialize.c",
+ "src/static_literals.c",
"src/token_type.c",
"src/util/pm_buffer.c",
"src/util/pm_char.c",
"src/util/pm_constant_pool.c",
+ "src/util/pm_integer.c",
"src/util/pm_list.c",
"src/util/pm_memchr.c",
"src/util/pm_newline_list.c",
- "src/util/pm_state_stack.c",
"src/util/pm_string.c",
- "src/util/pm_string_list.c",
"src/util/pm_strncasecmp.c",
- "src/util/pm_strpbrk.c",
- "src/options.c",
- "src/prism.c",
- "prism.gemspec",
- "sig/prism.rbs",
- "sig/prism_static.rbs",
- "rbi/prism.rbi",
- "rbi/prism_static.rbi"
+ "src/util/pm_strpbrk.c"
]
spec.extensions = ["ext/prism/extconf.rb"]
diff --git a/lib/prism/ripper_compat.rb b/lib/prism/ripper_compat.rb
deleted file mode 100644
index 624e608cc1..0000000000
--- a/lib/prism/ripper_compat.rb
+++ /dev/null
@@ -1,192 +0,0 @@
-# frozen_string_literal: true
-
-require "ripper"
-
-module Prism
- # This class is meant to provide a compatibility layer between prism and
- # Ripper. It functions by parsing the entire tree first and then walking it
- # and executing each of the Ripper callbacks as it goes.
- #
- # This class is going to necessarily be slower than the native Ripper API. It
- # is meant as a stopgap until developers migrate to using prism. It is also
- # meant as a test harness for the prism parser.
- class RipperCompat
- # This class mirrors the ::Ripper::SexpBuilder subclass of ::Ripper that
- # returns the arrays of [type, *children].
- class SexpBuilder < RipperCompat
- private
-
- Ripper::PARSER_EVENTS.each do |event|
- define_method(:"on_#{event}") do |*args|
- [event, *args]
- end
- end
-
- Ripper::SCANNER_EVENTS.each do |event|
- define_method(:"on_#{event}") do |value|
- [:"@#{event}", value, [lineno, column]]
- end
- end
- end
-
- # This class mirrors the ::Ripper::SexpBuilderPP subclass of ::Ripper that
- # returns the same values as ::Ripper::SexpBuilder except with a couple of
- # niceties that flatten linked lists into arrays.
- class SexpBuilderPP < SexpBuilder
- private
-
- def _dispatch_event_new # :nodoc:
- []
- end
-
- def _dispatch_event_push(list, item) # :nodoc:
- list << item
- list
- end
-
- Ripper::PARSER_EVENT_TABLE.each do |event, arity|
- case event
- when /_new\z/
- alias_method :"on_#{event}", :_dispatch_event_new if arity == 0
- when /_add\z/
- alias_method :"on_#{event}", :_dispatch_event_push
- end
- end
- end
-
- # The source that is being parsed.
- attr_reader :source
-
- # The current line number of the parser.
- attr_reader :lineno
-
- # The current column number of the parser.
- attr_reader :column
-
- # Create a new RipperCompat object with the given source.
- def initialize(source)
- @source = source
- @result = nil
- @lineno = nil
- @column = nil
- end
-
- ############################################################################
- # Public interface
- ############################################################################
-
- # True if the parser encountered an error during parsing.
- def error?
- result.errors.any?
- end
-
- # Parse the source and return the result.
- def parse
- result.value.accept(self) unless error?
- end
-
- ############################################################################
- # Visitor methods
- ############################################################################
-
- # This method is responsible for dispatching to the correct visitor method
- # based on the type of the node.
- def visit(node)
- node&.accept(self)
- end
-
- # Visit a CallNode node.
- def visit_call_node(node)
- if !node.opening_loc && node.arguments.arguments.length == 1
- bounds(node.receiver.location)
- left = visit(node.receiver)
-
- bounds(node.arguments.arguments.first.location)
- right = visit(node.arguments.arguments.first)
-
- on_binary(left, source[node.message_loc.start_offset...node.message_loc.end_offset].to_sym, right)
- else
- raise NotImplementedError
- end
- end
-
- # Visit an IntegerNode node.
- def visit_integer_node(node)
- bounds(node.location)
- on_int(source[node.location.start_offset...node.location.end_offset])
- end
-
- # Visit a StatementsNode node.
- def visit_statements_node(node)
- bounds(node.location)
- node.body.inject(on_stmts_new) do |stmts, stmt|
- on_stmts_add(stmts, visit(stmt))
- end
- end
-
- # Visit a token found during parsing.
- def visit_token(node)
- bounds(node.location)
-
- case node.type
- when :MINUS
- on_op(node.value)
- when :PLUS
- on_op(node.value)
- else
- raise NotImplementedError, "Unknown token: #{node.type}"
- end
- end
-
- # Visit a ProgramNode node.
- def visit_program_node(node)
- bounds(node.location)
- on_program(visit(node.statements))
- end
-
- ############################################################################
- # Entrypoints for subclasses
- ############################################################################
-
- # This is a convenience method that runs the SexpBuilder subclass parser.
- def self.sexp_raw(source)
- SexpBuilder.new(source).parse
- end
-
- # This is a convenience method that runs the SexpBuilderPP subclass parser.
- def self.sexp(source)
- SexpBuilderPP.new(source).parse
- end
-
- private
-
- # This method is responsible for updating lineno and column information
- # to reflect the current node.
- #
- # This method could be drastically improved with some caching on the start
- # of every line, but for now it's good enough.
- def bounds(location)
- start_offset = location.start_offset
-
- @lineno = source[0..start_offset].count("\n") + 1
- @column = start_offset - (source.rindex("\n", start_offset) || 0)
- end
-
- # Lazily initialize the parse result.
- def result
- @result ||= Prism.parse(source)
- end
-
- def _dispatch0; end # :nodoc:
- def _dispatch1(_); end # :nodoc:
- def _dispatch2(_, _); end # :nodoc:
- def _dispatch3(_, _, _); end # :nodoc:
- def _dispatch4(_, _, _, _); end # :nodoc:
- def _dispatch5(_, _, _, _, _); end # :nodoc:
- def _dispatch7(_, _, _, _, _, _, _); end # :nodoc:
-
- (Ripper::SCANNER_EVENT_TABLE.merge(Ripper::PARSER_EVENT_TABLE)).each do |event, arity|
- alias_method :"on_#{event}", :"_dispatch#{arity}"
- end
- end
-end
diff --git a/lib/prism/translation.rb b/lib/prism/translation.rb
new file mode 100644
index 0000000000..8b75e8a3ab
--- /dev/null
+++ b/lib/prism/translation.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Prism
+ # This module is responsible for converting the prism syntax tree into other
+ # syntax trees.
+ module Translation # steep:ignore
+ autoload :Parser, "prism/translation/parser"
+ autoload :Parser33, "prism/translation/parser33"
+ autoload :Parser34, "prism/translation/parser34"
+ autoload :Ripper, "prism/translation/ripper"
+ autoload :RubyParser, "prism/translation/ruby_parser"
+ end
+end
diff --git a/lib/prism/translation/parser.rb b/lib/prism/translation/parser.rb
new file mode 100644
index 0000000000..3748fc896e
--- /dev/null
+++ b/lib/prism/translation/parser.rb
@@ -0,0 +1,307 @@
+# frozen_string_literal: true
+
+begin
+ require "parser"
+rescue LoadError
+ warn(%q{Error: Unable to load parser. Add `gem "parser"` to your Gemfile.})
+ exit(1)
+end
+
+module Prism
+ module Translation
+ # This class is the entry-point for converting a prism syntax tree into the
+ # whitequark/parser gem's syntax tree. It inherits from the base parser for
+ # the parser gem, and overrides the parse* methods to parse with prism and
+ # then translate.
+ class Parser < ::Parser::Base
+ Diagnostic = ::Parser::Diagnostic # :nodoc:
+ private_constant :Diagnostic
+
+ # The parser gem has a list of diagnostics with a hard-coded set of error
+ # messages. We create our own diagnostic class in order to set our own
+ # error messages.
+ class PrismDiagnostic < Diagnostic
+ # This is the cached message coming from prism.
+ attr_reader :message
+
+ # Initialize a new diagnostic with the given message and location.
+ def initialize(message, level, reason, location)
+ @message = message
+ super(level, reason, {}, location, [])
+ end
+ end
+
+ Racc_debug_parser = false # :nodoc:
+
+ def version # :nodoc:
+ 34
+ end
+
+ # The default encoding for Ruby files is UTF-8.
+ def default_encoding
+ Encoding::UTF_8
+ end
+
+ def yyerror # :nodoc:
+ end
+
+ # Parses a source buffer and returns the AST.
+ def parse(source_buffer)
+ @source_buffer = source_buffer
+ source = source_buffer.source
+
+ offset_cache = build_offset_cache(source)
+ result = unwrap(Prism.parse(source, filepath: source_buffer.name, version: convert_for_prism(version), scopes: [[]]), offset_cache)
+
+ build_ast(result.value, offset_cache)
+ ensure
+ @source_buffer = nil
+ end
+
+ # Parses a source buffer and returns the AST and the source code comments.
+ def parse_with_comments(source_buffer)
+ @source_buffer = source_buffer
+ source = source_buffer.source
+
+ offset_cache = build_offset_cache(source)
+ result = unwrap(Prism.parse(source, filepath: source_buffer.name, version: convert_for_prism(version), scopes: [[]]), offset_cache)
+
+ [
+ build_ast(result.value, offset_cache),
+ build_comments(result.comments, offset_cache)
+ ]
+ ensure
+ @source_buffer = nil
+ end
+
+ # Parses a source buffer and returns the AST, the source code comments,
+ # and the tokens emitted by the lexer.
+ def tokenize(source_buffer, recover = false)
+ @source_buffer = source_buffer
+ source = source_buffer.source
+
+ offset_cache = build_offset_cache(source)
+ result =
+ begin
+ unwrap(Prism.parse_lex(source, filepath: source_buffer.name, version: convert_for_prism(version), scopes: [[]]), offset_cache)
+ rescue ::Parser::SyntaxError
+ raise if !recover
+ end
+
+ program, tokens = result.value
+ ast = build_ast(program, offset_cache) if result.success?
+
+ [
+ ast,
+ build_comments(result.comments, offset_cache),
+ build_tokens(tokens, offset_cache)
+ ]
+ ensure
+ @source_buffer = nil
+ end
+
+ # Since prism resolves num params for us, we don't need to support this
+ # kind of logic here.
+ def try_declare_numparam(node)
+ node.children[0].match?(/\A_[1-9]\z/)
+ end
+
+ private
+
+ # This is a hook to allow consumers to disable some errors if they don't
+ # want them to block creating the syntax tree.
+ def valid_error?(error)
+ true
+ end
+
+ # This is a hook to allow consumers to disable some warnings if they don't
+ # want them to block creating the syntax tree.
+ def valid_warning?(warning)
+ true
+ end
+
+ # Build a diagnostic from the given prism parse error.
+ def error_diagnostic(error, offset_cache)
+ location = error.location
+ diagnostic_location = build_range(location, offset_cache)
+
+ case error.type
+ when :argument_block_multi
+ Diagnostic.new(:error, :block_and_blockarg, {}, diagnostic_location, [])
+ when :argument_formal_constant
+ Diagnostic.new(:error, :argument_const, {}, diagnostic_location, [])
+ when :argument_formal_class
+ Diagnostic.new(:error, :argument_cvar, {}, diagnostic_location, [])
+ when :argument_formal_global
+ Diagnostic.new(:error, :argument_gvar, {}, diagnostic_location, [])
+ when :argument_formal_ivar
+ Diagnostic.new(:error, :argument_ivar, {}, diagnostic_location, [])
+ when :argument_no_forwarding_amp
+ Diagnostic.new(:error, :no_anonymous_blockarg, {}, diagnostic_location, [])
+ when :argument_no_forwarding_star
+ Diagnostic.new(:error, :no_anonymous_restarg, {}, diagnostic_location, [])
+ when :argument_no_forwarding_star_star
+ Diagnostic.new(:error, :no_anonymous_kwrestarg, {}, diagnostic_location, [])
+ when :begin_lonely_else
+ location = location.copy(length: 4)
+ diagnostic_location = build_range(location, offset_cache)
+ Diagnostic.new(:error, :useless_else, {}, diagnostic_location, [])
+ when :class_name, :module_name
+ Diagnostic.new(:error, :module_name_const, {}, diagnostic_location, [])
+ when :class_in_method
+ Diagnostic.new(:error, :class_in_def, {}, diagnostic_location, [])
+ when :def_endless_setter
+ Diagnostic.new(:error, :endless_setter, {}, diagnostic_location, [])
+ when :embdoc_term
+ Diagnostic.new(:error, :embedded_document, {}, diagnostic_location, [])
+ when :incomplete_variable_class, :incomplete_variable_class_3_3
+ location = location.copy(length: location.length + 1)
+ diagnostic_location = build_range(location, offset_cache)
+
+ Diagnostic.new(:error, :cvar_name, { name: location.slice }, diagnostic_location, [])
+ when :incomplete_variable_instance, :incomplete_variable_instance_3_3
+ location = location.copy(length: location.length + 1)
+ diagnostic_location = build_range(location, offset_cache)
+
+ Diagnostic.new(:error, :ivar_name, { name: location.slice }, diagnostic_location, [])
+ when :invalid_variable_global, :invalid_variable_global_3_3
+ Diagnostic.new(:error, :gvar_name, { name: location.slice }, diagnostic_location, [])
+ when :module_in_method
+ Diagnostic.new(:error, :module_in_def, {}, diagnostic_location, [])
+ when :numbered_parameter_ordinary
+ Diagnostic.new(:error, :ordinary_param_defined, {}, diagnostic_location, [])
+ when :numbered_parameter_outer_scope
+ Diagnostic.new(:error, :numparam_used_in_outer_scope, {}, diagnostic_location, [])
+ when :parameter_circular
+ Diagnostic.new(:error, :circular_argument_reference, { var_name: location.slice }, diagnostic_location, [])
+ when :parameter_name_repeat
+ Diagnostic.new(:error, :duplicate_argument, {}, diagnostic_location, [])
+ when :parameter_numbered_reserved
+ Diagnostic.new(:error, :reserved_for_numparam, { name: location.slice }, diagnostic_location, [])
+ when :regexp_unknown_options
+ Diagnostic.new(:error, :regexp_options, { options: location.slice[1..] }, diagnostic_location, [])
+ when :singleton_for_literals
+ Diagnostic.new(:error, :singleton_literal, {}, diagnostic_location, [])
+ when :string_literal_eof
+ Diagnostic.new(:error, :string_eof, {}, diagnostic_location, [])
+ when :unexpected_token_ignore
+ Diagnostic.new(:error, :unexpected_token, { token: location.slice }, diagnostic_location, [])
+ when :write_target_in_method
+ Diagnostic.new(:error, :dynamic_const, {}, diagnostic_location, [])
+ else
+ PrismDiagnostic.new(error.message, :error, error.type, diagnostic_location)
+ end
+ end
+
+ # Build a diagnostic from the given prism parse warning.
+ def warning_diagnostic(warning, offset_cache)
+ diagnostic_location = build_range(warning.location, offset_cache)
+
+ case warning.type
+ when :ambiguous_first_argument_plus
+ Diagnostic.new(:warning, :ambiguous_prefix, { prefix: "+" }, diagnostic_location, [])
+ when :ambiguous_first_argument_minus
+ Diagnostic.new(:warning, :ambiguous_prefix, { prefix: "-" }, diagnostic_location, [])
+ when :ambiguous_prefix_ampersand
+ Diagnostic.new(:warning, :ambiguous_prefix, { prefix: "&" }, diagnostic_location, [])
+ when :ambiguous_prefix_star
+ Diagnostic.new(:warning, :ambiguous_prefix, { prefix: "*" }, diagnostic_location, [])
+ when :ambiguous_prefix_star_star
+ Diagnostic.new(:warning, :ambiguous_prefix, { prefix: "**" }, diagnostic_location, [])
+ when :ambiguous_slash
+ Diagnostic.new(:warning, :ambiguous_regexp, {}, diagnostic_location, [])
+ when :dot_dot_dot_eol
+ Diagnostic.new(:warning, :triple_dot_at_eol, {}, diagnostic_location, [])
+ when :duplicated_hash_key
+ # skip, parser does this on its own
+ else
+ PrismDiagnostic.new(warning.message, :warning, warning.type, diagnostic_location)
+ end
+ end
+
+ # If there was a error generated during the parse, then raise an
+ # appropriate syntax error. Otherwise return the result.
+ def unwrap(result, offset_cache)
+ result.errors.each do |error|
+ next unless valid_error?(error)
+ diagnostics.process(error_diagnostic(error, offset_cache))
+ end
+
+ result.warnings.each do |warning|
+ next unless valid_warning?(warning)
+ diagnostic = warning_diagnostic(warning, offset_cache)
+ diagnostics.process(diagnostic) if diagnostic
+ end
+
+ result
+ end
+
+ # Prism deals with offsets in bytes, while the parser gem deals with
+ # offsets in characters. We need to handle this conversion in order to
+ # build the parser gem AST.
+ #
+ # If the bytesize of the source is the same as the length, then we can
+ # just use the offset directly. Otherwise, we build an array where the
+ # index is the byte offset and the value is the character offset.
+ def build_offset_cache(source)
+ if source.bytesize == source.length
+ -> (offset) { offset }
+ else
+ offset_cache = []
+ offset = 0
+
+ source.each_char do |char|
+ char.bytesize.times { offset_cache << offset }
+ offset += 1
+ end
+
+ offset_cache << offset
+ end
+ end
+
+ # Build the parser gem AST from the prism AST.
+ def build_ast(program, offset_cache)
+ program.accept(Compiler.new(self, offset_cache))
+ end
+
+ # Build the parser gem comments from the prism comments.
+ def build_comments(comments, offset_cache)
+ comments.map do |comment|
+ ::Parser::Source::Comment.new(build_range(comment.location, offset_cache))
+ end
+ end
+
+ # Build the parser gem tokens from the prism tokens.
+ def build_tokens(tokens, offset_cache)
+ Lexer.new(source_buffer, tokens, offset_cache).to_a
+ end
+
+ # Build a range from a prism location.
+ def build_range(location, offset_cache)
+ ::Parser::Source::Range.new(
+ source_buffer,
+ offset_cache[location.start_offset],
+ offset_cache[location.end_offset]
+ )
+ end
+
+ # Converts the version format handled by Parser to the format handled by Prism.
+ def convert_for_prism(version)
+ case version
+ when 33
+ "3.3.1"
+ when 34
+ "3.4.0"
+ else
+ "latest"
+ end
+ end
+
+ require_relative "parser/compiler"
+ require_relative "parser/lexer"
+
+ private_constant :Compiler
+ private_constant :Lexer
+ end
+ end
+end
diff --git a/lib/prism/translation/parser/compiler.rb b/lib/prism/translation/parser/compiler.rb
new file mode 100644
index 0000000000..48f3d4db5c
--- /dev/null
+++ b/lib/prism/translation/parser/compiler.rb
@@ -0,0 +1,2146 @@
+# frozen_string_literal: true
+
+module Prism
+ module Translation
+ class Parser
+ # A visitor that knows how to convert a prism syntax tree into the
+ # whitequark/parser gem's syntax tree.
+ class Compiler < ::Prism::Compiler
+ # Raised when the tree is malformed or there is a bug in the compiler.
+ class CompilationError < StandardError
+ end
+
+ # The Parser::Base instance that is being used to build the AST.
+ attr_reader :parser
+
+ # The Parser::Builders::Default instance that is being used to build the
+ # AST.
+ attr_reader :builder
+
+ # The Parser::Source::Buffer instance that is holding a reference to the
+ # source code.
+ attr_reader :source_buffer
+
+ # The offset cache that is used to map between byte and character
+ # offsets in the file.
+ attr_reader :offset_cache
+
+ # The types of values that can be forwarded in the current scope.
+ attr_reader :forwarding
+
+ # Whether or not the current node is in a destructure.
+ attr_reader :in_destructure
+
+ # Whether or not the current node is in a pattern.
+ attr_reader :in_pattern
+
+ # Initialize a new compiler with the given parser, offset cache, and
+ # options.
+ def initialize(parser, offset_cache, forwarding: [], in_destructure: false, in_pattern: false)
+ @parser = parser
+ @builder = parser.builder
+ @source_buffer = parser.source_buffer
+ @offset_cache = offset_cache
+
+ @forwarding = forwarding
+ @in_destructure = in_destructure
+ @in_pattern = in_pattern
+ end
+
+ # alias foo bar
+ # ^^^^^^^^^^^^^
+ def visit_alias_method_node(node)
+ builder.alias(token(node.keyword_loc), visit(node.new_name), visit(node.old_name))
+ end
+
+ # alias $foo $bar
+ # ^^^^^^^^^^^^^^^
+ def visit_alias_global_variable_node(node)
+ builder.alias(token(node.keyword_loc), visit(node.new_name), visit(node.old_name))
+ end
+
+ # foo => bar | baz
+ # ^^^^^^^^^
+ def visit_alternation_pattern_node(node)
+ builder.match_alt(visit(node.left), token(node.operator_loc), visit(node.right))
+ end
+
+ # a and b
+ # ^^^^^^^
+ def visit_and_node(node)
+ builder.logical_op(:and, visit(node.left), token(node.operator_loc), visit(node.right))
+ end
+
+ # []
+ # ^^
+ def visit_array_node(node)
+ builder.array(token(node.opening_loc), visit_all(node.elements), token(node.closing_loc))
+ end
+
+ # foo => [bar]
+ # ^^^^^
+ def visit_array_pattern_node(node)
+ elements = [*node.requireds]
+ elements << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode)
+ elements.concat(node.posts)
+ visited = visit_all(elements)
+
+ if node.rest.is_a?(ImplicitRestNode)
+ visited[-1] = builder.match_with_trailing_comma(visited[-1], token(node.rest.location))
+ end
+
+ if node.constant
+ if visited.empty?
+ builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.array_pattern(token(node.opening_loc), visited, token(node.closing_loc)), token(node.closing_loc))
+ else
+ builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.array_pattern(nil, visited, nil), token(node.closing_loc))
+ end
+ else
+ builder.array_pattern(token(node.opening_loc), visited, token(node.closing_loc))
+ end
+ end
+
+ # foo(bar)
+ # ^^^
+ def visit_arguments_node(node)
+ visit_all(node.arguments)
+ end
+
+ # { a: 1 }
+ # ^^^^
+ def visit_assoc_node(node)
+ key = node.key
+
+ if in_pattern
+ if node.value.is_a?(ImplicitNode)
+ if key.is_a?(SymbolNode)
+ if key.opening.nil?
+ builder.match_hash_var([key.unescaped, srange(key.location)])
+ else
+ builder.match_hash_var_from_str(token(key.opening_loc), [builder.string_internal([key.unescaped, srange(key.value_loc)])], token(key.closing_loc))
+ end
+ else
+ builder.match_hash_var_from_str(token(key.opening_loc), visit_all(key.parts), token(key.closing_loc))
+ end
+ elsif key.opening.nil?
+ builder.pair_keyword([key.unescaped, srange(key.location)], visit(node.value))
+ else
+ builder.pair_quoted(token(key.opening_loc), [builder.string_internal([key.unescaped, srange(key.value_loc)])], token(key.closing_loc), visit(node.value))
+ end
+ elsif node.value.is_a?(ImplicitNode)
+ if (value = node.value.value).is_a?(LocalVariableReadNode)
+ builder.pair_keyword(
+ [key.unescaped, srange(key)],
+ builder.ident([value.name, srange(key.value_loc)]).updated(:lvar)
+ )
+ else
+ builder.pair_label([key.unescaped, srange(key.location)])
+ end
+ elsif node.operator_loc
+ builder.pair(visit(key), token(node.operator_loc), visit(node.value))
+ elsif key.is_a?(SymbolNode) && key.opening_loc.nil?
+ builder.pair_keyword([key.unescaped, srange(key.location)], visit(node.value))
+ else
+ parts =
+ if key.is_a?(SymbolNode)
+ [builder.string_internal([key.unescaped, srange(key.value_loc)])]
+ else
+ visit_all(key.parts)
+ end
+
+ builder.pair_quoted(token(key.opening_loc), parts, token(key.closing_loc), visit(node.value))
+ end
+ end
+
+ # def foo(**); bar(**); end
+ # ^^
+ #
+ # { **foo }
+ # ^^^^^
+ def visit_assoc_splat_node(node)
+ if in_pattern
+ builder.match_rest(token(node.operator_loc), token(node.value&.location))
+ elsif node.value.nil? && forwarding.include?(:**)
+ builder.forwarded_kwrestarg(token(node.operator_loc))
+ else
+ builder.kwsplat(token(node.operator_loc), visit(node.value))
+ end
+ end
+
+ # $+
+ # ^^
+ def visit_back_reference_read_node(node)
+ builder.back_ref(token(node.location))
+ end
+
+ # begin end
+ # ^^^^^^^^^
+ def visit_begin_node(node)
+ rescue_bodies = []
+
+ if (rescue_clause = node.rescue_clause)
+ begin
+ find_start_offset = (rescue_clause.reference&.location || rescue_clause.exceptions.last&.location || rescue_clause.keyword_loc).end_offset
+ find_end_offset = (rescue_clause.statements&.location&.start_offset || rescue_clause.consequent&.location&.start_offset || (find_start_offset + 1))
+
+ rescue_bodies << builder.rescue_body(
+ token(rescue_clause.keyword_loc),
+ rescue_clause.exceptions.any? ? builder.array(nil, visit_all(rescue_clause.exceptions), nil) : nil,
+ token(rescue_clause.operator_loc),
+ visit(rescue_clause.reference),
+ srange_find(find_start_offset, find_end_offset, [";"]),
+ visit(rescue_clause.statements)
+ )
+ end until (rescue_clause = rescue_clause.consequent).nil?
+ end
+
+ begin_body =
+ builder.begin_body(
+ visit(node.statements),
+ rescue_bodies,
+ token(node.else_clause&.else_keyword_loc),
+ visit(node.else_clause),
+ token(node.ensure_clause&.ensure_keyword_loc),
+ visit(node.ensure_clause&.statements)
+ )
+
+ if node.begin_keyword_loc
+ builder.begin_keyword(token(node.begin_keyword_loc), begin_body, token(node.end_keyword_loc))
+ else
+ begin_body
+ end
+ end
+
+ # foo(&bar)
+ # ^^^^
+ def visit_block_argument_node(node)
+ builder.block_pass(token(node.operator_loc), visit(node.expression))
+ end
+
+ # foo { |; bar| }
+ # ^^^
+ def visit_block_local_variable_node(node)
+ builder.shadowarg(token(node.location))
+ end
+
+ # A block on a keyword or method call.
+ def visit_block_node(node)
+ raise CompilationError, "Cannot directly compile block nodes"
+ end
+
+ # def foo(&bar); end
+ # ^^^^
+ def visit_block_parameter_node(node)
+ builder.blockarg(token(node.operator_loc), token(node.name_loc))
+ end
+
+ # A block's parameters.
+ def visit_block_parameters_node(node)
+ [*visit(node.parameters)].concat(visit_all(node.locals))
+ end
+
+ # break
+ # ^^^^^
+ #
+ # break foo
+ # ^^^^^^^^^
+ def visit_break_node(node)
+ builder.keyword_cmd(:break, token(node.keyword_loc), nil, visit(node.arguments) || [], nil)
+ end
+
+ # foo
+ # ^^^
+ #
+ # foo.bar
+ # ^^^^^^^
+ #
+ # foo.bar() {}
+ # ^^^^^^^^^^^^
+ def visit_call_node(node)
+ name = node.name
+ arguments = node.arguments&.arguments || []
+ block = node.block
+
+ if block.is_a?(BlockArgumentNode)
+ arguments = [*arguments, block]
+ block = nil
+ end
+
+ if node.call_operator_loc.nil?
+ case name
+ when :-@
+ case (receiver = node.receiver).type
+ when :integer_node, :float_node, :rational_node, :imaginary_node
+ return visit(numeric_negate(node.message_loc, receiver))
+ end
+ when :!
+ return visit_block(builder.not_op(token(node.message_loc), token(node.opening_loc), visit(node.receiver), token(node.closing_loc)), block)
+ when :=~
+ if (receiver = node.receiver).is_a?(RegularExpressionNode)
+ return builder.match_op(visit(receiver), token(node.message_loc), visit(node.arguments.arguments.first))
+ end
+ when :[]
+ return visit_block(builder.index(visit(node.receiver), token(node.opening_loc), visit_all(arguments), token(node.closing_loc)), block)
+ when :[]=
+ if node.message != "[]=" && node.arguments && block.nil? && !node.safe_navigation?
+ arguments = node.arguments.arguments[...-1]
+ arguments << node.block if node.block
+
+ return visit_block(
+ builder.assign(
+ builder.index_asgn(
+ visit(node.receiver),
+ token(node.opening_loc),
+ visit_all(arguments),
+ token(node.closing_loc),
+ ),
+ srange_find(node.message_loc.end_offset, node.arguments.arguments.last.location.start_offset, ["="]),
+ visit(node.arguments.arguments.last)
+ ),
+ block
+ )
+ end
+ end
+ end
+
+ message_loc = node.message_loc
+ call_operator_loc = node.call_operator_loc
+ call_operator = [{ "." => :dot, "&." => :anddot, "::" => "::" }.fetch(call_operator_loc.slice), srange(call_operator_loc)] if call_operator_loc
+
+ visit_block(
+ if name.end_with?("=") && !message_loc.slice.end_with?("=") && node.arguments && block.nil?
+ builder.assign(
+ builder.attr_asgn(visit(node.receiver), call_operator, token(message_loc)),
+ srange_find(message_loc.end_offset, node.arguments.location.start_offset, ["="]),
+ visit(node.arguments.arguments.last)
+ )
+ else
+ builder.call_method(
+ visit(node.receiver),
+ call_operator,
+ message_loc ? [node.name, srange(message_loc)] : nil,
+ token(node.opening_loc),
+ visit_all(arguments),
+ token(node.closing_loc)
+ )
+ end,
+ block
+ )
+ end
+
+ # foo.bar += baz
+ # ^^^^^^^^^^^^^^^
+ def visit_call_operator_write_node(node)
+ call_operator_loc = node.call_operator_loc
+
+ builder.op_assign(
+ builder.call_method(
+ visit(node.receiver),
+ call_operator_loc.nil? ? nil : [{ "." => :dot, "&." => :anddot, "::" => "::" }.fetch(call_operator_loc.slice), srange(call_operator_loc)],
+ node.message_loc ? [node.read_name, srange(node.message_loc)] : nil,
+ nil,
+ [],
+ nil
+ ),
+ [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)],
+ visit(node.value)
+ )
+ end
+
+ # foo.bar &&= baz
+ # ^^^^^^^^^^^^^^^
+ def visit_call_and_write_node(node)
+ call_operator_loc = node.call_operator_loc
+
+ builder.op_assign(
+ builder.call_method(
+ visit(node.receiver),
+ call_operator_loc.nil? ? nil : [{ "." => :dot, "&." => :anddot, "::" => "::" }.fetch(call_operator_loc.slice), srange(call_operator_loc)],
+ node.message_loc ? [node.read_name, srange(node.message_loc)] : nil,
+ nil,
+ [],
+ nil
+ ),
+ [node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
+ visit(node.value)
+ )
+ end
+
+ # foo.bar ||= baz
+ # ^^^^^^^^^^^^^^^
+ def visit_call_or_write_node(node)
+ call_operator_loc = node.call_operator_loc
+
+ builder.op_assign(
+ builder.call_method(
+ visit(node.receiver),
+ call_operator_loc.nil? ? nil : [{ "." => :dot, "&." => :anddot, "::" => "::" }.fetch(call_operator_loc.slice), srange(call_operator_loc)],
+ node.message_loc ? [node.read_name, srange(node.message_loc)] : nil,
+ nil,
+ [],
+ nil
+ ),
+ [node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
+ visit(node.value)
+ )
+ end
+
+ # foo.bar, = 1
+ # ^^^^^^^
+ def visit_call_target_node(node)
+ call_operator_loc = node.call_operator_loc
+
+ builder.attr_asgn(
+ visit(node.receiver),
+ call_operator_loc.nil? ? nil : [{ "." => :dot, "&." => :anddot, "::" => "::" }.fetch(call_operator_loc.slice), srange(call_operator_loc)],
+ token(node.message_loc)
+ )
+ end
+
+ # foo => bar => baz
+ # ^^^^^^^^^^
+ def visit_capture_pattern_node(node)
+ builder.match_as(visit(node.value), token(node.operator_loc), visit(node.target))
+ end
+
+ # case foo; when bar; end
+ # ^^^^^^^^^^^^^^^^^^^^^^^
+ def visit_case_node(node)
+ builder.case(
+ token(node.case_keyword_loc),
+ visit(node.predicate),
+ visit_all(node.conditions),
+ token(node.consequent&.else_keyword_loc),
+ visit(node.consequent),
+ token(node.end_keyword_loc)
+ )
+ end
+
+ # case foo; in bar; end
+ # ^^^^^^^^^^^^^^^^^^^^^
+ def visit_case_match_node(node)
+ builder.case_match(
+ token(node.case_keyword_loc),
+ visit(node.predicate),
+ visit_all(node.conditions),
+ token(node.consequent&.else_keyword_loc),
+ visit(node.consequent),
+ token(node.end_keyword_loc)
+ )
+ end
+
+ # class Foo; end
+ # ^^^^^^^^^^^^^^
+ def visit_class_node(node)
+ builder.def_class(
+ token(node.class_keyword_loc),
+ visit(node.constant_path),
+ token(node.inheritance_operator_loc),
+ visit(node.superclass),
+ node.body&.accept(copy_compiler(forwarding: [])),
+ token(node.end_keyword_loc)
+ )
+ end
+
+ # @@foo
+ # ^^^^^
+ def visit_class_variable_read_node(node)
+ builder.cvar(token(node.location))
+ end
+
+ # @@foo = 1
+ # ^^^^^^^^^
+ def visit_class_variable_write_node(node)
+ builder.assign(
+ builder.assignable(builder.cvar(token(node.name_loc))),
+ token(node.operator_loc),
+ visit(node.value)
+ )
+ end
+
+ # @@foo += bar
+ # ^^^^^^^^^^^^
+ def visit_class_variable_operator_write_node(node)
+ builder.op_assign(
+ builder.assignable(builder.cvar(token(node.name_loc))),
+ [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)],
+ visit(node.value)
+ )
+ end
+
+ # @@foo &&= bar
+ # ^^^^^^^^^^^^^
+ def visit_class_variable_and_write_node(node)
+ builder.op_assign(
+ builder.assignable(builder.cvar(token(node.name_loc))),
+ [node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
+ visit(node.value)
+ )
+ end
+
+ # @@foo ||= bar
+ # ^^^^^^^^^^^^^
+ def visit_class_variable_or_write_node(node)
+ builder.op_assign(
+ builder.assignable(builder.cvar(token(node.name_loc))),
+ [node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
+ visit(node.value)
+ )
+ end
+
+ # @@foo, = bar
+ # ^^^^^
+ def visit_class_variable_target_node(node)
+ builder.assignable(builder.cvar(token(node.location)))
+ end
+
+ # Foo
+ # ^^^
+ def visit_constant_read_node(node)
+ builder.const([node.name, srange(node.location)])
+ end
+
+ # Foo = 1
+ # ^^^^^^^
+ #
+ # Foo, Bar = 1
+ # ^^^ ^^^
+ def visit_constant_write_node(node)
+ builder.assign(builder.assignable(builder.const([node.name, srange(node.name_loc)])), token(node.operator_loc), visit(node.value))
+ end
+
+ # Foo += bar
+ # ^^^^^^^^^^^
+ def visit_constant_operator_write_node(node)
+ builder.op_assign(
+ builder.assignable(builder.const([node.name, srange(node.name_loc)])),
+ [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)],
+ visit(node.value)
+ )
+ end
+
+ # Foo &&= bar
+ # ^^^^^^^^^^^^
+ def visit_constant_and_write_node(node)
+ builder.op_assign(
+ builder.assignable(builder.const([node.name, srange(node.name_loc)])),
+ [node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
+ visit(node.value)
+ )
+ end
+
+ # Foo ||= bar
+ # ^^^^^^^^^^^^
+ def visit_constant_or_write_node(node)
+ builder.op_assign(
+ builder.assignable(builder.const([node.name, srange(node.name_loc)])),
+ [node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
+ visit(node.value)
+ )
+ end
+
+ # Foo, = bar
+ # ^^^
+ def visit_constant_target_node(node)
+ builder.assignable(builder.const([node.name, srange(node.location)]))
+ end
+
+ # Foo::Bar
+ # ^^^^^^^^
+ def visit_constant_path_node(node)
+ if node.parent.nil?
+ builder.const_global(
+ token(node.delimiter_loc),
+ [node.name, srange(node.name_loc)]
+ )
+ else
+ builder.const_fetch(
+ visit(node.parent),
+ token(node.delimiter_loc),
+ [node.name, srange(node.name_loc)]
+ )
+ end
+ end
+
+ # Foo::Bar = 1
+ # ^^^^^^^^^^^^
+ #
+ # Foo::Foo, Bar::Bar = 1
+ # ^^^^^^^^ ^^^^^^^^
+ def visit_constant_path_write_node(node)
+ builder.assign(
+ builder.assignable(visit(node.target)),
+ token(node.operator_loc),
+ visit(node.value)
+ )
+ end
+
+ # Foo::Bar += baz
+ # ^^^^^^^^^^^^^^^
+ def visit_constant_path_operator_write_node(node)
+ builder.op_assign(
+ builder.assignable(visit(node.target)),
+ [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)],
+ visit(node.value)
+ )
+ end
+
+ # Foo::Bar &&= baz
+ # ^^^^^^^^^^^^^^^^
+ def visit_constant_path_and_write_node(node)
+ builder.op_assign(
+ builder.assignable(visit(node.target)),
+ [node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
+ visit(node.value)
+ )
+ end
+
+ # Foo::Bar ||= baz
+ # ^^^^^^^^^^^^^^^^
+ def visit_constant_path_or_write_node(node)
+ builder.op_assign(
+ builder.assignable(visit(node.target)),
+ [node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
+ visit(node.value)
+ )
+ end
+
+ # Foo::Bar, = baz
+ # ^^^^^^^^
+ def visit_constant_path_target_node(node)
+ builder.assignable(visit_constant_path_node(node))
+ end
+
+ # def foo; end
+ # ^^^^^^^^^^^^
+ #
+ # def self.foo; end
+ # ^^^^^^^^^^^^^^^^^
+ def visit_def_node(node)
+ if node.equal_loc
+ if node.receiver
+ builder.def_endless_singleton(
+ token(node.def_keyword_loc),
+ visit(node.receiver.is_a?(ParenthesesNode) ? node.receiver.body : node.receiver),
+ token(node.operator_loc),
+ token(node.name_loc),
+ builder.args(token(node.lparen_loc), visit(node.parameters) || [], token(node.rparen_loc), false),
+ token(node.equal_loc),
+ node.body&.accept(copy_compiler(forwarding: find_forwarding(node.parameters)))
+ )
+ else
+ builder.def_endless_method(
+ token(node.def_keyword_loc),
+ token(node.name_loc),
+ builder.args(token(node.lparen_loc), visit(node.parameters) || [], token(node.rparen_loc), false),
+ token(node.equal_loc),
+ node.body&.accept(copy_compiler(forwarding: find_forwarding(node.parameters)))
+ )
+ end
+ elsif node.receiver
+ builder.def_singleton(
+ token(node.def_keyword_loc),
+ visit(node.receiver.is_a?(ParenthesesNode) ? node.receiver.body : node.receiver),
+ token(node.operator_loc),
+ token(node.name_loc),
+ builder.args(token(node.lparen_loc), visit(node.parameters) || [], token(node.rparen_loc), false),
+ node.body&.accept(copy_compiler(forwarding: find_forwarding(node.parameters))),
+ token(node.end_keyword_loc)
+ )
+ else
+ builder.def_method(
+ token(node.def_keyword_loc),
+ token(node.name_loc),
+ builder.args(token(node.lparen_loc), visit(node.parameters) || [], token(node.rparen_loc), false),
+ node.body&.accept(copy_compiler(forwarding: find_forwarding(node.parameters))),
+ token(node.end_keyword_loc)
+ )
+ end
+ end
+
+ # defined? a
+ # ^^^^^^^^^^
+ #
+ # defined?(a)
+ # ^^^^^^^^^^^
+ def visit_defined_node(node)
+ builder.keyword_cmd(
+ :defined?,
+ token(node.keyword_loc),
+ token(node.lparen_loc),
+ [visit(node.value)],
+ token(node.rparen_loc)
+ )
+ end
+
+ # if foo then bar else baz end
+ # ^^^^^^^^^^^^
+ def visit_else_node(node)
+ visit(node.statements)
+ end
+
+ # "foo #{bar}"
+ # ^^^^^^
+ def visit_embedded_statements_node(node)
+ builder.begin(
+ token(node.opening_loc),
+ visit(node.statements),
+ token(node.closing_loc)
+ )
+ end
+
+ # "foo #@bar"
+ # ^^^^^
+ def visit_embedded_variable_node(node)
+ visit(node.variable)
+ end
+
+ # begin; foo; ensure; bar; end
+ # ^^^^^^^^^^^^
+ def visit_ensure_node(node)
+ raise CompilationError, "Cannot directly compile ensure nodes"
+ end
+
+ # false
+ # ^^^^^
+ def visit_false_node(node)
+ builder.false(token(node.location))
+ end
+
+ # foo => [*, bar, *]
+ # ^^^^^^^^^^^
+ def visit_find_pattern_node(node)
+ elements = [node.left, *node.requireds, node.right]
+
+ if node.constant
+ builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.find_pattern(nil, visit_all(elements), nil), token(node.closing_loc))
+ else
+ builder.find_pattern(token(node.opening_loc), visit_all(elements), token(node.closing_loc))
+ end
+ end
+
+ # 1.0
+ # ^^^
+ def visit_float_node(node)
+ visit_numeric(node, builder.float([node.value, srange(node.location)]))
+ end
+
+ # for foo in bar do end
+ # ^^^^^^^^^^^^^^^^^^^^^
+ def visit_for_node(node)
+ builder.for(
+ token(node.for_keyword_loc),
+ visit(node.index),
+ token(node.in_keyword_loc),
+ visit(node.collection),
+ if node.do_keyword_loc
+ token(node.do_keyword_loc)
+ else
+ srange_find(node.collection.location.end_offset, (node.statements&.location || node.end_keyword_loc).start_offset, [";"])
+ end,
+ visit(node.statements),
+ token(node.end_keyword_loc)
+ )
+ end
+
+ # def foo(...); bar(...); end
+ # ^^^
+ def visit_forwarding_arguments_node(node)
+ builder.forwarded_args(token(node.location))
+ end
+
+ # def foo(...); end
+ # ^^^
+ def visit_forwarding_parameter_node(node)
+ builder.forward_arg(token(node.location))
+ end
+
+ # super
+ # ^^^^^
+ #
+ # super {}
+ # ^^^^^^^^
+ def visit_forwarding_super_node(node)
+ visit_block(
+ builder.keyword_cmd(
+ :zsuper,
+ ["super", srange_offsets(node.location.start_offset, node.location.start_offset + 5)]
+ ),
+ node.block
+ )
+ end
+
+ # $foo
+ # ^^^^
+ def visit_global_variable_read_node(node)
+ builder.gvar(token(node.location))
+ end
+
+ # $foo = 1
+ # ^^^^^^^^
+ def visit_global_variable_write_node(node)
+ builder.assign(
+ builder.assignable(builder.gvar(token(node.name_loc))),
+ token(node.operator_loc),
+ visit(node.value)
+ )
+ end
+
+ # $foo += bar
+ # ^^^^^^^^^^^
+ def visit_global_variable_operator_write_node(node)
+ builder.op_assign(
+ builder.assignable(builder.gvar(token(node.name_loc))),
+ [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)],
+ visit(node.value)
+ )
+ end
+
+ # $foo &&= bar
+ # ^^^^^^^^^^^^
+ def visit_global_variable_and_write_node(node)
+ builder.op_assign(
+ builder.assignable(builder.gvar(token(node.name_loc))),
+ [node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
+ visit(node.value)
+ )
+ end
+
+ # $foo ||= bar
+ # ^^^^^^^^^^^^
+ def visit_global_variable_or_write_node(node)
+ builder.op_assign(
+ builder.assignable(builder.gvar(token(node.name_loc))),
+ [node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
+ visit(node.value)
+ )
+ end
+
+ # $foo, = bar
+ # ^^^^
+ def visit_global_variable_target_node(node)
+ builder.assignable(builder.gvar([node.slice, srange(node.location)]))
+ end
+
+ # {}
+ # ^^
+ def visit_hash_node(node)
+ builder.associate(
+ token(node.opening_loc),
+ visit_all(node.elements),
+ token(node.closing_loc)
+ )
+ end
+
+ # foo => {}
+ # ^^
+ def visit_hash_pattern_node(node)
+ elements = [*node.elements, *node.rest]
+
+ if node.constant
+ builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.hash_pattern(nil, visit_all(elements), nil), token(node.closing_loc))
+ else
+ builder.hash_pattern(token(node.opening_loc), visit_all(elements), token(node.closing_loc))
+ end
+ end
+
+ # if foo then bar end
+ # ^^^^^^^^^^^^^^^^^^^
+ #
+ # bar if foo
+ # ^^^^^^^^^^
+ #
+ # foo ? bar : baz
+ # ^^^^^^^^^^^^^^^
+ def visit_if_node(node)
+ if !node.if_keyword_loc
+ builder.ternary(
+ visit(node.predicate),
+ token(node.then_keyword_loc),
+ visit(node.statements),
+ token(node.consequent.else_keyword_loc),
+ visit(node.consequent)
+ )
+ elsif node.if_keyword_loc.start_offset == node.location.start_offset
+ builder.condition(
+ token(node.if_keyword_loc),
+ visit(node.predicate),
+ if node.then_keyword_loc
+ token(node.then_keyword_loc)
+ else
+ srange_find(node.predicate.location.end_offset, (node.statements&.location || node.consequent&.location || node.end_keyword_loc).start_offset, [";"])
+ end,
+ visit(node.statements),
+ case node.consequent
+ when IfNode
+ token(node.consequent.if_keyword_loc)
+ when ElseNode
+ token(node.consequent.else_keyword_loc)
+ end,
+ visit(node.consequent),
+ if node.if_keyword != "elsif"
+ token(node.end_keyword_loc)
+ end
+ )
+ else
+ builder.condition_mod(
+ visit(node.statements),
+ visit(node.consequent),
+ token(node.if_keyword_loc),
+ visit(node.predicate)
+ )
+ end
+ end
+
+ # 1i
+ # ^^
+ def visit_imaginary_node(node)
+ visit_numeric(node, builder.complex([Complex(0, node.numeric.value), srange(node.location)]))
+ end
+
+ # { foo: }
+ # ^^^^
+ def visit_implicit_node(node)
+ raise CompilationError, "Cannot directly compile implicit nodes"
+ end
+
+ # foo { |bar,| }
+ # ^
+ def visit_implicit_rest_node(node)
+ raise CompilationError, "Cannot compile implicit rest nodes"
+ end
+
+ # case foo; in bar; end
+ # ^^^^^^^^^^^^^^^^^^^^^
+ def visit_in_node(node)
+ pattern = nil
+ guard = nil
+
+ case node.pattern
+ when IfNode
+ pattern = within_pattern { |compiler| node.pattern.statements.accept(compiler) }
+ guard = builder.if_guard(token(node.pattern.if_keyword_loc), visit(node.pattern.predicate))
+ when UnlessNode
+ pattern = within_pattern { |compiler| node.pattern.statements.accept(compiler) }
+ guard = builder.unless_guard(token(node.pattern.keyword_loc), visit(node.pattern.predicate))
+ else
+ pattern = within_pattern { |compiler| node.pattern.accept(compiler) }
+ end
+
+ builder.in_pattern(
+ token(node.in_loc),
+ pattern,
+ guard,
+ srange_find(node.pattern.location.end_offset, node.statements&.location&.start_offset, [";", "then"]),
+ visit(node.statements)
+ )
+ end
+
+ # foo[bar] += baz
+ # ^^^^^^^^^^^^^^^
+ def visit_index_operator_write_node(node)
+ arguments = node.arguments&.arguments || []
+ arguments << node.block if node.block
+
+ builder.op_assign(
+ builder.index(
+ visit(node.receiver),
+ token(node.opening_loc),
+ visit_all(arguments),
+ token(node.closing_loc)
+ ),
+ [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)],
+ visit(node.value)
+ )
+ end
+
+ # foo[bar] &&= baz
+ # ^^^^^^^^^^^^^^^^
+ def visit_index_and_write_node(node)
+ arguments = node.arguments&.arguments || []
+ arguments << node.block if node.block
+
+ builder.op_assign(
+ builder.index(
+ visit(node.receiver),
+ token(node.opening_loc),
+ visit_all(arguments),
+ token(node.closing_loc)
+ ),
+ [node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
+ visit(node.value)
+ )
+ end
+
+ # foo[bar] ||= baz
+ # ^^^^^^^^^^^^^^^^
+ def visit_index_or_write_node(node)
+ arguments = node.arguments&.arguments || []
+ arguments << node.block if node.block
+
+ builder.op_assign(
+ builder.index(
+ visit(node.receiver),
+ token(node.opening_loc),
+ visit_all(arguments),
+ token(node.closing_loc)
+ ),
+ [node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
+ visit(node.value)
+ )
+ end
+
+ # foo[bar], = 1
+ # ^^^^^^^^
+ def visit_index_target_node(node)
+ builder.index_asgn(
+ visit(node.receiver),
+ token(node.opening_loc),
+ visit_all(node.arguments.arguments),
+ token(node.closing_loc),
+ )
+ end
+
+ # @foo
+ # ^^^^
+ def visit_instance_variable_read_node(node)
+ builder.ivar(token(node.location))
+ end
+
+ # @foo = 1
+ # ^^^^^^^^
+ def visit_instance_variable_write_node(node)
+ builder.assign(
+ builder.assignable(builder.ivar(token(node.name_loc))),
+ token(node.operator_loc),
+ visit(node.value)
+ )
+ end
+
+ # @foo += bar
+ # ^^^^^^^^^^^
+ def visit_instance_variable_operator_write_node(node)
+ builder.op_assign(
+ builder.assignable(builder.ivar(token(node.name_loc))),
+ [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)],
+ visit(node.value)
+ )
+ end
+
+ # @foo &&= bar
+ # ^^^^^^^^^^^^
+ def visit_instance_variable_and_write_node(node)
+ builder.op_assign(
+ builder.assignable(builder.ivar(token(node.name_loc))),
+ [node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
+ visit(node.value)
+ )
+ end
+
+ # @foo ||= bar
+ # ^^^^^^^^^^^^
+ def visit_instance_variable_or_write_node(node)
+ builder.op_assign(
+ builder.assignable(builder.ivar(token(node.name_loc))),
+ [node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
+ visit(node.value)
+ )
+ end
+
+ # @foo, = bar
+ # ^^^^
+ def visit_instance_variable_target_node(node)
+ builder.assignable(builder.ivar(token(node.location)))
+ end
+
+ # 1
+ # ^
+ def visit_integer_node(node)
+ visit_numeric(node, builder.integer([node.value, srange(node.location)]))
+ end
+
+ # /foo #{bar}/
+ # ^^^^^^^^^^^^
+ def visit_interpolated_regular_expression_node(node)
+ builder.regexp_compose(
+ token(node.opening_loc),
+ visit_all(node.parts),
+ [node.closing[0], srange_offsets(node.closing_loc.start_offset, node.closing_loc.start_offset + 1)],
+ builder.regexp_options([node.closing[1..], srange_offsets(node.closing_loc.start_offset + 1, node.closing_loc.end_offset)])
+ )
+ end
+
+ # if /foo #{bar}/ then end
+ # ^^^^^^^^^^^^
+ alias visit_interpolated_match_last_line_node visit_interpolated_regular_expression_node
+
+ # "foo #{bar}"
+ # ^^^^^^^^^^^^
+ def visit_interpolated_string_node(node)
+ if node.heredoc?
+ return visit_heredoc(node) { |children, closing| builder.string_compose(token(node.opening_loc), children, closing) }
+ end
+
+ parts = if node.parts.one? { |part| part.type == :string_node }
+ node.parts.flat_map do |node|
+ if node.type == :string_node && node.unescaped.lines.count >= 2
+ start_offset = node.content_loc.start_offset
+
+ node.unescaped.lines.map do |line|
+ end_offset = start_offset + line.length
+ offsets = srange_offsets(start_offset, end_offset)
+ start_offset = end_offset
+
+ builder.string_internal([line, offsets])
+ end
+ else
+ visit(node)
+ end
+ end
+ else
+ visit_all(node.parts)
+ end
+
+ builder.string_compose(
+ token(node.opening_loc),
+ parts,
+ token(node.closing_loc)
+ )
+ end
+
+ # :"foo #{bar}"
+ # ^^^^^^^^^^^^^
+ def visit_interpolated_symbol_node(node)
+ builder.symbol_compose(
+ token(node.opening_loc),
+ visit_all(node.parts),
+ token(node.closing_loc)
+ )
+ end
+
+ # `foo #{bar}`
+ # ^^^^^^^^^^^^
+ def visit_interpolated_x_string_node(node)
+ if node.heredoc?
+ visit_heredoc(node) { |children, closing| builder.xstring_compose(token(node.opening_loc), children, closing) }
+ else
+ builder.xstring_compose(
+ token(node.opening_loc),
+ visit_all(node.parts),
+ token(node.closing_loc)
+ )
+ end
+ end
+
+ # -> { it }
+ # ^^
+ def visit_it_local_variable_read_node(node)
+ builder.ident([:it, srange(node.location)]).updated(:lvar)
+ end
+
+ # -> { it }
+ # ^^^^^^^^^
+ def visit_it_parameters_node(node)
+ builder.args(nil, [], nil, false)
+ end
+
+ # foo(bar: baz)
+ # ^^^^^^^^
+ def visit_keyword_hash_node(node)
+ builder.associate(nil, visit_all(node.elements), nil)
+ end
+
+ # def foo(**bar); end
+ # ^^^^^
+ #
+ # def foo(**); end
+ # ^^
+ def visit_keyword_rest_parameter_node(node)
+ builder.kwrestarg(
+ token(node.operator_loc),
+ node.name ? [node.name, srange(node.name_loc)] : nil
+ )
+ end
+
+ # -> {}
+ # ^^^^^
+ def visit_lambda_node(node)
+ parameters = node.parameters
+ implicit_parameters = parameters.is_a?(NumberedParametersNode) || parameters.is_a?(ItParametersNode)
+
+ builder.block(
+ builder.call_lambda(token(node.operator_loc)),
+ [node.opening, srange(node.opening_loc)],
+ if parameters.nil?
+ builder.args(nil, [], nil, false)
+ elsif implicit_parameters
+ visit(node.parameters)
+ else
+ builder.args(
+ token(node.parameters.opening_loc),
+ visit(node.parameters),
+ token(node.parameters.closing_loc),
+ false
+ )
+ end,
+ node.body&.accept(copy_compiler(forwarding: implicit_parameters ? [] : find_forwarding(parameters&.parameters))),
+ [node.closing, srange(node.closing_loc)]
+ )
+ end
+
+ # foo
+ # ^^^
+ def visit_local_variable_read_node(node)
+ builder.ident([node.name, srange(node.location)]).updated(:lvar)
+ end
+
+ # foo = 1
+ # ^^^^^^^
+ def visit_local_variable_write_node(node)
+ builder.assign(
+ builder.assignable(builder.ident(token(node.name_loc))),
+ token(node.operator_loc),
+ visit(node.value)
+ )
+ end
+
+ # foo += bar
+ # ^^^^^^^^^^
+ def visit_local_variable_operator_write_node(node)
+ builder.op_assign(
+ builder.assignable(builder.ident(token(node.name_loc))),
+ [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)],
+ visit(node.value)
+ )
+ end
+
+ # foo &&= bar
+ # ^^^^^^^^^^^
+ def visit_local_variable_and_write_node(node)
+ builder.op_assign(
+ builder.assignable(builder.ident(token(node.name_loc))),
+ [node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
+ visit(node.value)
+ )
+ end
+
+ # foo ||= bar
+ # ^^^^^^^^^^^
+ def visit_local_variable_or_write_node(node)
+ builder.op_assign(
+ builder.assignable(builder.ident(token(node.name_loc))),
+ [node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
+ visit(node.value)
+ )
+ end
+
+ # foo, = bar
+ # ^^^
+ def visit_local_variable_target_node(node)
+ if in_pattern
+ builder.assignable(builder.match_var([node.name, srange(node.location)]))
+ else
+ builder.assignable(builder.ident(token(node.location)))
+ end
+ end
+
+ # foo in bar
+ # ^^^^^^^^^^
+ def visit_match_predicate_node(node)
+ builder.match_pattern_p(
+ visit(node.value),
+ token(node.operator_loc),
+ within_pattern { |compiler| node.pattern.accept(compiler) }
+ )
+ end
+
+ # foo => bar
+ # ^^^^^^^^^^
+ def visit_match_required_node(node)
+ builder.match_pattern(
+ visit(node.value),
+ token(node.operator_loc),
+ within_pattern { |compiler| node.pattern.accept(compiler) }
+ )
+ end
+
+ # /(?<foo>foo)/ =~ bar
+ # ^^^^^^^^^^^^^^^^^^^^
+ def visit_match_write_node(node)
+ builder.match_op(
+ visit(node.call.receiver),
+ token(node.call.message_loc),
+ visit(node.call.arguments.arguments.first)
+ )
+ end
+
+ # A node that is missing from the syntax tree. This is only used in the
+ # case of a syntax error. The parser gem doesn't have such a concept, so
+ # we invent our own here.
+ def visit_missing_node(node)
+ ::AST::Node.new(:missing, [], location: ::Parser::Source::Map.new(srange(node.location)))
+ end
+
+ # module Foo; end
+ # ^^^^^^^^^^^^^^^
+ def visit_module_node(node)
+ builder.def_module(
+ token(node.module_keyword_loc),
+ visit(node.constant_path),
+ node.body&.accept(copy_compiler(forwarding: [])),
+ token(node.end_keyword_loc)
+ )
+ end
+
+ # foo, bar = baz
+ # ^^^^^^^^
+ def visit_multi_target_node(node)
+ builder.multi_lhs(
+ token(node.lparen_loc),
+ visit_all(multi_target_elements(node)),
+ token(node.rparen_loc)
+ )
+ end
+
+ # foo, bar = baz
+ # ^^^^^^^^^^^^^^
+ def visit_multi_write_node(node)
+ elements = multi_target_elements(node)
+
+ if elements.length == 1 && elements.first.is_a?(MultiTargetNode)
+ elements = multi_target_elements(elements.first)
+ end
+
+ builder.multi_assign(
+ builder.multi_lhs(
+ token(node.lparen_loc),
+ visit_all(elements),
+ token(node.rparen_loc)
+ ),
+ token(node.operator_loc),
+ visit(node.value)
+ )
+ end
+
+ # next
+ # ^^^^
+ #
+ # next foo
+ # ^^^^^^^^
+ def visit_next_node(node)
+ builder.keyword_cmd(
+ :next,
+ token(node.keyword_loc),
+ nil,
+ visit(node.arguments) || [],
+ nil
+ )
+ end
+
+ # nil
+ # ^^^
+ def visit_nil_node(node)
+ builder.nil(token(node.location))
+ end
+
+ # def foo(**nil); end
+ # ^^^^^
+ def visit_no_keywords_parameter_node(node)
+ if in_pattern
+ builder.match_nil_pattern(token(node.operator_loc), token(node.keyword_loc))
+ else
+ builder.kwnilarg(token(node.operator_loc), token(node.keyword_loc))
+ end
+ end
+
+ # -> { _1 + _2 }
+ # ^^^^^^^^^^^^^^
+ def visit_numbered_parameters_node(node)
+ builder.numargs(node.maximum)
+ end
+
+ # $1
+ # ^^
+ def visit_numbered_reference_read_node(node)
+ builder.nth_ref([node.number, srange(node.location)])
+ end
+
+ # def foo(bar: baz); end
+ # ^^^^^^^^
+ def visit_optional_keyword_parameter_node(node)
+ builder.kwoptarg([node.name, srange(node.name_loc)], visit(node.value))
+ end
+
+ # def foo(bar = 1); end
+ # ^^^^^^^
+ def visit_optional_parameter_node(node)
+ builder.optarg(token(node.name_loc), token(node.operator_loc), visit(node.value))
+ end
+
+ # a or b
+ # ^^^^^^
+ def visit_or_node(node)
+ builder.logical_op(:or, visit(node.left), token(node.operator_loc), visit(node.right))
+ end
+
+ # def foo(bar, *baz); end
+ # ^^^^^^^^^
+ def visit_parameters_node(node)
+ params = []
+
+ if node.requireds.any?
+ node.requireds.each do |required|
+ params <<
+ if required.is_a?(RequiredParameterNode)
+ visit(required)
+ else
+ required.accept(copy_compiler(in_destructure: true))
+ end
+ end
+ end
+
+ params.concat(visit_all(node.optionals)) if node.optionals.any?
+ params << visit(node.rest) if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode)
+
+ if node.posts.any?
+ node.posts.each do |post|
+ params <<
+ if post.is_a?(RequiredParameterNode)
+ visit(post)
+ else
+ post.accept(copy_compiler(in_destructure: true))
+ end
+ end
+ end
+
+ params.concat(visit_all(node.keywords)) if node.keywords.any?
+ params << visit(node.keyword_rest) if !node.keyword_rest.nil?
+ params << visit(node.block) if !node.block.nil?
+ params
+ end
+
+ # ()
+ # ^^
+ #
+ # (1)
+ # ^^^
+ def visit_parentheses_node(node)
+ builder.begin(
+ token(node.opening_loc),
+ visit(node.body),
+ token(node.closing_loc)
+ )
+ end
+
+ # foo => ^(bar)
+ # ^^^^^^
+ def visit_pinned_expression_node(node)
+ expression = builder.begin(token(node.lparen_loc), visit(node.expression), token(node.rparen_loc))
+ builder.pin(token(node.operator_loc), expression)
+ end
+
+ # foo = 1 and bar => ^foo
+ # ^^^^
+ def visit_pinned_variable_node(node)
+ builder.pin(token(node.operator_loc), visit(node.variable))
+ end
+
+ # END {}
+ def visit_post_execution_node(node)
+ builder.postexe(
+ token(node.keyword_loc),
+ token(node.opening_loc),
+ visit(node.statements),
+ token(node.closing_loc)
+ )
+ end
+
+ # BEGIN {}
+ def visit_pre_execution_node(node)
+ builder.preexe(
+ token(node.keyword_loc),
+ token(node.opening_loc),
+ visit(node.statements),
+ token(node.closing_loc)
+ )
+ end
+
+ # The top-level program node.
+ def visit_program_node(node)
+ visit(node.statements)
+ end
+
+ # 0..5
+ # ^^^^
+ def visit_range_node(node)
+ if node.exclude_end?
+ builder.range_exclusive(
+ visit(node.left),
+ token(node.operator_loc),
+ visit(node.right)
+ )
+ else
+ builder.range_inclusive(
+ visit(node.left),
+ token(node.operator_loc),
+ visit(node.right)
+ )
+ end
+ end
+
+ # if foo .. bar; end
+ # ^^^^^^^^^^
+ alias visit_flip_flop_node visit_range_node
+
+ # 1r
+ # ^^
+ def visit_rational_node(node)
+ visit_numeric(node, builder.rational([node.value, srange(node.location)]))
+ end
+
+ # redo
+ # ^^^^
+ def visit_redo_node(node)
+ builder.keyword_cmd(:redo, token(node.location))
+ end
+
+ # /foo/
+ # ^^^^^
+ def visit_regular_expression_node(node)
+ content = node.content
+ parts =
+ if content.include?("\n")
+ offset = node.content_loc.start_offset
+ content.lines.map do |line|
+ builder.string_internal([line, srange_offsets(offset, offset += line.bytesize)])
+ end
+ else
+ [builder.string_internal(token(node.content_loc))]
+ end
+
+ builder.regexp_compose(
+ token(node.opening_loc),
+ parts,
+ [node.closing[0], srange_offsets(node.closing_loc.start_offset, node.closing_loc.start_offset + 1)],
+ builder.regexp_options([node.closing[1..], srange_offsets(node.closing_loc.start_offset + 1, node.closing_loc.end_offset)])
+ )
+ end
+
+ # if /foo/ then end
+ # ^^^^^
+ alias visit_match_last_line_node visit_regular_expression_node
+
+ # def foo(bar:); end
+ # ^^^^
+ def visit_required_keyword_parameter_node(node)
+ builder.kwarg([node.name, srange(node.name_loc)])
+ end
+
+ # def foo(bar); end
+ # ^^^
+ def visit_required_parameter_node(node)
+ builder.arg(token(node.location))
+ end
+
+ # foo rescue bar
+ # ^^^^^^^^^^^^^^
+ def visit_rescue_modifier_node(node)
+ builder.begin_body(
+ visit(node.expression),
+ [
+ builder.rescue_body(
+ token(node.keyword_loc),
+ nil,
+ nil,
+ nil,
+ nil,
+ visit(node.rescue_expression)
+ )
+ ]
+ )
+ end
+
+ # begin; rescue; end
+ # ^^^^^^^
+ def visit_rescue_node(node)
+ raise CompilationError, "Cannot directly compile rescue nodes"
+ end
+
+ # def foo(*bar); end
+ # ^^^^
+ #
+ # def foo(*); end
+ # ^
+ def visit_rest_parameter_node(node)
+ builder.restarg(token(node.operator_loc), token(node.name_loc))
+ end
+
+ # retry
+ # ^^^^^
+ def visit_retry_node(node)
+ builder.keyword_cmd(:retry, token(node.location))
+ end
+
+ # return
+ # ^^^^^^
+ #
+ # return 1
+ # ^^^^^^^^
+ def visit_return_node(node)
+ builder.keyword_cmd(
+ :return,
+ token(node.keyword_loc),
+ nil,
+ visit(node.arguments) || [],
+ nil
+ )
+ end
+
+ # self
+ # ^^^^
+ def visit_self_node(node)
+ builder.self(token(node.location))
+ end
+
+ # A shareable constant.
+ def visit_shareable_constant_node(node)
+ visit(node.write)
+ end
+
+ # class << self; end
+ # ^^^^^^^^^^^^^^^^^^
+ def visit_singleton_class_node(node)
+ builder.def_sclass(
+ token(node.class_keyword_loc),
+ token(node.operator_loc),
+ visit(node.expression),
+ node.body&.accept(copy_compiler(forwarding: [])),
+ token(node.end_keyword_loc)
+ )
+ end
+
+ # __ENCODING__
+ # ^^^^^^^^^^^^
+ def visit_source_encoding_node(node)
+ builder.accessible(builder.__ENCODING__(token(node.location)))
+ end
+
+ # __FILE__
+ # ^^^^^^^^
+ def visit_source_file_node(node)
+ builder.accessible(builder.__FILE__(token(node.location)))
+ end
+
+ # __LINE__
+ # ^^^^^^^^
+ def visit_source_line_node(node)
+ builder.accessible(builder.__LINE__(token(node.location)))
+ end
+
+ # foo(*bar)
+ # ^^^^
+ #
+ # def foo((bar, *baz)); end
+ # ^^^^
+ #
+ # def foo(*); bar(*); end
+ # ^
+ def visit_splat_node(node)
+ if node.expression.nil? && forwarding.include?(:*)
+ builder.forwarded_restarg(token(node.operator_loc))
+ elsif in_destructure
+ builder.restarg(token(node.operator_loc), token(node.expression&.location))
+ elsif in_pattern
+ builder.match_rest(token(node.operator_loc), token(node.expression&.location))
+ else
+ builder.splat(token(node.operator_loc), visit(node.expression))
+ end
+ end
+
+ # A list of statements.
+ def visit_statements_node(node)
+ builder.compstmt(visit_all(node.body))
+ end
+
+ # "foo"
+ # ^^^^^
+ def visit_string_node(node)
+ if node.heredoc?
+ visit_heredoc(node.to_interpolated) { |children, closing| builder.string_compose(token(node.opening_loc), children, closing) }
+ elsif node.opening == "?"
+ builder.character([node.unescaped, srange(node.location)])
+ elsif node.opening&.start_with?("%") && node.unescaped.empty?
+ builder.string_compose(token(node.opening_loc), [], token(node.closing_loc))
+ else
+ content_lines = node.content.lines
+ unescaped_lines = node.unescaped.lines
+
+ parts =
+ if content_lines.length <= 1 || unescaped_lines.length <= 1
+ [builder.string_internal([node.unescaped, srange(node.content_loc)])]
+ elsif content_lines.length != unescaped_lines.length
+ # This occurs when we have line continuations in the string. We
+ # need to come back and fix this, but for now this stops the
+ # code from breaking when we encounter it because of trying to
+ # transpose arrays of different lengths.
+ [builder.string_internal([node.unescaped, srange(node.content_loc)])]
+ else
+ start_offset = node.content_loc.start_offset
+
+ [content_lines, unescaped_lines].transpose.map do |content_line, unescaped_line|
+ end_offset = start_offset + content_line.length
+ offsets = srange_offsets(start_offset, end_offset)
+ start_offset = end_offset
+
+ builder.string_internal([unescaped_line, offsets])
+ end
+ end
+
+ builder.string_compose(
+ token(node.opening_loc),
+ parts,
+ token(node.closing_loc)
+ )
+ end
+ end
+
+ # super(foo)
+ # ^^^^^^^^^^
+ def visit_super_node(node)
+ arguments = node.arguments&.arguments || []
+ block = node.block
+
+ if block.is_a?(BlockArgumentNode)
+ arguments = [*arguments, block]
+ block = nil
+ end
+
+ visit_block(
+ builder.keyword_cmd(
+ :super,
+ token(node.keyword_loc),
+ token(node.lparen_loc),
+ visit_all(arguments),
+ token(node.rparen_loc)
+ ),
+ block
+ )
+ end
+
+ # :foo
+ # ^^^^
+ def visit_symbol_node(node)
+ if node.closing_loc.nil?
+ if node.opening_loc.nil?
+ builder.symbol_internal([node.unescaped, srange(node.location)])
+ else
+ builder.symbol([node.unescaped, srange(node.location)])
+ end
+ else
+ parts = if node.value.lines.one?
+ [builder.string_internal([node.unescaped, srange(node.value_loc)])]
+ else
+ start_offset = node.value_loc.start_offset
+
+ node.value.lines.map do |line|
+ end_offset = start_offset + line.length
+ offsets = srange_offsets(start_offset, end_offset)
+ start_offset = end_offset
+
+ builder.string_internal([line, offsets])
+ end
+ end
+
+ builder.symbol_compose(
+ token(node.opening_loc),
+ parts,
+ token(node.closing_loc)
+ )
+ end
+ end
+
+ # true
+ # ^^^^
+ def visit_true_node(node)
+ builder.true(token(node.location))
+ end
+
+ # undef foo
+ # ^^^^^^^^^
+ def visit_undef_node(node)
+ builder.undef_method(token(node.keyword_loc), visit_all(node.names))
+ end
+
+ # unless foo; bar end
+ # ^^^^^^^^^^^^^^^^^^^
+ #
+ # bar unless foo
+ # ^^^^^^^^^^^^^^
+ def visit_unless_node(node)
+ if node.keyword_loc.start_offset == node.location.start_offset
+ builder.condition(
+ token(node.keyword_loc),
+ visit(node.predicate),
+ if node.then_keyword_loc
+ token(node.then_keyword_loc)
+ else
+ srange_find(node.predicate.location.end_offset, (node.statements&.location || node.consequent&.location || node.end_keyword_loc).start_offset, [";"])
+ end,
+ visit(node.consequent),
+ token(node.consequent&.else_keyword_loc),
+ visit(node.statements),
+ token(node.end_keyword_loc)
+ )
+ else
+ builder.condition_mod(
+ visit(node.consequent),
+ visit(node.statements),
+ token(node.keyword_loc),
+ visit(node.predicate)
+ )
+ end
+ end
+
+ # until foo; bar end
+ # ^^^^^^^^^^^^^^^^^^
+ #
+ # bar until foo
+ # ^^^^^^^^^^^^^
+ def visit_until_node(node)
+ if node.location.start_offset == node.keyword_loc.start_offset
+ builder.loop(
+ :until,
+ token(node.keyword_loc),
+ visit(node.predicate),
+ srange_find(node.predicate.location.end_offset, (node.statements&.location || node.closing_loc).start_offset, [";", "do"]),
+ visit(node.statements),
+ token(node.closing_loc)
+ )
+ else
+ builder.loop_mod(
+ :until,
+ visit(node.statements),
+ token(node.keyword_loc),
+ visit(node.predicate)
+ )
+ end
+ end
+
+ # case foo; when bar; end
+ # ^^^^^^^^^^^^^
+ def visit_when_node(node)
+ builder.when(
+ token(node.keyword_loc),
+ visit_all(node.conditions),
+ if node.then_keyword_loc
+ token(node.then_keyword_loc)
+ else
+ srange_find(node.conditions.last.location.end_offset, node.statements&.location&.start_offset, [";"])
+ end,
+ visit(node.statements)
+ )
+ end
+
+ # while foo; bar end
+ # ^^^^^^^^^^^^^^^^^^
+ #
+ # bar while foo
+ # ^^^^^^^^^^^^^
+ def visit_while_node(node)
+ if node.location.start_offset == node.keyword_loc.start_offset
+ builder.loop(
+ :while,
+ token(node.keyword_loc),
+ visit(node.predicate),
+ srange_find(node.predicate.location.end_offset, (node.statements&.location || node.closing_loc).start_offset, [";", "do"]),
+ visit(node.statements),
+ token(node.closing_loc)
+ )
+ else
+ builder.loop_mod(
+ :while,
+ visit(node.statements),
+ token(node.keyword_loc),
+ visit(node.predicate)
+ )
+ end
+ end
+
+ # `foo`
+ # ^^^^^
+ def visit_x_string_node(node)
+ if node.heredoc?
+ visit_heredoc(node.to_interpolated) { |children, closing| builder.xstring_compose(token(node.opening_loc), children, closing) }
+ else
+ parts = if node.unescaped.lines.one?
+ [builder.string_internal([node.unescaped, srange(node.content_loc)])]
+ else
+ start_offset = node.content_loc.start_offset
+
+ node.unescaped.lines.map do |line|
+ end_offset = start_offset + line.length
+ offsets = srange_offsets(start_offset, end_offset)
+ start_offset = end_offset
+
+ builder.string_internal([line, offsets])
+ end
+ end
+
+ builder.xstring_compose(
+ token(node.opening_loc),
+ parts,
+ token(node.closing_loc)
+ )
+ end
+ end
+
+ # yield
+ # ^^^^^
+ #
+ # yield 1
+ # ^^^^^^^
+ def visit_yield_node(node)
+ builder.keyword_cmd(
+ :yield,
+ token(node.keyword_loc),
+ token(node.lparen_loc),
+ visit(node.arguments) || [],
+ token(node.rparen_loc)
+ )
+ end
+
+ private
+
+ # Initialize a new compiler with the given option overrides, used to
+ # visit a subtree with the given options.
+ def copy_compiler(forwarding: self.forwarding, in_destructure: self.in_destructure, in_pattern: self.in_pattern)
+ Compiler.new(parser, offset_cache, forwarding: forwarding, in_destructure: in_destructure, in_pattern: in_pattern)
+ end
+
+ # When *, **, &, or ... are used as an argument in a method call, we
+ # check if they were allowed by the current context. To determine that
+ # we build this lookup table.
+ def find_forwarding(node)
+ return [] if node.nil?
+
+ forwarding = []
+ forwarding << :* if node.rest.is_a?(RestParameterNode) && node.rest.name.nil?
+ forwarding << :** if node.keyword_rest.is_a?(KeywordRestParameterNode) && node.keyword_rest.name.nil?
+ forwarding << :& if !node.block.nil? && node.block.name.nil?
+ forwarding |= [:&, :"..."] if node.keyword_rest.is_a?(ForwardingParameterNode)
+
+ forwarding
+ end
+
+ # Returns the set of targets for a MultiTargetNode or a MultiWriteNode.
+ def multi_target_elements(node)
+ elements = [*node.lefts]
+ elements << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode)
+ elements.concat(node.rights)
+ elements
+ end
+
+ # Negate the value of a numeric node. This is a special case where you
+ # have a negative sign on one line and then a number on the next line.
+ # In normal Ruby, this will always be a method call. The parser gem,
+ # however, marks this as a numeric literal. We have to massage the tree
+ # here to get it into the correct form.
+ def numeric_negate(message_loc, receiver)
+ case receiver.type
+ when :integer_node, :float_node
+ receiver.copy(value: -receiver.value, location: message_loc.join(receiver.location))
+ when :rational_node
+ receiver.copy(numerator: -receiver.numerator, location: message_loc.join(receiver.location))
+ when :imaginary_node
+ receiver.copy(numeric: numeric_negate(message_loc, receiver.numeric), location: message_loc.join(receiver.location))
+ end
+ end
+
+ # Blocks can have a special set of parameters that automatically expand
+ # when given arrays if they have a single required parameter and no
+ # other parameters.
+ def procarg0?(parameters)
+ parameters &&
+ parameters.requireds.length == 1 &&
+ parameters.optionals.empty? &&
+ parameters.rest.nil? &&
+ parameters.posts.empty? &&
+ parameters.keywords.empty? &&
+ parameters.keyword_rest.nil? &&
+ parameters.block.nil?
+ end
+
+ # Locations in the parser gem AST are generated using this class. We
+ # store a reference to its constant to make it slightly faster to look
+ # up.
+ Range = ::Parser::Source::Range
+
+ # Constructs a new source range from the given start and end offsets.
+ def srange(location)
+ Range.new(source_buffer, offset_cache[location.start_offset], offset_cache[location.end_offset]) if location
+ end
+
+ # Constructs a new source range from the given start and end offsets.
+ def srange_offsets(start_offset, end_offset)
+ Range.new(source_buffer, offset_cache[start_offset], offset_cache[end_offset])
+ end
+
+ # Constructs a new source range by finding the given tokens between the
+ # given start offset and end offset. If the needle is not found, it
+ # returns nil. Importantly it does not search past newlines or comments.
+ #
+ # Note that end_offset is allowed to be nil, in which case this will
+ # search until the end of the string.
+ def srange_find(start_offset, end_offset, tokens)
+ if (match = source_buffer.source.byteslice(start_offset...end_offset).match(/\A(\s*)(#{tokens.join("|")})/))
+ _, whitespace, token = *match
+ token_offset = start_offset + whitespace.bytesize
+
+ [token, Range.new(source_buffer, offset_cache[token_offset], offset_cache[token_offset + token.bytesize])]
+ end
+ end
+
+ # Transform a location into a token that the parser gem expects.
+ def token(location)
+ [location.slice, Range.new(source_buffer, offset_cache[location.start_offset], offset_cache[location.end_offset])] if location
+ end
+
+ # Visit a block node on a call.
+ def visit_block(call, block)
+ if block
+ parameters = block.parameters
+ implicit_parameters = parameters.is_a?(NumberedParametersNode) || parameters.is_a?(ItParametersNode)
+
+ builder.block(
+ call,
+ token(block.opening_loc),
+ if parameters.nil?
+ builder.args(nil, [], nil, false)
+ elsif implicit_parameters
+ visit(parameters)
+ else
+ builder.args(
+ token(parameters.opening_loc),
+ if procarg0?(parameters.parameters)
+ parameter = parameters.parameters.requireds.first
+ visited = parameter.is_a?(RequiredParameterNode) ? visit(parameter) : parameter.accept(copy_compiler(in_destructure: true))
+ [builder.procarg0(visited)].concat(visit_all(parameters.locals))
+ else
+ visit(parameters)
+ end,
+ token(parameters.closing_loc),
+ false
+ )
+ end,
+ block.body&.accept(copy_compiler(forwarding: implicit_parameters ? [] : find_forwarding(parameters&.parameters))),
+ token(block.closing_loc)
+ )
+ else
+ call
+ end
+ end
+
+ # The parser gem automatically converts \r\n to \n, meaning our offsets
+ # need to be adjusted to always subtract 1 from the length.
+ def chomped_bytesize(line)
+ chomped = line.chomp
+ chomped.bytesize + (chomped == line ? 0 : 1)
+ end
+
+ # Visit a heredoc that can be either a string or an xstring.
+ def visit_heredoc(node)
+ children = Array.new
+ indented = false
+
+ # If this is a dedenting heredoc, then we need to insert the opening
+ # content into the children as well.
+ if node.opening.start_with?("<<~") && node.parts.length > 0 && !node.parts.first.is_a?(StringNode)
+ location = node.parts.first.location
+ location = location.copy(start_offset: location.start_offset - location.start_line_slice.bytesize)
+ children << builder.string_internal(token(location))
+ indented = true
+ end
+
+ node.parts.each do |part|
+ pushing =
+ if part.is_a?(StringNode) && part.unescaped.include?("\n")
+ unescaped = part.unescaped.lines
+ escaped = part.content.lines
+
+ escaped_lengths = []
+ normalized_lengths = []
+
+ if node.opening.end_with?("'")
+ escaped.each do |line|
+ escaped_lengths << line.bytesize
+ normalized_lengths << chomped_bytesize(line)
+ end
+ else
+ escaped
+ .chunk_while { |before, after| before.match?(/(?<!\\)\\\r?\n$/) }
+ .each do |lines|
+ escaped_lengths << lines.sum(&:bytesize)
+ normalized_lengths << lines.sum { |line| chomped_bytesize(line) }
+ end
+ end
+
+ start_offset = part.location.start_offset
+
+ unescaped.map.with_index do |unescaped_line, index|
+ inner_part = builder.string_internal([unescaped_line, srange_offsets(start_offset, start_offset + normalized_lengths.fetch(index, 0))])
+ start_offset += escaped_lengths.fetch(index, 0)
+ inner_part
+ end
+ else
+ [visit(part)]
+ end
+
+ pushing.each do |child|
+ if child.type == :str && child.children.last == ""
+ # nothing
+ elsif child.type == :str && children.last && children.last.type == :str && !children.last.children.first.end_with?("\n")
+ appendee = children[-1]
+
+ location = appendee.loc
+ location = location.with_expression(location.expression.join(child.loc.expression))
+
+ children[-1] = appendee.updated(:str, [appendee.children.first << child.children.first], location: location)
+ else
+ children << child
+ end
+ end
+ end
+
+ closing = node.closing
+ closing_t = [closing.chomp, srange_offsets(node.closing_loc.start_offset, node.closing_loc.end_offset - (closing[/\s+$/]&.length || 0))]
+ composed = yield children, closing_t
+
+ composed = composed.updated(nil, children[1..-1]) if indented
+ composed
+ end
+
+ # Visit a numeric node and account for the optional sign.
+ def visit_numeric(node, value)
+ if (slice = node.slice).match?(/^[+-]/)
+ builder.unary_num(
+ [slice[0].to_sym, srange_offsets(node.location.start_offset, node.location.start_offset + 1)],
+ value
+ )
+ else
+ value
+ end
+ end
+
+ # Within the given block, track that we're within a pattern.
+ def within_pattern
+ begin
+ parser.pattern_variables.push
+ yield copy_compiler(in_pattern: true)
+ ensure
+ parser.pattern_variables.pop
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/prism/translation/parser/lexer.rb b/lib/prism/translation/parser/lexer.rb
new file mode 100644
index 0000000000..9d7caae0ba
--- /dev/null
+++ b/lib/prism/translation/parser/lexer.rb
@@ -0,0 +1,416 @@
+# frozen_string_literal: true
+
+module Prism
+ module Translation
+ class Parser
+ # Accepts a list of prism tokens and converts them into the expected
+ # format for the parser gem.
+ class Lexer
+ # The direct translating of types between the two lexers.
+ TYPES = {
+ # These tokens should never appear in the output of the lexer.
+ EOF: nil,
+ MISSING: nil,
+ NOT_PROVIDED: nil,
+ IGNORED_NEWLINE: nil,
+ EMBDOC_END: nil,
+ EMBDOC_LINE: nil,
+ __END__: nil,
+
+ # These tokens have more or less direct mappings.
+ AMPERSAND: :tAMPER2,
+ AMPERSAND_AMPERSAND: :tANDOP,
+ AMPERSAND_AMPERSAND_EQUAL: :tOP_ASGN,
+ AMPERSAND_DOT: :tANDDOT,
+ AMPERSAND_EQUAL: :tOP_ASGN,
+ BACK_REFERENCE: :tBACK_REF,
+ BACKTICK: :tXSTRING_BEG,
+ BANG: :tBANG,
+ BANG_EQUAL: :tNEQ,
+ BANG_TILDE: :tNMATCH,
+ BRACE_LEFT: :tLCURLY,
+ BRACE_RIGHT: :tRCURLY,
+ BRACKET_LEFT: :tLBRACK2,
+ BRACKET_LEFT_ARRAY: :tLBRACK,
+ BRACKET_LEFT_RIGHT: :tAREF,
+ BRACKET_LEFT_RIGHT_EQUAL: :tASET,
+ BRACKET_RIGHT: :tRBRACK,
+ CARET: :tCARET,
+ CARET_EQUAL: :tOP_ASGN,
+ CHARACTER_LITERAL: :tCHARACTER,
+ CLASS_VARIABLE: :tCVAR,
+ COLON: :tCOLON,
+ COLON_COLON: :tCOLON2,
+ COMMA: :tCOMMA,
+ COMMENT: :tCOMMENT,
+ CONSTANT: :tCONSTANT,
+ DOT: :tDOT,
+ DOT_DOT: :tDOT2,
+ DOT_DOT_DOT: :tDOT3,
+ EMBDOC_BEGIN: :tCOMMENT,
+ EMBEXPR_BEGIN: :tSTRING_DBEG,
+ EMBEXPR_END: :tSTRING_DEND,
+ EMBVAR: :tSTRING_DVAR,
+ EQUAL: :tEQL,
+ EQUAL_EQUAL: :tEQ,
+ EQUAL_EQUAL_EQUAL: :tEQQ,
+ EQUAL_GREATER: :tASSOC,
+ EQUAL_TILDE: :tMATCH,
+ FLOAT: :tFLOAT,
+ FLOAT_IMAGINARY: :tIMAGINARY,
+ FLOAT_RATIONAL: :tRATIONAL,
+ FLOAT_RATIONAL_IMAGINARY: :tIMAGINARY,
+ GLOBAL_VARIABLE: :tGVAR,
+ GREATER: :tGT,
+ GREATER_EQUAL: :tGEQ,
+ GREATER_GREATER: :tRSHFT,
+ GREATER_GREATER_EQUAL: :tOP_ASGN,
+ HEREDOC_START: :tSTRING_BEG,
+ HEREDOC_END: :tSTRING_END,
+ IDENTIFIER: :tIDENTIFIER,
+ INSTANCE_VARIABLE: :tIVAR,
+ INTEGER: :tINTEGER,
+ INTEGER_IMAGINARY: :tIMAGINARY,
+ INTEGER_RATIONAL: :tRATIONAL,
+ INTEGER_RATIONAL_IMAGINARY: :tIMAGINARY,
+ KEYWORD_ALIAS: :kALIAS,
+ KEYWORD_AND: :kAND,
+ KEYWORD_BEGIN: :kBEGIN,
+ KEYWORD_BEGIN_UPCASE: :klBEGIN,
+ KEYWORD_BREAK: :kBREAK,
+ KEYWORD_CASE: :kCASE,
+ KEYWORD_CLASS: :kCLASS,
+ KEYWORD_DEF: :kDEF,
+ KEYWORD_DEFINED: :kDEFINED,
+ KEYWORD_DO: :kDO,
+ KEYWORD_DO_LOOP: :kDO_COND,
+ KEYWORD_END: :kEND,
+ KEYWORD_END_UPCASE: :klEND,
+ KEYWORD_ENSURE: :kENSURE,
+ KEYWORD_ELSE: :kELSE,
+ KEYWORD_ELSIF: :kELSIF,
+ KEYWORD_FALSE: :kFALSE,
+ KEYWORD_FOR: :kFOR,
+ KEYWORD_IF: :kIF,
+ KEYWORD_IF_MODIFIER: :kIF_MOD,
+ KEYWORD_IN: :kIN,
+ KEYWORD_MODULE: :kMODULE,
+ KEYWORD_NEXT: :kNEXT,
+ KEYWORD_NIL: :kNIL,
+ KEYWORD_NOT: :kNOT,
+ KEYWORD_OR: :kOR,
+ KEYWORD_REDO: :kREDO,
+ KEYWORD_RESCUE: :kRESCUE,
+ KEYWORD_RESCUE_MODIFIER: :kRESCUE_MOD,
+ KEYWORD_RETRY: :kRETRY,
+ KEYWORD_RETURN: :kRETURN,
+ KEYWORD_SELF: :kSELF,
+ KEYWORD_SUPER: :kSUPER,
+ KEYWORD_THEN: :kTHEN,
+ KEYWORD_TRUE: :kTRUE,
+ KEYWORD_UNDEF: :kUNDEF,
+ KEYWORD_UNLESS: :kUNLESS,
+ KEYWORD_UNLESS_MODIFIER: :kUNLESS_MOD,
+ KEYWORD_UNTIL: :kUNTIL,
+ KEYWORD_UNTIL_MODIFIER: :kUNTIL_MOD,
+ KEYWORD_WHEN: :kWHEN,
+ KEYWORD_WHILE: :kWHILE,
+ KEYWORD_WHILE_MODIFIER: :kWHILE_MOD,
+ KEYWORD_YIELD: :kYIELD,
+ KEYWORD___ENCODING__: :k__ENCODING__,
+ KEYWORD___FILE__: :k__FILE__,
+ KEYWORD___LINE__: :k__LINE__,
+ LABEL: :tLABEL,
+ LABEL_END: :tLABEL_END,
+ LAMBDA_BEGIN: :tLAMBEG,
+ LESS: :tLT,
+ LESS_EQUAL: :tLEQ,
+ LESS_EQUAL_GREATER: :tCMP,
+ LESS_LESS: :tLSHFT,
+ LESS_LESS_EQUAL: :tOP_ASGN,
+ METHOD_NAME: :tFID,
+ MINUS: :tMINUS,
+ MINUS_EQUAL: :tOP_ASGN,
+ MINUS_GREATER: :tLAMBDA,
+ NEWLINE: :tNL,
+ NUMBERED_REFERENCE: :tNTH_REF,
+ PARENTHESIS_LEFT: :tLPAREN,
+ PARENTHESIS_LEFT_PARENTHESES: :tLPAREN_ARG,
+ PARENTHESIS_RIGHT: :tRPAREN,
+ PERCENT: :tPERCENT,
+ PERCENT_EQUAL: :tOP_ASGN,
+ PERCENT_LOWER_I: :tQSYMBOLS_BEG,
+ PERCENT_LOWER_W: :tQWORDS_BEG,
+ PERCENT_UPPER_I: :tSYMBOLS_BEG,
+ PERCENT_UPPER_W: :tWORDS_BEG,
+ PERCENT_LOWER_X: :tXSTRING_BEG,
+ PLUS: :tPLUS,
+ PLUS_EQUAL: :tOP_ASGN,
+ PIPE_EQUAL: :tOP_ASGN,
+ PIPE: :tPIPE,
+ PIPE_PIPE: :tOROP,
+ PIPE_PIPE_EQUAL: :tOP_ASGN,
+ QUESTION_MARK: :tEH,
+ REGEXP_BEGIN: :tREGEXP_BEG,
+ REGEXP_END: :tSTRING_END,
+ SEMICOLON: :tSEMI,
+ SLASH: :tDIVIDE,
+ SLASH_EQUAL: :tOP_ASGN,
+ STAR: :tSTAR2,
+ STAR_EQUAL: :tOP_ASGN,
+ STAR_STAR: :tPOW,
+ STAR_STAR_EQUAL: :tOP_ASGN,
+ STRING_BEGIN: :tSTRING_BEG,
+ STRING_CONTENT: :tSTRING_CONTENT,
+ STRING_END: :tSTRING_END,
+ SYMBOL_BEGIN: :tSYMBEG,
+ TILDE: :tTILDE,
+ UAMPERSAND: :tAMPER,
+ UCOLON_COLON: :tCOLON3,
+ UDOT_DOT: :tBDOT2,
+ UDOT_DOT_DOT: :tBDOT3,
+ UMINUS: :tUMINUS,
+ UMINUS_NUM: :tUNARY_NUM,
+ UPLUS: :tUPLUS,
+ USTAR: :tSTAR,
+ USTAR_STAR: :tPOW,
+ WORDS_SEP: :tSPACE
+ }
+
+ # These constants represent flags in our lex state. We really, really
+ # don't want to be using them and we really, really don't want to be
+ # exposing them as part of our public API. Unfortunately, we don't have
+ # another way of matching the exact tokens that the parser gem expects
+ # without them. We should find another way to do this, but in the
+ # meantime we'll hide them from the documentation and mark them as
+ # private constants.
+ EXPR_BEG = 0x1 # :nodoc:
+ EXPR_LABEL = 0x400 # :nodoc:
+
+ private_constant :TYPES, :EXPR_BEG, :EXPR_LABEL
+
+ # The Parser::Source::Buffer that the tokens were lexed from.
+ attr_reader :source_buffer
+
+ # An array of tuples that contain prism tokens and their associated lex
+ # state when they were lexed.
+ attr_reader :lexed
+
+ # A hash that maps offsets in bytes to offsets in characters.
+ attr_reader :offset_cache
+
+ # Initialize the lexer with the given source buffer, prism tokens, and
+ # offset cache.
+ def initialize(source_buffer, lexed, offset_cache)
+ @source_buffer = source_buffer
+ @lexed = lexed
+ @offset_cache = offset_cache
+ end
+
+ Range = ::Parser::Source::Range # :nodoc:
+ private_constant :Range
+
+ # Convert the prism tokens into the expected format for the parser gem.
+ def to_a
+ tokens = []
+
+ index = 0
+ length = lexed.length
+
+ heredoc_identifier_stack = []
+
+ while index < length
+ token, state = lexed[index]
+ index += 1
+ next if %i[IGNORED_NEWLINE __END__ EOF].include?(token.type)
+
+ type = TYPES.fetch(token.type)
+ value = token.value
+ location = Range.new(source_buffer, offset_cache[token.location.start_offset], offset_cache[token.location.end_offset])
+
+ case type
+ when :tCHARACTER
+ value.delete_prefix!("?")
+ when :tCOMMENT
+ if token.type == :EMBDOC_BEGIN
+ start_index = index
+
+ while !((next_token = lexed[index][0]) && next_token.type == :EMBDOC_END) && (index < length - 1)
+ value += next_token.value
+ index += 1
+ end
+
+ if start_index != index
+ value += next_token.value
+ location = Range.new(source_buffer, offset_cache[token.location.start_offset], offset_cache[lexed[index][0].location.end_offset])
+ index += 1
+ end
+ else
+ value.chomp!
+ location = Range.new(source_buffer, offset_cache[token.location.start_offset], offset_cache[token.location.end_offset - 1])
+ end
+ when :tNL
+ value = nil
+ when :tFLOAT
+ value = parse_float(value)
+ when :tIMAGINARY
+ value = parse_complex(value)
+ when :tINTEGER
+ if value.start_with?("+")
+ tokens << [:tUNARY_NUM, ["+", Range.new(source_buffer, offset_cache[token.location.start_offset], offset_cache[token.location.start_offset + 1])]]
+ location = Range.new(source_buffer, offset_cache[token.location.start_offset + 1], offset_cache[token.location.end_offset])
+ end
+
+ value = parse_integer(value)
+ when :tLABEL
+ value.chomp!(":")
+ when :tLABEL_END
+ value.chomp!(":")
+ when :tLCURLY
+ type = :tLBRACE if state == EXPR_BEG | EXPR_LABEL
+ when :tNTH_REF
+ value = parse_integer(value.delete_prefix("$"))
+ when :tOP_ASGN
+ value.chomp!("=")
+ when :tRATIONAL
+ value = parse_rational(value)
+ when :tSPACE
+ value = nil
+ when :tSTRING_BEG
+ if token.type == :HEREDOC_START
+ heredoc_identifier_stack.push(value.match(/<<[-~]?["'`]?(?<heredoc_identifier>.*?)["'`]?\z/)[:heredoc_identifier])
+ end
+ if ["\"", "'"].include?(value) && (next_token = lexed[index][0]) && next_token.type == :STRING_END
+ next_location = token.location.join(next_token.location)
+ type = :tSTRING
+ value = ""
+ location = Range.new(source_buffer, offset_cache[next_location.start_offset], offset_cache[next_location.end_offset])
+ index += 1
+ elsif ["\"", "'"].include?(value) && (next_token = lexed[index][0]) && next_token.type == :STRING_CONTENT && next_token.value.lines.count <= 1 && (next_next_token = lexed[index + 1][0]) && next_next_token.type == :STRING_END
+ next_location = token.location.join(next_next_token.location)
+ type = :tSTRING
+ value = next_token.value.gsub("\\\\", "\\")
+ location = Range.new(source_buffer, offset_cache[next_location.start_offset], offset_cache[next_location.end_offset])
+ index += 2
+ elsif value.start_with?("<<")
+ quote = value[2] == "-" || value[2] == "~" ? value[3] : value[2]
+ if quote == "`"
+ type = :tXSTRING_BEG
+ value = "<<`"
+ else
+ value = "<<#{quote == "'" || quote == "\"" ? quote : "\""}"
+ end
+ end
+ when :tSTRING_CONTENT
+ unless (lines = token.value.lines).one?
+ start_offset = offset_cache[token.location.start_offset]
+ lines.map do |line|
+ newline = line.end_with?("\r\n") ? "\r\n" : "\n"
+ chomped_line = line.chomp
+ if match = chomped_line.match(/(?<backslashes>\\+)\z/)
+ adjustment = match[:backslashes].size / 2
+ adjusted_line = chomped_line.delete_suffix("\\" * adjustment)
+ if match[:backslashes].size.odd?
+ adjusted_line.delete_suffix!("\\")
+ adjustment += 2
+ else
+ adjusted_line << newline
+ end
+ else
+ adjusted_line = line
+ adjustment = 0
+ end
+
+ end_offset = start_offset + adjusted_line.length + adjustment
+ tokens << [:tSTRING_CONTENT, [adjusted_line, Range.new(source_buffer, offset_cache[start_offset], offset_cache[end_offset])]]
+ start_offset = end_offset
+ end
+ next
+ end
+ when :tSTRING_DVAR
+ value = nil
+ when :tSTRING_END
+ if token.type == :HEREDOC_END && value.end_with?("\n")
+ newline_length = value.end_with?("\r\n") ? 2 : 1
+ value = heredoc_identifier_stack.pop
+ location = Range.new(source_buffer, offset_cache[token.location.start_offset], offset_cache[token.location.end_offset - newline_length])
+ elsif token.type == :REGEXP_END
+ value = value[0]
+ location = Range.new(source_buffer, offset_cache[token.location.start_offset], offset_cache[token.location.start_offset + 1])
+ end
+ when :tSYMBEG
+ if (next_token = lexed[index][0]) && next_token.type != :STRING_CONTENT && next_token.type != :EMBEXPR_BEGIN && next_token.type != :EMBVAR
+ next_location = token.location.join(next_token.location)
+ type = :tSYMBOL
+ value = next_token.value
+ value = { "~@" => "~", "!@" => "!" }.fetch(value, value)
+ location = Range.new(source_buffer, offset_cache[next_location.start_offset], offset_cache[next_location.end_offset])
+ index += 1
+ end
+ when :tFID
+ if !tokens.empty? && tokens.dig(-1, 0) == :kDEF
+ type = :tIDENTIFIER
+ end
+ when :tXSTRING_BEG
+ if (next_token = lexed[index][0]) && next_token.type != :STRING_CONTENT && next_token.type != :STRING_END
+ type = :tBACK_REF2
+ end
+ end
+
+ tokens << [type, [value, location]]
+
+ if token.type == :REGEXP_END
+ tokens << [:tREGEXP_OPT, [token.value[1..], Range.new(source_buffer, offset_cache[token.location.start_offset + 1], offset_cache[token.location.end_offset])]]
+ end
+ end
+
+ tokens
+ end
+
+ private
+
+ # Parse an integer from the string representation.
+ def parse_integer(value)
+ Integer(value)
+ rescue ArgumentError
+ 0
+ end
+
+ # Parse a float from the string representation.
+ def parse_float(value)
+ Float(value)
+ rescue ArgumentError
+ 0.0
+ end
+
+ # Parse a complex from the string representation.
+ def parse_complex(value)
+ value.chomp!("i")
+
+ if value.end_with?("r")
+ Complex(0, parse_rational(value))
+ elsif value.start_with?(/0[BbOoDdXx]/)
+ Complex(0, parse_integer(value))
+ else
+ Complex(0, value)
+ end
+ rescue ArgumentError
+ 0i
+ end
+
+ # Parse a rational from the string representation.
+ def parse_rational(value)
+ value.chomp!("r")
+
+ if value.start_with?(/0[BbOoDdXx]/)
+ Rational(parse_integer(value))
+ else
+ Rational(value)
+ end
+ rescue ArgumentError
+ 0r
+ end
+ end
+ end
+ end
+end
diff --git a/lib/prism/translation/parser/rubocop.rb b/lib/prism/translation/parser/rubocop.rb
new file mode 100644
index 0000000000..6c9687a5cc
--- /dev/null
+++ b/lib/prism/translation/parser/rubocop.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+# typed: ignore
+
+warn "WARN: Prism is directly supported since RuboCop 1.62. The `prism/translation/parser/rubocop` file is deprecated."
+
+require "parser"
+require "rubocop"
+
+require_relative "../../prism"
+require_relative "../parser"
+
+module Prism
+ module Translation
+ class Parser
+ # This is the special version numbers that should be used in RuboCop
+ # configuration files to trigger using prism.
+
+ # For Ruby 3.3
+ VERSION_3_3 = 80_82_73_83_77.33
+
+ # For Ruby 3.4
+ VERSION_3_4 = 80_82_73_83_77.34
+
+ # This module gets prepended into RuboCop::AST::ProcessedSource.
+ module ProcessedSource
+ # This condition is compatible with rubocop-ast versions up to 1.30.0.
+ if RuboCop::AST::ProcessedSource.instance_method(:parser_class).arity == 1
+ # Redefine parser_class so that we can inject the prism parser into the
+ # list of known parsers.
+ def parser_class(ruby_version)
+ if ruby_version == Prism::Translation::Parser::VERSION_3_3
+ warn "WARN: Setting `TargetRubyVersion: 80_82_73_83_77.33` is deprecated. " \
+ "Set to `ParserEngine: parser_prism` and `TargetRubyVersion: 3.3` instead."
+ require_relative "../parser33"
+ Prism::Translation::Parser33
+ elsif ruby_version == Prism::Translation::Parser::VERSION_3_4
+ warn "WARN: Setting `TargetRubyVersion: 80_82_73_83_77.34` is deprecated. " \
+ "Set to `ParserEngine: parser_prism` and `TargetRubyVersion: 3.4` instead."
+ require_relative "../parser34"
+ Prism::Translation::Parser34
+ else
+ super
+ end
+ end
+ else
+ # Redefine parser_class so that we can inject the prism parser into the
+ # list of known parsers.
+ def parser_class(ruby_version, _parser_engine)
+ if ruby_version == Prism::Translation::Parser::VERSION_3_3
+ warn "WARN: Setting `TargetRubyVersion: 80_82_73_83_77.33` is deprecated. " \
+ "Set to `ParserEngine: parser_prism` and `TargetRubyVersion: 3.3` instead."
+ require_relative "../parser33"
+ Prism::Translation::Parser33
+ elsif ruby_version == Prism::Translation::Parser::VERSION_3_4
+ warn "WARN: Setting `TargetRubyVersion: 80_82_73_83_77.34` is deprecated. " \
+ "Set to `ParserEngine: parser_prism` and `TargetRubyVersion: 3.4` instead."
+ require_relative "../parser34"
+ Prism::Translation::Parser34
+ else
+ super
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+# :stopdoc:
+RuboCop::AST::ProcessedSource.prepend(Prism::Translation::Parser::ProcessedSource)
+known_rubies = RuboCop::TargetRuby.const_get(:KNOWN_RUBIES)
+RuboCop::TargetRuby.send(:remove_const, :KNOWN_RUBIES)
+RuboCop::TargetRuby::KNOWN_RUBIES = [*known_rubies, Prism::Translation::Parser::VERSION_3_3].freeze
diff --git a/lib/prism/translation/parser33.rb b/lib/prism/translation/parser33.rb
new file mode 100644
index 0000000000..b09266e06a
--- /dev/null
+++ b/lib/prism/translation/parser33.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Prism
+ module Translation
+ # This class is the entry-point for Ruby 3.3 of `Prism::Translation::Parser`.
+ class Parser33 < Parser
+ def version # :nodoc:
+ 33
+ end
+ end
+ end
+end
diff --git a/lib/prism/translation/parser34.rb b/lib/prism/translation/parser34.rb
new file mode 100644
index 0000000000..0ead70ad3c
--- /dev/null
+++ b/lib/prism/translation/parser34.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Prism
+ module Translation
+ # This class is the entry-point for Ruby 3.4 of `Prism::Translation::Parser`.
+ class Parser34 < Parser
+ def version # :nodoc:
+ 34
+ end
+ end
+ end
+end
diff --git a/lib/prism/translation/ripper.rb b/lib/prism/translation/ripper.rb
new file mode 100644
index 0000000000..79ba0e7ab3
--- /dev/null
+++ b/lib/prism/translation/ripper.rb
@@ -0,0 +1,3452 @@
+# frozen_string_literal: true
+
+require "ripper"
+
+module Prism
+ module Translation
+ # This class provides a compatibility layer between prism and Ripper. It
+ # functions by parsing the entire tree first and then walking it and
+ # executing each of the Ripper callbacks as it goes. To use this class, you
+ # treat `Prism::Translation::Ripper` effectively as you would treat the
+ # `Ripper` class.
+ #
+ # Note that this class will serve the most common use cases, but Ripper's
+ # API is extensive and undocumented. It relies on reporting the state of the
+ # parser at any given time. We do our best to replicate that here, but
+ # because it is a different architecture it is not possible to perfectly
+ # replicate the behavior of Ripper.
+ #
+ # The main known difference is that we may omit dispatching some events in
+ # some cases. This impacts the following events:
+ #
+ # - on_assign_error
+ # - on_comma
+ # - on_ignored_nl
+ # - on_ignored_sp
+ # - on_kw
+ # - on_label_end
+ # - on_lbrace
+ # - on_lbracket
+ # - on_lparen
+ # - on_nl
+ # - on_op
+ # - on_operator_ambiguous
+ # - on_rbrace
+ # - on_rbracket
+ # - on_rparen
+ # - on_semicolon
+ # - on_sp
+ # - on_symbeg
+ # - on_tstring_beg
+ # - on_tstring_end
+ #
+ class Ripper < Compiler
+ # Parses the given Ruby program read from +src+.
+ # +src+ must be a String or an IO or a object with a #gets method.
+ def self.parse(src, filename = "(ripper)", lineno = 1)
+ new(src, filename, lineno).parse
+ end
+
+ # Tokenizes the Ruby program and returns an array of an array,
+ # which is formatted like
+ # <code>[[lineno, column], type, token, state]</code>.
+ # The +filename+ argument is mostly ignored.
+ # By default, this method does not handle syntax errors in +src+,
+ # use the +raise_errors+ keyword to raise a SyntaxError for an error in +src+.
+ #
+ # require "ripper"
+ # require "pp"
+ #
+ # pp Ripper.lex("def m(a) nil end")
+ # #=> [[[1, 0], :on_kw, "def", FNAME ],
+ # [[1, 3], :on_sp, " ", FNAME ],
+ # [[1, 4], :on_ident, "m", ENDFN ],
+ # [[1, 5], :on_lparen, "(", BEG|LABEL],
+ # [[1, 6], :on_ident, "a", ARG ],
+ # [[1, 7], :on_rparen, ")", ENDFN ],
+ # [[1, 8], :on_sp, " ", BEG ],
+ # [[1, 9], :on_kw, "nil", END ],
+ # [[1, 12], :on_sp, " ", END ],
+ # [[1, 13], :on_kw, "end", END ]]
+ #
+ def self.lex(src, filename = "-", lineno = 1, raise_errors: false)
+ result = Prism.lex_compat(src, filepath: filename, line: lineno)
+
+ if result.failure? && raise_errors
+ raise SyntaxError, result.errors.first.message
+ else
+ result.value
+ end
+ end
+
+ # This contains a table of all of the parser events and their
+ # corresponding arity.
+ PARSER_EVENT_TABLE = {
+ BEGIN: 1,
+ END: 1,
+ alias: 2,
+ alias_error: 2,
+ aref: 2,
+ aref_field: 2,
+ arg_ambiguous: 1,
+ arg_paren: 1,
+ args_add: 2,
+ args_add_block: 2,
+ args_add_star: 2,
+ args_forward: 0,
+ args_new: 0,
+ array: 1,
+ aryptn: 4,
+ assign: 2,
+ assign_error: 2,
+ assoc_new: 2,
+ assoc_splat: 1,
+ assoclist_from_args: 1,
+ bare_assoc_hash: 1,
+ begin: 1,
+ binary: 3,
+ block_var: 2,
+ blockarg: 1,
+ bodystmt: 4,
+ brace_block: 2,
+ break: 1,
+ call: 3,
+ case: 2,
+ class: 3,
+ class_name_error: 2,
+ command: 2,
+ command_call: 4,
+ const_path_field: 2,
+ const_path_ref: 2,
+ const_ref: 1,
+ def: 3,
+ defined: 1,
+ defs: 5,
+ do_block: 2,
+ dot2: 2,
+ dot3: 2,
+ dyna_symbol: 1,
+ else: 1,
+ elsif: 3,
+ ensure: 1,
+ excessed_comma: 0,
+ fcall: 1,
+ field: 3,
+ fndptn: 4,
+ for: 3,
+ hash: 1,
+ heredoc_dedent: 2,
+ hshptn: 3,
+ if: 3,
+ if_mod: 2,
+ ifop: 3,
+ in: 3,
+ kwrest_param: 1,
+ lambda: 2,
+ magic_comment: 2,
+ massign: 2,
+ method_add_arg: 2,
+ method_add_block: 2,
+ mlhs_add: 2,
+ mlhs_add_post: 2,
+ mlhs_add_star: 2,
+ mlhs_new: 0,
+ mlhs_paren: 1,
+ module: 2,
+ mrhs_add: 2,
+ mrhs_add_star: 2,
+ mrhs_new: 0,
+ mrhs_new_from_args: 1,
+ next: 1,
+ nokw_param: 1,
+ opassign: 3,
+ operator_ambiguous: 2,
+ param_error: 2,
+ params: 7,
+ paren: 1,
+ parse_error: 1,
+ program: 1,
+ qsymbols_add: 2,
+ qsymbols_new: 0,
+ qwords_add: 2,
+ qwords_new: 0,
+ redo: 0,
+ regexp_add: 2,
+ regexp_literal: 2,
+ regexp_new: 0,
+ rescue: 4,
+ rescue_mod: 2,
+ rest_param: 1,
+ retry: 0,
+ return: 1,
+ return0: 0,
+ sclass: 2,
+ stmts_add: 2,
+ stmts_new: 0,
+ string_add: 2,
+ string_concat: 2,
+ string_content: 0,
+ string_dvar: 1,
+ string_embexpr: 1,
+ string_literal: 1,
+ super: 1,
+ symbol: 1,
+ symbol_literal: 1,
+ symbols_add: 2,
+ symbols_new: 0,
+ top_const_field: 1,
+ top_const_ref: 1,
+ unary: 2,
+ undef: 1,
+ unless: 3,
+ unless_mod: 2,
+ until: 2,
+ until_mod: 2,
+ var_alias: 2,
+ var_field: 1,
+ var_ref: 1,
+ vcall: 1,
+ void_stmt: 0,
+ when: 3,
+ while: 2,
+ while_mod: 2,
+ word_add: 2,
+ word_new: 0,
+ words_add: 2,
+ words_new: 0,
+ xstring_add: 2,
+ xstring_literal: 1,
+ xstring_new: 0,
+ yield: 1,
+ yield0: 0,
+ zsuper: 0
+ }
+
+ # This contains a table of all of the scanner events and their
+ # corresponding arity.
+ SCANNER_EVENT_TABLE = {
+ CHAR: 1,
+ __end__: 1,
+ backref: 1,
+ backtick: 1,
+ comma: 1,
+ comment: 1,
+ const: 1,
+ cvar: 1,
+ embdoc: 1,
+ embdoc_beg: 1,
+ embdoc_end: 1,
+ embexpr_beg: 1,
+ embexpr_end: 1,
+ embvar: 1,
+ float: 1,
+ gvar: 1,
+ heredoc_beg: 1,
+ heredoc_end: 1,
+ ident: 1,
+ ignored_nl: 1,
+ imaginary: 1,
+ int: 1,
+ ivar: 1,
+ kw: 1,
+ label: 1,
+ label_end: 1,
+ lbrace: 1,
+ lbracket: 1,
+ lparen: 1,
+ nl: 1,
+ op: 1,
+ period: 1,
+ qsymbols_beg: 1,
+ qwords_beg: 1,
+ rational: 1,
+ rbrace: 1,
+ rbracket: 1,
+ regexp_beg: 1,
+ regexp_end: 1,
+ rparen: 1,
+ semicolon: 1,
+ sp: 1,
+ symbeg: 1,
+ symbols_beg: 1,
+ tlambda: 1,
+ tlambeg: 1,
+ tstring_beg: 1,
+ tstring_content: 1,
+ tstring_end: 1,
+ words_beg: 1,
+ words_sep: 1,
+ ignored_sp: 1
+ }
+
+ # This array contains name of parser events.
+ PARSER_EVENTS = PARSER_EVENT_TABLE.keys
+
+ # This array contains name of scanner events.
+ SCANNER_EVENTS = SCANNER_EVENT_TABLE.keys
+
+ # This array contains name of all ripper events.
+ EVENTS = PARSER_EVENTS + SCANNER_EVENTS
+
+ # A list of all of the Ruby keywords.
+ KEYWORDS = [
+ "alias",
+ "and",
+ "begin",
+ "BEGIN",
+ "break",
+ "case",
+ "class",
+ "def",
+ "defined?",
+ "do",
+ "else",
+ "elsif",
+ "end",
+ "END",
+ "ensure",
+ "false",
+ "for",
+ "if",
+ "in",
+ "module",
+ "next",
+ "nil",
+ "not",
+ "or",
+ "redo",
+ "rescue",
+ "retry",
+ "return",
+ "self",
+ "super",
+ "then",
+ "true",
+ "undef",
+ "unless",
+ "until",
+ "when",
+ "while",
+ "yield",
+ "__ENCODING__",
+ "__FILE__",
+ "__LINE__"
+ ]
+
+ # A list of all of the Ruby binary operators.
+ BINARY_OPERATORS = [
+ :!=,
+ :!~,
+ :=~,
+ :==,
+ :===,
+ :<=>,
+ :>,
+ :>=,
+ :<,
+ :<=,
+ :&,
+ :|,
+ :^,
+ :>>,
+ :<<,
+ :-,
+ :+,
+ :%,
+ :/,
+ :*,
+ :**
+ ]
+
+ private_constant :KEYWORDS, :BINARY_OPERATORS
+
+ # Parses +src+ and create S-exp tree.
+ # Returns more readable tree rather than Ripper.sexp_raw.
+ # This method is mainly for developer use.
+ # The +filename+ argument is mostly ignored.
+ # By default, this method does not handle syntax errors in +src+,
+ # returning +nil+ in such cases. Use the +raise_errors+ keyword
+ # to raise a SyntaxError for an error in +src+.
+ #
+ # require "ripper"
+ # require "pp"
+ #
+ # pp Ripper.sexp("def m(a) nil end")
+ # #=> [:program,
+ # [[:def,
+ # [:@ident, "m", [1, 4]],
+ # [:paren, [:params, [[:@ident, "a", [1, 6]]], nil, nil, nil, nil, nil, nil]],
+ # [:bodystmt, [[:var_ref, [:@kw, "nil", [1, 9]]]], nil, nil, nil]]]]
+ #
+ def self.sexp(src, filename = "-", lineno = 1, raise_errors: false)
+ builder = SexpBuilderPP.new(src, filename, lineno)
+ sexp = builder.parse
+ if builder.error?
+ if raise_errors
+ raise SyntaxError, builder.error
+ end
+ else
+ sexp
+ end
+ end
+
+ # Parses +src+ and create S-exp tree.
+ # This method is mainly for developer use.
+ # The +filename+ argument is mostly ignored.
+ # By default, this method does not handle syntax errors in +src+,
+ # returning +nil+ in such cases. Use the +raise_errors+ keyword
+ # to raise a SyntaxError for an error in +src+.
+ #
+ # require "ripper"
+ # require "pp"
+ #
+ # pp Ripper.sexp_raw("def m(a) nil end")
+ # #=> [:program,
+ # [:stmts_add,
+ # [:stmts_new],
+ # [:def,
+ # [:@ident, "m", [1, 4]],
+ # [:paren, [:params, [[:@ident, "a", [1, 6]]], nil, nil, nil]],
+ # [:bodystmt,
+ # [:stmts_add, [:stmts_new], [:var_ref, [:@kw, "nil", [1, 9]]]],
+ # nil,
+ # nil,
+ # nil]]]]
+ #
+ def self.sexp_raw(src, filename = "-", lineno = 1, raise_errors: false)
+ builder = SexpBuilder.new(src, filename, lineno)
+ sexp = builder.parse
+ if builder.error?
+ if raise_errors
+ raise SyntaxError, builder.error
+ end
+ else
+ sexp
+ end
+ end
+
+ autoload :SexpBuilder, "prism/translation/ripper/sexp"
+ autoload :SexpBuilderPP, "prism/translation/ripper/sexp"
+
+ # The source that is being parsed.
+ attr_reader :source
+
+ # The filename of the source being parsed.
+ attr_reader :filename
+
+ # The current line number of the parser.
+ attr_reader :lineno
+
+ # The current column number of the parser.
+ attr_reader :column
+
+ # Create a new Translation::Ripper object with the given source.
+ def initialize(source, filename = "(ripper)", lineno = 1)
+ @source = source
+ @filename = filename
+ @lineno = lineno
+ @column = 0
+ @result = nil
+ end
+
+ ##########################################################################
+ # Public interface
+ ##########################################################################
+
+ # True if the parser encountered an error during parsing.
+ def error?
+ result.failure?
+ end
+
+ # Parse the source and return the result.
+ def parse
+ result.comments.each do |comment|
+ location = comment.location
+ bounds(location)
+
+ if comment.is_a?(InlineComment)
+ on_comment(comment.slice)
+ else
+ offset = location.start_offset
+ lines = comment.slice.lines
+
+ lines.each_with_index do |line, index|
+ bounds(location.copy(start_offset: offset))
+
+ if index == 0
+ on_embdoc_beg(line)
+ elsif index == lines.size - 1
+ on_embdoc_end(line)
+ else
+ on_embdoc(line)
+ end
+
+ offset += line.bytesize
+ end
+ end
+ end
+
+ result.magic_comments.each do |magic_comment|
+ on_magic_comment(magic_comment.key, magic_comment.value)
+ end
+
+ unless result.data_loc.nil?
+ on___end__(result.data_loc.slice.each_line.first)
+ end
+
+ result.warnings.each do |warning|
+ bounds(warning.location)
+
+ if warning.level == :default
+ warning(warning.message)
+ else
+ case warning.type
+ when :ambiguous_first_argument_plus
+ on_arg_ambiguous("+")
+ when :ambiguous_first_argument_minus
+ on_arg_ambiguous("-")
+ when :ambiguous_slash
+ on_arg_ambiguous("/")
+ else
+ warn(warning.message)
+ end
+ end
+ end
+
+ if error?
+ result.errors.each do |error|
+ location = error.location
+ bounds(location)
+
+ case error.type
+ when :alias_argument
+ on_alias_error("can't make alias for the number variables", location.slice)
+ when :argument_formal_class
+ on_param_error("formal argument cannot be a class variable", location.slice)
+ when :argument_format_constant
+ on_param_error("formal argument cannot be a constant", location.slice)
+ when :argument_formal_global
+ on_param_error("formal argument cannot be a global variable", location.slice)
+ when :argument_formal_ivar
+ on_param_error("formal argument cannot be an instance variable", location.slice)
+ when :class_name, :module_name
+ on_class_name_error("class/module name must be CONSTANT", location.slice)
+ else
+ on_parse_error(error.message)
+ end
+ end
+
+ nil
+ else
+ result.value.accept(self)
+ end
+ end
+
+ ##########################################################################
+ # Visitor methods
+ ##########################################################################
+
+ # alias foo bar
+ # ^^^^^^^^^^^^^
+ def visit_alias_method_node(node)
+ new_name = visit(node.new_name)
+ old_name = visit(node.old_name)
+
+ bounds(node.location)
+ on_alias(new_name, old_name)
+ end
+
+ # alias $foo $bar
+ # ^^^^^^^^^^^^^^^
+ def visit_alias_global_variable_node(node)
+ new_name = visit_alias_global_variable_node_value(node.new_name)
+ old_name = visit_alias_global_variable_node_value(node.old_name)
+
+ bounds(node.location)
+ on_var_alias(new_name, old_name)
+ end
+
+ # Visit one side of an alias global variable node.
+ private def visit_alias_global_variable_node_value(node)
+ bounds(node.location)
+
+ case node
+ when BackReferenceReadNode
+ on_backref(node.slice)
+ when GlobalVariableReadNode
+ on_gvar(node.name.to_s)
+ else
+ raise
+ end
+ end
+
+ # foo => bar | baz
+ # ^^^^^^^^^
+ def visit_alternation_pattern_node(node)
+ left = visit_pattern_node(node.left)
+ right = visit_pattern_node(node.right)
+
+ bounds(node.location)
+ on_binary(left, :|, right)
+ end
+
+ # Visit a pattern within a pattern match. This is used to bypass the
+ # parenthesis node that can be used to wrap patterns.
+ private def visit_pattern_node(node)
+ if node.is_a?(ParenthesesNode)
+ visit(node.body)
+ else
+ visit(node)
+ end
+ end
+
+ # a and b
+ # ^^^^^^^
+ def visit_and_node(node)
+ left = visit(node.left)
+ right = visit(node.right)
+
+ bounds(node.location)
+ on_binary(left, node.operator.to_sym, right)
+ end
+
+ # []
+ # ^^
+ def visit_array_node(node)
+ case (opening = node.opening)
+ when /^%w/
+ opening_loc = node.opening_loc
+ bounds(opening_loc)
+ on_qwords_beg(opening)
+
+ elements = on_qwords_new
+ previous = nil
+
+ node.elements.each do |element|
+ visit_words_sep(opening_loc, previous, element)
+
+ bounds(element.location)
+ elements = on_qwords_add(elements, on_tstring_content(element.content))
+
+ previous = element
+ end
+
+ bounds(node.closing_loc)
+ on_tstring_end(node.closing)
+ when /^%i/
+ opening_loc = node.opening_loc
+ bounds(opening_loc)
+ on_qsymbols_beg(opening)
+
+ elements = on_qsymbols_new
+ previous = nil
+
+ node.elements.each do |element|
+ visit_words_sep(opening_loc, previous, element)
+
+ bounds(element.location)
+ elements = on_qsymbols_add(elements, on_tstring_content(element.value))
+
+ previous = element
+ end
+
+ bounds(node.closing_loc)
+ on_tstring_end(node.closing)
+ when /^%W/
+ opening_loc = node.opening_loc
+ bounds(opening_loc)
+ on_words_beg(opening)
+
+ elements = on_words_new
+ previous = nil
+
+ node.elements.each do |element|
+ visit_words_sep(opening_loc, previous, element)
+
+ bounds(element.location)
+ elements =
+ on_words_add(
+ elements,
+ if element.is_a?(StringNode)
+ on_word_add(on_word_new, on_tstring_content(element.content))
+ else
+ element.parts.inject(on_word_new) do |word, part|
+ word_part =
+ if part.is_a?(StringNode)
+ bounds(part.location)
+ on_tstring_content(part.content)
+ else
+ visit(part)
+ end
+
+ on_word_add(word, word_part)
+ end
+ end
+ )
+
+ previous = element
+ end
+
+ bounds(node.closing_loc)
+ on_tstring_end(node.closing)
+ when /^%I/
+ opening_loc = node.opening_loc
+ bounds(opening_loc)
+ on_symbols_beg(opening)
+
+ elements = on_symbols_new
+ previous = nil
+
+ node.elements.each do |element|
+ visit_words_sep(opening_loc, previous, element)
+
+ bounds(element.location)
+ elements =
+ on_symbols_add(
+ elements,
+ if element.is_a?(SymbolNode)
+ on_word_add(on_word_new, on_tstring_content(element.value))
+ else
+ element.parts.inject(on_word_new) do |word, part|
+ word_part =
+ if part.is_a?(StringNode)
+ bounds(part.location)
+ on_tstring_content(part.content)
+ else
+ visit(part)
+ end
+
+ on_word_add(word, word_part)
+ end
+ end
+ )
+
+ previous = element
+ end
+
+ bounds(node.closing_loc)
+ on_tstring_end(node.closing)
+ else
+ bounds(node.opening_loc)
+ on_lbracket(opening)
+
+ elements = visit_arguments(node.elements) unless node.elements.empty?
+
+ bounds(node.closing_loc)
+ on_rbracket(node.closing)
+ end
+
+ bounds(node.location)
+ on_array(elements)
+ end
+
+ # Dispatch a words_sep event that contains the space between the elements
+ # of list literals.
+ private def visit_words_sep(opening_loc, previous, current)
+ end_offset = (previous.nil? ? opening_loc : previous.location).end_offset
+ start_offset = current.location.start_offset
+
+ if end_offset != start_offset
+ bounds(current.location.copy(start_offset: end_offset))
+ on_words_sep(source.byteslice(end_offset...start_offset))
+ end
+ end
+
+ # Visit a list of elements, like the elements of an array or arguments.
+ private def visit_arguments(elements)
+ bounds(elements.first.location)
+ elements.inject(on_args_new) do |args, element|
+ arg = visit(element)
+ bounds(element.location)
+
+ case element
+ when BlockArgumentNode
+ on_args_add_block(args, arg)
+ when SplatNode
+ on_args_add_star(args, arg)
+ else
+ on_args_add(args, arg)
+ end
+ end
+ end
+
+ # foo => [bar]
+ # ^^^^^
+ def visit_array_pattern_node(node)
+ constant = visit(node.constant)
+ requireds = visit_all(node.requireds) if node.requireds.any?
+ rest =
+ if (rest_node = node.rest).is_a?(SplatNode)
+ if rest_node.expression.nil?
+ bounds(rest_node.location)
+ on_var_field(nil)
+ else
+ visit(rest_node.expression)
+ end
+ end
+
+ posts = visit_all(node.posts) if node.posts.any?
+
+ bounds(node.location)
+ on_aryptn(constant, requireds, rest, posts)
+ end
+
+ # foo(bar)
+ # ^^^
+ def visit_arguments_node(node)
+ arguments, _ = visit_call_node_arguments(node, nil, false)
+ arguments
+ end
+
+ # { a: 1 }
+ # ^^^^
+ def visit_assoc_node(node)
+ key = visit(node.key)
+ value = visit(node.value)
+
+ bounds(node.location)
+ on_assoc_new(key, value)
+ end
+
+ # def foo(**); bar(**); end
+ # ^^
+ #
+ # { **foo }
+ # ^^^^^
+ def visit_assoc_splat_node(node)
+ value = visit(node.value)
+
+ bounds(node.location)
+ on_assoc_splat(value)
+ end
+
+ # $+
+ # ^^
+ def visit_back_reference_read_node(node)
+ bounds(node.location)
+ on_backref(node.slice)
+ end
+
+ # begin end
+ # ^^^^^^^^^
+ def visit_begin_node(node)
+ clauses = visit_begin_node_clauses(node.begin_keyword_loc, node, false)
+
+ bounds(node.location)
+ on_begin(clauses)
+ end
+
+ # Visit the clauses of a begin node to form an on_bodystmt call.
+ private def visit_begin_node_clauses(location, node, allow_newline)
+ statements =
+ if node.statements.nil?
+ on_stmts_add(on_stmts_new, on_void_stmt)
+ else
+ body = node.statements.body
+ body.unshift(nil) if void_stmt?(location, node.statements.body[0].location, allow_newline)
+
+ bounds(node.statements.location)
+ visit_statements_node_body(body)
+ end
+
+ rescue_clause = visit(node.rescue_clause)
+ else_clause =
+ unless (else_clause_node = node.else_clause).nil?
+ else_statements =
+ if else_clause_node.statements.nil?
+ [nil]
+ else
+ body = else_clause_node.statements.body
+ body.unshift(nil) if void_stmt?(else_clause_node.else_keyword_loc, else_clause_node.statements.body[0].location, allow_newline)
+ body
+ end
+
+ bounds(else_clause_node.location)
+ visit_statements_node_body(else_statements)
+ end
+ ensure_clause = visit(node.ensure_clause)
+
+ bounds(node.location)
+ on_bodystmt(statements, rescue_clause, else_clause, ensure_clause)
+ end
+
+ # Visit the body of a structure that can have either a set of statements
+ # or statements wrapped in rescue/else/ensure.
+ private def visit_body_node(location, node, allow_newline = false)
+ case node
+ when nil
+ bounds(location)
+ on_bodystmt(visit_statements_node_body([nil]), nil, nil, nil)
+ when StatementsNode
+ body = [*node.body]
+ body.unshift(nil) if void_stmt?(location, body[0].location, allow_newline)
+ stmts = visit_statements_node_body(body)
+
+ bounds(node.body.first.location)
+ on_bodystmt(stmts, nil, nil, nil)
+ when BeginNode
+ visit_begin_node_clauses(location, node, allow_newline)
+ else
+ raise
+ end
+ end
+
+ # foo(&bar)
+ # ^^^^
+ def visit_block_argument_node(node)
+ visit(node.expression)
+ end
+
+ # foo { |; bar| }
+ # ^^^
+ def visit_block_local_variable_node(node)
+ bounds(node.location)
+ on_ident(node.name.to_s)
+ end
+
+ # Visit a BlockNode.
+ def visit_block_node(node)
+ braces = node.opening == "{"
+ parameters = visit(node.parameters)
+
+ body =
+ case node.body
+ when nil
+ bounds(node.location)
+ stmts = on_stmts_add(on_stmts_new, on_void_stmt)
+
+ bounds(node.location)
+ braces ? stmts : on_bodystmt(stmts, nil, nil, nil)
+ when StatementsNode
+ stmts = node.body.body
+ stmts.unshift(nil) if void_stmt?(node.parameters&.location || node.opening_loc, node.body.location, false)
+ stmts = visit_statements_node_body(stmts)
+
+ bounds(node.body.location)
+ braces ? stmts : on_bodystmt(stmts, nil, nil, nil)
+ when BeginNode
+ visit_body_node(node.parameters&.location || node.opening_loc, node.body)
+ else
+ raise
+ end
+
+ if braces
+ bounds(node.location)
+ on_brace_block(parameters, body)
+ else
+ bounds(node.location)
+ on_do_block(parameters, body)
+ end
+ end
+
+ # def foo(&bar); end
+ # ^^^^
+ def visit_block_parameter_node(node)
+ if node.name_loc.nil?
+ bounds(node.location)
+ on_blockarg(nil)
+ else
+ bounds(node.name_loc)
+ name = visit_token(node.name.to_s)
+
+ bounds(node.location)
+ on_blockarg(name)
+ end
+ end
+
+ # A block's parameters.
+ def visit_block_parameters_node(node)
+ parameters =
+ if node.parameters.nil?
+ on_params(nil, nil, nil, nil, nil, nil, nil)
+ else
+ visit(node.parameters)
+ end
+
+ locals =
+ if node.locals.any?
+ visit_all(node.locals)
+ else
+ false
+ end
+
+ bounds(node.location)
+ on_block_var(parameters, locals)
+ end
+
+ # break
+ # ^^^^^
+ #
+ # break foo
+ # ^^^^^^^^^
+ def visit_break_node(node)
+ if node.arguments.nil?
+ bounds(node.location)
+ on_break(on_args_new)
+ else
+ arguments = visit(node.arguments)
+
+ bounds(node.location)
+ on_break(arguments)
+ end
+ end
+
+ # foo
+ # ^^^
+ #
+ # foo.bar
+ # ^^^^^^^
+ #
+ # foo.bar() {}
+ # ^^^^^^^^^^^^
+ def visit_call_node(node)
+ if node.call_operator_loc.nil?
+ case node.name
+ when :[]
+ receiver = visit(node.receiver)
+ arguments, block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))
+
+ bounds(node.location)
+ call = on_aref(receiver, arguments)
+
+ if block.nil?
+ call
+ else
+ bounds(node.location)
+ on_method_add_block(call, block)
+ end
+ when :[]=
+ receiver = visit(node.receiver)
+
+ *arguments, last_argument = node.arguments.arguments
+ arguments << node.block if !node.block.nil?
+
+ arguments =
+ if arguments.any?
+ args = visit_arguments(arguments)
+
+ if !node.block.nil?
+ args
+ else
+ bounds(arguments.first.location)
+ on_args_add_block(args, false)
+ end
+ end
+
+ bounds(node.location)
+ call = on_aref_field(receiver, arguments)
+ value = visit_write_value(last_argument)
+
+ bounds(last_argument.location)
+ on_assign(call, value)
+ when :-@, :+@, :~
+ receiver = visit(node.receiver)
+
+ bounds(node.location)
+ on_unary(node.name, receiver)
+ when :!
+ receiver = visit(node.receiver)
+
+ bounds(node.location)
+ on_unary(node.message == "not" ? :not : :!, receiver)
+ when *BINARY_OPERATORS
+ receiver = visit(node.receiver)
+ value = visit(node.arguments.arguments.first)
+
+ bounds(node.location)
+ on_binary(receiver, node.name, value)
+ else
+ bounds(node.message_loc)
+ message = visit_token(node.message, false)
+
+ if node.variable_call?
+ on_vcall(message)
+ else
+ arguments, block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc || node.location))
+ call =
+ if node.opening_loc.nil? && arguments&.any?
+ bounds(node.location)
+ on_command(message, arguments)
+ elsif !node.opening_loc.nil?
+ bounds(node.location)
+ on_method_add_arg(on_fcall(message), on_arg_paren(arguments))
+ else
+ bounds(node.location)
+ on_method_add_arg(on_fcall(message), on_args_new)
+ end
+
+ if block.nil?
+ call
+ else
+ bounds(node.block.location)
+ on_method_add_block(call, block)
+ end
+ end
+ end
+ else
+ receiver = visit(node.receiver)
+
+ bounds(node.call_operator_loc)
+ call_operator = visit_token(node.call_operator)
+
+ message =
+ if node.message_loc.nil?
+ :call
+ else
+ bounds(node.message_loc)
+ visit_token(node.message, false)
+ end
+
+ if node.name.end_with?("=") && !node.message.end_with?("=") && !node.arguments.nil? && node.block.nil?
+ value = visit_write_value(node.arguments.arguments.first)
+
+ bounds(node.location)
+ on_assign(on_field(receiver, call_operator, message), value)
+ else
+ arguments, block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc || node.location))
+ call =
+ if node.opening_loc.nil?
+ bounds(node.location)
+
+ if node.arguments.nil? && !node.block.is_a?(BlockArgumentNode)
+ on_call(receiver, call_operator, message)
+ else
+ on_command_call(receiver, call_operator, message, arguments)
+ end
+ else
+ bounds(node.opening_loc)
+ arguments = on_arg_paren(arguments)
+
+ bounds(node.location)
+ on_method_add_arg(on_call(receiver, call_operator, message), arguments)
+ end
+
+ if block.nil?
+ call
+ else
+ bounds(node.block.location)
+ on_method_add_block(call, block)
+ end
+ end
+ end
+ end
+
+ # Visit the arguments and block of a call node and return the arguments
+ # and block as they should be used.
+ private def visit_call_node_arguments(arguments_node, block_node, trailing_comma)
+ arguments = arguments_node&.arguments || []
+ block = block_node
+
+ if block.is_a?(BlockArgumentNode)
+ arguments << block
+ block = nil
+ end
+
+ [
+ if arguments.length == 1 && arguments.first.is_a?(ForwardingArgumentsNode)
+ visit(arguments.first)
+ elsif arguments.any?
+ args = visit_arguments(arguments)
+
+ if block_node.is_a?(BlockArgumentNode) || arguments.last.is_a?(ForwardingArgumentsNode) || command?(arguments.last) || trailing_comma
+ args
+ else
+ bounds(arguments.first.location)
+ on_args_add_block(args, false)
+ end
+ end,
+ visit(block)
+ ]
+ end
+
+ # Returns true if the given node is a command node.
+ private def command?(node)
+ node.is_a?(CallNode) &&
+ node.opening_loc.nil? &&
+ (!node.arguments.nil? || node.block.is_a?(BlockArgumentNode)) &&
+ !BINARY_OPERATORS.include?(node.name)
+ end
+
+ # foo.bar += baz
+ # ^^^^^^^^^^^^^^^
+ def visit_call_operator_write_node(node)
+ receiver = visit(node.receiver)
+
+ bounds(node.call_operator_loc)
+ call_operator = visit_token(node.call_operator)
+
+ bounds(node.message_loc)
+ message = visit_token(node.message)
+
+ bounds(node.location)
+ target = on_field(receiver, call_operator, message)
+
+ bounds(node.binary_operator_loc)
+ operator = on_op("#{node.binary_operator}=")
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_opassign(target, operator, value)
+ end
+
+ # foo.bar &&= baz
+ # ^^^^^^^^^^^^^^^
+ def visit_call_and_write_node(node)
+ receiver = visit(node.receiver)
+
+ bounds(node.call_operator_loc)
+ call_operator = visit_token(node.call_operator)
+
+ bounds(node.message_loc)
+ message = visit_token(node.message)
+
+ bounds(node.location)
+ target = on_field(receiver, call_operator, message)
+
+ bounds(node.operator_loc)
+ operator = on_op("&&=")
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_opassign(target, operator, value)
+ end
+
+ # foo.bar ||= baz
+ # ^^^^^^^^^^^^^^^
+ def visit_call_or_write_node(node)
+ receiver = visit(node.receiver)
+
+ bounds(node.call_operator_loc)
+ call_operator = visit_token(node.call_operator)
+
+ bounds(node.message_loc)
+ message = visit_token(node.message)
+
+ bounds(node.location)
+ target = on_field(receiver, call_operator, message)
+
+ bounds(node.operator_loc)
+ operator = on_op("||=")
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_opassign(target, operator, value)
+ end
+
+ # foo.bar, = 1
+ # ^^^^^^^
+ def visit_call_target_node(node)
+ if node.call_operator == "::"
+ receiver = visit(node.receiver)
+
+ bounds(node.message_loc)
+ message = visit_token(node.message)
+
+ bounds(node.location)
+ on_const_path_field(receiver, message)
+ else
+ receiver = visit(node.receiver)
+
+ bounds(node.call_operator_loc)
+ call_operator = visit_token(node.call_operator)
+
+ bounds(node.message_loc)
+ message = visit_token(node.message)
+
+ bounds(node.location)
+ on_field(receiver, call_operator, message)
+ end
+ end
+
+ # foo => bar => baz
+ # ^^^^^^^^^^
+ def visit_capture_pattern_node(node)
+ value = visit(node.value)
+ target = visit(node.target)
+
+ bounds(node.location)
+ on_binary(value, :"=>", target)
+ end
+
+ # case foo; when bar; end
+ # ^^^^^^^^^^^^^^^^^^^^^^^
+ def visit_case_node(node)
+ predicate = visit(node.predicate)
+ clauses =
+ node.conditions.reverse_each.inject(visit(node.consequent)) do |consequent, condition|
+ on_when(*visit(condition), consequent)
+ end
+
+ bounds(node.location)
+ on_case(predicate, clauses)
+ end
+
+ # case foo; in bar; end
+ # ^^^^^^^^^^^^^^^^^^^^^
+ def visit_case_match_node(node)
+ predicate = visit(node.predicate)
+ clauses =
+ node.conditions.reverse_each.inject(visit(node.consequent)) do |consequent, condition|
+ on_in(*visit(condition), consequent)
+ end
+
+ bounds(node.location)
+ on_case(predicate, clauses)
+ end
+
+ # class Foo; end
+ # ^^^^^^^^^^^^^^
+ def visit_class_node(node)
+ constant_path =
+ if node.constant_path.is_a?(ConstantReadNode)
+ bounds(node.constant_path.location)
+ on_const_ref(on_const(node.constant_path.name.to_s))
+ else
+ visit(node.constant_path)
+ end
+
+ superclass = visit(node.superclass)
+ bodystmt = visit_body_node(node.superclass&.location || node.constant_path.location, node.body, node.superclass.nil?)
+
+ bounds(node.location)
+ on_class(constant_path, superclass, bodystmt)
+ end
+
+ # @@foo
+ # ^^^^^
+ def visit_class_variable_read_node(node)
+ bounds(node.location)
+ on_var_ref(on_cvar(node.slice))
+ end
+
+ # @@foo = 1
+ # ^^^^^^^^^
+ #
+ # @@foo, @@bar = 1
+ # ^^^^^ ^^^^^
+ def visit_class_variable_write_node(node)
+ bounds(node.name_loc)
+ target = on_var_field(on_cvar(node.name.to_s))
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_assign(target, value)
+ end
+
+ # @@foo += bar
+ # ^^^^^^^^^^^^
+ def visit_class_variable_operator_write_node(node)
+ bounds(node.name_loc)
+ target = on_var_field(on_cvar(node.name.to_s))
+
+ bounds(node.binary_operator_loc)
+ operator = on_op("#{node.binary_operator}=")
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_opassign(target, operator, value)
+ end
+
+ # @@foo &&= bar
+ # ^^^^^^^^^^^^^
+ def visit_class_variable_and_write_node(node)
+ bounds(node.name_loc)
+ target = on_var_field(on_cvar(node.name.to_s))
+
+ bounds(node.operator_loc)
+ operator = on_op("&&=")
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_opassign(target, operator, value)
+ end
+
+ # @@foo ||= bar
+ # ^^^^^^^^^^^^^
+ def visit_class_variable_or_write_node(node)
+ bounds(node.name_loc)
+ target = on_var_field(on_cvar(node.name.to_s))
+
+ bounds(node.operator_loc)
+ operator = on_op("||=")
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_opassign(target, operator, value)
+ end
+
+ # @@foo, = bar
+ # ^^^^^
+ def visit_class_variable_target_node(node)
+ bounds(node.location)
+ on_var_field(on_cvar(node.name.to_s))
+ end
+
+ # Foo
+ # ^^^
+ def visit_constant_read_node(node)
+ bounds(node.location)
+ on_var_ref(on_const(node.name.to_s))
+ end
+
+ # Foo = 1
+ # ^^^^^^^
+ #
+ # Foo, Bar = 1
+ # ^^^ ^^^
+ def visit_constant_write_node(node)
+ bounds(node.name_loc)
+ target = on_var_field(on_const(node.name.to_s))
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_assign(target, value)
+ end
+
+ # Foo += bar
+ # ^^^^^^^^^^^
+ def visit_constant_operator_write_node(node)
+ bounds(node.name_loc)
+ target = on_var_field(on_const(node.name.to_s))
+
+ bounds(node.binary_operator_loc)
+ operator = on_op("#{node.binary_operator}=")
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_opassign(target, operator, value)
+ end
+
+ # Foo &&= bar
+ # ^^^^^^^^^^^^
+ def visit_constant_and_write_node(node)
+ bounds(node.name_loc)
+ target = on_var_field(on_const(node.name.to_s))
+
+ bounds(node.operator_loc)
+ operator = on_op("&&=")
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_opassign(target, operator, value)
+ end
+
+ # Foo ||= bar
+ # ^^^^^^^^^^^^
+ def visit_constant_or_write_node(node)
+ bounds(node.name_loc)
+ target = on_var_field(on_const(node.name.to_s))
+
+ bounds(node.operator_loc)
+ operator = on_op("||=")
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_opassign(target, operator, value)
+ end
+
+ # Foo, = bar
+ # ^^^
+ def visit_constant_target_node(node)
+ bounds(node.location)
+ on_var_field(on_const(node.name.to_s))
+ end
+
+ # Foo::Bar
+ # ^^^^^^^^
+ def visit_constant_path_node(node)
+ if node.parent.nil?
+ bounds(node.name_loc)
+ child = on_const(node.name.to_s)
+
+ bounds(node.location)
+ on_top_const_ref(child)
+ else
+ parent = visit(node.parent)
+
+ bounds(node.name_loc)
+ child = on_const(node.name.to_s)
+
+ bounds(node.location)
+ on_const_path_ref(parent, child)
+ end
+ end
+
+ # Foo::Bar = 1
+ # ^^^^^^^^^^^^
+ #
+ # Foo::Foo, Bar::Bar = 1
+ # ^^^^^^^^ ^^^^^^^^
+ def visit_constant_path_write_node(node)
+ target = visit_constant_path_write_node_target(node.target)
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_assign(target, value)
+ end
+
+ # Visit a constant path that is part of a write node.
+ private def visit_constant_path_write_node_target(node)
+ if node.parent.nil?
+ bounds(node.name_loc)
+ child = on_const(node.name.to_s)
+
+ bounds(node.location)
+ on_top_const_field(child)
+ else
+ parent = visit(node.parent)
+
+ bounds(node.name_loc)
+ child = on_const(node.name.to_s)
+
+ bounds(node.location)
+ on_const_path_field(parent, child)
+ end
+ end
+
+ # Foo::Bar += baz
+ # ^^^^^^^^^^^^^^^
+ def visit_constant_path_operator_write_node(node)
+ target = visit_constant_path_write_node_target(node.target)
+ value = visit(node.value)
+
+ bounds(node.binary_operator_loc)
+ operator = on_op("#{node.binary_operator}=")
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_opassign(target, operator, value)
+ end
+
+ # Foo::Bar &&= baz
+ # ^^^^^^^^^^^^^^^^
+ def visit_constant_path_and_write_node(node)
+ target = visit_constant_path_write_node_target(node.target)
+ value = visit(node.value)
+
+ bounds(node.operator_loc)
+ operator = on_op("&&=")
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_opassign(target, operator, value)
+ end
+
+ # Foo::Bar ||= baz
+ # ^^^^^^^^^^^^^^^^
+ def visit_constant_path_or_write_node(node)
+ target = visit_constant_path_write_node_target(node.target)
+ value = visit(node.value)
+
+ bounds(node.operator_loc)
+ operator = on_op("||=")
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_opassign(target, operator, value)
+ end
+
+ # Foo::Bar, = baz
+ # ^^^^^^^^
+ def visit_constant_path_target_node(node)
+ visit_constant_path_write_node_target(node)
+ end
+
+ # def foo; end
+ # ^^^^^^^^^^^^
+ #
+ # def self.foo; end
+ # ^^^^^^^^^^^^^^^^^
+ def visit_def_node(node)
+ receiver = visit(node.receiver)
+ operator =
+ if !node.operator_loc.nil?
+ bounds(node.operator_loc)
+ visit_token(node.operator)
+ end
+
+ bounds(node.name_loc)
+ name = visit_token(node.name_loc.slice)
+
+ parameters =
+ if node.parameters.nil?
+ bounds(node.location)
+ on_params(nil, nil, nil, nil, nil, nil, nil)
+ else
+ visit(node.parameters)
+ end
+
+ if !node.lparen_loc.nil?
+ bounds(node.lparen_loc)
+ parameters = on_paren(parameters)
+ end
+
+ bodystmt =
+ if node.equal_loc.nil?
+ visit_body_node(node.rparen_loc || node.end_keyword_loc, node.body)
+ else
+ body = visit(node.body.body.first)
+
+ bounds(node.body.location)
+ on_bodystmt(body, nil, nil, nil)
+ end
+
+ bounds(node.location)
+ if receiver.nil?
+ on_def(name, parameters, bodystmt)
+ else
+ on_defs(receiver, operator, name, parameters, bodystmt)
+ end
+ end
+
+ # defined? a
+ # ^^^^^^^^^^
+ #
+ # defined?(a)
+ # ^^^^^^^^^^^
+ def visit_defined_node(node)
+ bounds(node.location)
+ on_defined(visit(node.value))
+ end
+
+ # if foo then bar else baz end
+ # ^^^^^^^^^^^^
+ def visit_else_node(node)
+ statements =
+ if node.statements.nil?
+ [nil]
+ else
+ body = node.statements.body
+ body.unshift(nil) if void_stmt?(node.else_keyword_loc, node.statements.body[0].location, false)
+ body
+ end
+
+ bounds(node.location)
+ on_else(visit_statements_node_body(statements))
+ end
+
+ # "foo #{bar}"
+ # ^^^^^^
+ def visit_embedded_statements_node(node)
+ bounds(node.opening_loc)
+ on_embexpr_beg(node.opening)
+
+ statements =
+ if node.statements.nil?
+ bounds(node.location)
+ on_stmts_add(on_stmts_new, on_void_stmt)
+ else
+ visit(node.statements)
+ end
+
+ bounds(node.closing_loc)
+ on_embexpr_end(node.closing)
+
+ bounds(node.location)
+ on_string_embexpr(statements)
+ end
+
+ # "foo #@bar"
+ # ^^^^^
+ def visit_embedded_variable_node(node)
+ bounds(node.operator_loc)
+ on_embvar(node.operator)
+
+ variable = visit(node.variable)
+
+ bounds(node.location)
+ on_string_dvar(variable)
+ end
+
+ # Visit an EnsureNode node.
+ def visit_ensure_node(node)
+ statements =
+ if node.statements.nil?
+ [nil]
+ else
+ body = node.statements.body
+ body.unshift(nil) if void_stmt?(node.ensure_keyword_loc, body[0].location, false)
+ body
+ end
+
+ statements = visit_statements_node_body(statements)
+
+ bounds(node.location)
+ on_ensure(statements)
+ end
+
+ # false
+ # ^^^^^
+ def visit_false_node(node)
+ bounds(node.location)
+ on_var_ref(on_kw("false"))
+ end
+
+ # foo => [*, bar, *]
+ # ^^^^^^^^^^^
+ def visit_find_pattern_node(node)
+ constant = visit(node.constant)
+ left =
+ if node.left.expression.nil?
+ bounds(node.left.location)
+ on_var_field(nil)
+ else
+ visit(node.left.expression)
+ end
+
+ requireds = visit_all(node.requireds) if node.requireds.any?
+ right =
+ if node.right.expression.nil?
+ bounds(node.right.location)
+ on_var_field(nil)
+ else
+ visit(node.right.expression)
+ end
+
+ bounds(node.location)
+ on_fndptn(constant, left, requireds, right)
+ end
+
+ # if foo .. bar; end
+ # ^^^^^^^^^^
+ def visit_flip_flop_node(node)
+ left = visit(node.left)
+ right = visit(node.right)
+
+ bounds(node.location)
+ if node.exclude_end?
+ on_dot3(left, right)
+ else
+ on_dot2(left, right)
+ end
+ end
+
+ # 1.0
+ # ^^^
+ def visit_float_node(node)
+ visit_number_node(node) { |text| on_float(text) }
+ end
+
+ # for foo in bar do end
+ # ^^^^^^^^^^^^^^^^^^^^^
+ def visit_for_node(node)
+ index = visit(node.index)
+ collection = visit(node.collection)
+ statements =
+ if node.statements.nil?
+ bounds(node.location)
+ on_stmts_add(on_stmts_new, on_void_stmt)
+ else
+ visit(node.statements)
+ end
+
+ bounds(node.location)
+ on_for(index, collection, statements)
+ end
+
+ # def foo(...); bar(...); end
+ # ^^^
+ def visit_forwarding_arguments_node(node)
+ bounds(node.location)
+ on_args_forward
+ end
+
+ # def foo(...); end
+ # ^^^
+ def visit_forwarding_parameter_node(node)
+ bounds(node.location)
+ on_args_forward
+ end
+
+ # super
+ # ^^^^^
+ #
+ # super {}
+ # ^^^^^^^^
+ def visit_forwarding_super_node(node)
+ if node.block.nil?
+ bounds(node.location)
+ on_zsuper
+ else
+ block = visit(node.block)
+
+ bounds(node.location)
+ on_method_add_block(on_zsuper, block)
+ end
+ end
+
+ # $foo
+ # ^^^^
+ def visit_global_variable_read_node(node)
+ bounds(node.location)
+ on_var_ref(on_gvar(node.name.to_s))
+ end
+
+ # $foo = 1
+ # ^^^^^^^^
+ #
+ # $foo, $bar = 1
+ # ^^^^ ^^^^
+ def visit_global_variable_write_node(node)
+ bounds(node.name_loc)
+ target = on_var_field(on_gvar(node.name.to_s))
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_assign(target, value)
+ end
+
+ # $foo += bar
+ # ^^^^^^^^^^^
+ def visit_global_variable_operator_write_node(node)
+ bounds(node.name_loc)
+ target = on_var_field(on_gvar(node.name.to_s))
+
+ bounds(node.binary_operator_loc)
+ operator = on_op("#{node.binary_operator}=")
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_opassign(target, operator, value)
+ end
+
+ # $foo &&= bar
+ # ^^^^^^^^^^^^
+ def visit_global_variable_and_write_node(node)
+ bounds(node.name_loc)
+ target = on_var_field(on_gvar(node.name.to_s))
+
+ bounds(node.operator_loc)
+ operator = on_op("&&=")
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_opassign(target, operator, value)
+ end
+
+ # $foo ||= bar
+ # ^^^^^^^^^^^^
+ def visit_global_variable_or_write_node(node)
+ bounds(node.name_loc)
+ target = on_var_field(on_gvar(node.name.to_s))
+
+ bounds(node.operator_loc)
+ operator = on_op("||=")
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_opassign(target, operator, value)
+ end
+
+ # $foo, = bar
+ # ^^^^
+ def visit_global_variable_target_node(node)
+ bounds(node.location)
+ on_var_field(on_gvar(node.name.to_s))
+ end
+
+ # {}
+ # ^^
+ def visit_hash_node(node)
+ elements =
+ if node.elements.any?
+ args = visit_all(node.elements)
+
+ bounds(node.elements.first.location)
+ on_assoclist_from_args(args)
+ end
+
+ bounds(node.location)
+ on_hash(elements)
+ end
+
+ # foo => {}
+ # ^^
+ def visit_hash_pattern_node(node)
+ constant = visit(node.constant)
+ elements =
+ if node.elements.any? || !node.rest.nil?
+ node.elements.map do |element|
+ [
+ if (key = element.key).opening_loc.nil?
+ visit(key)
+ else
+ bounds(key.value_loc)
+ if (value = key.value).empty?
+ on_string_content
+ else
+ on_string_add(on_string_content, on_tstring_content(value))
+ end
+ end,
+ visit(element.value)
+ ]
+ end
+ end
+
+ rest =
+ case node.rest
+ when AssocSplatNode
+ visit(node.rest.value)
+ when NoKeywordsParameterNode
+ bounds(node.rest.location)
+ on_var_field(visit(node.rest))
+ end
+
+ bounds(node.location)
+ on_hshptn(constant, elements, rest)
+ end
+
+ # if foo then bar end
+ # ^^^^^^^^^^^^^^^^^^^
+ #
+ # bar if foo
+ # ^^^^^^^^^^
+ #
+ # foo ? bar : baz
+ # ^^^^^^^^^^^^^^^
+ def visit_if_node(node)
+ if node.then_keyword == "?"
+ predicate = visit(node.predicate)
+ truthy = visit(node.statements.body.first)
+ falsy = visit(node.consequent.statements.body.first)
+
+ bounds(node.location)
+ on_ifop(predicate, truthy, falsy)
+ elsif node.statements.nil? || (node.predicate.location.start_offset < node.statements.location.start_offset)
+ predicate = visit(node.predicate)
+ statements =
+ if node.statements.nil?
+ bounds(node.location)
+ on_stmts_add(on_stmts_new, on_void_stmt)
+ else
+ visit(node.statements)
+ end
+ consequent = visit(node.consequent)
+
+ bounds(node.location)
+ if node.if_keyword == "if"
+ on_if(predicate, statements, consequent)
+ else
+ on_elsif(predicate, statements, consequent)
+ end
+ else
+ statements = visit(node.statements.body.first)
+ predicate = visit(node.predicate)
+
+ bounds(node.location)
+ on_if_mod(predicate, statements)
+ end
+ end
+
+ # 1i
+ # ^^
+ def visit_imaginary_node(node)
+ visit_number_node(node) { |text| on_imaginary(text) }
+ end
+
+ # { foo: }
+ # ^^^^
+ def visit_implicit_node(node)
+ end
+
+ # foo { |bar,| }
+ # ^
+ def visit_implicit_rest_node(node)
+ bounds(node.location)
+ on_excessed_comma
+ end
+
+ # case foo; in bar; end
+ # ^^^^^^^^^^^^^^^^^^^^^
+ def visit_in_node(node)
+ # This is a special case where we're not going to call on_in directly
+ # because we don't have access to the consequent. Instead, we'll return
+ # the component parts and let the parent node handle it.
+ pattern = visit_pattern_node(node.pattern)
+ statements =
+ if node.statements.nil?
+ bounds(node.location)
+ on_stmts_add(on_stmts_new, on_void_stmt)
+ else
+ visit(node.statements)
+ end
+
+ [pattern, statements]
+ end
+
+ # foo[bar] += baz
+ # ^^^^^^^^^^^^^^^
+ def visit_index_operator_write_node(node)
+ receiver = visit(node.receiver)
+ arguments, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))
+
+ bounds(node.location)
+ target = on_aref_field(receiver, arguments)
+
+ bounds(node.binary_operator_loc)
+ operator = on_op("#{node.binary_operator}=")
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_opassign(target, operator, value)
+ end
+
+ # foo[bar] &&= baz
+ # ^^^^^^^^^^^^^^^^
+ def visit_index_and_write_node(node)
+ receiver = visit(node.receiver)
+ arguments, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))
+
+ bounds(node.location)
+ target = on_aref_field(receiver, arguments)
+
+ bounds(node.operator_loc)
+ operator = on_op("&&=")
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_opassign(target, operator, value)
+ end
+
+ # foo[bar] ||= baz
+ # ^^^^^^^^^^^^^^^^
+ def visit_index_or_write_node(node)
+ receiver = visit(node.receiver)
+ arguments, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))
+
+ bounds(node.location)
+ target = on_aref_field(receiver, arguments)
+
+ bounds(node.operator_loc)
+ operator = on_op("||=")
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_opassign(target, operator, value)
+ end
+
+ # foo[bar], = 1
+ # ^^^^^^^^
+ def visit_index_target_node(node)
+ receiver = visit(node.receiver)
+ arguments, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))
+
+ bounds(node.location)
+ on_aref_field(receiver, arguments)
+ end
+
+ # @foo
+ # ^^^^
+ def visit_instance_variable_read_node(node)
+ bounds(node.location)
+ on_var_ref(on_ivar(node.name.to_s))
+ end
+
+ # @foo = 1
+ # ^^^^^^^^
+ def visit_instance_variable_write_node(node)
+ bounds(node.name_loc)
+ target = on_var_field(on_ivar(node.name.to_s))
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_assign(target, value)
+ end
+
+ # @foo += bar
+ # ^^^^^^^^^^^
+ def visit_instance_variable_operator_write_node(node)
+ bounds(node.name_loc)
+ target = on_var_field(on_ivar(node.name.to_s))
+
+ bounds(node.binary_operator_loc)
+ operator = on_op("#{node.binary_operator}=")
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_opassign(target, operator, value)
+ end
+
+ # @foo &&= bar
+ # ^^^^^^^^^^^^
+ def visit_instance_variable_and_write_node(node)
+ bounds(node.name_loc)
+ target = on_var_field(on_ivar(node.name.to_s))
+
+ bounds(node.operator_loc)
+ operator = on_op("&&=")
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_opassign(target, operator, value)
+ end
+
+ # @foo ||= bar
+ # ^^^^^^^^^^^^
+ def visit_instance_variable_or_write_node(node)
+ bounds(node.name_loc)
+ target = on_var_field(on_ivar(node.name.to_s))
+
+ bounds(node.operator_loc)
+ operator = on_op("||=")
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_opassign(target, operator, value)
+ end
+
+ # @foo, = bar
+ # ^^^^
+ def visit_instance_variable_target_node(node)
+ bounds(node.location)
+ on_var_field(on_ivar(node.name.to_s))
+ end
+
+ # 1
+ # ^
+ def visit_integer_node(node)
+ visit_number_node(node) { |text| on_int(text) }
+ end
+
+ # if /foo #{bar}/ then end
+ # ^^^^^^^^^^^^
+ def visit_interpolated_match_last_line_node(node)
+ bounds(node.opening_loc)
+ on_regexp_beg(node.opening)
+
+ bounds(node.parts.first.location)
+ parts =
+ node.parts.inject(on_regexp_new) do |content, part|
+ on_regexp_add(content, visit_string_content(part))
+ end
+
+ bounds(node.closing_loc)
+ closing = on_regexp_end(node.closing)
+
+ bounds(node.location)
+ on_regexp_literal(parts, closing)
+ end
+
+ # /foo #{bar}/
+ # ^^^^^^^^^^^^
+ def visit_interpolated_regular_expression_node(node)
+ bounds(node.opening_loc)
+ on_regexp_beg(node.opening)
+
+ bounds(node.parts.first.location)
+ parts =
+ node.parts.inject(on_regexp_new) do |content, part|
+ on_regexp_add(content, visit_string_content(part))
+ end
+
+ bounds(node.closing_loc)
+ closing = on_regexp_end(node.closing)
+
+ bounds(node.location)
+ on_regexp_literal(parts, closing)
+ end
+
+ # "foo #{bar}"
+ # ^^^^^^^^^^^^
+ def visit_interpolated_string_node(node)
+ if node.opening&.start_with?("<<~")
+ heredoc = visit_heredoc_string_node(node)
+
+ bounds(node.location)
+ on_string_literal(heredoc)
+ elsif !node.heredoc? && node.parts.length > 1 && node.parts.any? { |part| (part.is_a?(StringNode) || part.is_a?(InterpolatedStringNode)) && !part.opening_loc.nil? }
+ first, *rest = node.parts
+ rest.inject(visit(first)) do |content, part|
+ concat = visit(part)
+
+ bounds(part.location)
+ on_string_concat(content, concat)
+ end
+ else
+ bounds(node.parts.first.location)
+ parts =
+ node.parts.inject(on_string_content) do |content, part|
+ on_string_add(content, visit_string_content(part))
+ end
+
+ bounds(node.location)
+ on_string_literal(parts)
+ end
+ end
+
+ # :"foo #{bar}"
+ # ^^^^^^^^^^^^^
+ def visit_interpolated_symbol_node(node)
+ bounds(node.parts.first.location)
+ parts =
+ node.parts.inject(on_string_content) do |content, part|
+ on_string_add(content, visit_string_content(part))
+ end
+
+ bounds(node.location)
+ on_dyna_symbol(parts)
+ end
+
+ # `foo #{bar}`
+ # ^^^^^^^^^^^^
+ def visit_interpolated_x_string_node(node)
+ if node.opening.start_with?("<<~")
+ heredoc = visit_heredoc_x_string_node(node)
+
+ bounds(node.location)
+ on_xstring_literal(heredoc)
+ else
+ bounds(node.parts.first.location)
+ parts =
+ node.parts.inject(on_xstring_new) do |content, part|
+ on_xstring_add(content, visit_string_content(part))
+ end
+
+ bounds(node.location)
+ on_xstring_literal(parts)
+ end
+ end
+
+ # Visit an individual part of a string-like node.
+ private def visit_string_content(part)
+ if part.is_a?(StringNode)
+ bounds(part.content_loc)
+ on_tstring_content(part.content)
+ else
+ visit(part)
+ end
+ end
+
+ # -> { it }
+ # ^^
+ def visit_it_local_variable_read_node(node)
+ bounds(node.location)
+ on_vcall(on_ident(node.slice))
+ end
+
+ # -> { it }
+ # ^^^^^^^^^
+ def visit_it_parameters_node(node)
+ end
+
+ # foo(bar: baz)
+ # ^^^^^^^^
+ def visit_keyword_hash_node(node)
+ elements = visit_all(node.elements)
+
+ bounds(node.location)
+ on_bare_assoc_hash(elements)
+ end
+
+ # def foo(**bar); end
+ # ^^^^^
+ #
+ # def foo(**); end
+ # ^^
+ def visit_keyword_rest_parameter_node(node)
+ if node.name_loc.nil?
+ bounds(node.location)
+ on_kwrest_param(nil)
+ else
+ bounds(node.name_loc)
+ name = on_ident(node.name.to_s)
+
+ bounds(node.location)
+ on_kwrest_param(name)
+ end
+ end
+
+ # -> {}
+ def visit_lambda_node(node)
+ bounds(node.operator_loc)
+ on_tlambda(node.operator)
+
+ parameters =
+ if node.parameters.is_a?(BlockParametersNode)
+ # Ripper does not track block-locals within lambdas, so we skip
+ # directly to the parameters here.
+ params =
+ if node.parameters.parameters.nil?
+ bounds(node.location)
+ on_params(nil, nil, nil, nil, nil, nil, nil)
+ else
+ visit(node.parameters.parameters)
+ end
+
+ if node.parameters.opening_loc.nil?
+ params
+ else
+ bounds(node.parameters.opening_loc)
+ on_paren(params)
+ end
+ else
+ bounds(node.location)
+ on_params(nil, nil, nil, nil, nil, nil, nil)
+ end
+
+ braces = node.opening == "{"
+ if braces
+ bounds(node.opening_loc)
+ on_tlambeg(node.opening)
+ end
+
+ body =
+ case node.body
+ when nil
+ bounds(node.location)
+ stmts = on_stmts_add(on_stmts_new, on_void_stmt)
+
+ bounds(node.location)
+ braces ? stmts : on_bodystmt(stmts, nil, nil, nil)
+ when StatementsNode
+ stmts = node.body.body
+ stmts.unshift(nil) if void_stmt?(node.parameters&.location || node.opening_loc, node.body.location, false)
+ stmts = visit_statements_node_body(stmts)
+
+ bounds(node.body.location)
+ braces ? stmts : on_bodystmt(stmts, nil, nil, nil)
+ when BeginNode
+ visit_body_node(node.opening_loc, node.body)
+ else
+ raise
+ end
+
+ bounds(node.location)
+ on_lambda(parameters, body)
+ end
+
+ # foo
+ # ^^^
+ def visit_local_variable_read_node(node)
+ bounds(node.location)
+ on_var_ref(on_ident(node.slice))
+ end
+
+ # foo = 1
+ # ^^^^^^^
+ def visit_local_variable_write_node(node)
+ bounds(node.name_loc)
+ target = on_var_field(on_ident(node.name_loc.slice))
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_assign(target, value)
+ end
+
+ # foo += bar
+ # ^^^^^^^^^^
+ def visit_local_variable_operator_write_node(node)
+ bounds(node.name_loc)
+ target = on_var_field(on_ident(node.name_loc.slice))
+
+ bounds(node.binary_operator_loc)
+ operator = on_op("#{node.binary_operator}=")
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_opassign(target, operator, value)
+ end
+
+ # foo &&= bar
+ # ^^^^^^^^^^^
+ def visit_local_variable_and_write_node(node)
+ bounds(node.name_loc)
+ target = on_var_field(on_ident(node.name_loc.slice))
+
+ bounds(node.operator_loc)
+ operator = on_op("&&=")
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_opassign(target, operator, value)
+ end
+
+ # foo ||= bar
+ # ^^^^^^^^^^^
+ def visit_local_variable_or_write_node(node)
+ bounds(node.name_loc)
+ target = on_var_field(on_ident(node.name_loc.slice))
+
+ bounds(node.operator_loc)
+ operator = on_op("||=")
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_opassign(target, operator, value)
+ end
+
+ # foo, = bar
+ # ^^^
+ def visit_local_variable_target_node(node)
+ bounds(node.location)
+ on_var_field(on_ident(node.name.to_s))
+ end
+
+ # if /foo/ then end
+ # ^^^^^
+ def visit_match_last_line_node(node)
+ bounds(node.opening_loc)
+ on_regexp_beg(node.opening)
+
+ bounds(node.content_loc)
+ tstring_content = on_tstring_content(node.content)
+
+ bounds(node.closing_loc)
+ closing = on_regexp_end(node.closing)
+
+ on_regexp_literal(on_regexp_add(on_regexp_new, tstring_content), closing)
+ end
+
+ # foo in bar
+ # ^^^^^^^^^^
+ def visit_match_predicate_node(node)
+ value = visit(node.value)
+ pattern = on_in(visit_pattern_node(node.pattern), nil, nil)
+
+ on_case(value, pattern)
+ end
+
+ # foo => bar
+ # ^^^^^^^^^^
+ def visit_match_required_node(node)
+ value = visit(node.value)
+ pattern = on_in(visit_pattern_node(node.pattern), nil, nil)
+
+ on_case(value, pattern)
+ end
+
+ # /(?<foo>foo)/ =~ bar
+ # ^^^^^^^^^^^^^^^^^^^^
+ def visit_match_write_node(node)
+ visit(node.call)
+ end
+
+ # A node that is missing from the syntax tree. This is only used in the
+ # case of a syntax error.
+ def visit_missing_node(node)
+ raise "Cannot visit missing nodes directly."
+ end
+
+ # module Foo; end
+ # ^^^^^^^^^^^^^^^
+ def visit_module_node(node)
+ constant_path =
+ if node.constant_path.is_a?(ConstantReadNode)
+ bounds(node.constant_path.location)
+ on_const_ref(on_const(node.constant_path.name.to_s))
+ else
+ visit(node.constant_path)
+ end
+
+ bodystmt = visit_body_node(node.constant_path.location, node.body, true)
+
+ bounds(node.location)
+ on_module(constant_path, bodystmt)
+ end
+
+ # (foo, bar), bar = qux
+ # ^^^^^^^^^^
+ def visit_multi_target_node(node)
+ bounds(node.location)
+ targets = visit_multi_target_node_targets(node.lefts, node.rest, node.rights, true)
+
+ if node.lparen_loc.nil?
+ targets
+ else
+ bounds(node.lparen_loc)
+ on_mlhs_paren(targets)
+ end
+ end
+
+ # Visit the targets of a multi-target node.
+ private def visit_multi_target_node_targets(lefts, rest, rights, skippable)
+ if skippable && lefts.length == 1 && lefts.first.is_a?(MultiTargetNode) && rest.nil? && rights.empty?
+ return visit(lefts.first)
+ end
+
+ mlhs = on_mlhs_new
+
+ lefts.each do |left|
+ bounds(left.location)
+ mlhs = on_mlhs_add(mlhs, visit(left))
+ end
+
+ case rest
+ when nil
+ # do nothing
+ when ImplicitRestNode
+ # these do not get put into the generated tree
+ bounds(rest.location)
+ on_excessed_comma
+ else
+ bounds(rest.location)
+ mlhs = on_mlhs_add_star(mlhs, visit(rest))
+ end
+
+ if rights.any?
+ bounds(rights.first.location)
+ post = on_mlhs_new
+
+ rights.each do |right|
+ bounds(right.location)
+ post = on_mlhs_add(post, visit(right))
+ end
+
+ mlhs = on_mlhs_add_post(mlhs, post)
+ end
+
+ mlhs
+ end
+
+ # foo, bar = baz
+ # ^^^^^^^^^^^^^^
+ def visit_multi_write_node(node)
+ bounds(node.location)
+ targets = visit_multi_target_node_targets(node.lefts, node.rest, node.rights, true)
+
+ unless node.lparen_loc.nil?
+ bounds(node.lparen_loc)
+ targets = on_mlhs_paren(targets)
+ end
+
+ value = visit_write_value(node.value)
+
+ bounds(node.location)
+ on_massign(targets, value)
+ end
+
+ # next
+ # ^^^^
+ #
+ # next foo
+ # ^^^^^^^^
+ def visit_next_node(node)
+ if node.arguments.nil?
+ bounds(node.location)
+ on_next(on_args_new)
+ else
+ arguments = visit(node.arguments)
+
+ bounds(node.location)
+ on_next(arguments)
+ end
+ end
+
+ # nil
+ # ^^^
+ def visit_nil_node(node)
+ bounds(node.location)
+ on_var_ref(on_kw("nil"))
+ end
+
+ # def foo(**nil); end
+ # ^^^^^
+ def visit_no_keywords_parameter_node(node)
+ bounds(node.location)
+ on_nokw_param(nil)
+
+ :nil
+ end
+
+ # -> { _1 + _2 }
+ # ^^^^^^^^^^^^^^
+ def visit_numbered_parameters_node(node)
+ end
+
+ # $1
+ # ^^
+ def visit_numbered_reference_read_node(node)
+ bounds(node.location)
+ on_backref(node.slice)
+ end
+
+ # def foo(bar: baz); end
+ # ^^^^^^^^
+ def visit_optional_keyword_parameter_node(node)
+ bounds(node.name_loc)
+ name = on_label("#{node.name}:")
+ value = visit(node.value)
+
+ [name, value]
+ end
+
+ # def foo(bar = 1); end
+ # ^^^^^^^
+ def visit_optional_parameter_node(node)
+ bounds(node.name_loc)
+ name = visit_token(node.name.to_s)
+ value = visit(node.value)
+
+ [name, value]
+ end
+
+ # a or b
+ # ^^^^^^
+ def visit_or_node(node)
+ left = visit(node.left)
+ right = visit(node.right)
+
+ bounds(node.location)
+ on_binary(left, node.operator.to_sym, right)
+ end
+
+ # def foo(bar, *baz); end
+ # ^^^^^^^^^
+ def visit_parameters_node(node)
+ requireds = node.requireds.map { |required| required.is_a?(MultiTargetNode) ? visit_destructured_parameter_node(required) : visit(required) } if node.requireds.any?
+ optionals = visit_all(node.optionals) if node.optionals.any?
+ rest = visit(node.rest)
+ posts = node.posts.map { |post| post.is_a?(MultiTargetNode) ? visit_destructured_parameter_node(post) : visit(post) } if node.posts.any?
+ keywords = visit_all(node.keywords) if node.keywords.any?
+ keyword_rest = visit(node.keyword_rest)
+ block = visit(node.block)
+
+ bounds(node.location)
+ on_params(requireds, optionals, rest, posts, keywords, keyword_rest, block)
+ end
+
+ # Visit a destructured positional parameter node.
+ private def visit_destructured_parameter_node(node)
+ bounds(node.location)
+ targets = visit_multi_target_node_targets(node.lefts, node.rest, node.rights, false)
+
+ bounds(node.lparen_loc)
+ on_mlhs_paren(targets)
+ end
+
+ # ()
+ # ^^
+ #
+ # (1)
+ # ^^^
+ def visit_parentheses_node(node)
+ body =
+ if node.body.nil?
+ on_stmts_add(on_stmts_new, on_void_stmt)
+ else
+ visit(node.body)
+ end
+
+ bounds(node.location)
+ on_paren(body)
+ end
+
+ # foo => ^(bar)
+ # ^^^^^^
+ def visit_pinned_expression_node(node)
+ expression = visit(node.expression)
+
+ bounds(node.location)
+ on_begin(expression)
+ end
+
+ # foo = 1 and bar => ^foo
+ # ^^^^
+ def visit_pinned_variable_node(node)
+ visit(node.variable)
+ end
+
+ # END {}
+ # ^^^^^^
+ def visit_post_execution_node(node)
+ statements =
+ if node.statements.nil?
+ bounds(node.location)
+ on_stmts_add(on_stmts_new, on_void_stmt)
+ else
+ visit(node.statements)
+ end
+
+ bounds(node.location)
+ on_END(statements)
+ end
+
+ # BEGIN {}
+ # ^^^^^^^^
+ def visit_pre_execution_node(node)
+ statements =
+ if node.statements.nil?
+ bounds(node.location)
+ on_stmts_add(on_stmts_new, on_void_stmt)
+ else
+ visit(node.statements)
+ end
+
+ bounds(node.location)
+ on_BEGIN(statements)
+ end
+
+ # The top-level program node.
+ def visit_program_node(node)
+ body = node.statements.body
+ body << nil if body.empty?
+ statements = visit_statements_node_body(body)
+
+ bounds(node.location)
+ on_program(statements)
+ end
+
+ # 0..5
+ # ^^^^
+ def visit_range_node(node)
+ left = visit(node.left)
+ right = visit(node.right)
+
+ bounds(node.location)
+ if node.exclude_end?
+ on_dot3(left, right)
+ else
+ on_dot2(left, right)
+ end
+ end
+
+ # 1r
+ # ^^
+ def visit_rational_node(node)
+ visit_number_node(node) { |text| on_rational(text) }
+ end
+
+ # redo
+ # ^^^^
+ def visit_redo_node(node)
+ bounds(node.location)
+ on_redo
+ end
+
+ # /foo/
+ # ^^^^^
+ def visit_regular_expression_node(node)
+ bounds(node.opening_loc)
+ on_regexp_beg(node.opening)
+
+ if node.content.empty?
+ bounds(node.closing_loc)
+ closing = on_regexp_end(node.closing)
+
+ on_regexp_literal(on_regexp_new, closing)
+ else
+ bounds(node.content_loc)
+ tstring_content = on_tstring_content(node.content)
+
+ bounds(node.closing_loc)
+ closing = on_regexp_end(node.closing)
+
+ on_regexp_literal(on_regexp_add(on_regexp_new, tstring_content), closing)
+ end
+ end
+
+ # def foo(bar:); end
+ # ^^^^
+ def visit_required_keyword_parameter_node(node)
+ bounds(node.name_loc)
+ [on_label("#{node.name}:"), false]
+ end
+
+ # def foo(bar); end
+ # ^^^
+ def visit_required_parameter_node(node)
+ bounds(node.location)
+ on_ident(node.name.to_s)
+ end
+
+ # foo rescue bar
+ # ^^^^^^^^^^^^^^
+ def visit_rescue_modifier_node(node)
+ expression = visit_write_value(node.expression)
+ rescue_expression = visit(node.rescue_expression)
+
+ bounds(node.location)
+ on_rescue_mod(expression, rescue_expression)
+ end
+
+ # begin; rescue; end
+ # ^^^^^^^
+ def visit_rescue_node(node)
+ exceptions =
+ case node.exceptions.length
+ when 0
+ nil
+ when 1
+ if (exception = node.exceptions.first).is_a?(SplatNode)
+ bounds(exception.location)
+ on_mrhs_add_star(on_mrhs_new, visit(exception))
+ else
+ [visit(node.exceptions.first)]
+ end
+ else
+ bounds(node.location)
+ length = node.exceptions.length
+
+ node.exceptions.each_with_index.inject(on_args_new) do |mrhs, (exception, index)|
+ arg = visit(exception)
+
+ bounds(exception.location)
+ mrhs = on_mrhs_new_from_args(mrhs) if index == length - 1
+
+ if exception.is_a?(SplatNode)
+ if index == length - 1
+ on_mrhs_add_star(mrhs, arg)
+ else
+ on_args_add_star(mrhs, arg)
+ end
+ else
+ if index == length - 1
+ on_mrhs_add(mrhs, arg)
+ else
+ on_args_add(mrhs, arg)
+ end
+ end
+ end
+ end
+
+ reference = visit(node.reference)
+ statements =
+ if node.statements.nil?
+ bounds(node.location)
+ on_stmts_add(on_stmts_new, on_void_stmt)
+ else
+ visit(node.statements)
+ end
+
+ consequent = visit(node.consequent)
+
+ bounds(node.location)
+ on_rescue(exceptions, reference, statements, consequent)
+ end
+
+ # def foo(*bar); end
+ # ^^^^
+ #
+ # def foo(*); end
+ # ^
+ def visit_rest_parameter_node(node)
+ if node.name_loc.nil?
+ bounds(node.location)
+ on_rest_param(nil)
+ else
+ bounds(node.name_loc)
+ on_rest_param(visit_token(node.name.to_s))
+ end
+ end
+
+ # retry
+ # ^^^^^
+ def visit_retry_node(node)
+ bounds(node.location)
+ on_retry
+ end
+
+ # return
+ # ^^^^^^
+ #
+ # return 1
+ # ^^^^^^^^
+ def visit_return_node(node)
+ if node.arguments.nil?
+ bounds(node.location)
+ on_return0
+ else
+ arguments = visit(node.arguments)
+
+ bounds(node.location)
+ on_return(arguments)
+ end
+ end
+
+ # self
+ # ^^^^
+ def visit_self_node(node)
+ bounds(node.location)
+ on_var_ref(on_kw("self"))
+ end
+
+ # A shareable constant.
+ def visit_shareable_constant_node(node)
+ visit(node.write)
+ end
+
+ # class << self; end
+ # ^^^^^^^^^^^^^^^^^^
+ def visit_singleton_class_node(node)
+ expression = visit(node.expression)
+ bodystmt = visit_body_node(node.body&.location || node.end_keyword_loc, node.body)
+
+ bounds(node.location)
+ on_sclass(expression, bodystmt)
+ end
+
+ # __ENCODING__
+ # ^^^^^^^^^^^^
+ def visit_source_encoding_node(node)
+ bounds(node.location)
+ on_var_ref(on_kw("__ENCODING__"))
+ end
+
+ # __FILE__
+ # ^^^^^^^^
+ def visit_source_file_node(node)
+ bounds(node.location)
+ on_var_ref(on_kw("__FILE__"))
+ end
+
+ # __LINE__
+ # ^^^^^^^^
+ def visit_source_line_node(node)
+ bounds(node.location)
+ on_var_ref(on_kw("__LINE__"))
+ end
+
+ # foo(*bar)
+ # ^^^^
+ #
+ # def foo((bar, *baz)); end
+ # ^^^^
+ #
+ # def foo(*); bar(*); end
+ # ^
+ def visit_splat_node(node)
+ visit(node.expression)
+ end
+
+ # A list of statements.
+ def visit_statements_node(node)
+ bounds(node.location)
+ visit_statements_node_body(node.body)
+ end
+
+ # Visit the list of statements of a statements node. We support nil
+ # statements in the list. This would normally not be allowed by the
+ # structure of the prism parse tree, but we manually add them here so that
+ # we can mirror Ripper's void stmt.
+ private def visit_statements_node_body(body)
+ body.inject(on_stmts_new) do |stmts, stmt|
+ on_stmts_add(stmts, stmt.nil? ? on_void_stmt : visit(stmt))
+ end
+ end
+
+ # "foo"
+ # ^^^^^
+ def visit_string_node(node)
+ if (content = node.content).empty?
+ bounds(node.location)
+ on_string_literal(on_string_content)
+ elsif (opening = node.opening) == "?"
+ bounds(node.location)
+ on_CHAR("?#{node.content}")
+ elsif opening.start_with?("<<~")
+ heredoc = visit_heredoc_string_node(node.to_interpolated)
+
+ bounds(node.location)
+ on_string_literal(heredoc)
+ else
+ bounds(node.content_loc)
+ tstring_content = on_tstring_content(content)
+
+ bounds(node.location)
+ on_string_literal(on_string_add(on_string_content, tstring_content))
+ end
+ end
+
+ # Ripper gives back the escaped string content but strips out the common
+ # leading whitespace. Prism gives back the unescaped string content and
+ # a location for the escaped string content. Unfortunately these don't
+ # work well together, so here we need to re-derive the common leading
+ # whitespace.
+ private def visit_heredoc_node_whitespace(parts)
+ common_whitespace = nil
+ dedent_next = true
+
+ parts.each do |part|
+ if part.is_a?(StringNode)
+ if dedent_next && !(content = part.content).chomp.empty?
+ common_whitespace = [
+ common_whitespace || Float::INFINITY,
+ content[/\A\s*/].each_char.inject(0) do |part_whitespace, char|
+ char == "\t" ? ((part_whitespace / 8 + 1) * 8) : (part_whitespace + 1)
+ end
+ ].min
+ end
+
+ dedent_next = true
+ else
+ dedent_next = false
+ end
+ end
+
+ common_whitespace || 0
+ end
+
+ # Visit a string that is expressed using a <<~ heredoc.
+ private def visit_heredoc_node(parts, base)
+ common_whitespace = visit_heredoc_node_whitespace(parts)
+
+ if common_whitespace == 0
+ bounds(parts.first.location)
+
+ string = []
+ result = base
+
+ parts.each do |part|
+ if part.is_a?(StringNode)
+ if string.empty?
+ string = [part]
+ else
+ string << part
+ end
+ else
+ unless string.empty?
+ bounds(string[0].location)
+ result = yield result, on_tstring_content(string.map(&:content).join)
+ string = []
+ end
+
+ result = yield result, visit(part)
+ end
+ end
+
+ unless string.empty?
+ bounds(string[0].location)
+ result = yield result, on_tstring_content(string.map(&:content).join)
+ end
+
+ result
+ else
+ bounds(parts.first.location)
+ result =
+ parts.inject(base) do |string_content, part|
+ yield string_content, visit_string_content(part)
+ end
+
+ bounds(parts.first.location)
+ on_heredoc_dedent(result, common_whitespace)
+ end
+ end
+
+ # Visit a heredoc node that is representing a string.
+ private def visit_heredoc_string_node(node)
+ bounds(node.opening_loc)
+ on_heredoc_beg(node.opening)
+
+ bounds(node.location)
+ result =
+ visit_heredoc_node(node.parts, on_string_content) do |parts, part|
+ on_string_add(parts, part)
+ end
+
+ bounds(node.closing_loc)
+ on_heredoc_end(node.closing)
+
+ result
+ end
+
+ # Visit a heredoc node that is representing an xstring.
+ private def visit_heredoc_x_string_node(node)
+ bounds(node.opening_loc)
+ on_heredoc_beg(node.opening)
+
+ bounds(node.location)
+ result =
+ visit_heredoc_node(node.parts, on_xstring_new) do |parts, part|
+ on_xstring_add(parts, part)
+ end
+
+ bounds(node.closing_loc)
+ on_heredoc_end(node.closing)
+
+ result
+ end
+
+ # super(foo)
+ # ^^^^^^^^^^
+ def visit_super_node(node)
+ arguments, block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.rparen_loc || node.location))
+
+ if !node.lparen_loc.nil?
+ bounds(node.lparen_loc)
+ arguments = on_arg_paren(arguments)
+ end
+
+ bounds(node.location)
+ call = on_super(arguments)
+
+ if block.nil?
+ call
+ else
+ bounds(node.block.location)
+ on_method_add_block(call, block)
+ end
+ end
+
+ # :foo
+ # ^^^^
+ def visit_symbol_node(node)
+ if (opening = node.opening)&.match?(/^%s|['"]:?$/)
+ bounds(node.value_loc)
+ content = on_string_content
+
+ if !(value = node.value).empty?
+ content = on_string_add(content, on_tstring_content(value))
+ end
+
+ on_dyna_symbol(content)
+ elsif (closing = node.closing) == ":"
+ bounds(node.location)
+ on_label("#{node.value}:")
+ elsif opening.nil? && node.closing_loc.nil?
+ bounds(node.value_loc)
+ on_symbol_literal(visit_token(node.value))
+ else
+ bounds(node.value_loc)
+ on_symbol_literal(on_symbol(visit_token(node.value)))
+ end
+ end
+
+ # true
+ # ^^^^
+ def visit_true_node(node)
+ bounds(node.location)
+ on_var_ref(on_kw("true"))
+ end
+
+ # undef foo
+ # ^^^^^^^^^
+ def visit_undef_node(node)
+ names = visit_all(node.names)
+
+ bounds(node.location)
+ on_undef(names)
+ end
+
+ # unless foo; bar end
+ # ^^^^^^^^^^^^^^^^^^^
+ #
+ # bar unless foo
+ # ^^^^^^^^^^^^^^
+ def visit_unless_node(node)
+ if node.statements.nil? || (node.predicate.location.start_offset < node.statements.location.start_offset)
+ predicate = visit(node.predicate)
+ statements =
+ if node.statements.nil?
+ bounds(node.location)
+ on_stmts_add(on_stmts_new, on_void_stmt)
+ else
+ visit(node.statements)
+ end
+ consequent = visit(node.consequent)
+
+ bounds(node.location)
+ on_unless(predicate, statements, consequent)
+ else
+ statements = visit(node.statements.body.first)
+ predicate = visit(node.predicate)
+
+ bounds(node.location)
+ on_unless_mod(predicate, statements)
+ end
+ end
+
+ # until foo; bar end
+ # ^^^^^^^^^^^^^^^^^
+ #
+ # bar until foo
+ # ^^^^^^^^^^^^^
+ def visit_until_node(node)
+ if node.statements.nil? || (node.predicate.location.start_offset < node.statements.location.start_offset)
+ predicate = visit(node.predicate)
+ statements =
+ if node.statements.nil?
+ bounds(node.location)
+ on_stmts_add(on_stmts_new, on_void_stmt)
+ else
+ visit(node.statements)
+ end
+
+ bounds(node.location)
+ on_until(predicate, statements)
+ else
+ statements = visit(node.statements.body.first)
+ predicate = visit(node.predicate)
+
+ bounds(node.location)
+ on_until_mod(predicate, statements)
+ end
+ end
+
+ # case foo; when bar; end
+ # ^^^^^^^^^^^^^
+ def visit_when_node(node)
+ # This is a special case where we're not going to call on_when directly
+ # because we don't have access to the consequent. Instead, we'll return
+ # the component parts and let the parent node handle it.
+ conditions = visit_arguments(node.conditions)
+ statements =
+ if node.statements.nil?
+ bounds(node.location)
+ on_stmts_add(on_stmts_new, on_void_stmt)
+ else
+ visit(node.statements)
+ end
+
+ [conditions, statements]
+ end
+
+ # while foo; bar end
+ # ^^^^^^^^^^^^^^^^^^
+ #
+ # bar while foo
+ # ^^^^^^^^^^^^^
+ def visit_while_node(node)
+ if node.statements.nil? || (node.predicate.location.start_offset < node.statements.location.start_offset)
+ predicate = visit(node.predicate)
+ statements =
+ if node.statements.nil?
+ bounds(node.location)
+ on_stmts_add(on_stmts_new, on_void_stmt)
+ else
+ visit(node.statements)
+ end
+
+ bounds(node.location)
+ on_while(predicate, statements)
+ else
+ statements = visit(node.statements.body.first)
+ predicate = visit(node.predicate)
+
+ bounds(node.location)
+ on_while_mod(predicate, statements)
+ end
+ end
+
+ # `foo`
+ # ^^^^^
+ def visit_x_string_node(node)
+ if node.unescaped.empty?
+ bounds(node.location)
+ on_xstring_literal(on_xstring_new)
+ elsif node.opening.start_with?("<<~")
+ heredoc = visit_heredoc_x_string_node(node.to_interpolated)
+
+ bounds(node.location)
+ on_xstring_literal(heredoc)
+ else
+ bounds(node.content_loc)
+ content = on_tstring_content(node.content)
+
+ bounds(node.location)
+ on_xstring_literal(on_xstring_add(on_xstring_new, content))
+ end
+ end
+
+ # yield
+ # ^^^^^
+ #
+ # yield 1
+ # ^^^^^^^
+ def visit_yield_node(node)
+ if node.arguments.nil? && node.lparen_loc.nil?
+ bounds(node.location)
+ on_yield0
+ else
+ arguments =
+ if node.arguments.nil?
+ bounds(node.location)
+ on_args_new
+ else
+ visit(node.arguments)
+ end
+
+ unless node.lparen_loc.nil?
+ bounds(node.lparen_loc)
+ arguments = on_paren(arguments)
+ end
+
+ bounds(node.location)
+ on_yield(arguments)
+ end
+ end
+
+ private
+
+ # Lazily initialize the parse result.
+ def result
+ @result ||=
+ begin
+ scopes = RUBY_VERSION >= "3.3.0" ? [] : [[]]
+ Prism.parse(source, scopes: scopes)
+ end
+ end
+
+ ##########################################################################
+ # Helpers
+ ##########################################################################
+
+ # Returns true if there is a comma between the two locations.
+ def trailing_comma?(left, right)
+ source.byteslice(left.end_offset...right.start_offset).include?(",")
+ end
+
+ # Returns true if there is a semicolon between the two locations.
+ def void_stmt?(left, right, allow_newline)
+ pattern = allow_newline ? /[;\n]/ : /;/
+ source.byteslice(left.end_offset...right.start_offset).match?(pattern)
+ end
+
+ # Visit the string content of a particular node. This method is used to
+ # split into the various token types.
+ def visit_token(token, allow_keywords = true)
+ case token
+ when "."
+ on_period(token)
+ when "`"
+ on_backtick(token)
+ when *(allow_keywords ? KEYWORDS : [])
+ on_kw(token)
+ when /^_/
+ on_ident(token)
+ when /^[[:upper:]]\w*$/
+ on_const(token)
+ when /^@@/
+ on_cvar(token)
+ when /^@/
+ on_ivar(token)
+ when /^\$/
+ on_gvar(token)
+ when /^[[:punct:]]/
+ on_op(token)
+ else
+ on_ident(token)
+ end
+ end
+
+ # Visit a node that represents a number. We need to explicitly handle the
+ # unary - operator.
+ def visit_number_node(node)
+ slice = node.slice
+ location = node.location
+
+ if slice[0] == "-"
+ bounds(location.copy(start_offset: location.start_offset + 1))
+ value = yield slice[1..-1]
+
+ bounds(node.location)
+ on_unary(:-@, value)
+ else
+ bounds(location)
+ yield slice
+ end
+ end
+
+ # Visit a node that represents a write value. This is used to handle the
+ # special case of an implicit array that is generated without brackets.
+ def visit_write_value(node)
+ if node.is_a?(ArrayNode) && node.opening_loc.nil?
+ elements = node.elements
+ length = elements.length
+
+ bounds(elements.first.location)
+ elements.each_with_index.inject((elements.first.is_a?(SplatNode) && length == 1) ? on_mrhs_new : on_args_new) do |args, (element, index)|
+ arg = visit(element)
+ bounds(element.location)
+
+ if index == length - 1
+ if element.is_a?(SplatNode)
+ mrhs = index == 0 ? args : on_mrhs_new_from_args(args)
+ on_mrhs_add_star(mrhs, arg)
+ else
+ on_mrhs_add(on_mrhs_new_from_args(args), arg)
+ end
+ else
+ case element
+ when BlockArgumentNode
+ on_args_add_block(args, arg)
+ when SplatNode
+ on_args_add_star(args, arg)
+ else
+ on_args_add(args, arg)
+ end
+ end
+ end
+ else
+ visit(node)
+ end
+ end
+
+ # This method is responsible for updating lineno and column information
+ # to reflect the current node.
+ #
+ # This method could be drastically improved with some caching on the start
+ # of every line, but for now it's good enough.
+ def bounds(location)
+ @lineno = location.start_line
+ @column = location.start_column
+ end
+
+ ##########################################################################
+ # Ripper interface
+ ##########################################################################
+
+ # :stopdoc:
+ def _dispatch_0; end
+ def _dispatch_1(_); end
+ def _dispatch_2(_, _); end
+ def _dispatch_3(_, _, _); end
+ def _dispatch_4(_, _, _, _); end
+ def _dispatch_5(_, _, _, _, _); end
+ def _dispatch_7(_, _, _, _, _, _, _); end
+ # :startdoc:
+
+ #
+ # Parser Events
+ #
+
+ PARSER_EVENT_TABLE.each do |id, arity|
+ alias_method "on_#{id}", "_dispatch_#{arity}"
+ end
+
+ # This method is called when weak warning is produced by the parser.
+ # +fmt+ and +args+ is printf style.
+ def warn(fmt, *args)
+ end
+
+ # This method is called when strong warning is produced by the parser.
+ # +fmt+ and +args+ is printf style.
+ def warning(fmt, *args)
+ end
+
+ # This method is called when the parser found syntax error.
+ def compile_error(msg)
+ end
+
+ #
+ # Scanner Events
+ #
+
+ SCANNER_EVENTS.each do |id|
+ alias_method "on_#{id}", :_dispatch_1
+ end
+
+ # This method is provided by the Ripper C extension. It is called when a
+ # string needs to be dedented because of a tilde heredoc. It is expected
+ # that it will modify the string in place and return the number of bytes
+ # that were removed.
+ def dedent_string(string, width)
+ whitespace = 0
+ cursor = 0
+
+ while cursor < string.length && string[cursor].match?(/\s/) && whitespace < width
+ if string[cursor] == "\t"
+ whitespace = ((whitespace / 8 + 1) * 8)
+ break if whitespace > width
+ else
+ whitespace += 1
+ end
+
+ cursor += 1
+ end
+
+ string.replace(string[cursor..])
+ cursor
+ end
+ end
+ end
+end
diff --git a/lib/prism/translation/ripper/sexp.rb b/lib/prism/translation/ripper/sexp.rb
new file mode 100644
index 0000000000..dc26a639a3
--- /dev/null
+++ b/lib/prism/translation/ripper/sexp.rb
@@ -0,0 +1,125 @@
+# frozen_string_literal: true
+
+require_relative "../ripper"
+
+module Prism
+ module Translation
+ class Ripper
+ # This class mirrors the ::Ripper::SexpBuilder subclass of ::Ripper that
+ # returns the arrays of [type, *children].
+ class SexpBuilder < Ripper
+ # :stopdoc:
+
+ attr_reader :error
+
+ private
+
+ def dedent_element(e, width)
+ if (n = dedent_string(e[1], width)) > 0
+ e[2][1] += n
+ end
+ e
+ end
+
+ def on_heredoc_dedent(val, width)
+ sub = proc do |cont|
+ cont.map! do |e|
+ if Array === e
+ case e[0]
+ when :@tstring_content
+ e = dedent_element(e, width)
+ when /_add\z/
+ e[1] = sub[e[1]]
+ end
+ elsif String === e
+ dedent_string(e, width)
+ end
+ e
+ end
+ end
+ sub[val]
+ val
+ end
+
+ events = private_instance_methods(false).grep(/\Aon_/) {$'.to_sym}
+ (PARSER_EVENTS - events).each do |event|
+ module_eval(<<-End, __FILE__, __LINE__ + 1)
+ def on_#{event}(*args)
+ args.unshift :#{event}
+ end
+ End
+ end
+
+ SCANNER_EVENTS.each do |event|
+ module_eval(<<-End, __FILE__, __LINE__ + 1)
+ def on_#{event}(tok)
+ [:@#{event}, tok, [lineno(), column()]]
+ end
+ End
+ end
+
+ def on_error(mesg)
+ @error = mesg
+ end
+ remove_method :on_parse_error
+ alias on_parse_error on_error
+ alias compile_error on_error
+
+ # :startdoc:
+ end
+
+ # This class mirrors the ::Ripper::SexpBuilderPP subclass of ::Ripper that
+ # returns the same values as ::Ripper::SexpBuilder except with a couple of
+ # niceties that flatten linked lists into arrays.
+ class SexpBuilderPP < SexpBuilder
+ # :stopdoc:
+
+ private
+
+ def on_heredoc_dedent(val, width)
+ val.map! do |e|
+ next e if Symbol === e and /_content\z/ =~ e
+ if Array === e and e[0] == :@tstring_content
+ e = dedent_element(e, width)
+ elsif String === e
+ dedent_string(e, width)
+ end
+ e
+ end
+ val
+ end
+
+ def _dispatch_event_new
+ []
+ end
+
+ def _dispatch_event_push(list, item)
+ list.push item
+ list
+ end
+
+ def on_mlhs_paren(list)
+ [:mlhs, *list]
+ end
+
+ def on_mlhs_add_star(list, star)
+ list.push([:rest_param, star])
+ end
+
+ def on_mlhs_add_post(list, post)
+ list.concat(post)
+ end
+
+ PARSER_EVENT_TABLE.each do |event, arity|
+ if /_new\z/ =~ event and arity == 0
+ alias_method "on_#{event}", :_dispatch_event_new
+ elsif /_add\z/ =~ event
+ alias_method "on_#{event}", :_dispatch_event_push
+ end
+ end
+
+ # :startdoc:
+ end
+ end
+ end
+end
diff --git a/lib/prism/translation/ripper/shim.rb b/lib/prism/translation/ripper/shim.rb
new file mode 100644
index 0000000000..10e21cd16a
--- /dev/null
+++ b/lib/prism/translation/ripper/shim.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+# This writes the prism ripper translation into the Ripper constant so that
+# users can transparently use Ripper without any changes.
+Ripper = Prism::Translation::Ripper
diff --git a/lib/prism/translation/ruby_parser.rb b/lib/prism/translation/ruby_parser.rb
new file mode 100644
index 0000000000..38690c54b3
--- /dev/null
+++ b/lib/prism/translation/ruby_parser.rb
@@ -0,0 +1,1594 @@
+# frozen_string_literal: true
+
+begin
+ require "ruby_parser"
+rescue LoadError
+ warn(%q{Error: Unable to load ruby_parser. Add `gem "ruby_parser"` to your Gemfile.})
+ exit(1)
+end
+
+module Prism
+ module Translation
+ # This module is the entry-point for converting a prism syntax tree into the
+ # seattlerb/ruby_parser gem's syntax tree.
+ class RubyParser
+ # A prism visitor that builds Sexp objects.
+ class Compiler < ::Prism::Compiler
+ # This is the name of the file that we are compiling. We set it on every
+ # Sexp object that is generated, and also use it to compile __FILE__
+ # nodes.
+ attr_reader :file
+
+ # Class variables will change their type based on if they are inside of
+ # a method definition or not, so we need to track that state.
+ attr_reader :in_def
+
+ # Some nodes will change their representation if they are inside of a
+ # pattern, so we need to track that state.
+ attr_reader :in_pattern
+
+ # Initialize a new compiler with the given file name.
+ def initialize(file, in_def: false, in_pattern: false)
+ @file = file
+ @in_def = in_def
+ @in_pattern = in_pattern
+ end
+
+ # alias foo bar
+ # ^^^^^^^^^^^^^
+ def visit_alias_method_node(node)
+ s(node, :alias, visit(node.new_name), visit(node.old_name))
+ end
+
+ # alias $foo $bar
+ # ^^^^^^^^^^^^^^^
+ def visit_alias_global_variable_node(node)
+ s(node, :valias, node.new_name.name, node.old_name.name)
+ end
+
+ # foo => bar | baz
+ # ^^^^^^^^^
+ def visit_alternation_pattern_node(node)
+ s(node, :or, visit(node.left), visit(node.right))
+ end
+
+ # a and b
+ # ^^^^^^^
+ def visit_and_node(node)
+ s(node, :and, visit(node.left), visit(node.right))
+ end
+
+ # []
+ # ^^
+ def visit_array_node(node)
+ if in_pattern
+ s(node, :array_pat, nil).concat(visit_all(node.elements))
+ else
+ s(node, :array).concat(visit_all(node.elements))
+ end
+ end
+
+ # foo => [bar]
+ # ^^^^^
+ def visit_array_pattern_node(node)
+ if node.constant.nil? && node.requireds.empty? && node.rest.nil? && node.posts.empty?
+ s(node, :array_pat)
+ else
+ result = s(node, :array_pat, visit_pattern_constant(node.constant)).concat(visit_all(node.requireds))
+
+ case node.rest
+ when SplatNode
+ result << :"*#{node.rest.expression&.name}"
+ when ImplicitRestNode
+ result << :*
+
+ # This doesn't make any sense at all, but since we're trying to
+ # replicate the behavior directly, we'll copy it.
+ result.line(666)
+ end
+
+ result.concat(visit_all(node.posts))
+ end
+ end
+
+ # foo(bar)
+ # ^^^
+ def visit_arguments_node(node)
+ raise "Cannot visit arguments directly"
+ end
+
+ # { a: 1 }
+ # ^^^^
+ def visit_assoc_node(node)
+ [visit(node.key), visit(node.value)]
+ end
+
+ # def foo(**); bar(**); end
+ # ^^
+ #
+ # { **foo }
+ # ^^^^^
+ def visit_assoc_splat_node(node)
+ if node.value.nil?
+ [s(node, :kwsplat)]
+ else
+ [s(node, :kwsplat, visit(node.value))]
+ end
+ end
+
+ # $+
+ # ^^
+ def visit_back_reference_read_node(node)
+ s(node, :back_ref, node.name.name.delete_prefix("$").to_sym)
+ end
+
+ # begin end
+ # ^^^^^^^^^
+ def visit_begin_node(node)
+ result = node.statements.nil? ? s(node, :nil) : visit(node.statements)
+
+ if !node.rescue_clause.nil?
+ if !node.statements.nil?
+ result = s(node.statements, :rescue, result, visit(node.rescue_clause))
+ else
+ result = s(node.rescue_clause, :rescue, visit(node.rescue_clause))
+ end
+
+ current = node.rescue_clause
+ until (current = current.consequent).nil?
+ result << visit(current)
+ end
+ end
+
+ if !node.else_clause&.statements.nil?
+ result << visit(node.else_clause)
+ end
+
+ if !node.ensure_clause.nil?
+ if !node.statements.nil? || !node.rescue_clause.nil? || !node.else_clause.nil?
+ result = s(node.statements || node.rescue_clause || node.else_clause || node.ensure_clause, :ensure, result, visit(node.ensure_clause))
+ else
+ result = s(node.ensure_clause, :ensure, visit(node.ensure_clause))
+ end
+ end
+
+ result
+ end
+
+ # foo(&bar)
+ # ^^^^
+ def visit_block_argument_node(node)
+ s(node, :block_pass).tap do |result|
+ result << visit(node.expression) unless node.expression.nil?
+ end
+ end
+
+ # foo { |; bar| }
+ # ^^^
+ def visit_block_local_variable_node(node)
+ node.name
+ end
+
+ # A block on a keyword or method call.
+ def visit_block_node(node)
+ s(node, :block_pass, visit(node.expression))
+ end
+
+ # def foo(&bar); end
+ # ^^^^
+ def visit_block_parameter_node(node)
+ :"&#{node.name}"
+ end
+
+ # A block's parameters.
+ def visit_block_parameters_node(node)
+ # If this block parameters has no parameters and is using pipes, then
+ # it inherits its location from its shadow locals, even if they're not
+ # on the same lines as the pipes.
+ shadow_loc = true
+
+ result =
+ if node.parameters.nil?
+ s(node, :args)
+ else
+ shadow_loc = false
+ visit(node.parameters)
+ end
+
+ if node.opening == "("
+ result.line = node.opening_loc.start_line
+ result.line_max = node.closing_loc.end_line
+ shadow_loc = false
+ end
+
+ if node.locals.any?
+ shadow = s(node, :shadow).concat(visit_all(node.locals))
+ shadow.line = node.locals.first.location.start_line
+ shadow.line_max = node.locals.last.location.end_line
+ result << shadow
+
+ if shadow_loc
+ result.line = shadow.line
+ result.line_max = shadow.line_max
+ end
+ end
+
+ result
+ end
+
+ # break
+ # ^^^^^
+ #
+ # break foo
+ # ^^^^^^^^^
+ def visit_break_node(node)
+ if node.arguments.nil?
+ s(node, :break)
+ elsif node.arguments.arguments.length == 1
+ s(node, :break, visit(node.arguments.arguments.first))
+ else
+ s(node, :break, s(node.arguments, :array).concat(visit_all(node.arguments.arguments)))
+ end
+ end
+
+ # foo
+ # ^^^
+ #
+ # foo.bar
+ # ^^^^^^^
+ #
+ # foo.bar() {}
+ # ^^^^^^^^^^^^
+ def visit_call_node(node)
+ case node.name
+ when :!~
+ return s(node, :not, visit(node.copy(name: :"=~")))
+ when :=~
+ if node.arguments&.arguments&.length == 1 && node.block.nil?
+ case node.receiver
+ when StringNode
+ return s(node, :match3, visit(node.arguments.arguments.first), visit(node.receiver))
+ when RegularExpressionNode, InterpolatedRegularExpressionNode
+ return s(node, :match2, visit(node.receiver), visit(node.arguments.arguments.first))
+ end
+ end
+ end
+
+ type = node.attribute_write? ? :attrasgn : :call
+ type = :"safe_#{type}" if node.safe_navigation?
+
+ arguments = node.arguments&.arguments || []
+ write_value = arguments.pop if type == :attrasgn
+ block = node.block
+
+ if block.is_a?(BlockArgumentNode)
+ arguments << block
+ block = nil
+ end
+
+ result = s(node, type, visit(node.receiver), node.name).concat(visit_all(arguments))
+ result << visit_write_value(write_value) unless write_value.nil?
+
+ visit_block(node, result, block)
+ end
+
+ # foo.bar += baz
+ # ^^^^^^^^^^^^^^^
+ def visit_call_operator_write_node(node)
+ if op_asgn?(node)
+ s(node, op_asgn_type(node, :op_asgn), visit(node.receiver), visit_write_value(node.value), node.read_name, node.binary_operator)
+ else
+ s(node, op_asgn_type(node, :op_asgn2), visit(node.receiver), node.write_name, node.binary_operator, visit_write_value(node.value))
+ end
+ end
+
+ # foo.bar &&= baz
+ # ^^^^^^^^^^^^^^^
+ def visit_call_and_write_node(node)
+ if op_asgn?(node)
+ s(node, op_asgn_type(node, :op_asgn), visit(node.receiver), visit_write_value(node.value), node.read_name, :"&&")
+ else
+ s(node, op_asgn_type(node, :op_asgn2), visit(node.receiver), node.write_name, :"&&", visit_write_value(node.value))
+ end
+ end
+
+ # foo.bar ||= baz
+ # ^^^^^^^^^^^^^^^
+ def visit_call_or_write_node(node)
+ if op_asgn?(node)
+ s(node, op_asgn_type(node, :op_asgn), visit(node.receiver), visit_write_value(node.value), node.read_name, :"||")
+ else
+ s(node, op_asgn_type(node, :op_asgn2), visit(node.receiver), node.write_name, :"||", visit_write_value(node.value))
+ end
+ end
+
+ # Call nodes with operators following them will either be op_asgn or
+ # op_asgn2 nodes. That is determined by their call operator and their
+ # right-hand side.
+ private def op_asgn?(node)
+ node.call_operator == "::" || (node.value.is_a?(CallNode) && node.value.opening_loc.nil? && !node.value.arguments.nil?)
+ end
+
+ # Call nodes with operators following them can use &. as an operator,
+ # which changes their type by prefixing "safe_".
+ private def op_asgn_type(node, type)
+ node.safe_navigation? ? :"safe_#{type}" : type
+ end
+
+ # foo.bar, = 1
+ # ^^^^^^^
+ def visit_call_target_node(node)
+ s(node, :attrasgn, visit(node.receiver), node.name)
+ end
+
+ # foo => bar => baz
+ # ^^^^^^^^^^
+ def visit_capture_pattern_node(node)
+ visit(node.target) << visit(node.value)
+ end
+
+ # case foo; when bar; end
+ # ^^^^^^^^^^^^^^^^^^^^^^^
+ def visit_case_node(node)
+ s(node, :case, visit(node.predicate)).concat(visit_all(node.conditions)) << visit(node.consequent)
+ end
+
+ # case foo; in bar; end
+ # ^^^^^^^^^^^^^^^^^^^^^
+ def visit_case_match_node(node)
+ s(node, :case, visit(node.predicate)).concat(visit_all(node.conditions)) << visit(node.consequent)
+ end
+
+ # class Foo; end
+ # ^^^^^^^^^^^^^^
+ def visit_class_node(node)
+ name =
+ if node.constant_path.is_a?(ConstantReadNode)
+ node.name
+ else
+ visit(node.constant_path)
+ end
+
+ if node.body.nil?
+ s(node, :class, name, visit(node.superclass))
+ elsif node.body.is_a?(StatementsNode)
+ compiler = copy_compiler(in_def: false)
+ s(node, :class, name, visit(node.superclass)).concat(node.body.body.map { |child| child.accept(compiler) })
+ else
+ s(node, :class, name, visit(node.superclass), node.body.accept(copy_compiler(in_def: false)))
+ end
+ end
+
+ # @@foo
+ # ^^^^^
+ def visit_class_variable_read_node(node)
+ s(node, :cvar, node.name)
+ end
+
+ # @@foo = 1
+ # ^^^^^^^^^
+ #
+ # @@foo, @@bar = 1
+ # ^^^^^ ^^^^^
+ def visit_class_variable_write_node(node)
+ s(node, class_variable_write_type, node.name, visit_write_value(node.value))
+ end
+
+ # @@foo += bar
+ # ^^^^^^^^^^^^
+ def visit_class_variable_operator_write_node(node)
+ s(node, class_variable_write_type, node.name, s(node, :call, s(node, :cvar, node.name), node.binary_operator, visit_write_value(node.value)))
+ end
+
+ # @@foo &&= bar
+ # ^^^^^^^^^^^^^
+ def visit_class_variable_and_write_node(node)
+ s(node, :op_asgn_and, s(node, :cvar, node.name), s(node, class_variable_write_type, node.name, visit_write_value(node.value)))
+ end
+
+ # @@foo ||= bar
+ # ^^^^^^^^^^^^^
+ def visit_class_variable_or_write_node(node)
+ s(node, :op_asgn_or, s(node, :cvar, node.name), s(node, class_variable_write_type, node.name, visit_write_value(node.value)))
+ end
+
+ # @@foo, = bar
+ # ^^^^^
+ def visit_class_variable_target_node(node)
+ s(node, class_variable_write_type, node.name)
+ end
+
+ # If a class variable is written within a method definition, it has a
+ # different type than everywhere else.
+ private def class_variable_write_type
+ in_def ? :cvasgn : :cvdecl
+ end
+
+ # Foo
+ # ^^^
+ def visit_constant_read_node(node)
+ s(node, :const, node.name)
+ end
+
+ # Foo = 1
+ # ^^^^^^^
+ #
+ # Foo, Bar = 1
+ # ^^^ ^^^
+ def visit_constant_write_node(node)
+ s(node, :cdecl, node.name, visit_write_value(node.value))
+ end
+
+ # Foo += bar
+ # ^^^^^^^^^^^
+ def visit_constant_operator_write_node(node)
+ s(node, :cdecl, node.name, s(node, :call, s(node, :const, node.name), node.binary_operator, visit_write_value(node.value)))
+ end
+
+ # Foo &&= bar
+ # ^^^^^^^^^^^^
+ def visit_constant_and_write_node(node)
+ s(node, :op_asgn_and, s(node, :const, node.name), s(node, :cdecl, node.name, visit(node.value)))
+ end
+
+ # Foo ||= bar
+ # ^^^^^^^^^^^^
+ def visit_constant_or_write_node(node)
+ s(node, :op_asgn_or, s(node, :const, node.name), s(node, :cdecl, node.name, visit(node.value)))
+ end
+
+ # Foo, = bar
+ # ^^^
+ def visit_constant_target_node(node)
+ s(node, :cdecl, node.name)
+ end
+
+ # Foo::Bar
+ # ^^^^^^^^
+ def visit_constant_path_node(node)
+ if node.parent.nil?
+ s(node, :colon3, node.name)
+ else
+ s(node, :colon2, visit(node.parent), node.name)
+ end
+ end
+
+ # Foo::Bar = 1
+ # ^^^^^^^^^^^^
+ #
+ # Foo::Foo, Bar::Bar = 1
+ # ^^^^^^^^ ^^^^^^^^
+ def visit_constant_path_write_node(node)
+ s(node, :cdecl, visit(node.target), visit_write_value(node.value))
+ end
+
+ # Foo::Bar += baz
+ # ^^^^^^^^^^^^^^^
+ def visit_constant_path_operator_write_node(node)
+ s(node, :op_asgn, visit(node.target), node.binary_operator, visit_write_value(node.value))
+ end
+
+ # Foo::Bar &&= baz
+ # ^^^^^^^^^^^^^^^^
+ def visit_constant_path_and_write_node(node)
+ s(node, :op_asgn_and, visit(node.target), visit_write_value(node.value))
+ end
+
+ # Foo::Bar ||= baz
+ # ^^^^^^^^^^^^^^^^
+ def visit_constant_path_or_write_node(node)
+ s(node, :op_asgn_or, visit(node.target), visit_write_value(node.value))
+ end
+
+ # Foo::Bar, = baz
+ # ^^^^^^^^
+ def visit_constant_path_target_node(node)
+ inner =
+ if node.parent.nil?
+ s(node, :colon3, node.name)
+ else
+ s(node, :colon2, visit(node.parent), node.name)
+ end
+
+ s(node, :const, inner)
+ end
+
+ # def foo; end
+ # ^^^^^^^^^^^^
+ #
+ # def self.foo; end
+ # ^^^^^^^^^^^^^^^^^
+ def visit_def_node(node)
+ name = node.name_loc.slice.to_sym
+ result =
+ if node.receiver.nil?
+ s(node, :defn, name)
+ else
+ s(node, :defs, visit(node.receiver), name)
+ end
+
+ result.line(node.name_loc.start_line)
+ if node.parameters.nil?
+ result << s(node, :args).line(node.name_loc.start_line)
+ else
+ result << visit(node.parameters)
+ end
+
+ if node.body.nil?
+ result << s(node, :nil)
+ elsif node.body.is_a?(StatementsNode)
+ compiler = copy_compiler(in_def: true)
+ result.concat(node.body.body.map { |child| child.accept(compiler) })
+ else
+ result << node.body.accept(copy_compiler(in_def: true))
+ end
+ end
+
+ # defined? a
+ # ^^^^^^^^^^
+ #
+ # defined?(a)
+ # ^^^^^^^^^^^
+ def visit_defined_node(node)
+ s(node, :defined, visit(node.value))
+ end
+
+ # if foo then bar else baz end
+ # ^^^^^^^^^^^^
+ def visit_else_node(node)
+ visit(node.statements)
+ end
+
+ # "foo #{bar}"
+ # ^^^^^^
+ def visit_embedded_statements_node(node)
+ result = s(node, :evstr)
+ result << visit(node.statements) unless node.statements.nil?
+ result
+ end
+
+ # "foo #@bar"
+ # ^^^^^
+ def visit_embedded_variable_node(node)
+ s(node, :evstr, visit(node.variable))
+ end
+
+ # begin; foo; ensure; bar; end
+ # ^^^^^^^^^^^^
+ def visit_ensure_node(node)
+ node.statements.nil? ? s(node, :nil) : visit(node.statements)
+ end
+
+ # false
+ # ^^^^^
+ def visit_false_node(node)
+ s(node, :false)
+ end
+
+ # foo => [*, bar, *]
+ # ^^^^^^^^^^^
+ def visit_find_pattern_node(node)
+ s(node, :find_pat, visit_pattern_constant(node.constant), :"*#{node.left.expression&.name}", *visit_all(node.requireds), :"*#{node.right.expression&.name}")
+ end
+
+ # if foo .. bar; end
+ # ^^^^^^^^^^
+ def visit_flip_flop_node(node)
+ if node.left.is_a?(IntegerNode) && node.right.is_a?(IntegerNode)
+ s(node, :lit, Range.new(node.left.value, node.right.value, node.exclude_end?))
+ else
+ s(node, node.exclude_end? ? :flip3 : :flip2, visit(node.left), visit(node.right))
+ end
+ end
+
+ # 1.0
+ # ^^^
+ def visit_float_node(node)
+ s(node, :lit, node.value)
+ end
+
+ # for foo in bar do end
+ # ^^^^^^^^^^^^^^^^^^^^^
+ def visit_for_node(node)
+ s(node, :for, visit(node.collection), visit(node.index), visit(node.statements))
+ end
+
+ # def foo(...); bar(...); end
+ # ^^^
+ def visit_forwarding_arguments_node(node)
+ s(node, :forward_args)
+ end
+
+ # def foo(...); end
+ # ^^^
+ def visit_forwarding_parameter_node(node)
+ s(node, :forward_args)
+ end
+
+ # super
+ # ^^^^^
+ #
+ # super {}
+ # ^^^^^^^^
+ def visit_forwarding_super_node(node)
+ visit_block(node, s(node, :zsuper), node.block)
+ end
+
+ # $foo
+ # ^^^^
+ def visit_global_variable_read_node(node)
+ s(node, :gvar, node.name)
+ end
+
+ # $foo = 1
+ # ^^^^^^^^
+ #
+ # $foo, $bar = 1
+ # ^^^^ ^^^^
+ def visit_global_variable_write_node(node)
+ s(node, :gasgn, node.name, visit_write_value(node.value))
+ end
+
+ # $foo += bar
+ # ^^^^^^^^^^^
+ def visit_global_variable_operator_write_node(node)
+ s(node, :gasgn, node.name, s(node, :call, s(node, :gvar, node.name), node.binary_operator, visit(node.value)))
+ end
+
+ # $foo &&= bar
+ # ^^^^^^^^^^^^
+ def visit_global_variable_and_write_node(node)
+ s(node, :op_asgn_and, s(node, :gvar, node.name), s(node, :gasgn, node.name, visit_write_value(node.value)))
+ end
+
+ # $foo ||= bar
+ # ^^^^^^^^^^^^
+ def visit_global_variable_or_write_node(node)
+ s(node, :op_asgn_or, s(node, :gvar, node.name), s(node, :gasgn, node.name, visit_write_value(node.value)))
+ end
+
+ # $foo, = bar
+ # ^^^^
+ def visit_global_variable_target_node(node)
+ s(node, :gasgn, node.name)
+ end
+
+ # {}
+ # ^^
+ def visit_hash_node(node)
+ s(node, :hash).concat(node.elements.flat_map { |element| visit(element) })
+ end
+
+ # foo => {}
+ # ^^
+ def visit_hash_pattern_node(node)
+ result = s(node, :hash_pat, visit_pattern_constant(node.constant)).concat(node.elements.flat_map { |element| visit(element) })
+
+ case node.rest
+ when AssocSplatNode
+ result << s(node.rest, :kwrest, :"**#{node.rest.value&.name}")
+ when NoKeywordsParameterNode
+ result << visit(node.rest)
+ end
+
+ result
+ end
+
+ # if foo then bar end
+ # ^^^^^^^^^^^^^^^^^^^
+ #
+ # bar if foo
+ # ^^^^^^^^^^
+ #
+ # foo ? bar : baz
+ # ^^^^^^^^^^^^^^^
+ def visit_if_node(node)
+ s(node, :if, visit(node.predicate), visit(node.statements), visit(node.consequent))
+ end
+
+ # 1i
+ def visit_imaginary_node(node)
+ s(node, :lit, node.value)
+ end
+
+ # { foo: }
+ # ^^^^
+ def visit_implicit_node(node)
+ end
+
+ # foo { |bar,| }
+ # ^
+ def visit_implicit_rest_node(node)
+ end
+
+ # case foo; in bar; end
+ # ^^^^^^^^^^^^^^^^^^^^^
+ def visit_in_node(node)
+ pattern =
+ if node.pattern.is_a?(ConstantPathNode)
+ s(node.pattern, :const, visit(node.pattern))
+ else
+ node.pattern.accept(copy_compiler(in_pattern: true))
+ end
+
+ s(node, :in, pattern).concat(node.statements.nil? ? [nil] : visit_all(node.statements.body))
+ end
+
+ # foo[bar] += baz
+ # ^^^^^^^^^^^^^^^
+ def visit_index_operator_write_node(node)
+ arglist = nil
+
+ if !node.arguments.nil? || !node.block.nil?
+ arglist = s(node, :arglist).concat(visit_all(node.arguments&.arguments || []))
+ arglist << visit(node.block) if !node.block.nil?
+ end
+
+ s(node, :op_asgn1, visit(node.receiver), arglist, node.binary_operator, visit_write_value(node.value))
+ end
+
+ # foo[bar] &&= baz
+ # ^^^^^^^^^^^^^^^^
+ def visit_index_and_write_node(node)
+ arglist = nil
+
+ if !node.arguments.nil? || !node.block.nil?
+ arglist = s(node, :arglist).concat(visit_all(node.arguments&.arguments || []))
+ arglist << visit(node.block) if !node.block.nil?
+ end
+
+ s(node, :op_asgn1, visit(node.receiver), arglist, :"&&", visit_write_value(node.value))
+ end
+
+ # foo[bar] ||= baz
+ # ^^^^^^^^^^^^^^^^
+ def visit_index_or_write_node(node)
+ arglist = nil
+
+ if !node.arguments.nil? || !node.block.nil?
+ arglist = s(node, :arglist).concat(visit_all(node.arguments&.arguments || []))
+ arglist << visit(node.block) if !node.block.nil?
+ end
+
+ s(node, :op_asgn1, visit(node.receiver), arglist, :"||", visit_write_value(node.value))
+ end
+
+ # foo[bar], = 1
+ # ^^^^^^^^
+ def visit_index_target_node(node)
+ arguments = visit_all(node.arguments&.arguments || [])
+ arguments << visit(node.block) unless node.block.nil?
+
+ s(node, :attrasgn, visit(node.receiver), :[]=).concat(arguments)
+ end
+
+ # @foo
+ # ^^^^
+ def visit_instance_variable_read_node(node)
+ s(node, :ivar, node.name)
+ end
+
+ # @foo = 1
+ # ^^^^^^^^
+ #
+ # @foo, @bar = 1
+ # ^^^^ ^^^^
+ def visit_instance_variable_write_node(node)
+ s(node, :iasgn, node.name, visit_write_value(node.value))
+ end
+
+ # @foo += bar
+ # ^^^^^^^^^^^
+ def visit_instance_variable_operator_write_node(node)
+ s(node, :iasgn, node.name, s(node, :call, s(node, :ivar, node.name), node.binary_operator, visit_write_value(node.value)))
+ end
+
+ # @foo &&= bar
+ # ^^^^^^^^^^^^
+ def visit_instance_variable_and_write_node(node)
+ s(node, :op_asgn_and, s(node, :ivar, node.name), s(node, :iasgn, node.name, visit(node.value)))
+ end
+
+ # @foo ||= bar
+ # ^^^^^^^^^^^^
+ def visit_instance_variable_or_write_node(node)
+ s(node, :op_asgn_or, s(node, :ivar, node.name), s(node, :iasgn, node.name, visit(node.value)))
+ end
+
+ # @foo, = bar
+ # ^^^^
+ def visit_instance_variable_target_node(node)
+ s(node, :iasgn, node.name)
+ end
+
+ # 1
+ # ^
+ def visit_integer_node(node)
+ s(node, :lit, node.value)
+ end
+
+ # if /foo #{bar}/ then end
+ # ^^^^^^^^^^^^
+ def visit_interpolated_match_last_line_node(node)
+ parts = visit_interpolated_parts(node.parts)
+ regexp =
+ if parts.length == 1
+ s(node, :lit, Regexp.new(parts.first, node.options))
+ else
+ s(node, :dregx).concat(parts).tap do |result|
+ options = node.options
+ result << options if options != 0
+ end
+ end
+
+ s(node, :match, regexp)
+ end
+
+ # /foo #{bar}/
+ # ^^^^^^^^^^^^
+ def visit_interpolated_regular_expression_node(node)
+ parts = visit_interpolated_parts(node.parts)
+
+ if parts.length == 1
+ s(node, :lit, Regexp.new(parts.first, node.options))
+ else
+ s(node, :dregx).concat(parts).tap do |result|
+ options = node.options
+ result << options if options != 0
+ end
+ end
+ end
+
+ # "foo #{bar}"
+ # ^^^^^^^^^^^^
+ def visit_interpolated_string_node(node)
+ parts = visit_interpolated_parts(node.parts)
+ parts.length == 1 ? s(node, :str, parts.first) : s(node, :dstr).concat(parts)
+ end
+
+ # :"foo #{bar}"
+ # ^^^^^^^^^^^^^
+ def visit_interpolated_symbol_node(node)
+ parts = visit_interpolated_parts(node.parts)
+ parts.length == 1 ? s(node, :lit, parts.first.to_sym) : s(node, :dsym).concat(parts)
+ end
+
+ # `foo #{bar}`
+ # ^^^^^^^^^^^^
+ def visit_interpolated_x_string_node(node)
+ source = node.heredoc? ? node.parts.first : node
+ parts = visit_interpolated_parts(node.parts)
+ parts.length == 1 ? s(source, :xstr, parts.first) : s(source, :dxstr).concat(parts)
+ end
+
+ # Visit the interpolated content of the string-like node.
+ private def visit_interpolated_parts(parts)
+ visited = []
+ parts.each do |part|
+ result = visit(part)
+
+ if result[0] == :evstr && result[1]
+ if result[1][0] == :str
+ visited << result[1]
+ elsif result[1][0] == :dstr
+ visited.concat(result[1][1..-1])
+ else
+ visited << result
+ end
+ elsif result[0] == :dstr
+ visited.concat(result[1..-1])
+ else
+ visited << result
+ end
+ end
+
+ state = :beginning #: :beginning | :string_content | :interpolated_content
+
+ visited.each_with_object([]) do |result, results|
+ case state
+ when :beginning
+ if result.is_a?(String)
+ results << result
+ state = :string_content
+ elsif result.is_a?(Array) && result[0] == :str
+ results << result[1]
+ state = :string_content
+ else
+ results << ""
+ results << result
+ state = :interpolated_content
+ end
+ when :string_content
+ if result.is_a?(String)
+ results[0] << result
+ elsif result.is_a?(Array) && result[0] == :str
+ results[0] << result[1]
+ else
+ results << result
+ state = :interpolated_content
+ end
+ when :interpolated_content
+ if result.is_a?(Array) && result[0] == :str && results[-1][0] == :str && (results[-1].line_max == result.line)
+ results[-1][1] << result[1]
+ results[-1].line_max = result.line_max
+ else
+ results << result
+ end
+ end
+ end
+ end
+
+ # -> { it }
+ # ^^
+ def visit_it_local_variable_read_node(node)
+ s(node, :call, nil, :it)
+ end
+
+ # foo(bar: baz)
+ # ^^^^^^^^
+ def visit_keyword_hash_node(node)
+ s(node, :hash).concat(node.elements.flat_map { |element| visit(element) })
+ end
+
+ # def foo(**bar); end
+ # ^^^^^
+ #
+ # def foo(**); end
+ # ^^
+ def visit_keyword_rest_parameter_node(node)
+ :"**#{node.name}"
+ end
+
+ # -> {}
+ def visit_lambda_node(node)
+ parameters =
+ case node.parameters
+ when nil, NumberedParametersNode
+ s(node, :args)
+ else
+ visit(node.parameters)
+ end
+
+ if node.body.nil?
+ s(node, :iter, s(node, :lambda), parameters)
+ else
+ s(node, :iter, s(node, :lambda), parameters, visit(node.body))
+ end
+ end
+
+ # foo
+ # ^^^
+ def visit_local_variable_read_node(node)
+ if node.name.match?(/^_\d$/)
+ s(node, :call, nil, node.name)
+ else
+ s(node, :lvar, node.name)
+ end
+ end
+
+ # foo = 1
+ # ^^^^^^^
+ #
+ # foo, bar = 1
+ # ^^^ ^^^
+ def visit_local_variable_write_node(node)
+ s(node, :lasgn, node.name, visit_write_value(node.value))
+ end
+
+ # foo += bar
+ # ^^^^^^^^^^
+ def visit_local_variable_operator_write_node(node)
+ s(node, :lasgn, node.name, s(node, :call, s(node, :lvar, node.name), node.binary_operator, visit_write_value(node.value)))
+ end
+
+ # foo &&= bar
+ # ^^^^^^^^^^^
+ def visit_local_variable_and_write_node(node)
+ s(node, :op_asgn_and, s(node, :lvar, node.name), s(node, :lasgn, node.name, visit_write_value(node.value)))
+ end
+
+ # foo ||= bar
+ # ^^^^^^^^^^^
+ def visit_local_variable_or_write_node(node)
+ s(node, :op_asgn_or, s(node, :lvar, node.name), s(node, :lasgn, node.name, visit_write_value(node.value)))
+ end
+
+ # foo, = bar
+ # ^^^
+ def visit_local_variable_target_node(node)
+ s(node, :lasgn, node.name)
+ end
+
+ # if /foo/ then end
+ # ^^^^^
+ def visit_match_last_line_node(node)
+ s(node, :match, s(node, :lit, Regexp.new(node.unescaped, node.options)))
+ end
+
+ # foo in bar
+ # ^^^^^^^^^^
+ def visit_match_predicate_node(node)
+ s(node, :case, visit(node.value), s(node, :in, node.pattern.accept(copy_compiler(in_pattern: true)), nil), nil)
+ end
+
+ # foo => bar
+ # ^^^^^^^^^^
+ def visit_match_required_node(node)
+ s(node, :case, visit(node.value), s(node, :in, node.pattern.accept(copy_compiler(in_pattern: true)), nil), nil)
+ end
+
+ # /(?<foo>foo)/ =~ bar
+ # ^^^^^^^^^^^^^^^^^^^^
+ def visit_match_write_node(node)
+ s(node, :match2, visit(node.call.receiver), visit(node.call.arguments.arguments.first))
+ end
+
+ # A node that is missing from the syntax tree. This is only used in the
+ # case of a syntax error. The parser gem doesn't have such a concept, so
+ # we invent our own here.
+ def visit_missing_node(node)
+ raise "Cannot visit missing node directly"
+ end
+
+ # module Foo; end
+ # ^^^^^^^^^^^^^^^
+ def visit_module_node(node)
+ name =
+ if node.constant_path.is_a?(ConstantReadNode)
+ node.name
+ else
+ visit(node.constant_path)
+ end
+
+ if node.body.nil?
+ s(node, :module, name)
+ elsif node.body.is_a?(StatementsNode)
+ compiler = copy_compiler(in_def: false)
+ s(node, :module, name).concat(node.body.body.map { |child| child.accept(compiler) })
+ else
+ s(node, :module, name, node.body.accept(copy_compiler(in_def: false)))
+ end
+ end
+
+ # foo, bar = baz
+ # ^^^^^^^^
+ def visit_multi_target_node(node)
+ targets = [*node.lefts]
+ targets << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode)
+ targets.concat(node.rights)
+
+ s(node, :masgn, s(node, :array).concat(visit_all(targets)))
+ end
+
+ # foo, bar = baz
+ # ^^^^^^^^^^^^^^
+ def visit_multi_write_node(node)
+ targets = [*node.lefts]
+ targets << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode)
+ targets.concat(node.rights)
+
+ value =
+ if node.value.is_a?(ArrayNode) && node.value.opening_loc.nil?
+ if node.value.elements.length == 1 && node.value.elements.first.is_a?(SplatNode)
+ visit(node.value.elements.first)
+ else
+ visit(node.value)
+ end
+ else
+ s(node.value, :to_ary, visit(node.value))
+ end
+
+ s(node, :masgn, s(node, :array).concat(visit_all(targets)), value)
+ end
+
+ # next
+ # ^^^^
+ #
+ # next foo
+ # ^^^^^^^^
+ def visit_next_node(node)
+ if node.arguments.nil?
+ s(node, :next)
+ elsif node.arguments.arguments.length == 1
+ argument = node.arguments.arguments.first
+ s(node, :next, argument.is_a?(SplatNode) ? s(node, :svalue, visit(argument)) : visit(argument))
+ else
+ s(node, :next, s(node, :array).concat(visit_all(node.arguments.arguments)))
+ end
+ end
+
+ # nil
+ # ^^^
+ def visit_nil_node(node)
+ s(node, :nil)
+ end
+
+ # def foo(**nil); end
+ # ^^^^^
+ def visit_no_keywords_parameter_node(node)
+ in_pattern ? s(node, :kwrest, :"**nil") : :"**nil"
+ end
+
+ # -> { _1 + _2 }
+ # ^^^^^^^^^^^^^^
+ def visit_numbered_parameters_node(node)
+ raise "Cannot visit numbered parameters directly"
+ end
+
+ # $1
+ # ^^
+ def visit_numbered_reference_read_node(node)
+ s(node, :nth_ref, node.number)
+ end
+
+ # def foo(bar: baz); end
+ # ^^^^^^^^
+ def visit_optional_keyword_parameter_node(node)
+ s(node, :kwarg, node.name, visit(node.value))
+ end
+
+ # def foo(bar = 1); end
+ # ^^^^^^^
+ def visit_optional_parameter_node(node)
+ s(node, :lasgn, node.name, visit(node.value))
+ end
+
+ # a or b
+ # ^^^^^^
+ def visit_or_node(node)
+ s(node, :or, visit(node.left), visit(node.right))
+ end
+
+ # def foo(bar, *baz); end
+ # ^^^^^^^^^
+ def visit_parameters_node(node)
+ children =
+ node.compact_child_nodes.map do |element|
+ if element.is_a?(MultiTargetNode)
+ visit_destructured_parameter(element)
+ else
+ visit(element)
+ end
+ end
+
+ s(node, :args).concat(children)
+ end
+
+ # def foo((bar, baz)); end
+ # ^^^^^^^^^^
+ private def visit_destructured_parameter(node)
+ children =
+ [*node.lefts, *node.rest, *node.rights].map do |child|
+ case child
+ when RequiredParameterNode
+ visit(child)
+ when MultiTargetNode
+ visit_destructured_parameter(child)
+ when SplatNode
+ :"*#{child.expression&.name}"
+ else
+ raise
+ end
+ end
+
+ s(node, :masgn).concat(children)
+ end
+
+ # ()
+ # ^^
+ #
+ # (1)
+ # ^^^
+ def visit_parentheses_node(node)
+ if node.body.nil?
+ s(node, :nil)
+ else
+ visit(node.body)
+ end
+ end
+
+ # foo => ^(bar)
+ # ^^^^^^
+ def visit_pinned_expression_node(node)
+ node.expression.accept(copy_compiler(in_pattern: false))
+ end
+
+ # foo = 1 and bar => ^foo
+ # ^^^^
+ def visit_pinned_variable_node(node)
+ if node.variable.is_a?(LocalVariableReadNode) && node.variable.name.match?(/^_\d$/)
+ s(node, :lvar, node.variable.name)
+ else
+ visit(node.variable)
+ end
+ end
+
+ # END {}
+ def visit_post_execution_node(node)
+ s(node, :iter, s(node, :postexe), 0, visit(node.statements))
+ end
+
+ # BEGIN {}
+ def visit_pre_execution_node(node)
+ s(node, :iter, s(node, :preexe), 0, visit(node.statements))
+ end
+
+ # The top-level program node.
+ def visit_program_node(node)
+ visit(node.statements)
+ end
+
+ # 0..5
+ # ^^^^
+ def visit_range_node(node)
+ if !in_pattern && !node.left.nil? && !node.right.nil? && ([node.left.type, node.right.type] - %i[nil_node integer_node]).empty?
+ left = node.left.value if node.left.is_a?(IntegerNode)
+ right = node.right.value if node.right.is_a?(IntegerNode)
+ s(node, :lit, Range.new(left, right, node.exclude_end?))
+ else
+ s(node, node.exclude_end? ? :dot3 : :dot2, visit_range_bounds_node(node.left), visit_range_bounds_node(node.right))
+ end
+ end
+
+ # If the bounds of a range node are empty parentheses, then they do not
+ # get replaced by their usual s(:nil), but instead are s(:begin).
+ private def visit_range_bounds_node(node)
+ if node.is_a?(ParenthesesNode) && node.body.nil?
+ s(node, :begin)
+ else
+ visit(node)
+ end
+ end
+
+ # 1r
+ # ^^
+ def visit_rational_node(node)
+ s(node, :lit, node.value)
+ end
+
+ # redo
+ # ^^^^
+ def visit_redo_node(node)
+ s(node, :redo)
+ end
+
+ # /foo/
+ # ^^^^^
+ def visit_regular_expression_node(node)
+ s(node, :lit, Regexp.new(node.unescaped, node.options))
+ end
+
+ # def foo(bar:); end
+ # ^^^^
+ def visit_required_keyword_parameter_node(node)
+ s(node, :kwarg, node.name)
+ end
+
+ # def foo(bar); end
+ # ^^^
+ def visit_required_parameter_node(node)
+ node.name
+ end
+
+ # foo rescue bar
+ # ^^^^^^^^^^^^^^
+ def visit_rescue_modifier_node(node)
+ s(node, :rescue, visit(node.expression), s(node.rescue_expression, :resbody, s(node.rescue_expression, :array), visit(node.rescue_expression)))
+ end
+
+ # begin; rescue; end
+ # ^^^^^^^
+ def visit_rescue_node(node)
+ exceptions =
+ if node.exceptions.length == 1 && node.exceptions.first.is_a?(SplatNode)
+ visit(node.exceptions.first)
+ else
+ s(node, :array).concat(visit_all(node.exceptions))
+ end
+
+ if !node.reference.nil?
+ exceptions << (visit(node.reference) << s(node.reference, :gvar, :"$!"))
+ end
+
+ s(node, :resbody, exceptions).concat(node.statements.nil? ? [nil] : visit_all(node.statements.body))
+ end
+
+ # def foo(*bar); end
+ # ^^^^
+ #
+ # def foo(*); end
+ # ^
+ def visit_rest_parameter_node(node)
+ :"*#{node.name}"
+ end
+
+ # retry
+ # ^^^^^
+ def visit_retry_node(node)
+ s(node, :retry)
+ end
+
+ # return
+ # ^^^^^^
+ #
+ # return 1
+ # ^^^^^^^^
+ def visit_return_node(node)
+ if node.arguments.nil?
+ s(node, :return)
+ elsif node.arguments.arguments.length == 1
+ argument = node.arguments.arguments.first
+ s(node, :return, argument.is_a?(SplatNode) ? s(node, :svalue, visit(argument)) : visit(argument))
+ else
+ s(node, :return, s(node, :array).concat(visit_all(node.arguments.arguments)))
+ end
+ end
+
+ # self
+ # ^^^^
+ def visit_self_node(node)
+ s(node, :self)
+ end
+
+ # A shareable constant.
+ def visit_shareable_constant_node(node)
+ visit(node.write)
+ end
+
+ # class << self; end
+ # ^^^^^^^^^^^^^^^^^^
+ def visit_singleton_class_node(node)
+ s(node, :sclass, visit(node.expression)).tap do |sexp|
+ sexp << node.body.accept(copy_compiler(in_def: false)) unless node.body.nil?
+ end
+ end
+
+ # __ENCODING__
+ # ^^^^^^^^^^^^
+ def visit_source_encoding_node(node)
+ # TODO
+ s(node, :colon2, s(node, :const, :Encoding), :UTF_8)
+ end
+
+ # __FILE__
+ # ^^^^^^^^
+ def visit_source_file_node(node)
+ s(node, :str, node.filepath)
+ end
+
+ # __LINE__
+ # ^^^^^^^^
+ def visit_source_line_node(node)
+ s(node, :lit, node.location.start_line)
+ end
+
+ # foo(*bar)
+ # ^^^^
+ #
+ # def foo((bar, *baz)); end
+ # ^^^^
+ #
+ # def foo(*); bar(*); end
+ # ^
+ def visit_splat_node(node)
+ if node.expression.nil?
+ s(node, :splat)
+ else
+ s(node, :splat, visit(node.expression))
+ end
+ end
+
+ # A list of statements.
+ def visit_statements_node(node)
+ first, *rest = node.body
+
+ if rest.empty?
+ visit(first)
+ else
+ s(node, :block).concat(visit_all(node.body))
+ end
+ end
+
+ # "foo"
+ # ^^^^^
+ def visit_string_node(node)
+ s(node, :str, node.unescaped)
+ end
+
+ # super(foo)
+ # ^^^^^^^^^^
+ def visit_super_node(node)
+ arguments = node.arguments&.arguments || []
+ block = node.block
+
+ if block.is_a?(BlockArgumentNode)
+ arguments << block
+ block = nil
+ end
+
+ visit_block(node, s(node, :super).concat(visit_all(arguments)), block)
+ end
+
+ # :foo
+ # ^^^^
+ def visit_symbol_node(node)
+ node.value == "!@" ? s(node, :lit, :"!@") : s(node, :lit, node.unescaped.to_sym)
+ end
+
+ # true
+ # ^^^^
+ def visit_true_node(node)
+ s(node, :true)
+ end
+
+ # undef foo
+ # ^^^^^^^^^
+ def visit_undef_node(node)
+ names = node.names.map { |name| s(node, :undef, visit(name)) }
+ names.length == 1 ? names.first : s(node, :block).concat(names)
+ end
+
+ # unless foo; bar end
+ # ^^^^^^^^^^^^^^^^^^^
+ #
+ # bar unless foo
+ # ^^^^^^^^^^^^^^
+ def visit_unless_node(node)
+ s(node, :if, visit(node.predicate), visit(node.consequent), visit(node.statements))
+ end
+
+ # until foo; bar end
+ # ^^^^^^^^^^^^^^^^^
+ #
+ # bar until foo
+ # ^^^^^^^^^^^^^
+ def visit_until_node(node)
+ s(node, :until, visit(node.predicate), visit(node.statements), !node.begin_modifier?)
+ end
+
+ # case foo; when bar; end
+ # ^^^^^^^^^^^^^
+ def visit_when_node(node)
+ s(node, :when, s(node, :array).concat(visit_all(node.conditions))).concat(node.statements.nil? ? [nil] : visit_all(node.statements.body))
+ end
+